mirror of
https://github.com/IntQuant/noita_entangled_worlds.git
synced 2025-10-19 07:03:16 +00:00
511 lines
No EOL
21 KiB
Lua
511 lines
No EOL
21 KiB
Lua
local ctx = dofile_once("mods/quant.ew/files/src/ctx.lua")
|
|
local inventory_helper = dofile_once("mods/quant.ew/files/src/inventory_helper.lua")
|
|
local util = dofile_once("mods/quant.ew/files/src/util.lua")
|
|
|
|
local ffi = require("ffi")
|
|
local np = require("noitapatcher")
|
|
|
|
ffi.cdef([[
|
|
#pragma pack(push, 1)
|
|
typedef struct A {
|
|
float aim_x;
|
|
float aim_y;
|
|
float aimNormal_x;
|
|
float aimNormal_y;
|
|
float aimNonZero_x;
|
|
float aimNonZero_y;
|
|
float mouse_x;
|
|
float mouse_y;
|
|
float mouseRaw_x;
|
|
float mouseRaw_y;
|
|
float mouseRawPrev_x;
|
|
float mouseRawPrev_y;
|
|
float mouseDelta_x;
|
|
float mouseDelta_y;
|
|
bool kick:1;
|
|
bool fire:1;
|
|
bool fire2:1;
|
|
bool action:1;
|
|
bool throw:1;
|
|
bool interact:1;
|
|
bool left:1;
|
|
bool right:1;
|
|
bool up:1;
|
|
bool down:1;
|
|
bool jump:1;
|
|
bool fly:1;
|
|
bool leftClick:1;
|
|
bool rightClick:1;
|
|
} Controls;
|
|
#pragma pack(pop)
|
|
]])
|
|
ffi.cdef([[
|
|
#pragma pack(push, 1)
|
|
typedef struct D {
|
|
int frames_in_air;
|
|
float x;
|
|
float y;
|
|
float vel_x;
|
|
float vel_y;
|
|
bool is_on_ground:1;
|
|
bool is_on_slippery_ground:1;
|
|
} CharacterPos;
|
|
#pragma pack(pop)
|
|
]])
|
|
ffi.cdef([[
|
|
#pragma pack(push, 1)
|
|
typedef struct E {
|
|
float x;
|
|
float y;
|
|
float r;
|
|
int special_seed;
|
|
int player_action_rng;
|
|
} FireWand;
|
|
#pragma pack(pop)
|
|
]])
|
|
|
|
local Controls = ffi.typeof("Controls")
|
|
local CharacterPos = ffi.typeof("CharacterPos")
|
|
local FireWand = ffi.typeof("FireWand")
|
|
|
|
local player_fns = {
|
|
deserialize_inputs = function(message, player_data)
|
|
if (player_data ~= nil and player_data.entity ~= nil and EntityGetIsAlive(player_data.entity)) then
|
|
--print(json.stringify(message))
|
|
|
|
local controls_data = player_data.controls
|
|
local controlsComp = EntityGetFirstComponentIncludingDisabled(player_data.entity, "ControlsComponent")
|
|
|
|
if(message.kick)then
|
|
ComponentSetValue2(controlsComp, "mButtonDownKick", true)
|
|
if (not controls_data.kick) then
|
|
ComponentSetValue2(controlsComp, "mButtonFrameKick", GameGetFrameNum() + 1)
|
|
end
|
|
controls_data.kick = true
|
|
else
|
|
ComponentSetValue2(controlsComp, "mButtonDownKick", false)
|
|
controls_data.kick = false
|
|
end
|
|
|
|
--EntityHelper.BlockFiring(data.players[tostring(user)].entity, true)
|
|
|
|
if(message.fire)then
|
|
ComponentSetValue2(controlsComp, "mButtonDownFire", true)
|
|
if (not controls_data.fire) then
|
|
ComponentSetValue2(controlsComp, "mButtonFrameFire", GameGetFrameNum()+1)
|
|
end
|
|
ComponentSetValue2(controlsComp, "mButtonLastFrameFire", GameGetFrameNum())
|
|
controls_data.fire = true
|
|
else
|
|
ComponentSetValue2(controlsComp, "mButtonDownFire", false)
|
|
controls_data.fire = false
|
|
end
|
|
|
|
if(message.fire2)then
|
|
ComponentSetValue2(controlsComp, "mButtonDownFire2", true)
|
|
if (not controls_data.fire2) then
|
|
ComponentSetValue2(controlsComp, "mButtonFrameFire2", GameGetFrameNum()+1)
|
|
end
|
|
controls_data.fire2 = true
|
|
else
|
|
ComponentSetValue2(controlsComp, "mButtonDownFire2", false)
|
|
controls_data.fire2 = false
|
|
end
|
|
|
|
if(message.action)then
|
|
ComponentSetValue2(controlsComp, "mButtonDownAction", true)
|
|
if (not controls_data.action) then
|
|
ComponentSetValue2(controlsComp, "mButtonFrameAction", GameGetFrameNum() + 1)
|
|
end
|
|
controls_data.action = true
|
|
else
|
|
ComponentSetValue2(controlsComp, "mButtonDownAction", false)
|
|
controls_data.action = false
|
|
end
|
|
|
|
-- Do not sync this one, as thrown items are handled by item_sync
|
|
-- if(message.throw)then
|
|
-- ComponentSetValue2(controlsComp, "mButtonDownThrow", true)
|
|
-- if (not controls_data.throw) then
|
|
-- ComponentSetValue2(controlsComp, "mButtonFrameThrow", GameGetFrameNum() + 1)
|
|
-- end
|
|
-- controls_data.throw = true
|
|
-- else
|
|
-- ComponentSetValue2(controlsComp, "mButtonDownThrow", false)
|
|
-- controls_data.throw = false
|
|
-- end
|
|
|
|
if(message.interact)then
|
|
ComponentSetValue2(controlsComp, "mButtonDownInteract", true)
|
|
if (not controls_data.interact) then
|
|
ComponentSetValue2(controlsComp, "mButtonFrameInteract", GameGetFrameNum() + 1)
|
|
end
|
|
controls_data.interact = true
|
|
else
|
|
ComponentSetValue2(controlsComp, "mButtonDownInteract", false)
|
|
controls_data.interact = false
|
|
end
|
|
|
|
if(message.left)then
|
|
ComponentSetValue2(controlsComp, "mButtonDownLeft", true)
|
|
if (not controls_data.left) then
|
|
ComponentSetValue2(controlsComp, "mButtonFrameLeft", GameGetFrameNum() + 1)
|
|
end
|
|
controls_data.left = true
|
|
else
|
|
ComponentSetValue2(controlsComp, "mButtonDownLeft", false)
|
|
controls_data.left = false
|
|
end
|
|
|
|
if(message.right)then
|
|
ComponentSetValue2(controlsComp, "mButtonDownRight", true)
|
|
if (not controls_data.right) then
|
|
ComponentSetValue2(controlsComp, "mButtonFrameRight", GameGetFrameNum() + 1)
|
|
end
|
|
controls_data.right = true
|
|
else
|
|
ComponentSetValue2(controlsComp, "mButtonDownRight", false)
|
|
controls_data.right = false
|
|
end
|
|
|
|
if(message.up)then
|
|
ComponentSetValue2(controlsComp, "mButtonDownUp", true)
|
|
if (not controls_data.up) then
|
|
ComponentSetValue2(controlsComp, "mButtonFrameUp", GameGetFrameNum() + 1)
|
|
end
|
|
controls_data.up = true
|
|
else
|
|
ComponentSetValue2(controlsComp, "mButtonDownUp", false)
|
|
controls_data.up = false
|
|
end
|
|
|
|
if(message.down)then
|
|
ComponentSetValue2(controlsComp, "mButtonDownDown", true)
|
|
if (not controls_data.down) then
|
|
ComponentSetValue2(controlsComp, "mButtonFrameDown", GameGetFrameNum() + 1)
|
|
end
|
|
controls_data.down = true
|
|
else
|
|
ComponentSetValue2(controlsComp, "mButtonDownDown", false)
|
|
controls_data.down = false
|
|
end
|
|
|
|
if(message.jump)then
|
|
ComponentSetValue2(controlsComp, "mButtonDownJump", true)
|
|
if (not controls_data.jump) then
|
|
ComponentSetValue2(controlsComp, "mButtonFrameJump", GameGetFrameNum() + 1)
|
|
end
|
|
controls_data.jump = true
|
|
else
|
|
ComponentSetValue2(controlsComp, "mButtonDownJump", false)
|
|
controls_data.jump = false
|
|
end
|
|
|
|
if(message.fly)then
|
|
ComponentSetValue2(controlsComp, "mButtonDownFly", true)
|
|
if (not controls_data.fly) then
|
|
ComponentSetValue2(controlsComp, "mButtonFrameFly", GameGetFrameNum() + 1)
|
|
end
|
|
controls_data.fly = true
|
|
else
|
|
ComponentSetValue2(controlsComp, "mButtonDownFly", false)
|
|
controls_data.fly = false
|
|
end
|
|
|
|
if(message.leftClick)then
|
|
ComponentSetValue2(controlsComp, "mButtonDownLeftClick", true)
|
|
if (not controls_data.leftClick) then
|
|
ComponentSetValue2(controlsComp, "mButtonFrameLeftClick", GameGetFrameNum() + 1)
|
|
end
|
|
controls_data.leftClick = true
|
|
else
|
|
ComponentSetValue2(controlsComp, "mButtonDownLeftClick", false)
|
|
controls_data.leftClick = false
|
|
end
|
|
|
|
if(message.rightClick)then
|
|
ComponentSetValue2(controlsComp, "mButtonDownRightClick", true)
|
|
if (not controls_data.rightClick) then
|
|
ComponentSetValue2(controlsComp, "mButtonFrameRightClick", GameGetFrameNum() + 1)
|
|
end
|
|
controls_data.rightClick = true
|
|
else
|
|
ComponentSetValue2(controlsComp, "mButtonDownRightClick", false)
|
|
controls_data.rightClick = false
|
|
end
|
|
|
|
|
|
--[[
|
|
local aim_x, aim_y = ComponentGetValue2(controls, "mAimingVector") -- float, float
|
|
local aimNormal_x, aimNormal_y = ComponentGetValue2(controls, "mAimingVectorNormalized") -- float, float
|
|
local aimNonZero_x, aimNonZero_y = ComponentGetValue2(controls, "mAimingVectorNonZeroLatest") -- float, float
|
|
local mouse_x, mouse_y = ComponentGetValue2(controls, "mMousePosition") -- float, float
|
|
local mouseRaw_x, mouseRaw_y = ComponentGetValue2(controls, "mMousePositionRaw") -- float, float
|
|
local mouseRawPrev_x, mouseRawPrev_y = ComponentGetValue2(controls, "mMousePositionRawPrev") -- float, float
|
|
local mouseDelta_x, mouseDelta_y = ComponentGetValue2(controls, "mMouseDelta") -- float, float
|
|
]]
|
|
|
|
ComponentSetValue2(controlsComp, "mAimingVector", message.aim_x, message.aim_y)
|
|
ComponentSetValue2(controlsComp, "mAimingVectorNormalized", message.aimNormal_x, message.aimNormal_y)
|
|
ComponentSetValue2(controlsComp, "mAimingVectorNonZeroLatest", message.aimNonZero_x, message.aimNonZero_y)
|
|
ComponentSetValue2(controlsComp, "mMousePosition", message.mouse_x, message.mouse_y)
|
|
ComponentSetValue2(controlsComp, "mMousePositionRaw", message.mouseRaw_x, message.mouseRaw_y)
|
|
ComponentSetValue2(controlsComp, "mMousePositionRawPrev", message.mouseRawPrev_x, message.mouseRawPrev_y)
|
|
ComponentSetValue2(controlsComp, "mMouseDelta", message.mouseDelta_x, message.mouseDelta_y)
|
|
|
|
local children = EntityGetAllChildren(player_data.entity) or {}
|
|
for i, child in ipairs(children) do
|
|
if (EntityGetName(child) == "cursor") then
|
|
--EntitySetTransform(child, message.mouse_x, message.mouse_y)
|
|
EntityApplyTransform(child, message.mouse_x, message.mouse_y)
|
|
end
|
|
end
|
|
|
|
end
|
|
end,
|
|
serialize_inputs = function(player_data)
|
|
local player = player_data.entity
|
|
if (player == nil) then
|
|
return
|
|
end
|
|
local controls = EntityGetFirstComponentIncludingDisabled(player, "ControlsComponent")
|
|
|
|
|
|
if (controls ~= nil) then
|
|
local kick = ComponentGetValue2(controls, "mButtonDownKick") -- boolean
|
|
local fire = ComponentGetValue2(controls, "mButtonDownFire") -- boolean
|
|
local fire2 = ComponentGetValue2(controls, "mButtonDownFire2") -- boolean
|
|
local action = ComponentGetValue2(controls, "mButtonDownAction") -- boolean
|
|
local throw = ComponentGetValue2(controls, "mButtonDownThrow") -- boolean
|
|
local interact = ComponentGetValue2(controls, "mButtonDownInteract") -- boolean
|
|
local left = ComponentGetValue2(controls, "mButtonDownLeft") -- boolean
|
|
local right = ComponentGetValue2(controls, "mButtonDownRight") -- boolean
|
|
local up = ComponentGetValue2(controls, "mButtonDownUp") -- boolean
|
|
local down = ComponentGetValue2(controls, "mButtonDownDown") -- boolean
|
|
local jump = ComponentGetValue2(controls, "mButtonDownJump") -- boolean
|
|
local fly = ComponentGetValue2(controls, "mButtonDownFly") -- boolean
|
|
local leftClick = ComponentGetValue2(controls, "mButtonDownLeftClick") -- boolean
|
|
local rightClick = ComponentGetValue2(controls, "mButtonDownRightClick") -- boolean
|
|
local aim_x, aim_y = ComponentGetValue2(controls, "mAimingVector") -- float, float
|
|
local aimNormal_x, aimNormal_y = ComponentGetValue2(controls, "mAimingVectorNormalized") -- float, float
|
|
local aimNonZero_x, aimNonZero_y = ComponentGetValue2(controls, "mAimingVectorNonZeroLatest") -- float, float
|
|
local mouse_x, mouse_y = ComponentGetValue2(controls, "mMousePosition") -- float, float
|
|
local mouseRaw_x, mouseRaw_y = ComponentGetValue2(controls, "mMousePositionRaw") -- float, float
|
|
local mouseRawPrev_x, mouseRawPrev_y = ComponentGetValue2(controls, "mMousePositionRawPrev") -- float, float
|
|
local mouseDelta_x, mouseDelta_y = ComponentGetValue2(controls, "mMouseDelta") -- float, float
|
|
|
|
local c = Controls{
|
|
kick = kick,
|
|
fire = fire,
|
|
fire2 = fire2,
|
|
action = action,
|
|
throw = throw,
|
|
interact = interact,
|
|
left = left,
|
|
right = right,
|
|
up = up,
|
|
down = down,
|
|
jump = jump,
|
|
fly = fly,
|
|
leftClick = leftClick,
|
|
rightClick = rightClick,
|
|
aim_x = aim_x,
|
|
aim_y = aim_y,
|
|
aimNormal_x = aimNormal_x,
|
|
aimNormal_y = aimNormal_y,
|
|
aimNonZero_x = aimNonZero_x,
|
|
aimNonZero_y = aimNonZero_y,
|
|
mouse_x = mouse_x,
|
|
mouse_y = mouse_y,
|
|
mouseRaw_x = mouseRaw_x,
|
|
mouseRaw_y = mouseRaw_y,
|
|
mouseRawPrev_x = mouseRawPrev_x,
|
|
mouseRawPrev_y = mouseRawPrev_y,
|
|
mouseDelta_x = mouseDelta_x,
|
|
mouseDelta_y = mouseDelta_y,
|
|
}
|
|
|
|
return c
|
|
end
|
|
end,
|
|
make_playerdata_for = function(entity_id, peer_id)
|
|
GamePrint("Made playerdata for "..entity_id)
|
|
return {
|
|
entity = entity_id,
|
|
peer_id = peer_id,
|
|
name = "[Peer "..peer_id.."]",
|
|
controls = {},
|
|
projectile_rng_init = {},
|
|
projectile_seed_chain = {}, -- TODO clean
|
|
}
|
|
end,
|
|
}
|
|
|
|
function player_fns.serialize_position(player_data)
|
|
local entity = player_data.entity
|
|
if not EntityGetIsAlive(entity) then
|
|
return
|
|
end
|
|
local x, y = EntityGetTransform(entity)
|
|
local character_data = EntityGetFirstComponentIncludingDisabled(entity, "CharacterDataComponent")
|
|
local character_platforming_comp = EntityGetFirstComponentIncludingDisabled(entity, "CharacterPlatformingComponent")
|
|
local vel_x, vel_y = ComponentGetValue2(character_data, "mVelocity")
|
|
|
|
local c = CharacterPos{
|
|
frames_in_air = ComponentGetValue2(character_platforming_comp, "mFramesInAirCounter"),
|
|
x = x,
|
|
y = y,
|
|
vx = vel_x,
|
|
vy = vel_y,
|
|
is_on_ground = ComponentGetValue2(character_data, "is_on_ground"),
|
|
is_on_slippery_ground = ComponentGetValue2(character_data, "is_on_slippery_ground"),
|
|
}
|
|
return c
|
|
end
|
|
|
|
function player_fns.deserialize_position(message, player_data)
|
|
local entity = player_data.entity
|
|
if not EntityGetIsAlive(entity) then
|
|
return
|
|
end
|
|
local character_data = EntityGetFirstComponentIncludingDisabled(entity, "CharacterDataComponent")
|
|
local velocity_comp = EntityGetFirstComponentIncludingDisabled(entity, "VelocityComponent")
|
|
|
|
ComponentSetValue2(character_data, "mVelocity", message.vel_x, message.vel_y)
|
|
ComponentSetValue2(velocity_comp, "mVelocity", message.vel_x, message.vel_y)
|
|
|
|
EntityApplyTransform(entity, message.x, message.y)
|
|
end
|
|
|
|
|
|
function player_fns.serialize_items(player_data)
|
|
local item_data, spell_data = inventory_helper.get_item_data(player_data)
|
|
return item_data
|
|
end
|
|
|
|
function player_fns.deserialize_items(inventory_state, player_data)
|
|
inventory_helper.set_item_data(inventory_state, player_data)
|
|
util.set_ent_firing_blocked(player_data.entity, true)
|
|
end
|
|
|
|
function player_fns.peer_has_player(peer_id)
|
|
return ctx.players[peer_id] ~= nil
|
|
end
|
|
|
|
function player_fns.peer_get_player_data(peer_id)
|
|
if not player_fns.peer_has_player(peer_id) then
|
|
player_fns.spawn_player_for(peer_id, ctx.initial_player_pos.x, ctx.initial_player_pos.y)
|
|
end
|
|
return ctx.players[peer_id]
|
|
end
|
|
|
|
function player_fns.get_player_data_by_local_entity_id(entity)
|
|
return ctx.player_data_by_local_entity[entity]
|
|
end
|
|
|
|
function player_fns.spawn_player_for(peer_id, x, y)
|
|
GamePrint("Spawning player for "..peer_id)
|
|
local new = EntityLoad("mods/quant.ew/files/entities/client.xml", x, y)
|
|
local new_playerdata = player_fns.make_playerdata_for(new, peer_id)
|
|
ctx.players[peer_id] = new_playerdata
|
|
EntitySetName(new, tostring(peer_id))
|
|
if ctx.is_host then
|
|
EntityAddComponent2(new, "LuaComponent", {script_damage_received = "mods/quant.ew/files/cbs/redirect_damage_to_host.lua"})
|
|
else
|
|
EntityAddComponent2(new, "LuaComponent", {script_damage_about_to_be_received = "mods/quant.ew/files/cbs/immortal.lua"})
|
|
end
|
|
util.set_ent_firing_blocked(new, true)
|
|
ctx.player_data_by_local_entity[new] = new_playerdata
|
|
ctx.events.new_player_just_spawned = true
|
|
end
|
|
|
|
function player_fns.is_inventory_open()
|
|
local player_entity = ctx.players[ctx.my_id].entity
|
|
local inventory_gui_comp = EntityGetFirstComponentIncludingDisabled(player_entity, "InventoryGuiComponent")
|
|
|
|
return ComponentGetValue2(inventory_gui_comp, "mActive")
|
|
end
|
|
|
|
local function get_active_held_item(player_entity)
|
|
local inventory2Comp = EntityGetFirstComponentIncludingDisabled(player_entity, "Inventory2Component")
|
|
local mActiveItem = ComponentGetValue2(inventory2Comp, "mActiveItem")
|
|
return mActiveItem
|
|
end
|
|
|
|
function player_fns.get_current_slot(player_data)
|
|
local held_item = get_active_held_item(player_data.entity)
|
|
if (held_item ~= nil and held_item ~= 0) then
|
|
local item_comp = EntityGetFirstComponentIncludingDisabled(held_item, "ItemComponent")
|
|
|
|
-- the hell??
|
|
if(item_comp == nil)then
|
|
return
|
|
end
|
|
|
|
local slot_x, slot_y = ComponentGetValue2(item_comp, "inventory_slot")
|
|
local ability_comp = EntityGetFirstComponentIncludingDisabled(held_item, "AbilityComponent")
|
|
|
|
local is_wand = false
|
|
if(ability_comp and ComponentGetValue2(ability_comp, "use_gun_script"))then
|
|
is_wand = true
|
|
end
|
|
return {is_wand, slot_x, slot_y}
|
|
end
|
|
end
|
|
|
|
function player_fns.set_current_slot(slot_data, player_data)
|
|
local is_wand, slot_x, slot_y = slot_data[1], slot_data[2], slot_data[3]
|
|
-- GamePrint("Switching item to slot: " .. tostring(slot_x) .. ", " .. tostring(slot_y))
|
|
if (player_data.entity and EntityGetIsAlive(player_data.entity)) then
|
|
local items = GameGetAllInventoryItems(player_data.entity) or {}
|
|
for i, item in ipairs(items) do
|
|
-- check id
|
|
local itemComp = EntityGetFirstComponentIncludingDisabled(item, "ItemComponent")
|
|
if itemComp ~= nil then
|
|
local item_slot_x, item_slot_y = ComponentGetValue2(itemComp, "inventory_slot")
|
|
|
|
local ability_comp = EntityGetFirstComponentIncludingDisabled(item, "AbilityComponent")
|
|
|
|
local item_is_wand = false
|
|
if(ability_comp and ComponentGetValue2(ability_comp, "use_gun_script"))then
|
|
item_is_wand = true
|
|
end
|
|
|
|
if (item_slot_x == slot_x and item_slot_y == slot_y and item_is_wand == is_wand) then
|
|
local inventory2Comp = EntityGetFirstComponentIncludingDisabled(
|
|
player_data.entity, "Inventory2Component")
|
|
local mActiveItem = ComponentGetValue2(inventory2Comp, "mActiveItem")
|
|
|
|
if (mActiveItem ~= item) then
|
|
np.SetActiveHeldEntity(player_data.entity, item, false, false)
|
|
end
|
|
return
|
|
end
|
|
else
|
|
print("something in inventory that is not an item")
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function player_fns.make_fire_data(special_seed, player_data)
|
|
local player = player_data.entity
|
|
local wand = get_active_held_item(player)
|
|
|
|
if (wand ~= nil) then
|
|
local x, y, r = EntityGetTransform(wand)
|
|
local c = FireWand{
|
|
x = x,
|
|
y = y,
|
|
r = r,
|
|
special_seed = tonumber(special_seed),
|
|
action_rng = tonumber(GlobalsGetValue("ew_player_action_rng", "0"))
|
|
}
|
|
GlobalsSetValue("ew_player_action_rng", "0")
|
|
local rng_init = player_data.projectile_rng_init
|
|
player_data.projectile_rng_init = {}
|
|
return {rng_init, c}
|
|
end
|
|
end
|
|
|
|
return player_fns |