diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..cadefe6 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,24 @@ +FROM alpine:latest as build +USER root +ENV USER=root +RUN apk add --no-cache build-base git lua-dev luarocks5.1 lua5.1-sec +RUN luarocks-5.1 install luasocket +RUN luarocks-5.1 install luacov +RUN luarocks-5.1 install busted 2.0.0-1 +RUN luarocks-5.1 install --server https://luarocks.org/dev mineunit + +# Mineunit base +FROM alpine:latest +COPY --from=build /usr/local /usr/local +RUN adduser -D mineunit +RUN apk add --no-cache lua5.1 + +# Alpine is fine but image size could still be optimized if needed +#RUN rm -rf /var/cache/apk +#FROM scratch +#COPY --from=mineunit / / + +USER mineunit +WORKDIR /home/mineunit +#ENTRYPOINT ["mineunit"] +ENTRYPOINT ["sh", "-l"] diff --git a/entity.lua b/entity.lua index 81d6f25..df3ee8d 100644 --- a/entity.lua +++ b/entity.lua @@ -15,7 +15,12 @@ function ObjectRef:set_roll(value) self._roll = value end function ObjectRef:get_pos() return table.copy(self._pos) end -function ObjectRef:set_pos(value) self._pos = vector.new(value) end +function ObjectRef:set_pos(value) + self._pos = vector.new(value) + for _, child in ipairs(self:get_children()) do + child:set_pos(vector.add(self._pos, child._attach.position)) + end +end function ObjectRef:get_velocity() return table.copy(self._velocity) end function ObjectRef:add_velocity(vel) -- * `vel` is a vector, e.g. `{x=0.0, y=2.3, z=1.0}` @@ -91,25 +96,54 @@ function ObjectRef:set_animation_frame_speed(frame_speed) -- * `frame_speed`: number, default: `15.0` end function ObjectRef:set_attach(parent, bone, position, rotation, forced_visible) - -- - -- * `bone`: string. Default is `""`, the root bone - -- * `position`: `{x=num, y=num, z=num}`, relative, default `{x=0, y=0, z=0}` - -- * `rotation`: `{x=num, y=num, z=num}` = Rotation on each axis, in degrees. - -- Default `{x=0, y=0, z=0}` - -- * `forced_visible`: Boolean to control whether the attached entity - -- should appear in first person. Default `false`. - -- * This command may fail silently (do nothing) when it would result - -- in circular attachments. + if not parent then return end + if self._attach and self._attach.parent == parent then + mineunit:info('Attempt to attach to parent that object is already attached to.') + return + end + -- detach if attached + self:set_detach() + local obj = parent + while true do + if not obj._attach then break end + if obj._attach.parent == self then + mineunit:warning('Mod bug: Attempted to attach object to an object that ' + .. 'is directly or indirectly attached to the first object. -> ' + .. 'circular attachment chain.') + return + end + obj = obj._attach.parent + end + if 'table' ~= type(parent._children) then parent._children = {} end + table.insert(parent._children, self) + self._attach = { + parent = parent, + bone = bone or '', + position = position or vector.new(), + rotation = rotation or vector.new(), + forced_visible = not not forced_visible, + } + self._pitch = self._attach.position.x + self._roll = self._attach.position.z + self._yaw = self._attach.position.y + self:set_pos(vector.add(parent:get_pos(), self._attach.position)) + -- TODO: bones depending on object type end function ObjectRef:get_attach() - --: returns parent, bone, position, rotation, forced_visible, - -- or nil if it isn't attached. + return self._attach end function ObjectRef:get_children() - --: returns a list of ObjectRefs that are attached to the - -- object. + return self._children or {} end function ObjectRef:set_detach() + if not self._attach then return end + + local new_children = {} + for _, child in ipairs(self._attach.parent._children) do + if child ~= self then table.insert(new_children, child) end + end + self._attach.parent._children = new_children + self._attach = nil end function ObjectRef:set_bone_position(bone, position, rotation) -- * `bone`: string. Default is `""`, the root bone @@ -123,12 +157,13 @@ function ObjectRef:set_properties(value) self._properties = value end function ObjectRef:get_properties() return table.copy(self._properties) end function ObjectRef:is_player() return true end -- FIXME! This is not actually player, add and test in Player class function ObjectRef:get_nametag_attributes() - -- * returns a table with the attributes of the nametag of an object - -- * { - -- text = "", - -- color = {a=0..255, r=0..255, g=0..255, b=0..255}, - -- bgcolor = {a=0..255, r=0..255, g=0..255, b=0..255}, - -- } + if not self._nametag_attributes then self._nametag_attributes = { + text = self._nametag_text or '', + color = self._nametag_color or { a = 255, r = 255, g = 255, b = 255 }, + bgcolor = self._nametag_bgcolor or { a = 0, r = 0, g = 0, b = 0 }, + } + end + return self._nametag_attributes end function ObjectRef:set_nametag_attributes(attributes) -- * sets the attributes of the nametag of an object @@ -142,6 +177,21 @@ function ObjectRef:set_nametag_attributes(attributes) -- -- `false` will cause the background to be set automatically based on user settings -- -- Default: false -- } + -- TODO: support ColorSpec and bgcolor of false and sync with self._nametag_* + if not self._nametag_attributes then self:get_nametag_attributes() end + for key, value in pairs(new_attributes) do + if nil ~= self._nametag_attributes[key] then + if 'text' == key then + self._nametag_attributes.text = tostring(value) + else + for subkey, subvalue in pairs(new_attributes[key]) do + if nil ~= self._nametag_attributes[key][subkey] then + self._nametag_attributes[key][subkey] = tonumber(subvalue) + end + end -- loop a, r, g, b + end + end -- if key exists + end -- loop new_attributes end mineunit.export_object(ObjectRef, { diff --git a/player.lua b/player.lua index 65ddb64..0beb815 100644 --- a/player.lua +++ b/player.lua @@ -422,6 +422,9 @@ function Player:do_reset() self._inv = InvRef() self._inv:set_size("main", 32) self._object:set_properties(table.copy(default_player_properties)) + self._hud_flags = { hotbar = true, healthbar = true, crosshair = true, + wielditem = true, breathbar = true, minimap = false, minimap_radar = false } + self._breath = 10 end -- @@ -454,12 +457,22 @@ function Player:get_look_yaw() DEPRECATED() end function Player:set_look_pitch(radians) DEPRECATED() end function Player:set_look_yaw(radians) DEPRECATED() end -function Player:get_breath() error("NOT IMPLEMENTED") end -function Player:set_breath(value) error("NOT IMPLEMENTED") end +function Player:get_breath() return self._breath or 10 end +function Player:set_breath(value) self._breath = assert(tonumber(value), "bad argument #1 to 'set_breath' (number expected, got "..type(value)..")") end function Player:set_fov(fov, is_multiplier, transition_time) error("NOT IMPLEMENTED") end function Player:get_fov() error("NOT IMPLEMENTED") end function Player:get_eye_offset() return self._eye_offset_first, self._eye_offset_third end +function Player:set_eye_offset(firstperson, thirdperson) + self._eye_offset_first = + firstperson and vector.new(firstperson) or vector.new() + + thirdperson = thirdperson and vector.new(thirdperson) or vector.new() + thirdperson.x = math.max(-10, math.min(10, thirdperson.x)) + thirdperson.y = math.max(-10, math.min(15, thirdperson.y)) + thirdperson.z = math.max(-5, math.min(5, thirdperson.z)) + self._eye_offset_third = thirdperson +end function Player:set_attribute(attribute, value) DEPRECATED() end function Player:get_attribute(attribute) DEPRECATED() end @@ -469,6 +482,15 @@ function Player:get_inventory_formspec() return "" end function Player:set_formspec_prepend(formspec) end function Player:get_formspec_prepend(formspec) return "" end +function Player:hud_get_flags() return self._hud_flags end +function Player:set_hud_flags(new_flags) + for flag, value in pairs(new_flags) do + if nil ~= self._hud_flags[flag] then + self._hud_flags[flag] = not not value + end + end +end + function Player:__index(key) local result = rawget(Player, key) if not result then @@ -509,3 +531,4 @@ mineunit.export_object(Player, { return obj end, }) +