--[[ This file is part of Ice Lua Components. Ice Lua Components is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Ice Lua Components is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Ice Lua Components. If not, see . ]] network = {} network.sys_tab_handlers = {} network.sys_tab_cli = {} network.sys_tab_throttle = {} function net_send(neth, msg) network.sys_tab_throttle[#(network.sys_tab_throttle)+1] = {neth, msg} end function net_send_flush() local i local failures = nil local n=#(network.sys_tab_throttle) for i=1,n do local v = network.sys_tab_throttle[i] network.sys_tab_throttle[i] = nil if client or v[1] then if not common.net_send(v[1], v[2]) then failures = failures or {} failures[v[1]] = true end else -- FIXME: this happens too often. -- It works perfectly fine, though. --GM --print("ignoring packet with nil neth:", #(v[2])) end end end if server then function net_broadcast(neth, msg) local i for i=1,#(client_list.fdlist) do if client_list.fdlist[i] ~= neth then --print("to", client_list.fdlist[i], type(msg)) net_send(client_list.fdlist[i], msg) end end end function net_broadcast_team(tidx, msg) local i for i=1,#(client_list.fdlist) do local cli = client_list[client_list.fdlist[i]] local plr = cli and players[cli.plrid] if plr and plr.team == tidx then --print("to", client_list.fdlist[i], type(msg)) net_send(client_list.fdlist[i], msg) end end end function net_broadcast_squad(tidx, squad, msg) local i for i=1,#(client_list.fdlist) do local cli = client_list[client_list.fdlist[i]] local plr = cli and players[cli.plrid] if plr and plr.team == tidx and plr.squad == squad then --print("to", client_list.fdlist[i], type(msg)) net_send(client_list.fdlist[i], msg) end end end end network.sys_val_nextpkt = 1 function network.sys_alloc_packet() local ret = network.sys_val_nextpkt network.sys_val_nextpkt = ret+1 return ret end function network.sys_handle_common(pktid, pstr, fn) network.sys_tab_handlers[pktid] = { s = pstr, f = fn } end function network.sys_handle_c2s(...) if server then return network.sys_handle_common(...) end end function network.sys_handle_s2c(...) if client then return network.sys_handle_common(...) end end -- base mod packets do local pktlist = { "PING", "PONG", "KEEPALIVE", "PLR_POS", "PLR_ORIENT", "PLR_ADD", "PLR_ID", "PLR_RM", "BLK_ADD", "BLK_RM1", "BLK_RM3", "BLK_COLLAPSE", "CHAT_SEND", "CHAT_SEND_TEAM", "CHAT_ADD_TEXT", "CHAT_ADD_KILLFEED", "PLR_SPAWN", "PLR_OFFER", "ITEM_POS", "PLR_GUN_HIT", "PLR_DAMAGE", "PLR_RESTOCK", "ITEM_CARRIER", "PLR_TOOL", "PLR_BLK_COLOR", "PLR_BLK_COUNT", "PLR_GUN_TRACER", "NADE_THROW", "MAP_RCIRC", "PLR_GUN_RELOAD", "CHAT_SEND_SQUAD", "TEAM_SCORE", "BLK_DAMAGE", "PIANO", "NADE_PIN", "BUILD_BOX", "PLR_GUN_SHOT", "NEW_MAP", "FOG_COLOR" } local i,p for i,p in pairs(pktlist) do _G["PKT_"..p] = network.sys_alloc_packet() end end function nwdec_plrset(f, fx) return (function (neth, cli, plr, sec_current, ...) if plr then return f(neth, cli, plr, sec_current, ...) elseif fx then return fx(neth, cli, plr, sec_current, ...) end end) end function nwdec_plrclear(f) return (function (neth, cli, plr, sec_current, ...) if not plr then return f(neth, cli, plr, sec_current, ...) end end) end function nwdec_plrsquadset(f) return (function (neth, cli, plr, sec_current, ...) if plr and plr.squad then return f(neth, cli, plr, sec_current, ...) end end) end -- S2C packets network.sys_handle_s2c(PKT_PLR_POS, "Bffffff", function (neth, cli, plr, sec_current, pid, x, y, z, vx, vy, vz, pkt) local plr = players[pid] if plr then plr.set_pos_recv(x, y, z) end end) network.sys_handle_s2c(PKT_PLR_ORIENT, "BbbB", function (neth, cli, plr, sec_current, pid, ya, xa, keys, pkt) ya = ya*math.pi/128 xa = xa*math.pi/256 local plr = players[pid] if plr then plr.set_orient_recv(ya, xa, keys) end end) network.sys_handle_s2c(PKT_PLR_ADD, "Bbbbhhhzz", function (neth, cli, plr, sec_current, pid, tidx, wpn, mode, score, kills, deaths, name, squad, pkt) if players[pid] then -- TODO: update wpn/name players[pid].squad = (squad ~= "" and squad) or nil players[pid].name = name players[pid].team = tidx if players[pid].mode ~= mode then players[pid].mode = mode players[pid].add_tools() end players[pid].recolor_team() if players[pid].weapon ~= wpn then players[pid].weapon = wpn players[pid].wpn = weapons[wpn](players[pid]) if pid == players.current then players[pid].create_hud() end end else players[pid] = new_player({ name = name, --[=[squad = squads[(i-1) % 2][ (math.floor((i-1)/2) % 4)+1],]=] squad = (squad ~= "" and squad) or nil, team = tidx, weapon = wpn, mode = mode, pid = pid, neth = neth }) end players[pid].score = score players[pid].kills = kills players[pid].deaths = deaths end) network.sys_handle_s2c(PKT_PLR_ID, "B", function (neth, cli, plr, sec_current, pid, pkt) players.current = pid end) network.sys_handle_s2c(PKT_PLR_RM, "B", function (neth, cli, plr, sec_current, pid, pkt) players[pid] = nil end) network.sys_handle_s2c(PKT_BLK_ADD, "HHHBBBB", function (neth, cli, plr, sec_current, x,y,z,cb,cg,cr,ct, pkt) bhealth_clear(x,y,z,false) client.wav_play_global(wav_buld,x+0.5,y+0.5,z+0.5) map_block_set(x,y,z,ct,cr,cg,cb) end) network.sys_handle_s2c(PKT_BLK_RM1, "HHH", function (neth, cli, plr, sec_current, x, y, z, pkt) bhealth_clear(x,y,z,false) map_block_break(x,y,z) client.wav_play_global(wav_pop, x, y, z) end) network.sys_handle_s2c(PKT_CHAT_ADD_TEXT, "Iz", function (neth, cli, plr, sec_current, color, msg, pkt) chat_add(chat_text, sec_current, msg, color) end) network.sys_handle_s2c(PKT_CHAT_ADD_KILLFEED, "Iz", function (neth, cli, plr, sec_current, color, msg, pkt) chat_add(chat_killfeed, sec_current, msg, color) end) network.sys_handle_s2c(PKT_PLR_SPAWN, "Bfffbb", function (neth, cli, plr, sec_current, pid, x, y, z, ya, xa, pkt) local plr = players[pid] --print("client respawn!", players.current, pid, plr) if plr then plr.spawn_at(x,y,z,ya*math.pi/128,xa*math.pi/256) end end) network.sys_handle_s2c(PKT_ITEM_POS, "HhhhB", function (neth, cli, plr, sec_current, iid, x,y,z, f, pkt) if miscents[iid] then if not miscents[iid].spawned then miscents[iid].spawn_at(x,y,z) else miscents[iid].set_pos_recv(x,y,z) end miscents[iid].set_flags_recv(f) end end) network.sys_handle_s2c(PKT_PLR_DAMAGE, "BB", function (neth, cli, plr, sec_current, pid, amt, pkt) local plr = players[pid] --print("hit pkt", pid, amt) if plr then plr.set_health_damage(amt, nil, nil, nil) end end) network.sys_handle_s2c(PKT_PLR_RESTOCK, "B", function (neth, cli, plr, sec_current, pid, pkt) local plr = players[pid] if plr then plr.tent_restock() end end) network.sys_handle_s2c(PKT_ITEM_CARRIER, "HB", function (neth, cli, plr, sec_current, iid, pid, pkt) local plr = (pid ~= 0 and players[pid]) or nil local item = miscents[iid] --print(">",iid,pid,plr,item) if (pid == 0 or plr) and item then local hplr = item.player if hplr then hplr.item_remove(item) end item.player = plr if plr then plr.item_add(item) end end end) network.sys_handle_s2c(PKT_PLR_TOOL, "BB", function (neth, cli, plr, sec_current, pid, tool, pkt) local plr = players[pid] if plr then plr.tool_switch(tool) end end) network.sys_handle_s2c(PKT_PLR_BLK_COLOR, "BBBB", function (neth, cli, plr, sec_current, pid, cr, cg, cb, pkt) local plr = players[pid] --print("recol",cr,cg,cb) if plr then plr.blk_color = {cr,cg,cb} plr.block_recolor() end end) network.sys_handle_s2c(PKT_PLR_BLK_COUNT, "BH", function (neth, cli, plr, sec_current, pid, blocks, pkt) local plr = players[pid] --print("19",pid,blocks) if plr then plr.blocks = blocks end end) network.sys_handle_s2c(PKT_PLR_GUN_TRACER, "B", function (neth, cli, plr, sec_current, pid, pkt) -- Refactor incoming - see PKT_PLR_GUN_SHOT local plr = players[pid] if plr then tracer_add(plr.x,plr.y,plr.z, plr.angy,plr.angx, sec_current) client.wav_play_global(wav_rifle_shot, plr.x, plr.y, plr.z) tracer_part_mdl = tracer_part_mdl or new_particle_model(250, 215, 0) particles_add(new_particle{ x = plr.x, y = plr.y, z = plr.z, vx = math.sin(plr.angy - math.pi / 4) / 2, vy = 0.1, vz = math.cos(plr.angy - math.pi / 4) / 2, model = tracer_part_mdl, size = 8, lifetime = 1 }) end end) network.sys_handle_s2c(PKT_NADE_THROW, "BhhhhhhH", function (neth, cli, plr, sec_current, pid,x,y,z,vx,vy,vz,fuse, pkt) local n = new_nade({ x = x/32, y = y/32, z = z/32, vx = vx/256, vy = vy/256, vz = vz/256, fuse = fuse/100, pid = pid }) client.wav_play_global(wav_whoosh, x, y, z) nade_add(n) end) network.sys_handle_s2c(PKT_MAP_RCIRC, "", function (neth, cli, plr, sec_current, pkt) local plr = players[players.current] if plr then plr.t_rcirc = sec_current + MODE_RCIRC_LINGER end end) network.sys_handle_s2c(PKT_PLR_GUN_RELOAD, "B", function (neth, cli, plr, sec_current, pid, pkt) local plr = players[pid] if plr then local tool = plr.tools[plr.tool+1] if tool and tool.remote_client_reload then tool.remote_client_reload(fire_type) end end end) network.sys_handle_s2c(PKT_TEAM_SCORE, "bh", function (neth, cli, plr, sec_current, tidx, score, pkt) teams[tidx].score = score end) network.sys_handle_s2c(PKT_BLK_DAMAGE, "HHHH", function (neth, cli, plr, sec_current, x, y, z, amt, pkt) if map_block_get(x, y, z) then client.wav_play_global(wav_hammer, x, y, z) bhealth_damage(x, y, z, amt) else client.wav_play_global(wav_swish, x, y, z) end end) network.sys_handle_s2c(PKT_PIANO, "B", function (neth, cli, plr, sec_current, pid, pkt) local plr = players[pid] if plr then plr.drop_piano() end end) network.sys_handle_s2c(PKT_NADE_PIN, "B", function (neth, cli, plr, sec_current, pid, pkt) local plr = players[pid] if plr then client.wav_play_global(wav_pin, plr.x, plr.y, plr.z) end end) network.sys_handle_s2c(PKT_NEW_MAP, "", function (neth, cli, plr, sec_current, pkt) --crashes --dofile("pkg/base/main_client.lua") map_loaded = common.map_load(map_fname, "auto") common.map_set(map_loaded) -- set borders do local xlen, ylen, zlen xlen, ylen, zlen = common.map_get_dims() local r,g,b r,g,b = client.map_fog_get() if MODE_BORDER_SHOW then borders = { new_border(-1, 0, 0, 1, 0, 0, r,g,b), new_border(xlen+1, ylen, zlen, 1, 0, 0, r,g,b), new_border(0, 0, -1, 0, 0, 1, r,g,b), new_border(xlen, ylen, zlen+1, 0, 0, 1, r,g,b), new_border(-1, 0, 0, 1, 0, 0, r,g,b), new_border(xlen+1, ylen, zlen, 1, 0, 0, r,g,b), new_border(0, 0, -1, 0, 0, 1, r,g,b), new_border(xlen, ylen, zlen+1, 0, 0, 1, r,g,b), } end end -- create map overview do local xlen, ylen, zlen xlen, ylen, zlen = common.map_get_dims() img_overview = common.img_new(xlen, zlen) img_overview_hmap = common.img_new(xlen, zlen) img_overview_grid = common.img_new(xlen, zlen) --img_overview_icons = common.img_new(xlen, zlen) local x,z for z=0,zlen-1 do for x=0,xlen-1 do local l = common.map_pillar_get(x,z) local c = argb_split_to_merged(l[7],l[6],l[5]) common.img_pixel_set(img_overview, x, z, c) common.img_pixel_set(img_overview_hmap, x, z, l[2]) end end for z=63,zlen-1,64 do for x=0,xlen-1 do common.img_pixel_set(img_overview_grid, x, z, 0xFFFFFFFF) end end for z=0,zlen-1 do for x=63,xlen-1,64 do common.img_pixel_set(img_overview_grid, x, z, 0xFFFFFFFF) end end for x=0,xlen-1 do common.img_pixel_set(img_overview_grid, x, zlen-1, 0xFFFF0000) end for z=0,zlen-1 do common.img_pixel_set(img_overview_grid, xlen-1, z, 0xFFFF0000) end end end) network.sys_handle_s2c(PKT_FOG_COLOR, "BBB", function (neth, cli, plr, sec_current, r, g, b, pkt) local xr, xg, xb, fdist = client.map_fog_get() client.map_fog_set(r, g, b, fdist) end) -- C2S packets network.sys_handle_c2s(PKT_KEEPALIVE, "B", function () end) network.sys_handle_c2s(PKT_PLR_POS, "Bffffff", nwdec_plrset(function (neth, cli, plr, sec_current, pid, x, y, z, vx, vy, vz, pkt) plr.set_pos_recv(x, y, z) net_broadcast(neth, common.net_pack("BBffffff", PKT_PLR_POS, cli.plrid, x, y, z, vx, vy, vz)) end)) network.sys_handle_c2s(PKT_PLR_ORIENT, "BbbB", nwdec_plrset(function (neth, cli, plr, sec_current, pid, ya2, xa2, keys, pkt) local ya = ya2*math.pi/128 local xa = xa2*math.pi/256 plr.set_orient_recv(ya, xa, keys) net_broadcast(neth, common.net_pack("BBbbB", PKT_PLR_ORIENT, cli.plrid, ya2, xa2, keys)) end)) network.sys_handle_c2s(PKT_BLK_ADD, "HHHBBBB", nwdec_plrset(function (neth, cli, plr, sec_current, x,y,z,cb,cg,cr,ct,pkt) if not (plr and plr.has_permission("build")) then return end local xlen,ylen,zlen xlen,ylen,zlen = common.map_get_dims() if x >= 0 and x < xlen and z >= 0 and z < zlen then if y >= 0 and y <= ylen-3 then local blocks = plr.blocks if blocks > 0 and map_is_buildable(x,y,z) then if plr.mode == PLM_NORMAL then blocks = blocks - 1 end map_block_set(x,y,z,ct,cr,cg,cb) net_broadcast(nil, common.net_pack("BHHHBBBB", PKT_BLK_ADD,x,y,z,cb,cg,cr,ct)) elseif blocks < 0 then blocks = 0 end plr.set_blocks(blocks) end end end)) network.sys_handle_c2s(PKT_BLK_RM1, "HHH", nwdec_plrset(function (neth, cli, plr, sec_current, x,y,z, pkt) if not (plr and plr.has_permission("build")) then return end local xlen,ylen,zlen xlen,ylen,zlen = common.map_get_dims() if x >= 0 and x < xlen and z >= 0 and z < zlen then if y >= 0 and y <= ylen-3 then if map_block_break(x,y,z) then net_broadcast(nil, common.net_pack("BHHH", PKT_BLK_RM1,x,y,z)) if plr.tool == TOOL_SPADE then local oblocks = plr.blocks oblocks = oblocks + 1 if oblocks > MODE_BLOCKS_MAX then oblocks = MODE_BLOCKS_MAX end plr.set_blocks(oblocks) end end end end end)) network.sys_handle_c2s(PKT_BLK_RM3, "HHH", nwdec_plrset(function (neth, cli, plr, sec_current, x,y,z, pkt) if not (plr and plr.has_permission("build")) then return end local xlen,ylen,zlen xlen,ylen,zlen = common.map_get_dims() if x >= 0 and x < xlen and z >= 0 and z < zlen then local i for i=-1,1 do if y+i >= 0 and y+i <= ylen-3 then map_block_break(x,y+i,z) net_broadcast(nil, common.net_pack("BHHH", PKT_BLK_RM1,x,y+i,z)) end end end end)) network.sys_handle_c2s(PKT_CHAT_SEND, "z", nwdec_plrset(function (neth, cli, plr, sec_current, msg, pkt) local s = nil local usage_colour = 0xFFDDDDFF if string.sub(msg,1,1) == "/" then --TODO: Better parameter parsing (param1 "param two" "param \"three\"") local params = string.split(string.sub(msg,2), " ") command_handle(plr, cli.plrid, neth, params, msg) else s = plr.name.." ("..teams[plr.team].name.."): "..msg irc.write(s) -- TODO: use a user-configurable table for these -- if you've read the "Pubbie Tears" section of the goonstation wiki, -- you'll understand why SOME of these are in there. if msg == "LOL" or msg:lower():find("nooo") or msg:lower():find("yolo") or ((msg:lower():find("suck") or msg:lower():find("suk")) and (msg:lower():find("dick") or msg:lower():find("pussy") or msg:lower():find("cock") or msg:lower():find("dik"))) or msg:lower():find("your not") or msg:lower():find("your real") or msg:lower():find("your da") or msg:lower():find("your a ") or msg:lower():find("your the") or msg:lower():find("your an ") or msg:lower():find("ur mom") or msg:lower():find("ur mum") or ((((msg:lower():find("please") or msg:lower():find("now")) and msg:lower():find("leave")) or msg:lower():find("go away")) and not (plr and (plr.has_permission("ban") or plr.has_permission("kick") or plr.has_permission("piano")))) or msg:lower():find("no kill") then plr.drop_piano() end end if s then net_broadcast(nil, common.net_pack("BIz", PKT_CHAT_ADD_TEXT, 0xFFFFFFFF, s)) end end)) network.sys_handle_c2s(PKT_CHAT_SEND_TEAM, "z", nwdec_plrset(function (neth, cli, plr, sec_current, msg, pkt) local s = nil if string.sub(msg,1,4) == "/me " then s = "* "..plr.name.." "..string.sub(msg,5) else s = plr.name..": "..msg end if s then local cb = teams[plr.team].color_chat local c = argb_split_to_merged(cb[1],cb[2],cb[3]) irc.write("teamchat["..teams[plr.team].name.."]: "..s) net_broadcast_team(plr.team, common.net_pack("BIz", PKT_CHAT_ADD_TEXT, c, s)) end end)) network.sys_handle_c2s(PKT_CHAT_SEND_SQUAD, "z", nwdec_plrset(function (neth, cli, plr, sec_current, msg, pkt) if plr.squad then local s = nil if string.sub(msg,1,4) == "/me " then s = "* "..plr.name.." "..string.sub(msg,5) else s = plr.name..": "..msg end if s then irc.write("squadchat["..teams[plr.team].name..":"..plr.squad.."]: "..s) net_broadcast_squad(plr.team, plr.squad, common.net_pack("BIz", PKT_CHAT_ADD_TEXT, 0xFFFFFF55, s)) end end end)) network.sys_handle_c2s(PKT_PLR_OFFER, "bbz", nwdec_plrset(function (neth, cli, plr, sec_current, tidx, wpn, name, pkt) name = (name ~= "" and name) or name_generate() plr.wpn = weapons[wpn](plr) if plr.team ~= tidx then plr.set_health_damage(0, 0xFF800000, plr.name.." changed teams", nil) if not teams[tidx] then print("HACK ATTEMPT from neth "..tostring(neth)) server.net_kick(neth, "Hack attempt") return end print(plr, tidx, teams[tidx]) net_broadcast(nil, common.net_pack("BIz", PKT_CHAT_ADD_TEXT, 0xFF800000, "* Player "..plr.name.." has joined the "..teams[tidx].name.." team")) elseif plr.weapon ~= wpn then plr.set_health_damage(0, 0xFF800000, plr.name.." changed weapons", nil) net_broadcast(nil, common.net_pack("BIz", PKT_CHAT_ADD_TEXT, 0xFF800000, "* Player "..plr.name.." is now using the "..plr.wpn.cfg.name)) end plr.team = tidx plr.weapon = wpn net_broadcast(nil, common.net_pack("BBBBBhhhzz", PKT_PLR_ADD, plr.pid, plr.team, plr.weapon, plr.mode, plr.score, plr.kills, plr.deaths, plr.name, plr.squad)) end, function (neth, cli, plr, sec_current, tidx, wpn, name, pkt) name = (name ~= "" and name) or name_generate() cli.plrid = slot_add(neth, tidx, wpn, name) if not cli.plrid then print("* server full") -- TODO: kick somehow! else plr = players[cli.plrid] print("* "..name.." joined team "..tidx..".") fog_send_to(neth) -- relay other players to this player local i for i=1,players.max do local plr = players[i] if plr then net_send(neth, common.net_pack("BBBBBhhhzz", PKT_PLR_ADD, i, plr.team, plr.weapon, plr.mode, plr.score, plr.kills, plr.deaths, plr.name, plr.squad)) net_send(neth, common.net_pack("BBfffBB", PKT_PLR_SPAWN, i, plr.x, plr.y, plr.z, plr.angy*128/math.pi, plr.angx*256/math.pi)) net_send(neth, common.net_pack("BBB", PKT_PLR_TOOL, i, plr.tool)) net_send(neth, common.net_pack("BBBBB", PKT_PLR_BLK_COLOR, i, plr.blk_color[1],plr.blk_color[2],plr.blk_color[3])) end end -- relay items to this player mode_relay_items(plr, neth) -- relay score to this player for i=0,teams.max do net_send(neth, common.net_pack("Bbh", PKT_TEAM_SCORE, i, teams[i].score)) end -- relay this player to everyone net_broadcast(nil, common.net_pack("BBBBBhhhzz", PKT_PLR_ADD, cli.plrid, plr.team, plr.weapon, plr.mode, plr.score, plr.kills, plr.deaths, plr.name, plr.squad)) net_broadcast(nil, common.net_pack("BBfffBB", PKT_PLR_SPAWN, cli.plrid, plr.x, plr.y, plr.z, plr.angy*128/math.pi, plr.angx*256/math.pi)) -- set player ID net_send(neth, common.net_pack("BB", PKT_PLR_ID, cli.plrid)) local s = "* Player "..name.." (#"..cli.plrid..", neth "..((neth == true and "(local)") or neth)..") has joined the "..teams[plr.team].name.." team" irc.write(s) local s = "* Player "..name.." has joined the "..teams[plr.team].name.." team" net_broadcast(nil, common.net_pack("BIz", PKT_CHAT_ADD_TEXT, 0xFF800000, s)) end end)) network.sys_handle_c2s(PKT_PLR_GUN_HIT, "BB", nwdec_plrset(function (neth, cli, plr, sec_current, tpid, styp) if not (plr and plr.has_permission("kill")) then return end local tplr = players[tpid] if tplr then if styp >= 1 and styp <= 3 then local tool = plr.tools[plr.tool+1] if tool.hit_player ~= nil then tool.hit_player(tplr, styp) else if tool.get_damage then local dmg, dtype dmg, dtype = tool.get_damage(styp, tplr) if dmg then tplr.wpn_damage(styp, dmg, plr, dtype) end end end end end end)) network.sys_handle_c2s(PKT_PLR_TOOL, "BB", nwdec_plrset(function (neth, cli, plr, sec_current, tpid, tool, pkt) if plr and tool >= 0 and tool <= 3 then plr.tool = tool net_broadcast(neth, common.net_pack("BBB" , PKT_PLR_TOOL, cli.plrid, tool)) end end)) network.sys_handle_c2s(PKT_PLR_BLK_COLOR, "BBBB", nwdec_plrset(function (neth, cli, plr, sec_current, tpid, cr, cg, cb, pkt) if plr then plr.blk_color = {cr,cg,cb} net_broadcast(neth, common.net_pack("BBBBB" , PKT_PLR_BLK_COLOR, cli.plrid, cr, cg, cb)) end end)) network.sys_handle_c2s(PKT_NADE_THROW, "hhhhhhH", nwdec_plrset(function (neth, cli, plr, sec_current, x, y, z, vx, vy, vz, fuse, pkt) if plr.expl_ammo_checkthrow() then local n = new_nade({ x = x/32, y = y/32, z = z/32, vx = vx/256, vy = vy/256, vz = vz/256, fuse = fuse/100, pid = cli.plrid }) nade_add(n) net_broadcast(neth, common.net_pack("BBhhhhhhH", PKT_NADE_THROW,cli.plrid,x,y,z,vx,vy,vz,fuse)) end end)) network.sys_handle_c2s(PKT_PLR_GUN_RELOAD, "", nwdec_plrset(function (neth, cli, plr, sec_current, pkt) net_broadcast(neth, common.net_pack("BB", PKT_PLR_GUN_RELOAD, cli.plrid)) local tool = plr.tools[plr.tool+1] if tool and tool.remote_client_reload then tool.remote_client_reload(fire_type) end end)) network.sys_handle_c2s(PKT_BLK_DAMAGE, "HHHH", nwdec_plrset(function (neth, cli, plr, sec_current, x, y, z, amt, pkt) if not (plr and plr.has_permission("build")) then return end net_broadcast(nil, common.net_pack("BHHHH", PKT_BLK_DAMAGE, x, y, z, amt)) bhealth_damage(x, y, z, amt, plr) end)) network.sys_handle_c2s(PKT_NADE_PIN, "", nwdec_plrset(function (neth, cli, plr, sec_current, pkt) net_broadcast(neth, common.net_pack("BB", PKT_NADE_PIN, cli.plrid)) end)) network.sys_handle_common(PKT_BUILD_BOX, "BhhhhhhBBBB", function (neth, cli, plr, sec_current, typ, x1, y1, z1, x2, y2, z2, cr, cg, cb, ct, pkt) if server then net_broadcast(nil, common.net_pack("BBhhhhhhBBBB", PKT_BUILD_BOX, typ, x1, y1, z1, x2, y2, z2, cr, cg, cb, ct)) end local x,y,z if x1 > x2 then x1, x2 = x2, x1 end if y1 > y2 then y1, y2 = y2, y1 end if z1 > z2 then z1, z2 = z2, z1 end local f = nil if typ == 0 then -- type 0: solid f = function (x,y,z) return true end elseif typ == 1 then -- type 1: hollow f = function (x,y,z) return x==x1 or x==x2 or y==y1 or y==y2 or z==z1 or z==z2 end elseif typ == 2 then -- type 2: walls f = function (x,y,z) return x==x1 or x==x2 or z==z1 or z==z2 end elseif typ == 3 then -- type 3: frame f = function (x,y,z) local xp = (x==x1 or x==x2) local yp = (y==y1 or y==y2) local zp = (z==z1 or z==z2) return (xp and (yp or zp)) or (yp and zp) end end if f then map_cache_start() for x=x1,x2 do for z=z1,z2 do for y=y1,y2 do if f(x,y,z) then map_block_set(x,y,z,ct,cr,cg,cb) end end end end map_cache_end() end end) network.sys_handle_s2c(PKT_PLR_GUN_SHOT, "BB", function (neth, cli, plr, sec_current, pid, fire_type, pkt) local plr = players[pid] if plr then local tool = plr.tools[plr.tool+1] if tool and tool.remote_client_fire then -- For now, we will spawn tracers in this function, but in future we need to sync the tracer directions somehow (either by sharing a seed, or sending the direction of every tracer) tool.remote_client_fire(fire_type) end end end) network.sys_handle_c2s(PKT_PLR_GUN_SHOT, "BB", nwdec_plrset(function (neth, cli, plr, sec_current, pid, fire_type, pkt) if plr then -- Copy-pasted - not sure why we need this check net_broadcast(neth, common.net_pack("BBB", PKT_PLR_GUN_SHOT, cli.plrid, fire_type)) local tool = plr.tools[plr.tool+1] if tool and tool.remote_client_fire then tool.remote_client_fire(fire_type) end end end))