parent
							
								
									3475759d1a
								
							
						
					
					
						commit
						b9377f26a1
					
				@ -34,7 +34,6 @@ core.register_entity(":__builtin:item", {
 | 
			
		||||
 | 
			
		||||
	itemstring = "",
 | 
			
		||||
	moving_state = true,
 | 
			
		||||
	slippery_state = false,
 | 
			
		||||
	physical_state = true,
 | 
			
		||||
	-- Item expiry
 | 
			
		||||
	age = 0,
 | 
			
		||||
@ -157,7 +156,7 @@ core.register_entity(":__builtin:item", {
 | 
			
		||||
		end
 | 
			
		||||
	end,
 | 
			
		||||
 | 
			
		||||
	on_step = function(self, dtime)
 | 
			
		||||
	on_step = function(self, dtime, moveresult)
 | 
			
		||||
		self.age = self.age + dtime
 | 
			
		||||
		if time_to_live > 0 and self.age > time_to_live then
 | 
			
		||||
			self.itemstring = ""
 | 
			
		||||
@ -178,6 +177,36 @@ core.register_entity(":__builtin:item", {
 | 
			
		||||
			return
 | 
			
		||||
		end
 | 
			
		||||
 | 
			
		||||
		if self.force_out then
 | 
			
		||||
			-- This code runs after the entity got a push from the is_stuck code.
 | 
			
		||||
			-- It makes sure the entity is entirely outside the solid node
 | 
			
		||||
			local c = self.object:get_properties().collisionbox
 | 
			
		||||
			local s = self.force_out_start
 | 
			
		||||
			local f = self.force_out
 | 
			
		||||
			local ok = (f.x > 0 and pos.x + c[1] > s.x + 0.5) or
 | 
			
		||||
				(f.y > 0 and pos.y + c[2] > s.y + 0.5) or
 | 
			
		||||
				(f.z > 0 and pos.z + c[3] > s.z + 0.5) or
 | 
			
		||||
				(f.x < 0 and pos.x + c[4] < s.x - 0.5) or
 | 
			
		||||
				(f.z < 0 and pos.z + c[6] < s.z - 0.5)
 | 
			
		||||
			if ok then
 | 
			
		||||
				-- Item was successfully forced out
 | 
			
		||||
				self.force_out = nil
 | 
			
		||||
				self:enable_physics()
 | 
			
		||||
				return
 | 
			
		||||
			end
 | 
			
		||||
		end
 | 
			
		||||
 | 
			
		||||
		if not self.physical_state then
 | 
			
		||||
			return -- Don't do anything
 | 
			
		||||
		end
 | 
			
		||||
 | 
			
		||||
		assert(moveresult)
 | 
			
		||||
		if not moveresult.collides then
 | 
			
		||||
			-- future TODO: items should probably decelerate in air
 | 
			
		||||
			return
 | 
			
		||||
		end
 | 
			
		||||
 | 
			
		||||
		-- Push item out when stuck inside solid node
 | 
			
		||||
		local is_stuck = false
 | 
			
		||||
		local snode = core.get_node_or_nil(pos)
 | 
			
		||||
		if snode then
 | 
			
		||||
@ -187,7 +216,6 @@ core.register_entity(":__builtin:item", {
 | 
			
		||||
				and (sdef.node_box == nil or sdef.node_box.type == "regular")
 | 
			
		||||
		end
 | 
			
		||||
 | 
			
		||||
		-- Push item out when stuck inside solid node
 | 
			
		||||
		if is_stuck then
 | 
			
		||||
			local shootdir
 | 
			
		||||
			local order = {
 | 
			
		||||
@ -223,69 +251,49 @@ core.register_entity(":__builtin:item", {
 | 
			
		||||
				self.force_out_start = vector.round(pos)
 | 
			
		||||
				return
 | 
			
		||||
			end
 | 
			
		||||
		elseif self.force_out then
 | 
			
		||||
			-- This code runs after the entity got a push from the above code.
 | 
			
		||||
			-- It makes sure the entity is entirely outside the solid node
 | 
			
		||||
			local c = self.object:get_properties().collisionbox
 | 
			
		||||
			local s = self.force_out_start
 | 
			
		||||
			local f = self.force_out
 | 
			
		||||
			local ok = (f.x > 0 and pos.x + c[1] > s.x + 0.5) or
 | 
			
		||||
				(f.y > 0 and pos.y + c[2] > s.y + 0.5) or
 | 
			
		||||
				(f.z > 0 and pos.z + c[3] > s.z + 0.5) or
 | 
			
		||||
				(f.x < 0 and pos.x + c[4] < s.x - 0.5) or
 | 
			
		||||
				(f.z < 0 and pos.z + c[6] < s.z - 0.5)
 | 
			
		||||
			if ok then
 | 
			
		||||
				-- Item was successfully forced out
 | 
			
		||||
				self.force_out = nil
 | 
			
		||||
				self:enable_physics()
 | 
			
		||||
			end
 | 
			
		||||
		end
 | 
			
		||||
 | 
			
		||||
		if not self.physical_state then
 | 
			
		||||
			return -- Don't do anything
 | 
			
		||||
		node = nil -- ground node we're colliding with
 | 
			
		||||
		if moveresult.touching_ground then
 | 
			
		||||
			for _, info in ipairs(moveresult.collisions) do
 | 
			
		||||
				if info.axis == "y" then
 | 
			
		||||
					node = core.get_node(info.node_pos)
 | 
			
		||||
					break
 | 
			
		||||
				end
 | 
			
		||||
			end
 | 
			
		||||
		end
 | 
			
		||||
 | 
			
		||||
		-- Slide on slippery nodes
 | 
			
		||||
		local vel = self.object:get_velocity()
 | 
			
		||||
		local def = node and core.registered_nodes[node.name]
 | 
			
		||||
		local is_moving = (def and not def.walkable) or
 | 
			
		||||
			vel.x ~= 0 or vel.y ~= 0 or vel.z ~= 0
 | 
			
		||||
		local is_slippery = false
 | 
			
		||||
		local keep_movement = false
 | 
			
		||||
 | 
			
		||||
		if def and def.walkable then
 | 
			
		||||
		if def then
 | 
			
		||||
			local slippery = core.get_item_group(node.name, "slippery")
 | 
			
		||||
			is_slippery = slippery ~= 0
 | 
			
		||||
			if is_slippery and (math.abs(vel.x) > 0.2 or math.abs(vel.z) > 0.2) then
 | 
			
		||||
			local vel = self.object:get_velocity()
 | 
			
		||||
			if slippery ~= 0 and (math.abs(vel.x) > 0.1 or math.abs(vel.z) > 0.1) then
 | 
			
		||||
				-- Horizontal deceleration
 | 
			
		||||
				local slip_factor = 4.0 / (slippery + 4)
 | 
			
		||||
				self.object:set_acceleration({
 | 
			
		||||
					x = -vel.x * slip_factor,
 | 
			
		||||
				local factor = math.min(4 / (slippery + 4) * dtime, 1)
 | 
			
		||||
				self.object:set_velocity({
 | 
			
		||||
					x = vel.x * (1 - factor),
 | 
			
		||||
					y = 0,
 | 
			
		||||
					z = -vel.z * slip_factor
 | 
			
		||||
					z = vel.z * (1 - factor)
 | 
			
		||||
				})
 | 
			
		||||
			elseif vel.y == 0 then
 | 
			
		||||
				is_moving = false
 | 
			
		||||
				keep_movement = true
 | 
			
		||||
			end
 | 
			
		||||
		end
 | 
			
		||||
 | 
			
		||||
		if self.moving_state == is_moving and
 | 
			
		||||
				self.slippery_state == is_slippery then
 | 
			
		||||
		if not keep_movement then
 | 
			
		||||
			self.object:set_velocity({x=0, y=0, z=0})
 | 
			
		||||
		end
 | 
			
		||||
 | 
			
		||||
		if self.moving_state == keep_movement then
 | 
			
		||||
			-- Do not update anything until the moving state changes
 | 
			
		||||
			return
 | 
			
		||||
		end
 | 
			
		||||
		self.moving_state = keep_movement
 | 
			
		||||
 | 
			
		||||
		self.moving_state = is_moving
 | 
			
		||||
		self.slippery_state = is_slippery
 | 
			
		||||
 | 
			
		||||
		if is_moving then
 | 
			
		||||
			self.object:set_acceleration({x = 0, y = -gravity, z = 0})
 | 
			
		||||
		else
 | 
			
		||||
			self.object:set_acceleration({x = 0, y = 0, z = 0})
 | 
			
		||||
			self.object:set_velocity({x = 0, y = 0, z = 0})
 | 
			
		||||
		end
 | 
			
		||||
 | 
			
		||||
		--Only collect items if not moving
 | 
			
		||||
		if is_moving then
 | 
			
		||||
		-- Only collect items if not moving
 | 
			
		||||
		if self.moving_state then
 | 
			
		||||
			return
 | 
			
		||||
		end
 | 
			
		||||
		-- Collect the items around to merge with
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user