diff --git a/docs/capabilities.md b/docs/capabilities.md
index dc86f1fc..29c61ea1 100644
--- a/docs/capabilities.md
+++ b/docs/capabilities.md
@@ -27,7 +27,7 @@ Used by:
## 'item_sync' capability
Functions:
- - `globalize(entity_id, instantly: bool)`
+ - `globalize(entity_id, instantly: bool | nil, give_authority_to: PeerId | nil)`
- `register_pickup_handler(fn(local_item_id))`
Provided by:
diff --git a/noita-proxy/tangled/src/common.rs b/noita-proxy/tangled/src/common.rs
index a5cf499d..af4c6bb5 100644
--- a/noita-proxy/tangled/src/common.rs
+++ b/noita-proxy/tangled/src/common.rs
@@ -1,23 +1,12 @@
//! Various common public types.
-use std::{fmt::Display, time::Duration};
+use std::fmt::Display;
use bitcode::{Decode, Encode};
/// Per-peer settings. Peers that are connected to the same host, as well as the host itself, should have the same settings.
#[derive(Debug, Clone)]
-pub struct Settings {
- /// A single datagram will confirm at most this much messages. Default is 128.
- pub confirm_max_per_message: usize,
- /// How much time can elapse before another confirm is sent.
- /// Confirms are also sent when enough messages are awaiting confirm.
- /// Note that confirms also double as "heartbeats" and keep the connection alive, so this value should be much less than `connection_timeout`.
- /// Default: 1 second.
- pub confirm_max_period: Duration,
- /// Peers will be disconnected after this much time without any datagrams from them has passed.
- /// Default: 10 seconds.
- pub connection_timeout: Duration,
-}
+pub struct Settings {}
/// Tells how reliable a message is.
#[derive(Encode, Decode, Clone, Copy, PartialEq, Debug)]
@@ -95,11 +84,7 @@ impl Display for PeerId {
impl Default for Settings {
fn default() -> Self {
- Self {
- confirm_max_per_message: 128,
- confirm_max_period: Duration::from_secs(1),
- connection_timeout: Duration::from_secs(10),
- }
+ Self {}
}
}
diff --git a/noita-proxy/tangled/src/connection_manager.rs b/noita-proxy/tangled/src/connection_manager.rs
index ba85b9b4..78f175d3 100644
--- a/noita-proxy/tangled/src/connection_manager.rs
+++ b/noita-proxy/tangled/src/connection_manager.rs
@@ -21,7 +21,7 @@ use quinn::{
pki_types::{CertificateDer, PrivatePkcs8KeyDer},
},
ClientConfig, ConnectError, Connecting, ConnectionError, Endpoint, Incoming, RecvStream,
- ServerConfig,
+ ServerConfig, TransportConfig,
};
use thiserror::Error;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
@@ -467,6 +467,10 @@ fn default_server_config() -> ServerConfig {
let cert_der = CertificateDer::from(cert.cert);
let priv_key = PrivatePkcs8KeyDer::from(cert.key_pair.serialize_der());
- let config = ServerConfig::with_single_cert(vec![cert_der.clone()], priv_key.into()).unwrap();
+ let mut config =
+ ServerConfig::with_single_cert(vec![cert_der.clone()], priv_key.into()).unwrap();
+ let mut transport_config = TransportConfig::default();
+ transport_config.keep_alive_interval(Some(Duration::from_secs(10)));
+ config.transport_config(Arc::new(transport_config));
config
}
diff --git a/noita-proxy/tangled/src/lib.rs b/noita-proxy/tangled/src/lib.rs
index 3c69b166..a679d3b3 100644
--- a/noita-proxy/tangled/src/lib.rs
+++ b/noita-proxy/tangled/src/lib.rs
@@ -159,8 +159,6 @@ mod test {
async fn test_peer() {
info!("Starting test_peer");
let settings = Some(Settings {
- confirm_max_period: Duration::from_millis(100),
- connection_timeout: Duration::from_millis(1000),
..Default::default()
});
let addr = "127.0.0.1:56001".parse().unwrap();
@@ -194,8 +192,6 @@ mod test {
#[test_log::test(tokio::test)]
async fn test_broadcast() {
let settings = Some(Settings {
- confirm_max_period: Duration::from_millis(100),
- connection_timeout: Duration::from_millis(1000),
..Default::default()
});
let addr = "127.0.0.1:56002".parse().unwrap();
@@ -233,8 +229,6 @@ mod test {
#[test_log::test(tokio::test)]
async fn test_host_has_conn() {
let settings = Some(Settings {
- confirm_max_period: Duration::from_millis(100),
- connection_timeout: Duration::from_millis(1000),
..Default::default()
});
let addr = "127.0.0.1:56003".parse().unwrap();
diff --git a/quant.ew/files/system/enemy_sync.lua b/quant.ew/files/system/enemy_sync.lua
index 62ea2306..19e2f907 100644
--- a/quant.ew/files/system/enemy_sync.lua
+++ b/quant.ew/files/system/enemy_sync.lua
@@ -313,7 +313,7 @@ function enemy_sync.client_cleanup()
local frame = GameGetFrameNum()
for remote_id, enemy_data in pairs(ctx.entity_by_remote_id) do
if frame - enemy_data.frame > 60*1 then
- print("Despawning stale "..remote_id.." "..enemy_data.id)
+ --print("Despawning stale "..remote_id.." "..enemy_data.id)
EntityKill(enemy_data.id)
ctx.entity_by_remote_id[remote_id] = nil
end
diff --git a/quant.ew/files/system/gen_sync/gen_sync.lua b/quant.ew/files/system/gen_sync/gen_sync.lua
index 01370870..a933f809 100644
--- a/quant.ew/files/system/gen_sync/gen_sync.lua
+++ b/quant.ew/files/system/gen_sync/gen_sync.lua
@@ -42,7 +42,11 @@ local function run_spawn_fn(fn_name, x, y, ...)
-- Function returns item's entity id.
if fn_info.kind == "item" then
local eid = ret
- ctx.cap.item_sync.globalize(eid, false)
+ ctx.cap.item_sync.globalize(eid, true, ctx.rpc_peer_id)
+ -- Avoid item losing it's cost on host.
+ local x, y = EntityGetTransform(eid)
+ local minishop = EntityLoad("mods/quant.ew/files/system/gen_sync/tmp_shop_area.xml", x, y)
+ EntityAddChild(eid, minishop)
end
end
diff --git a/quant.ew/files/system/gen_sync/tmp_shop_area.xml b/quant.ew/files/system/gen_sync/tmp_shop_area.xml
new file mode 100644
index 00000000..4492ccbe
--- /dev/null
+++ b/quant.ew/files/system/gen_sync/tmp_shop_area.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/quant.ew/files/system/gen_sync/tmp_shop_script.lua b/quant.ew/files/system/gen_sync/tmp_shop_script.lua
new file mode 100644
index 00000000..70dfccc3
--- /dev/null
+++ b/quant.ew/files/system/gen_sync/tmp_shop_script.lua
@@ -0,0 +1,7 @@
+-- Deletes the temporary shop entity after the world has been properly generated.
+
+local ent = GetUpdatedEntityID()
+local x, y = EntityGetTransform(ent)
+if DoesWorldExistAt(x-5, y-5, x+5, y+5) then
+ EntityKill(ent)
+end
diff --git a/quant.ew/files/system/item_sync.lua b/quant.ew/files/system/item_sync.lua
index 15e5ff56..35e9d7b5 100644
--- a/quant.ew/files/system/item_sync.lua
+++ b/quant.ew/files/system/item_sync.lua
@@ -47,7 +47,6 @@ end
function item_sync.get_global_item_id(item)
local gid = EntityGetFirstComponentIncludingDisabled(item, "VariableStorageComponent", "ew_global_item_id")
if gid == nil then
- GamePrint("Item has no gid")
return "unknown"
end
local ret = ComponentGetValue2(gid, "value_string")
@@ -110,7 +109,7 @@ function item_sync.host_localize_item(gid, peer_id)
rpc.item_localize(peer_id, gid)
end
-function item_sync.make_item_global(item, instant)
+function item_sync.make_item_global(item, instant, give_authority_to)
EntityAddTag(item, "ew_global_item")
async(function()
if not instant then
@@ -126,6 +125,9 @@ function item_sync.make_item_global(item, instant)
local gid
if gid_component == nil then
gid = allocate_global_id()
+ if give_authority_to ~= nil then
+ gid = give_authority_to..":"..gid
+ end
EntityAddComponent2(item, "VariableStorageComponent", {
_tags = "enabled_in_world,enabled_in_hand,enabled_in_inventory,ew_global_item_id",
value_string = gid,
@@ -317,7 +319,6 @@ end
rpc.opts_reliable()
function rpc.item_globalize(item_data)
if is_safe_to_remove() then
- print("remove in globalize")
item_sync.remove_item_with_id_now(item_data.gid)
end
local item = inventory_helper.deserialize_single_item(item_data)
diff --git a/quant.ew/files/system/local_health/entities/magical_symbol_player.xml b/quant.ew/files/system/local_health/entities/magical_symbol_player.xml
new file mode 100644
index 00000000..fe5ed20b
--- /dev/null
+++ b/quant.ew/files/system/local_health/entities/magical_symbol_player.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/quant.ew/files/system/local_health/local_health.lua b/quant.ew/files/system/local_health/local_health.lua
index 1386d8b4..9901f5d4 100644
--- a/quant.ew/files/system/local_health/local_health.lua
+++ b/quant.ew/files/system/local_health/local_health.lua
@@ -25,7 +25,7 @@ local function do_switch_effect(short)
return
end
local x, y = EntityGetTransform(ctx.my_player.entity)
- rpc.switch_effect(x, y)
+ rpc.switch_effect(x, y, short)
if short then
LoadGameEffectEntityTo(ctx.my_player.entity, "mods/quant.ew/files/system/local_health/notplayer/safe_effect2.xml")
else
@@ -315,8 +315,12 @@ function rpc.send_status(status)
end
rpc.opts_everywhere()
-function rpc.switch_effect(x, y)
- EntityLoad("data/entities/particles/image_emitters/magical_symbol_fast.xml", x, y)
+function rpc.switch_effect(x, y, to_normal_player)
+ if to_normal_player then
+ EntityLoad("mods/quant.ew/files/system/local_health/entities/magical_symbol_player.xml", x, y)
+ else
+ EntityLoad("data/entities/particles/image_emitters/magical_symbol_fast.xml", x, y)
+ end
end
return module
\ No newline at end of file
diff --git a/quant.ew/files/system/notplayer_ai/damage_tracker.lua b/quant.ew/files/system/notplayer_ai/damage_tracker.lua
new file mode 100644
index 00000000..7e7657f6
--- /dev/null
+++ b/quant.ew/files/system/notplayer_ai/damage_tracker.lua
@@ -0,0 +1,10 @@
+dofile_once("data/scripts/lib/utilities.lua")
+
+function damage_received( damage, desc, entity_who_caused, is_fatal )
+ local entity_id = GetUpdatedEntityID()
+ local var = EntityGetFirstComponentIncludingDisabled(entity_id, "VariableStorageComponent", "ew_damage_tracker")
+ if var ~= nil then
+ local dtype = GetDamageDetails().damage_types
+ ComponentSetValue2(var, "value_int", dtype)
+ end
+end
\ No newline at end of file
diff --git a/quant.ew/files/system/notplayer_ai/notplayer_ai.lua b/quant.ew/files/system/notplayer_ai/notplayer_ai.lua
index 1b6d0abe..d4b6df2f 100644
--- a/quant.ew/files/system/notplayer_ai/notplayer_ai.lua
+++ b/quant.ew/files/system/notplayer_ai/notplayer_ai.lua
@@ -221,7 +221,7 @@ local function needs_douse(entity)
if damage_model ~= nil then
local hp = ComponentGetValue2(damage_model, "hp")
local max_hp = ComponentGetValue2(damage_model, "max_hp")
- if hp / max_hp <= 0.02 then
+ if hp / max_hp <= 0.05 then
prot_toxic = true
end
end
@@ -451,7 +451,17 @@ local function init_state()
control_a = false,
control_w = false,
control_d = false,
+
+ dtype = 0
}
+ EntityAddComponent2(ctx.my_player.entity, "LuaComponent", {
+ script_damage_received = "mods/quant.ew/files/system/notplayer_ai/damage_tracker.lua"
+ })
+ EntityAddComponent2(ctx.my_player.entity, "VariableStorageComponent", {
+ _tags = "ew_damage_tracker",
+ name = "ew_damage_tracker",
+ value_int = 0,
+ })
end
local target
@@ -598,6 +608,15 @@ local function choose_movement()
give_space = 100
end
end
+ GamePrint(state.dtype)
+ if state.dtype == 32 then
+ if (dist > 0 and did_hit_2) or (dist < 0 and did_hit_1) then
+ give_space = give_space + 10
+ else
+ swap_side = true
+ end
+ state.control_w = false
+ end
end
local function position_to_area_number(x, y)
@@ -613,7 +632,7 @@ local function position_to_area_number(x, y)
elseif y < 12975 and (x < 2726 or x > 4135 or y < 12800) then
return 5
else
- return 8
+ return 6
end
elseif tonumber(SessionNumbersGetValue("NEW_GAME_PLUS_COUNT")) > 0 then
if y < 1199 then
@@ -627,7 +646,7 @@ local function position_to_area_number(x, y)
elseif y < 12975 and (x < 2726 or x > 4135 or y < 12800) then
return 5
else
- return 8
+ return 6
end
else
if y < 1199 then
@@ -1009,6 +1028,11 @@ end
local kick_wait = 0
local function update()
+ local var = EntityGetFirstComponentIncludingDisabled(ctx.my_player.entity, "VariableStorageComponent", "ew_damage_tracker")
+ if GameGetFrameNum() % 30 == 0 then
+ ComponentSetValue2(var, "value_int", 0)
+ end
+ state.dtype = ComponentGetValue2(var, "value_int")
-- No taking control back, even after pressing esc.
ComponentSetValue2(state.control_component, "enabled", false)
diff --git a/quant.ew/files/system/world_sync/world_sync.lua b/quant.ew/files/system/world_sync/world_sync.lua
index 4519b7f7..c7191df8 100644
--- a/quant.ew/files/system/world_sync/world_sync.lua
+++ b/quant.ew/files/system/world_sync/world_sync.lua
@@ -24,6 +24,21 @@ local iter_slow = 0
local iter_slow_2 = 0
+local function do_benchmark()
+ local world_ffi = require("noitapatcher.nsew.world_ffi")
+ local grid_world = world_ffi.get_grid_world()
+ local chunk_map = grid_world.vtable.get_chunk_map(grid_world)
+ local start = GameGetRealWorldTimeSinceStarted()
+ local iters = 10000
+ for i=1, iters do
+ world.encode_area(chunk_map, 0, 0, 128, 128, encode_area)
+ -- world_ffi.get_cell(chunk_map, 0, 0)
+ end
+ local end_time = GameGetRealWorldTimeSinceStarted()
+ local elapsed = (end_time - start) * 1000 * 1000 * 1000 / (iters * 128 * 128)
+ print("Benchmark:", elapsed, "ns/pixel")
+end
+
function world_sync.on_world_initialized()
local c = 0
while true do
@@ -53,14 +68,18 @@ local function send_chunks(cx, cy, chunk_map)
end
end
-local function get_all_chunks(ocx, ocy, pos_data, priority)
+local function get_all_chunks(ocx, ocy, pos_data, priority, give_0)
local grid_world = world_ffi.get_grid_world()
local chunk_map = grid_world.vtable.get_chunk_map(grid_world)
--local thread_impl = grid_world.mThreadImpl
local int = 4 -- ctx.proxy_opt.world_sync_interval
if GameGetFrameNum() % int == 0 then
send_chunks(ocx, ocy, chunk_map)
- net.proxy_bin_send(KEY_WORLD_END, string.char(priority))
+ local pri = priority
+ if give_0 then
+ pri = 0
+ end
+ net.proxy_bin_send(KEY_WORLD_END, string.char(pri))
elseif GameGetFrameNum() % int == 2 then
if iter_fast == 0 then
send_chunks(ocx + 1, ocy, chunk_map)
@@ -163,16 +182,16 @@ function world_sync.on_world_update()
local pos_data = ocx..":"..ocy..":"..cx..":"..cy
if math.abs(cx - ocx) > 2 or math.abs(cy - ocy) > 2 then
if GameGetFrameNum() % 3 ~= 2 then
- get_all_chunks(cx, cy, pos_data, 16)
+ get_all_chunks(cx, cy, pos_data, 16, false)
else
- get_all_chunks(ocx, ocy, pos_data, 16)
+ get_all_chunks(ocx, ocy, pos_data, 16, true)
end
else
local pri = 0
if EntityHasTag(ctx.my_player.entity, "ew_notplayer") then
pri = 16
end
- get_all_chunks(ocx, ocy, pos_data, pri)
+ get_all_chunks(ocx, ocy, pos_data, pri, true)
end
end