local mod_name = core.get_current_modname()
local S = core.get_translator(mod_name)

local check_player = aom_transit.transit_spire.check_player

aom_settings.register_setting("gameplay_transit_spire_activation_time", 160, "Transit Spire Activation Time", "server")
aom_settings.register_setting("gameplay_transit_spire_max_in_100m", 16, "Transit Spire Max Count in 100m Area", "server")
aom_settings.register_setting("gameplay_transit_spire_disabled", false, "Disable Transit Spires", "server")

local function log(t)
    do return end
    core.log(t)
end

function aom_transit.transit_spire.on_rightclick(pos, node, player, itemstack, pointed_thing)
    if aom_settings.get_setting(nil, "gameplay_transit_spire_disabled") then return end
	if not core.is_player(player) then return end
	log("rightclick")
    local meta = core.get_meta(pos)
    local is_completed = meta:get_string("aom_transit:ready") == "true"
    if not is_completed then
        core.sound_play("aom_transit_warp_disallow", {
            pos = pos,
            gain = 2,
        })
        return
    end
	aom_transit.transit_core.touch_spire(player, pos)
	aom_transit.transit_core.show_form(player, pos)
end

local function put_entity(pos)
    local obj = core.add_entity(vector.offset(pos, 0, 2, 0), "aom_transit:transit_spire_ENTITY")
    -- log("added ent")
    return obj
end

local function get_entity_from_pos(pos)
    local objs = core.get_objects_in_area(
        vector.offset(pos, -0.5, -0.5 + 2, -0.5),
        vector.offset(pos,  0.5,  0.5 + 2,  0.5)
    )
    for i, obj in ipairs(objs) do
        local ent = obj and obj:get_luaentity()
        if ent and ent.name == "aom_transit:transit_spire_ENTITY" then
            return ent
        end
    end
end

local function add_barriers(pos)
	for i = 1, 2 do
		local p = vector.offset(pos, 0, i, 0)
		core.dig_node(p)
		if i == 1 then
			core.set_node(p, {name="aom_transit:barrier"})
		else
			core.set_node(p, {name="aom_util:light_node_8"})
			core.get_node_timer(p):set(3,0)
		end
	end
end

local function remove_barriers(pos)
	for i = 1, 2 do
		local p = vector.offset(pos, 0, i, 0)
		local node = core.get_node(p)
		if node.name == "aom_transit:barrier" or node.name == "aom_util:light_node_8" then
			core.set_node(p, {name="air"})
		end
	end
end

-- node that stops you placing other nodes inside the spire
core.register_node("aom_transit:barrier", {
	drawtype = "airlike",
    groups = { not_in_creative_inventory = 1, unobtainable = 1 },
	walkable = false,
	pointable = false,
	sunlight_propagates = true,
	drop = "",
})


aom_transit.transit_core._icon_count = 13
aom_transit.transit_core._icon_colors = {
    "#ffffff", -- white
    "#3ea5e2", -- blue
    "#3ee260", -- green
    "#f5e993", -- yellow
    "#e23e3e", -- red
    "#e23ed3", -- pink
    "#888890", -- gray
}


function aom_transit.transit_core.init_form(player, pi)
    pi.form = aom_bform.element.form:new({24, 12}, 6, "aom_transit:spire_" .. player:get_player_name())
    pi.form:add_children({
        aom_bform.element.container.new({12, 12}, {1,0}, "main"):add_children({
            aom_bform.element.listcolors.new("#f00", "#f00", "#f00"),
            aom_bform.element.listcolors.new("#00000010", nil, "#0ff"),
            aom_bform.element.custom.new(nil, "bgcolor", {"bgcolor[#00000000;neither]"}),
            aom_bform.element.custom.new(nil, nil, {
                "style_type[image_button;textcolor=#bab1aa;border=false]",
                "style_type[image_button;bgimg_middle=8;border=false;",
                "bgcolor_hovered=#fff;bgcolor_pressed=#fff]",
                "style_type[button;bgimg_middle=8;border=false;",
                "bgimg=aom_transit_btn.png^[multiply:#8a8980;",
                "bgimg_hovered=aom_transit_btn.png^[multiply:#7b786a;",
                "bgimg_pressed=aom_transit_btn_press.png^[multiply:#7b786a;",
                "bgcolor_hovered=#fff;bgcolor_pressed=#fff]",
            }),

            aom_bform.element.container.new({0.4, 12}, {0,1}),
            aom_bform.element.container.new({6.5, 12}, {0,1}, "list_wrapper"):add_children({
                aom_bform.element.custom.new({6, 12}, "list_wrapper_scroll", {
                    "scroll_container[0,0;6,11.75;scroll;vertical;0.1]"
                }):add_children({
                    aom_bform.element.container.new({5, 11}, {0,1}, "main_list"):set_absolute_pos({0.5, 0.5}),
                }),
                aom_bform.element.custom.new({5, 0.0}, nil, {
                    "scroll_container_end[]",
                    "scrollbaroptions[arrows=hide;smallstep=10"..
                    ";thumbsize=80;max=1000]",
                    "scrollbar[-0.4,0.5;0.5,11;vertical;scroll;0]"
                }),
                aom_bform.element.background9.new(
                    nil, "bform_bg.png^[multiply:#445^bform_bg_outline.png", nil, false, 28
                ):set_fill({0,0}):set_ignore_spacing(true),
            }),
            aom_bform.element.container.new({6, 6}, {0,1}, "list_wrapper2"):add_children({
                aom_bform.element.container.new({5, 1}, {0,1}, "rename_section"):set_offset({0.5, 0.5}),
                aom_bform.element.container.new({5, 6}, {0,1}, "icon_section"):set_offset({0.5, 0.5}),
                aom_bform.element.background9.new(
                    nil, "bform_bg.png^[multiply:#445^bform_bg_outline.png^[multiply:#aaa", nil, false, 28
                ):set_fill({0,0}):set_ignore_spacing(true),
            }),
        }),
    }):set_params({
        auth_enabled = true,
        send_on_update = true,
    })
    pi.form_list = pi.form:get_element_by_id("main_list")

    -- add icon selection
    local last_hlist
    local icon_elems = {}
    local icon_size = 5 / 7
    for i = 0, aom_transit.transit_core._icon_count do
        if i % math.floor(5 / icon_size) == 0 then
            last_hlist = aom_bform.element.container.new({5, icon_size}, {1,0}, nil)
            table.insert(icon_elems, last_hlist)
        end
        last_hlist:add_child(aom_bform.element.image_button.new(
            {icon_size, icon_size}, "aom_transit_icon_"..i..".png", "", "lociconbutton:"..i,
            aom_transit.transit_core.on_fields_icon_button)):set_params({_num=i})
    end

    -- add icon color selection
    last_hlist = aom_bform.element.container.new({5, 1}, {1,0}, nil)
    table.insert(icon_elems, last_hlist)
    for i, color in ipairs(aom_transit.transit_core._icon_colors) do
        last_hlist:add_child(aom_bform.element.image_button.new(
            {icon_size, icon_size}, "aom_transit_icon_1.png^[multiply:" .. color, "", "loccolorbutton:"..i,
            aom_transit.transit_core.on_fields_color_button)):set_params({_num=i})
    end
    pi.form:get_element_by_id("icon_section"):add_children(icon_elems)
end


function aom_transit.transit_core.on_fields_color_button(elem, player, formname, fields)
    local pi = check_player(player)
    local hash = pi.last_touched_hash
    if not hash then return end
    local def = pi.locations[hash]
    if not def then return end

    local color_num = elem['_num']
    def.color = tonumber(color_num) or 0
    aom_transit.transit_core.save_touched_locations(player)
    aom_transit.transit_core.update_form(player, pi)
end


function aom_transit.transit_core.on_fields_icon_button(elem, player, formname, fields)
    local pi = check_player(player)
    local hash = pi.last_touched_hash
    if not hash then return end
    local def = pi.locations[hash]
    if not def then return end

    local icon_num = elem['_num']
    def.icon = tonumber(icon_num)
    if def.icon == 0 then def.icon = nil end
    aom_transit.transit_core.save_touched_locations(player)
    aom_transit.transit_core.update_form(player, pi)
end


function aom_transit.transit_core.on_fields_forget(elem, player, formname, fields)
    local hash = tonumber(elem.parent['loc_hash'])
    if not hash then return end
    aom_transit.transit_core.untouch_spire(player, core.get_position_from_hash(hash))
	local pi = check_player(player)
    aom_transit.transit_core.update_form(player, pi)
end


function aom_transit.transit_core.on_fields_rename(elem, player, formname, fields)
    local hash = elem.parent['loc_hash']
    if not hash then return end
    local new_name = fields.locrename
    if not new_name then return end
    local pi = check_player(player)
    local def = pi.locations[hash]
    if not def then return end
    if def.name == new_name then return end
    def.name = new_name
    aom_transit.transit_core.save_touched_locations(player)
    aom_transit.transit_core.update_form(player, pi)
end


function aom_transit.transit_core.on_fields_button(elem, player, formname, fields)
	local pi = check_player(player)
    if not pi.last_touched_pos then return end
    local start_pos = pi.last_touched_pos
    pi.last_touched_pos = nil
    local hash = elem.parent.loc_hash
    if not hash then
        log("error: no hash in button")
        return
    end
    if not pi.locations[hash] then
        log("error: player doesn't have that location touched: " .. tostring(hash))
        return
    end

    local dist = vector.distance(player:get_pos(), start_pos)
    if dist > 8 then
        core.sound_play("aom_transit_warp_disallow", {
            to_player = player:get_player_name(),
            gain = 1,
        })
        return
    end

    local target_pos = aom_transit.transit_core.is_spire_valid_at_hash(hash)
    if not target_pos then return end

    aom_transit.transit_core.start_teleport_sequence(start_pos, target_pos)
end


function aom_transit.transit_core.update_form(player, pi)
    ---@type bform
    local form = pi.form

    ---@type bform_prototype | nil
    local list_node = form:get_element_by_id("main_list")
    if not list_node then return end

    for i = #list_node.children, 1, -1 do
        list_node.children[i].parent:remove_child(list_node.children[i])
    end

    local button_height = 0.75
    local button_width = 5
    for hash, def in pairs(pi.locations) do if (hash ~= "count") then
        local child
        local color = aom_transit.transit_core._icon_colors[def.color or 1]
        local icon = ""
        if (not def.icon) or  def.icon == 0 then
            icon = "blank.png"
        else
            icon = "aom_transit_icon_" .. (def.icon or 0) .. ".png^[multiply:" .. (color or "#ffffff")
        end
        if (pi.last_touched_hash ~= hash) then
            child = aom_bform.element.container.new({5, button_height}, {1,0}, "loc:" .. tostring(hash)):add_children({
                aom_bform.element.image.new({button_height, button_height}, icon),
                aom_bform.element.button.new(
                    {button_width-button_height, button_height}, def.name, "locbutton:" .. tostring(hash), aom_transit.transit_core.on_fields_button
                ):set_close_on_enter(true),
                aom_bform.element.image_button.new(
                    {0.5, 0.5}, "aom_transit_gui_delete.png", "", "locforgetbutton:" .. tostring(hash),
                    aom_transit.transit_core.on_fields_forget),
            })
        else -- is the one you're interacting with, so disable
            child = aom_bform.element.container.new({5, button_height}, {1,0}, "loc:" .. tostring(hash)):add_children({
                aom_bform.element.image.new({button_height, button_height}, icon),
                aom_bform.element.image.new(
                    {button_width-button_height, button_height}, "aom_transit_btn.png^[multiply:#605c58", "locbg:" .. tostring(hash), 8
                ):set_spacing({-(button_width-button_height), 0}),
                aom_bform.element.image_button.new(
                    {button_width-button_height, button_height}, "blank.png", def.name, "locbutton:" .. tostring(hash)),
                aom_bform.element.image_button.new(
                    {0.5, 0.5}, "aom_transit_gui_delete.png", "", "locforgetbutton:" .. tostring(hash),
                    aom_transit.transit_core.on_fields_forget),
            })
        end
        child['loc_hash'] = hash
        child['_name'] = def.name
        list_node:add_child(child)
        log("added node: " .. "loc:" .. tostring(hash))
    end end

    table.sort(list_node.children, function(a,b) return a._name < b._name end)

    if pi.last_touched_hash and pi.locations[pi.last_touched_hash] then
        local rename_parent = form:get_element_by_id("rename_section")
        if not rename_parent then return end
        rename_parent:remove_child(rename_parent.children[1])
        local hash = pi.last_touched_hash
        local def = pi.locations[hash]
        local rename_elem = aom_bform.element.container.new({6,1}, {1,0}, "loccurrent"):add_children({
            aom_bform.element.field.new({3.7,1}, "locrename", "", def.name, aom_transit.transit_core.on_fields_rename),
            aom_bform.element.button.new({1.3,1}, "rename", "locrenamebutton", aom_transit.transit_core.on_fields_rename),
        })
        rename_elem['loc_hash'] = hash
        rename_parent:add_child(rename_elem)
    else
        log("NO LAST TOUCHED")
    end
end


function aom_transit.transit_core.show_form(player, pos)
	local pi = check_player(player)

    aom_transit.transit_core.validate_spire_data(player, pi.locations)

    if not pi.form then
        aom_transit.transit_core.init_form(player, pi)
    end

    ---@type bform
    local form = pi.form

    aom_transit.transit_core.update_form(player, pi)

    pi.last_form_spire_location = pos
    form:show_form(player, true)
end

aom_transit.transit_core.teleport_queue = {}
aom_transit.transit_core.teleport_map = {}
local t_queue = aom_transit.transit_core.teleport_queue

function aom_transit.transit_core.start_teleport_sequence(start_pos, target_pos)
    local node = core.get_node_or_nil(start_pos)
    if not node then return end
    if node.name ~= "aom_transit:transit_spire" then return end
    local hash = core.hash_node_position(start_pos)
    -- don't allow if already queued
    if aom_transit.transit_core.teleport_map[hash] then
        return
    end
    local task = {
        start_pos = start_pos,
        target_pos = target_pos,
        time = 65/24,
    }
    table.insert(t_queue, task)
    aom_transit.transit_core.teleport_map[hash] = task

    local ent = get_entity_from_pos(start_pos)
    if ent then
        ent.object:set_animation({x=90, y=170}, 24, 1, false)
        ent._aom_reset_time = 80/24
    end

    core.sound_play("aom_transit_warp_start", {
        pos = start_pos,
        gain = 2,
    })
end


function aom_transit.transit_core.end_teleport_sequence(start_pos, target_pos)
    -- do checks to make sure nothing has broken since you started the sequance
    if (not aom_transit.transit_core.is_spire_valid_at_pos(start_pos)) or
    (not aom_transit.transit_core.is_spire_valid_at_pos(target_pos)) then
        return
    end

    local has_effects = core.get_modpath("aom_statusfx") ~= nil

    local has_passenger = false
    local objects = core.get_objects_inside_radius(start_pos, 5)
    for i, object in ipairs(objects) do
        if core.is_player(object) then
            log("teleporting " .. object:get_player_name())
            local offset = object:get_pos() - start_pos
            if has_effects then
                aom_statusfx.apply_status(object, "blindness", 2, {
                    blend_in = 0,
                    blend_out = 1,
                })
            end
            core.close_formspec(object:get_player_name(), "aom_transit:spire_" .. object:get_player_name())
            has_passenger = true
            object:set_pos(target_pos + offset)
        end
    end

    if not has_passenger then return end

    -- since it might not be loaded yet, use meta to trigger the entity to start the animation
    core.get_meta(target_pos):set_string("aom_transit:do_teleport_anim", "1")

    -- try to set anim, but only if the ent is actually loaded
    local ent = get_entity_from_pos(target_pos)
    if ent then
        ent:_check_do_end_teleport_anim()
    end

    core.sound_play("aom_transit_warp_end", {
        pos = target_pos,
        gain = 2,
    })
end


core.register_globalstep(function(dtime)
    local task
    for i = #t_queue, 1, -1 do
        task = t_queue[i]
        task.time = task.time - dtime
        if task.time <= 0 then
            aom_transit.transit_core.end_teleport_sequence(task.start_pos, task.target_pos)
            table.remove(t_queue, i)
            aom_transit.transit_core.teleport_map[core.hash_node_position(task.start_pos)] = nil
        end
    end
end)


local function get_spire_count_in_radius(pos, r)
    local count = 0
    for object in core.objects_inside_radius(pos, r) do
        local ent = object:get_luaentity()
        if ent and ent.name == "aom_transit:transit_spire_ENTITY" then
            count = count + 1
        end
    end
    return count
end


core.register_node("aom_transit:transit_spire", {
    description = S("Transit Spire"),
    _tt_long_desc = (
        S("Allows teleportation between any other spire a player has used before.").."\n"..
        S("Takes some time to activate after being initially placed down.")
    ),
    _tt_how_to_use = S("Open Transit Menu: [place]"),
    _tt_color = 6,
	drawtype = "mesh",
	mesh = "aom_transit_spire.obj",
    tiles = {"aom_transit_spire.png"},
	collision_box = {type = "fixed", fixed = {
		-7/16, -8/16, -7/16,
		 7/16,  24/16, 7/16,
	}},
	selection_box = {type = "fixed", fixed = {
		-7/16, -8/16, -7/16,
		 7/16,  24/16, 7/16,
	}},
    groups = { item_transit_spire = 1, oddly_breakable_by_hand = 3, furniture = 1, cracky = 3, solid = 1 },
    sounds = aom_sounds.default_stone(),
    on_timer = function(pos, elapsed)
        local meta = core.get_meta(pos)
        local activation_time = aom_settings.get_setting(nil, "gameplay_transit_spire_activation_time")
        if aom_settings.get_setting(nil, "gameplay_transit_spire_disabled") then
            meta:set_string("aom_transit:cooldown", "1")
            meta:set_string("aom_transit:ready", "")
            return true
        end
        local is_completed = meta:get_string("aom_transit:ready") == "true"
        if not is_completed then
            local cooldown = tonumber(meta:get_string("aom_transit:cooldown")) or activation_time
            cooldown = cooldown - 1
            if cooldown > 0 then
                meta:set_string("aom_transit:cooldown", tostring(cooldown))
            else
                meta:set_string("aom_transit:cooldown", "0")
                meta:set_string("aom_transit:ready", "true")
            end
        end

        local ent = get_entity_from_pos(pos)
        if ent then return true end
        put_entity(pos)
        return true
    end,
    on_construct = function(pos)
        put_entity(pos)
        core.get_node_timer(pos):start(1)
		add_barriers(pos)
    end,
    on_destruct = function(pos)
        aom_transit.transit_core.untouch_spire_for_all_players(pos)
        local ent = get_entity_from_pos(pos)
        if ent then
            ent.object:remove() end
		remove_barriers(pos)
    end,
	on_place = function(itemstack, placer, pointed_thing)
		local ret = aom_util.try_rightclick(itemstack, placer, nil, false)
		if ret then return ret, nil end
        -- don't allow placing if serverside disabled
        if aom_settings.get_setting(nil, "gameplay_transit_spire_disabled") then
            return itemstack
        end
        -- don't allow spamming of them
        local max_in_radius = aom_settings.get_setting(nil, "gameplay_transit_spire_max_in_100m")
        if get_spire_count_in_radius(pointed_thing.above, 100) > max_in_radius then
            return itemstack
        end

		local place_pos = pointed_thing.under
		if core.registered_nodes[core.get_node(place_pos).name].buildable_to then
			core.dig_node(place_pos, placer)
		else
			place_pos = pointed_thing.above
		end
		-- test if placeable
		for i = 1, 2 do
			local p = vector.offset(place_pos, 0, i, 0)
			if not core.registered_nodes[core.get_node(p).name].buildable_to then
				place_pos = nil
				break
			end
		end
		if not place_pos then return nil, nil end

        if core.is_player(placer) and not core.is_creative_enabled(placer:get_player_name()) then
            itemstack:take_item(1)
        end
		core.set_node(place_pos, {name = "aom_transit:transit_spire"})
        return itemstack
	end,
    _on_node_update = function(pos, cause, user, count, payload)
        local timer = core.get_node_timer(pos)
        if timer:is_started() then return
        else timer:start(1) end
    end,
    on_rightclick = aom_transit.transit_spire.on_rightclick,
})




-- rotating visual entity
local csize = 0.2
core.register_entity("aom_transit:transit_spire_ENTITY", {
    initial_properties = {
        visual = "mesh",
        mesh = "aom_transit_spire_beacon.b3d",
        textures = {"aom_transit_spire_beacon.png"},
        stepheight = 0,
        hp_max = 1,
        physical = false,
        pointable = false,
        backface_culling = false,
        use_texture_alpha = true,
        glow = 8,
        collisionbox = {
            -csize, -csize, -csize, csize, csize, csize,
        },
        selectionbox = {
            -csize, -csize, -csize, csize, csize, csize,
        },
        static_save = false,
    },
    _check_cooldown_stage = function(self)
        local pos = self.object:get_pos()
		local npos = vector.offset(pos, 0, -2, 0)
        local node = core.get_node(npos)
        if node.name ~= "aom_transit:transit_spire" then return end
        local meta = core.get_meta(npos)
        local is_completed = meta:get_string("aom_transit:ready") == "true"
        if is_completed then
            if self._last_cooldown then
                self._last_cooldown = nil
                self._aom_reset_time = (280 - 237) / 24
                self.object:set_animation({x=237, y=280}, 24, 0, false)
                core.sound_play("aom_transit_warp_ready", {
                    pos = pos,
                    gain = 4,
                })
            end
            return
        end
        local activation_time = aom_settings.get_setting(nil, "gameplay_transit_spire_activation_time")
        local cooldown = tonumber(meta:get_string("aom_transit:cooldown")) or activation_time
        cooldown = 1 - math.min(cooldown / activation_time, 1)
        if (cooldown > 0) and (cooldown < 1/8) then
            cooldown = 1/8
        end
        cooldown = math.floor(cooldown * 8)
        if cooldown ~= self._last_cooldown or cooldown > 8 then
            if cooldown < 8 then
                local f = 230 + cooldown
                self.object:set_animation({x=f, y=f}, 24, 0, false)

                if self._last_cooldown then
                    core.sound_play("aom_transit_warp_tick", {
                        pos = pos,
                        gain = 0.3,
                    })
                end
            end
            self._last_cooldown = cooldown
        end
    end,
    on_step = function(self, dtime)
        -- avoid the weird "can just be nil" bug
        local pos = self.object:get_pos()
        if not pos then
            self.object:remove(); return end
        -- reset time to go back to idle anim
        if self._aom_reset_time > 0 then
            self._aom_reset_time = self._aom_reset_time - dtime
            if self._aom_reset_time <= 0 then
                self.object:set_animation({x=0, y=80}, 24, 1, true)
            end
        end

        -- when it's not in the activation / cooldown state, play an idle hum
        if not self._last_cooldown then
            self._aom_transit_sound_timer = (self._aom_transit_sound_timer or 2) + dtime
            if self._aom_transit_sound_timer > 2 then
                self._aom_transit_sound_timer = self._aom_transit_sound_timer - 2
                core.sound_play("aom_transit_warp_idle", {
                    object = self.object,
                    gain = 0.15,
                    max_hear_distance = 12,
                })
            end
        end

        -- only do the rest once per second
        self._timer = (self._timer or 1) + dtime
        if self._timer < 1 then return end
        self._timer = self._timer - 1

        -- change anim and play a sound when it gets to a new activation stage
        self:_check_cooldown_stage()

        -- destroy if not 'attached' to a spire below
		local bpos = vector.offset(pos, 0, -2, 0)
        local bnode = core.get_node(bpos)
        if bnode.name ~= "aom_transit:transit_spire" then
            self.object:remove()
            return
        end

        local node = core.get_node_or_nil(pos)
        if node and node.name == "aom_util:light_node_8" then
            core.get_node_timer(pos):set(3,0)
		elseif node then
            local ndef = node and core.registered_nodes[node.name]
            if ndef and ndef.buildable_to then
                core.set_node(pos, {name="aom_util:light_node_8"}, true)
            end
        end

        if self._sleeping then return end
        self._iter = (self._iter or -1) + 1
    end,
    -- if a spire teleports you to an unloaded area, the only way to know
    -- to play the anim is on_activate or on_step
    _check_do_end_teleport_anim = function(self)
		local npos = vector.offset(self.object:get_pos(), 0, -2, 0)
        local meta = core.get_meta(npos)
        if (core.get_node(npos).name == "aom_transit:transit_spire")
        and (meta:get_string("aom_transit:do_teleport_anim") == "1") then
            meta:set_string("aom_transit:do_teleport_anim", "")
            self._aom_reset_time = 40 / (24)
            self.object:set_animation({x=180, y=220}, 24, 0, false)
        end
    end,
    on_activate = function(self, staticdata, dtime_s)
        aom_entity_api.on_activate(self, staticdata, dtime_s)
        -- self.object:set_animation({x=0, y=80}, 24, 0, true)
        self.object:set_animation({x=0, y=80}, 24, 0, true)
        self:_check_do_end_teleport_anim()
        self:_check_cooldown_stage()
    end,
    on_deactivate = function(self, removal)
        local pos = self.object:get_pos()
        if core.get_node(pos).name == "aom_util:light_node_8" then
            core.set_node(pos, {name="air"})
        end
    end,
    get_staticdata = function(self)
        return aom_entity_api.get_staticdata(self)
    end,
    _aom_reset_time = 0,
})

if not aom_settings.get_setting(nil, "gameplay_transit_spire_disabled") then
    aom_tcraft.register_craft({
        output = "aom_transit:transit_spire",
        items = {
            ["aom_items:tin_bar"] = 12,
            ["aom_stone:cobble"] = 100,
            ["aom_items:gold_bar"] = 12,
        }
    })
end
