That's just incredible

This commit is contained in:
jordan4ibanez 2023-11-13 06:15:03 -05:00
parent 1ae063e94f
commit 297dd1450d
3 changed files with 139 additions and 440 deletions

88
minetest-api.d.ts vendored
View File

@ -1286,17 +1286,17 @@ declare global {
}
export interface EntityDefinition {
initial_properties: ObjectProperties
on_activate(staticData: string, delta: number): void
on_deactivate(removal: boolean): void
on_step(delta: number, moveResult: MoveResult): void
on_punch(puncher: ObjectRef, timeFromLastPunch: number, toolCapabilities: ToolCapabilities, dir: Vec3, damage: number): void
on_death(killer: ObjectRef): void
on_rightclick(clicker: ObjectRef): void
on_attach_child(child: ObjectRef): void
on_detach_child(child: ObjectRef): void
on_detach(parent: ObjectRef): void
get_staticdata(): void
initial_properties?: ObjectProperties
on_activate?(staticData: string, delta: number): void
on_deactivate?(removal: boolean): void
on_step?(delta: number, moveResult: MoveResult): void
on_punch?(puncher: ObjectRef, timeFromLastPunch: number, toolCapabilities: ToolCapabilities, dir: Vec3, damage: number): void
on_death?(killer: ObjectRef): void
on_rightclick?(clicker: ObjectRef): void
on_attach_child?(child: ObjectRef): void
on_detach_child?(child: ObjectRef): void
on_detach?(parent: ObjectRef): void
get_staticdata?(): void
}
export interface DetachedInventoryCallbacks {
@ -1606,39 +1606,39 @@ declare global {
export type CollisionBox = Array<number>
export interface ObjectProperties {
hp_max: number
breath_max: number
zoom_fov: number
eye_height: number
physical: boolean
collide_with_objects: boolean
collisionbox: CollisionBox
selectionbox: number[]
pointable: boolean
visual: EntityVisual
visual_size: Vec3
mesh: string
textures: string[]
colors: DynamicColorSpec[]
use_texture_alpha: boolean
spritediv: Vec2
initial_sprite_basepos: Vec2
is_visible: boolean
makes_footstep_sound: boolean
automatic_rotate: number
stepheight: number
automatic_face_movement_dir: number
automatic_face_movement_max_rotation_per_sec: number
backface_culling: boolean
glow: number
nametag: string
nametag_color: ColorSpec
nametag_bgcolor: ColorSpec
infotext: string
static_save: boolean
damage_texture_modifier: string
shaded: boolean
show_on_minimap: boolean
hp_max?: number
breath_max?: number
zoom_fov?: number
eye_height?: number
physical?: boolean
collide_with_objects?: boolean
collisionbox?: CollisionBox
selectionbox?: number[]
pointable?: boolean
visual?: EntityVisual
visual_size?: Vec3
mesh?: string
textures?: string[]
colors?: DynamicColorSpec[]
use_texture_alpha?: boolean
spritediv?: Vec2
initial_sprite_basepos?: Vec2
is_visible?: boolean
makes_footstep_sound?: boolean
automatic_rotate?: number
stepheight?: number
automatic_face_movement_dir?: number
automatic_face_movement_max_rotation_per_sec?: number
backface_culling?: boolean
glow?: number
nametag?: string
nametag_color?: ColorSpec
nametag_bgcolor?: ColorSpec
infotext?: string
static_save?: boolean
damage_texture_modifier?: string
shaded?: boolean
show_on_minimap?: boolean
}

View File

@ -1,400 +1,56 @@
local _tl_compat; if (tonumber((_VERSION or ''):match('[%d.]*$')) or 0) < 5.3 then local p, m = pcall(require, 'compat53.module'); if p then _tl_compat = m end end; local ipairs = _tl_compat and _tl_compat.ipairs or ipairs; local math = _tl_compat and _tl_compat.math or math; local pairs = _tl_compat and _tl_compat.pairs or pairs; local string = _tl_compat and _tl_compat.string or string; local table = _tl_compat and _tl_compat.table or table; local time_to_live = tonumber(minetest.settings:get("item_entity_ttl")) or 900
local gravity = tonumber(minetest.settings:get("movement_gravity")) or 9.81
local MagnetQueue = {}
MagnetQueue.players = {}
MagnetQueue.deletionQueue = {}
minetest.register_on_joinplayer(function(player)
local name = player:get_player_name()
MagnetQueue.players[name] = 0
end)
minetest.register_on_leaveplayer(function(player)
local name = player:get_player_name()
MagnetQueue.players[name] = nil
end)
local function add_magnet_pop(player)
local name = player:get_player_name()
MagnetQueue.players[name] = MagnetQueue.players[name] + 1
-- Lua Library inline imports
local function __TS__Class(self)
local c = {prototype = {}}
c.prototype.__index = c.prototype
c.prototype.constructor = c
return c
end
minetest.register_globalstep(function()
for name, remaining in pairs(MagnetQueue.players) do
if (remaining <= 0) then goto continue end
local player = minetest.get_player_by_name(name)
if (not player) then
table.insert(MagnetQueue.deletionQueue, name)
goto continue
end
minetest.sound_play({
name = "item_pickup",
}, {
gain = 0.15,
pitch = random_range(0.7, 1.0),
object = player,
})
MagnetQueue.players[name] = remaining - 1
::continue::
end
if (#MagnetQueue.deletionQueue > 0) then
for _, name in ipairs(MagnetQueue.deletionQueue) do
MagnetQueue.players[name] = nil
end
MagnetQueue.deletionQueue = {}
end
end)
local entity = {}
entity.initial_properties = {
hp_max = 1,
physical = true,
collide_with_objects = false,
collisionbox = { -0.3, -0.3, -0.3, 0.3, 0.3, 0.3 },
visual = "wielditem",
visual_size = { x = 0.4, y = 0.4 },
textures = { "" },
is_visible = false,
pointable = false,
}
entity.itemstring = ""
entity.moving_state = true
entity.physical_state = true
entity.age = 0
entity.force_out = nil
entity.force_out_start = nil
entity.collected = false
function entity:set_item(item)
local stack = ItemStack(item or self.itemstring)
self.itemstring = stack:to_string()
if self.itemstring == "" then
return
end
local itemname = stack:is_known() and stack:get_name() or "unknown"
local size = 0.21
local def = minetest.registered_items[itemname]
local glow = def and def.light_source and math.floor(def.light_source / 2 + 0.5)
local size_bias = 1e-3 * math.random()
local c = { -size, -size, -size, size, size, size }
self.object:set_properties({
is_visible = true,
visual = "wielditem",
textures = { itemname },
visual_size = { x = size + size_bias, y = size + size_bias },
collisionbox = c,
automatic_rotate = 1,
wield_item = self.itemstring,
glow = glow,
infotext = stack:get_description(),
})
self._collisionbox = c
local function __TS__New(target, ...)
local instance = setmetatable({}, target.prototype)
instance:____constructor(...)
return instance
end
function entity:get_staticdata()
return minetest.serialize({
itemstring = self.itemstring,
age = self.age,
dropped_by = self.dropped_by,
})
-- End of Lua Library inline imports
do
local println = utility.println
local nextID = 0
local function idGenerator()
local gotten = nextID
nextID = nextID + 1
return gotten
end
local ItemEntity = __TS__Class()
ItemEntity.name = "ItemEntity"
function ItemEntity.prototype.____constructor(self)
self.timer = 0
self.cool = 5
self.id = -1
end
function ItemEntity.prototype.on_activate(self, staticData, delta)
self.id = idGenerator()
print(self.cool)
self.cool = self.cool + 1
end
function ItemEntity.prototype.on_step(self, delta, moveResult)
self.timer = self.timer + delta
if self.timer > 2 then
print((("id: " .. tostring(self.id)) .. " | cool: ") .. tostring(self.cool))
self.cool = self.cool + math.random()
self.timer = 0
if math.random() > 0.7 then
self.on_step = function(self, delta)
self.timer = self.timer + delta
if self.timer > 2 then
print("I don't feel like it anymore | id:" .. tostring(self.id))
self.timer = 0
end
end
end
end
end
minetest.register_entity(
":test",
__TS__New(ItemEntity)
)
end
function entity:on_activate(staticdata, dtime_s)
if string.sub(staticdata, 1, string.len("return")) == "return" then
local data = minetest.deserialize(staticdata)
if data and type(data) == "table" then
self.itemstring = data.itemstring
self.age = (data.age or 0) + dtime_s
self.dropped_by = data.dropped_by
end
else
self.itemstring = staticdata
end
self.object:set_armor_groups({ immortal = 1 })
self.object:set_velocity({ x = 0, y = 2, z = 0 })
self.object:set_acceleration({ x = 0, y = -gravity, z = 0 })
self._collisionbox = self.initial_properties.collisionbox
self:set_item()
end
function entity:enable_physics()
if self.physical_state then return end
self.physical_state = true
self.object:set_properties({ physical = true })
self.object:set_velocity({ x = 0, y = 0, z = 0 })
self.object:set_acceleration({ x = 0, y = -gravity, z = 0 })
end
function entity:disable_physics()
if not self.physical_state then return end
self.physical_state = false
self.object:set_properties({ physical = false })
self.object:set_velocity({ x = 0, y = 0, z = 0 })
self.object:set_acceleration({ x = 0, y = 0, z = 0 })
end
function entity:tick_age(delta)
self.age = self.age + delta
if time_to_live > 0 and self.age > time_to_live then
self.itemstring = ""
self.object:remove()
return true
end
return false
end
function entity:check_out_of_bounds(node)
if node and (node).name == "ignore" then
self.itemstring = ""
self.object:remove()
return true
end
return false
end
function entity:slip_check(delta, def, node)
if not def then return false end
local slippery = minetest.get_item_group(node.name, "slippery")
local vel = self.object:get_velocity()
if slippery ~= 0 and (math.abs(vel.x) > 0.1 or math.abs(vel.z) > 0.1) then
local factor = math.min(4 / (slippery + 4) * delta, 1)
self.object:set_velocity({
x = vel.x * (1 - factor),
y = 0,
z = vel.z * (1 - factor),
})
return true
end
return false
end
function entity:force_out_check(pos)
if not self.force_out then return false end
local c = self._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 not ok then return false end
self.force_out = nil
self:enable_physics()
return true
end
function entity:unstuck_self(pos, is_stuck)
if not is_stuck then return end
local shootdir
local order = {
{ x = 1, y = 0, z = 0 }, { x = -1, y = 0, z = 0 },
{ x = 0, y = 0, z = 1 }, { x = 0, y = 0, z = -1 },
}
for o = 1, #order do
local cnode = minetest.get_node(vector.add(pos, order[o])).name
local cdef = minetest.registered_nodes[cnode] or {}
if cnode ~= "ignore" and cdef.walkable == false then
shootdir = order[o]
break
end
end
if not shootdir then
shootdir = { x = 0, y = 1, z = 0 }
local cnode = minetest.get_node(vector.add(pos, shootdir)).name
if cnode == "ignore" then
shootdir = nil
end
end
if not shootdir then return end
local newv = vector.multiply(shootdir, 3)
self:disable_physics()
self.object:set_velocity(newv)
self.force_out = newv
self.force_out_start = vector.round(pos)
return
end
local pos_a = vector.new()
local pos_b = vector.new()
local function distance_2d(vec_1, vec_2)
pos_a.x = vec_1.x
pos_a.y = 0
pos_a.z = vec_1.z
pos_b.x = vec_2.x
pos_b.y = 0
pos_b.z = vec_2.z
return vector.distance(pos_a, pos_b)
end
function entity:poll_players(pos)
if (self.collected) then return end
if (not self.age) then return end
if (self.age < 1.5) then return end
local solved = false
for _, player in ipairs(minetest.get_connected_players()) do
if (solved) then goto continue end
local player_pos = player:get_pos()
if (vector.distance(pos, player_pos) > 3) then goto continue end
if (distance_2d(pos, player_pos) > 1.5) then goto continue end
if (player_pos.y - pos.y > 0.05) then goto continue end
local inv = player:get_inventory()
if (not inv) then goto continue end
if (not inv:room_for_item("main", self.itemstring)) then return end
inv:add_item("main", self.itemstring)
player_pos.y = player_pos.y + 0.8
self:disable_physics()
self.object:set_velocity(vector.multiply(vector.direction(pos, player_pos), 10))
self.object:move_to(player_pos, true)
solved = true
self.age = 0
self.collected = true
add_magnet_pop(player)
::continue::
end
end
function entity:collection_cleanup(delta)
self.age = self.age + delta
if (self.age < 0.2) then return end
self.object:remove()
end
function entity:on_step(dtime, moveresult)
if (self.collected) then
self:collection_cleanup(dtime)
return
end
local pos = self.object:get_pos()
self:poll_players(pos)
if (self:tick_age(dtime)) then return end
local node = minetest.get_node_or_nil({
x = pos.x,
y = pos.y + self._collisionbox[2] - 0.05,
z = pos.z,
})
if (self:check_out_of_bounds(node)) then return end
if moveresult == nil and self.object:get_attach() then
return
end
if self:force_out_check(pos) then return end
if not self.physical_state then
return
end
if not moveresult.collides then
return
end
local is_stuck = false
local snode = minetest.get_node_or_nil(pos)
if snode then
local sdef = minetest.registered_nodes[(snode).name] or {}
is_stuck = (sdef.walkable == nil or sdef.walkable == true) and
(sdef.collision_box == nil or sdef.collision_box.type == "regular") and
(sdef.node_box == nil or sdef.node_box.type == "regular")
self:unstuck_self()
end
node = nil
if moveresult.touching_ground then
for _, info in ipairs(moveresult.collisions) do
if info.axis == "y" then
node = minetest.get_node(info.node_pos)
break
end
end
end
local def = node and minetest.registered_nodes[(node).name]
local keep_movement = self:slip_check(dtime, def, node)
if not keep_movement then
self.object:set_velocity({ x = 0, y = 0, z = 0 })
end
if self.moving_state == keep_movement then
return
end
self.moving_state = keep_movement
end
minetest.register_entity(":__builtin:item", entity)

43
mods/item_entity/init.ts Normal file
View File

@ -0,0 +1,43 @@
{
const println = utility.println;
let nextID = 0
function idGenerator(): number {
const gotten = nextID
nextID++
return gotten
}
class ItemEntity implements EntityDefinition {
timer = 0
cool = 5
id = -1
on_activate(staticData: string, delta: number): void {
// throw new Error("Method not implemented.");
this.id = idGenerator()
print(this.cool)
this.cool += 1
}
on_step(delta: number, moveResult: MoveResult): void {
this.timer += delta
if (this.timer > 2) {
print("id: " + this.id + " | cool: " + this.cool)
this.cool += math.random()
this.timer = 0
if (math.random() > 0.7) {
this.on_step = function(delta: number) {
this.timer += delta
if (this.timer > 2) {
print("I don't feel like it anymore | id:" + this.id)
this.timer = 0
}
}
}
}
}
}
minetest.register_entity(":test", new ItemEntity())
}