2009-01-11 10:40:14 +00:00
|
|
|
#include <string.h>
|
2008-08-27 15:48:50 +00:00
|
|
|
#include <engine/e_client_interface.h>
|
2008-11-17 16:13:12 +00:00
|
|
|
#include <engine/e_demorec.h>
|
2008-08-30 21:16:58 +00:00
|
|
|
|
2008-08-27 15:48:50 +00:00
|
|
|
#include <game/generated/g_protocol.hpp>
|
2008-08-30 21:16:58 +00:00
|
|
|
#include <game/generated/gc_data.hpp>
|
|
|
|
|
|
|
|
#include <game/layers.hpp>
|
2008-10-20 23:46:39 +00:00
|
|
|
#include "render.hpp"
|
2008-08-27 15:48:50 +00:00
|
|
|
|
|
|
|
#include "gameclient.hpp"
|
2008-08-31 13:36:30 +00:00
|
|
|
|
|
|
|
#include "components/binds.hpp"
|
2008-08-27 15:48:50 +00:00
|
|
|
#include "components/broadcast.hpp"
|
2008-08-31 13:36:30 +00:00
|
|
|
#include "components/camera.hpp"
|
|
|
|
#include "components/chat.hpp"
|
2008-08-27 15:48:50 +00:00
|
|
|
#include "components/console.hpp"
|
2008-08-31 13:36:30 +00:00
|
|
|
#include "components/controls.hpp"
|
|
|
|
#include "components/damageind.hpp"
|
|
|
|
#include "components/debughud.hpp"
|
|
|
|
#include "components/effects.hpp"
|
|
|
|
#include "components/emoticon.hpp"
|
2008-08-27 15:48:50 +00:00
|
|
|
#include "components/flow.hpp"
|
2008-08-31 13:36:30 +00:00
|
|
|
#include "components/hud.hpp"
|
2008-08-27 15:48:50 +00:00
|
|
|
#include "components/items.hpp"
|
2008-08-31 13:36:30 +00:00
|
|
|
#include "components/killmessages.hpp"
|
2008-09-01 05:54:00 +00:00
|
|
|
#include "components/mapimages.hpp"
|
2008-08-27 15:48:50 +00:00
|
|
|
#include "components/maplayers.hpp"
|
2008-08-31 13:36:30 +00:00
|
|
|
#include "components/menus.hpp"
|
|
|
|
#include "components/motd.hpp"
|
|
|
|
#include "components/particles.hpp"
|
|
|
|
#include "components/players.hpp"
|
2008-09-04 18:54:37 +00:00
|
|
|
#include "components/nameplates.hpp"
|
2008-08-27 19:50:33 +00:00
|
|
|
#include "components/scoreboard.hpp"
|
2008-08-31 13:36:30 +00:00
|
|
|
#include "components/skins.hpp"
|
2008-08-29 05:34:18 +00:00
|
|
|
#include "components/sounds.hpp"
|
2008-09-24 14:47:03 +00:00
|
|
|
#include "components/voting.hpp"
|
2008-08-27 15:48:50 +00:00
|
|
|
|
|
|
|
GAMECLIENT gameclient;
|
|
|
|
|
|
|
|
// instanciate all systems
|
|
|
|
static KILLMESSAGES killmessages;
|
|
|
|
static CAMERA camera;
|
|
|
|
static CHAT chat;
|
|
|
|
static MOTD motd;
|
|
|
|
static BROADCAST broadcast;
|
|
|
|
static CONSOLE console;
|
|
|
|
static BINDS binds;
|
|
|
|
static PARTICLES particles;
|
|
|
|
static MENUS menus;
|
|
|
|
static SKINS skins;
|
|
|
|
static FLOW flow;
|
|
|
|
static HUD hud;
|
|
|
|
static DEBUGHUD debughud;
|
|
|
|
static CONTROLS controls;
|
|
|
|
static EFFECTS effects;
|
2008-08-27 19:50:33 +00:00
|
|
|
static SCOREBOARD scoreboard;
|
2008-08-29 05:34:18 +00:00
|
|
|
static SOUNDS sounds;
|
2008-08-30 08:20:06 +00:00
|
|
|
static EMOTICON emoticon;
|
2008-08-31 13:36:30 +00:00
|
|
|
static DAMAGEIND damageind;
|
2008-09-24 14:47:03 +00:00
|
|
|
static VOTING voting;
|
2008-08-27 15:48:50 +00:00
|
|
|
|
|
|
|
static PLAYERS players;
|
2008-09-04 18:54:37 +00:00
|
|
|
static NAMEPLATES nameplates;
|
2008-08-27 15:48:50 +00:00
|
|
|
static ITEMS items;
|
2008-09-01 05:54:00 +00:00
|
|
|
static MAPIMAGES mapimages;
|
2008-08-27 15:48:50 +00:00
|
|
|
|
|
|
|
static MAPLAYERS maplayers_background(MAPLAYERS::TYPE_BACKGROUND);
|
|
|
|
static MAPLAYERS maplayers_foreground(MAPLAYERS::TYPE_FOREGROUND);
|
|
|
|
|
|
|
|
GAMECLIENT::STACK::STACK() { num = 0; }
|
|
|
|
void GAMECLIENT::STACK::add(class COMPONENT *component) { components[num++] = component; }
|
|
|
|
|
2008-08-30 22:38:56 +00:00
|
|
|
static int load_current;
|
|
|
|
static int load_total;
|
2008-08-30 21:16:58 +00:00
|
|
|
|
|
|
|
static void load_sounds_thread(void *do_render)
|
|
|
|
{
|
|
|
|
// load sounds
|
|
|
|
for(int s = 0; s < data->num_sounds; s++)
|
|
|
|
{
|
2008-08-31 21:50:14 +00:00
|
|
|
if(do_render)
|
2008-08-30 22:38:56 +00:00
|
|
|
gameclient.menus->render_loading(load_current/(float)load_total);
|
2008-08-30 21:16:58 +00:00
|
|
|
for(int i = 0; i < data->sounds[s].num_sounds; i++)
|
|
|
|
{
|
|
|
|
int id = snd_load_wv(data->sounds[s].sounds[i].filename);
|
|
|
|
data->sounds[s].sounds[i].id = id;
|
|
|
|
}
|
|
|
|
|
2008-08-30 22:38:56 +00:00
|
|
|
if(do_render)
|
|
|
|
load_current++;
|
2008-08-30 21:16:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-01-24 12:16:02 +00:00
|
|
|
static void con_serverdummy(void *result, void *user_data)
|
|
|
|
{
|
|
|
|
dbg_msg("client", "this command is not available on the client");
|
|
|
|
}
|
|
|
|
|
2008-09-04 21:36:44 +00:00
|
|
|
void GAMECLIENT::on_console_init()
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
|
|
|
// setup pointers
|
|
|
|
binds = &::binds;
|
|
|
|
console = &::console;
|
|
|
|
particles = &::particles;
|
|
|
|
menus = &::menus;
|
|
|
|
skins = &::skins;
|
|
|
|
chat = &::chat;
|
|
|
|
flow = &::flow;
|
|
|
|
camera = &::camera;
|
|
|
|
controls = &::controls;
|
|
|
|
effects = &::effects;
|
2008-08-29 05:34:18 +00:00
|
|
|
sounds = &::sounds;
|
2008-08-30 08:26:36 +00:00
|
|
|
motd = &::motd;
|
2008-08-31 13:36:30 +00:00
|
|
|
damageind = &::damageind;
|
2008-09-01 05:54:00 +00:00
|
|
|
mapimages = &::mapimages;
|
2008-09-24 14:47:03 +00:00
|
|
|
voting = &::voting;
|
2008-08-27 15:48:50 +00:00
|
|
|
|
|
|
|
// make a list of all the systems, make sure to add them in the corrent render order
|
|
|
|
all.add(skins);
|
2008-09-01 05:54:00 +00:00
|
|
|
all.add(mapimages);
|
2008-08-27 15:48:50 +00:00
|
|
|
all.add(effects); // doesn't render anything, just updates effects
|
|
|
|
all.add(particles);
|
|
|
|
all.add(binds);
|
|
|
|
all.add(controls);
|
|
|
|
all.add(camera);
|
2008-08-29 05:34:18 +00:00
|
|
|
all.add(sounds);
|
2008-09-24 14:47:03 +00:00
|
|
|
all.add(voting);
|
2008-08-27 15:48:50 +00:00
|
|
|
all.add(particles); // doesn't render anything, just updates all the particles
|
|
|
|
|
|
|
|
all.add(&maplayers_background); // first to render
|
|
|
|
all.add(&particles->render_trail);
|
|
|
|
all.add(&particles->render_explosions);
|
|
|
|
all.add(&items);
|
|
|
|
all.add(&players);
|
|
|
|
all.add(&maplayers_foreground);
|
2008-09-04 18:54:37 +00:00
|
|
|
all.add(&nameplates);
|
2008-08-27 15:48:50 +00:00
|
|
|
all.add(&particles->render_general);
|
2008-08-31 13:36:30 +00:00
|
|
|
all.add(damageind);
|
2008-08-27 15:48:50 +00:00
|
|
|
all.add(&hud);
|
2008-08-30 08:20:06 +00:00
|
|
|
all.add(&emoticon);
|
2008-08-27 15:48:50 +00:00
|
|
|
all.add(&killmessages);
|
|
|
|
all.add(chat);
|
|
|
|
all.add(&broadcast);
|
|
|
|
all.add(&debughud);
|
2008-08-27 19:50:33 +00:00
|
|
|
all.add(&scoreboard);
|
2008-08-30 08:26:36 +00:00
|
|
|
all.add(motd);
|
2008-08-27 15:48:50 +00:00
|
|
|
all.add(menus);
|
|
|
|
all.add(console);
|
|
|
|
|
|
|
|
// build the input stack
|
2008-10-20 23:10:00 +00:00
|
|
|
input.add(&menus->binder); // this will take over all input when we want to bind a key
|
2008-08-30 09:34:55 +00:00
|
|
|
input.add(&binds->special_binds);
|
2008-08-27 15:48:50 +00:00
|
|
|
input.add(console);
|
2008-08-30 09:28:31 +00:00
|
|
|
input.add(chat); // chat has higher prio due to tha you can quit it by pressing esc
|
2008-08-30 08:26:36 +00:00
|
|
|
input.add(motd); // for pressing esc to remove it
|
2008-08-27 15:48:50 +00:00
|
|
|
input.add(menus);
|
2008-08-30 08:20:06 +00:00
|
|
|
input.add(&emoticon);
|
2008-08-27 15:48:50 +00:00
|
|
|
input.add(controls);
|
|
|
|
input.add(binds);
|
2008-09-04 21:36:44 +00:00
|
|
|
|
|
|
|
// add the some console commands
|
2009-01-24 14:10:26 +00:00
|
|
|
MACRO_REGISTER_COMMAND("team", "i", CFGFLAG_CLIENT, con_team, this, "Switch team");
|
|
|
|
MACRO_REGISTER_COMMAND("kill", "", CFGFLAG_CLIENT, con_kill, this, "Kill yourself");
|
2009-01-24 12:16:02 +00:00
|
|
|
|
|
|
|
// register server dummy commands for tab completion
|
2009-01-24 14:10:26 +00:00
|
|
|
MACRO_REGISTER_COMMAND("tune", "si", CFGFLAG_SERVER, con_serverdummy, 0, "Tune variable to value");
|
|
|
|
MACRO_REGISTER_COMMAND("tune_reset", "", CFGFLAG_SERVER, con_serverdummy, 0, "Reset tuning");
|
|
|
|
MACRO_REGISTER_COMMAND("tune_dump", "", CFGFLAG_SERVER, con_serverdummy, 0, "Dump tuning");
|
|
|
|
MACRO_REGISTER_COMMAND("change_map", "r", CFGFLAG_SERVER, con_serverdummy, 0, "Change map");
|
|
|
|
MACRO_REGISTER_COMMAND("restart", "?i", CFGFLAG_SERVER, con_serverdummy, 0, "Restart in x seconds");
|
|
|
|
MACRO_REGISTER_COMMAND("broadcast", "r", CFGFLAG_SERVER, con_serverdummy, 0, "Broadcast message");
|
2009-01-24 12:16:02 +00:00
|
|
|
/*MACRO_REGISTER_COMMAND("say", "r", CFGFLAG_SERVER, con_serverdummy, 0);*/
|
2009-01-24 14:10:26 +00:00
|
|
|
MACRO_REGISTER_COMMAND("set_team", "ii", CFGFLAG_SERVER, con_serverdummy, 0, "Set team of player to team");
|
|
|
|
MACRO_REGISTER_COMMAND("addvote", "r", CFGFLAG_SERVER, con_serverdummy, 0, "Add a voting option");
|
2009-01-24 12:16:02 +00:00
|
|
|
/*MACRO_REGISTER_COMMAND("vote", "", CFGFLAG_SERVER, con_serverdummy, 0);*/
|
2008-09-23 07:43:41 +00:00
|
|
|
|
|
|
|
// let all the other components register their console commands
|
2008-09-04 21:36:44 +00:00
|
|
|
for(int i = 0; i < all.num; i++)
|
|
|
|
all.components[i]->on_console_init();
|
2008-12-19 11:41:17 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
suppress_events = false;
|
2008-09-04 21:36:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void GAMECLIENT::on_init()
|
|
|
|
{
|
2008-08-27 15:48:50 +00:00
|
|
|
// init all components
|
|
|
|
for(int i = 0; i < all.num; i++)
|
|
|
|
all.components[i]->on_init();
|
2008-08-30 22:38:56 +00:00
|
|
|
|
|
|
|
// setup item sizes
|
|
|
|
for(int i = 0; i < NUM_NETOBJTYPES; i++)
|
|
|
|
snap_set_staticsize(i, netobj_get_size(i));
|
|
|
|
|
|
|
|
int64 start = time_get();
|
|
|
|
|
2009-06-07 14:36:54 +00:00
|
|
|
// load default font
|
|
|
|
static FONT *default_font;
|
2009-06-07 16:06:03 +00:00
|
|
|
//default_font = gfx_font_load("data/fonts/sazanami-gothic.ttf");
|
2009-06-07 14:36:54 +00:00
|
|
|
default_font = gfx_font_load("data/fonts/vera.ttf");
|
|
|
|
gfx_text_set_default_font(default_font);
|
2008-08-30 22:38:56 +00:00
|
|
|
|
|
|
|
config.cl_threadsoundloading = 0;
|
|
|
|
|
|
|
|
// setup load amount
|
|
|
|
load_total = data->num_images;
|
|
|
|
load_current = 0;
|
|
|
|
if(!config.cl_threadsoundloading)
|
|
|
|
load_total += data->num_sounds;
|
|
|
|
|
|
|
|
// load textures
|
|
|
|
for(int i = 0; i < data->num_images; i++)
|
|
|
|
{
|
|
|
|
gameclient.menus->render_loading(load_current/load_total);
|
|
|
|
data->images[i].id = gfx_load_texture(data->images[i].filename, IMG_AUTO, 0);
|
|
|
|
load_current++;
|
|
|
|
}
|
|
|
|
|
|
|
|
::skins.init();
|
|
|
|
|
|
|
|
if(config.cl_threadsoundloading)
|
|
|
|
thread_create(load_sounds_thread, 0);
|
|
|
|
else
|
|
|
|
load_sounds_thread((void*)1);
|
2008-10-08 18:19:45 +00:00
|
|
|
|
|
|
|
for(int i = 0; i < all.num; i++)
|
|
|
|
all.components[i]->on_reset();
|
2008-08-30 22:38:56 +00:00
|
|
|
|
|
|
|
int64 end = time_get();
|
|
|
|
dbg_msg("", "%f.2ms", ((end-start)*1000)/(float)time_freq());
|
|
|
|
|
2009-01-11 10:40:14 +00:00
|
|
|
servermode = SERVERMODE_PURE;
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
|
|
|
|
2008-09-04 21:36:44 +00:00
|
|
|
void GAMECLIENT::on_save()
|
|
|
|
{
|
|
|
|
for(int i = 0; i < all.num; i++)
|
|
|
|
all.components[i]->on_save();
|
|
|
|
}
|
|
|
|
|
2008-08-27 15:48:50 +00:00
|
|
|
void GAMECLIENT::dispatch_input()
|
|
|
|
{
|
|
|
|
// handle mouse movement
|
|
|
|
int x=0, y=0;
|
|
|
|
inp_mouse_relative(&x, &y);
|
2008-09-12 07:20:26 +00:00
|
|
|
if(x || y)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2008-09-12 07:20:26 +00:00
|
|
|
for(int h = 0; h < input.num; h++)
|
|
|
|
{
|
|
|
|
if(input.components[h]->on_mousemove(x, y))
|
|
|
|
break;
|
|
|
|
}
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// handle key presses
|
|
|
|
for(int i = 0; i < inp_num_events(); i++)
|
|
|
|
{
|
|
|
|
INPUT_EVENT e = inp_get_event(i);
|
|
|
|
|
|
|
|
for(int h = 0; h < input.num; h++)
|
|
|
|
{
|
|
|
|
if(input.components[h]->on_input(e))
|
|
|
|
{
|
|
|
|
//dbg_msg("", "%d char=%d key=%d flags=%d", h, e.ch, e.key, e.flags);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// clear all events for this frame
|
|
|
|
inp_clear_events();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int GAMECLIENT::on_snapinput(int *data)
|
|
|
|
{
|
|
|
|
return controls->snapinput(data);
|
|
|
|
}
|
|
|
|
|
|
|
|
void GAMECLIENT::on_connected()
|
|
|
|
{
|
2008-08-30 21:16:58 +00:00
|
|
|
layers_init();
|
|
|
|
col_init();
|
|
|
|
render_tilemap_generate_skip();
|
2008-10-06 18:05:01 +00:00
|
|
|
|
|
|
|
for(int i = 0; i < all.num; i++)
|
2008-10-08 18:19:45 +00:00
|
|
|
{
|
2008-10-06 18:05:01 +00:00
|
|
|
all.components[i]->on_mapload();
|
2008-10-08 18:19:45 +00:00
|
|
|
all.components[i]->on_reset();
|
|
|
|
}
|
2008-08-27 15:48:50 +00:00
|
|
|
|
2009-01-11 10:40:14 +00:00
|
|
|
SERVER_INFO current_server_info;
|
|
|
|
client_serverinfo(¤t_server_info);
|
|
|
|
|
|
|
|
servermode = SERVERMODE_PURE;
|
|
|
|
|
2008-08-27 15:48:50 +00:00
|
|
|
// send the inital info
|
|
|
|
send_info(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void GAMECLIENT::on_reset()
|
|
|
|
{
|
|
|
|
// clear out the invalid pointers
|
|
|
|
last_new_predicted_tick = -1;
|
|
|
|
mem_zero(&gameclient.snap, sizeof(gameclient.snap));
|
|
|
|
|
|
|
|
for(int i = 0; i < MAX_CLIENTS; i++)
|
|
|
|
{
|
|
|
|
clients[i].name[0] = 0;
|
|
|
|
clients[i].skin_id = 0;
|
|
|
|
clients[i].team = 0;
|
|
|
|
clients[i].angle = 0;
|
|
|
|
clients[i].emoticon = 0;
|
|
|
|
clients[i].emoticon_start = -1;
|
|
|
|
clients[i].skin_info.texture = gameclient.skins->get(0)->color_texture;
|
|
|
|
clients[i].skin_info.color_body = vec4(1,1,1,1);
|
|
|
|
clients[i].skin_info.color_feet = vec4(1,1,1,1);
|
|
|
|
clients[i].update_render_info();
|
|
|
|
}
|
|
|
|
|
|
|
|
for(int i = 0; i < all.num; i++)
|
|
|
|
all.components[i]->on_reset();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GAMECLIENT::update_local_character_pos()
|
|
|
|
{
|
2008-10-14 12:11:42 +00:00
|
|
|
if(config.cl_predict && client_state() != CLIENTSTATE_DEMOPLAYBACK)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
|
|
|
if(!snap.local_character || (snap.local_character->health < 0) || (snap.gameobj && snap.gameobj->game_over))
|
|
|
|
{
|
|
|
|
// don't use predicted
|
|
|
|
}
|
|
|
|
else
|
|
|
|
local_character_pos = mix(predicted_prev_char.pos, predicted_char.pos, client_predintratick());
|
|
|
|
}
|
|
|
|
else if(snap.local_character && snap.local_prev_character)
|
|
|
|
{
|
|
|
|
local_character_pos = mix(
|
|
|
|
vec2(snap.local_prev_character->x, snap.local_prev_character->y),
|
|
|
|
vec2(snap.local_character->x, snap.local_character->y), client_intratick());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-10-06 18:05:01 +00:00
|
|
|
|
|
|
|
static void evolve(NETOBJ_CHARACTER *character, int tick)
|
|
|
|
{
|
|
|
|
WORLD_CORE tempworld;
|
|
|
|
CHARACTER_CORE tempcore;
|
|
|
|
mem_zero(&tempcore, sizeof(tempcore));
|
|
|
|
tempcore.world = &tempworld;
|
|
|
|
tempcore.read(character);
|
2008-10-14 12:11:42 +00:00
|
|
|
|
2008-10-06 18:05:01 +00:00
|
|
|
while(character->tick < tick)
|
|
|
|
{
|
|
|
|
character->tick++;
|
|
|
|
tempcore.tick(false);
|
|
|
|
tempcore.move();
|
|
|
|
tempcore.quantize();
|
|
|
|
}
|
2008-11-16 15:10:57 +00:00
|
|
|
|
2008-10-06 18:05:01 +00:00
|
|
|
tempcore.write(character);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-08-27 15:48:50 +00:00
|
|
|
void GAMECLIENT::on_render()
|
|
|
|
{
|
|
|
|
// update the local character position
|
|
|
|
update_local_character_pos();
|
|
|
|
|
|
|
|
// dispatch all input to systems
|
|
|
|
dispatch_input();
|
|
|
|
|
|
|
|
// render all systems
|
|
|
|
for(int i = 0; i < all.num; i++)
|
|
|
|
all.components[i]->on_render();
|
2009-01-11 15:51:43 +00:00
|
|
|
|
|
|
|
// clear new tick flags
|
|
|
|
new_tick = false;
|
|
|
|
new_predicted_tick = false;
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void GAMECLIENT::on_message(int msgtype)
|
|
|
|
{
|
2008-08-29 05:34:18 +00:00
|
|
|
|
|
|
|
// special messages
|
|
|
|
if(msgtype == NETMSGTYPE_SV_EXTRAPROJECTILE)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
int num = msg_unpack_int();
|
|
|
|
|
|
|
|
for(int k = 0; k < num; k++)
|
|
|
|
{
|
|
|
|
NETOBJ_PROJECTILE proj;
|
|
|
|
for(unsigned i = 0; i < sizeof(NETOBJ_PROJECTILE)/sizeof(int); i++)
|
|
|
|
((int *)&proj)[i] = msg_unpack_int();
|
|
|
|
|
|
|
|
if(msg_unpack_error())
|
|
|
|
return;
|
|
|
|
|
|
|
|
if(extraproj_num != MAX_EXTRA_PROJECTILES)
|
|
|
|
{
|
|
|
|
extraproj_projectiles[extraproj_num] = proj;
|
|
|
|
extraproj_num++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return;*/
|
|
|
|
}
|
|
|
|
else if(msgtype == NETMSGTYPE_SV_TUNEPARAMS)
|
|
|
|
{
|
|
|
|
// unpack the new tuning
|
|
|
|
TUNING_PARAMS new_tuning;
|
|
|
|
int *params = (int *)&new_tuning;
|
|
|
|
for(unsigned i = 0; i < sizeof(TUNING_PARAMS)/sizeof(int); i++)
|
|
|
|
params[i] = msg_unpack_int();
|
|
|
|
|
|
|
|
// check for unpacking errors
|
|
|
|
if(msg_unpack_error())
|
|
|
|
return;
|
2009-01-11 10:40:14 +00:00
|
|
|
|
|
|
|
servermode = SERVERMODE_PURE;
|
2008-08-29 05:34:18 +00:00
|
|
|
|
|
|
|
// apply new tuning
|
|
|
|
tuning = new_tuning;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-08-27 15:48:50 +00:00
|
|
|
void *rawmsg = netmsg_secure_unpack(msgtype);
|
|
|
|
if(!rawmsg)
|
|
|
|
{
|
|
|
|
dbg_msg("client", "dropped weird message '%s' (%d), failed on '%s'", netmsg_get_name(msgtype), msgtype, netmsg_failed_on());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: this should be done smarter
|
|
|
|
for(int i = 0; i < all.num; i++)
|
|
|
|
all.components[i]->on_message(msgtype, rawmsg);
|
2008-08-27 20:17:04 +00:00
|
|
|
|
2008-10-08 20:47:56 +00:00
|
|
|
if(msgtype == NETMSGTYPE_SV_READYTOENTER)
|
2008-08-27 20:17:04 +00:00
|
|
|
{
|
|
|
|
client_entergame();
|
|
|
|
}
|
|
|
|
else if (msgtype == NETMSGTYPE_SV_EMOTICON)
|
|
|
|
{
|
|
|
|
NETMSG_SV_EMOTICON *msg = (NETMSG_SV_EMOTICON *)rawmsg;
|
|
|
|
|
|
|
|
// apply
|
|
|
|
clients[msg->cid].emoticon = msg->emoticon;
|
|
|
|
clients[msg->cid].emoticon_start = client_tick();
|
|
|
|
}
|
|
|
|
else if(msgtype == NETMSGTYPE_SV_SOUNDGLOBAL)
|
|
|
|
{
|
2009-01-11 15:51:43 +00:00
|
|
|
if(suppress_events)
|
|
|
|
return;
|
|
|
|
|
2008-08-27 20:17:04 +00:00
|
|
|
NETMSG_SV_SOUNDGLOBAL *msg = (NETMSG_SV_SOUNDGLOBAL *)rawmsg;
|
2008-08-29 05:34:18 +00:00
|
|
|
gameclient.sounds->play(SOUNDS::CHN_GLOBAL, msg->soundid, 1.0f, vec2(0,0));
|
2008-08-27 20:17:04 +00:00
|
|
|
}
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void GAMECLIENT::on_statechange(int new_state, int old_state)
|
|
|
|
{
|
2008-11-17 16:13:12 +00:00
|
|
|
if(demorec_isrecording())
|
|
|
|
demorec_record_stop();
|
|
|
|
|
2008-10-18 10:32:36 +00:00
|
|
|
// reset everything
|
|
|
|
on_reset();
|
2008-10-17 11:23:21 +00:00
|
|
|
|
|
|
|
// then change the state
|
2008-08-27 15:48:50 +00:00
|
|
|
for(int i = 0; i < all.num; i++)
|
|
|
|
all.components[i]->on_statechange(new_state, old_state);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void GAMECLIENT::process_events()
|
|
|
|
{
|
2008-12-19 11:41:17 +00:00
|
|
|
if(suppress_events)
|
|
|
|
return;
|
|
|
|
|
2008-08-27 15:48:50 +00:00
|
|
|
int snaptype = SNAP_CURRENT;
|
|
|
|
int num = snap_num_items(snaptype);
|
|
|
|
for(int index = 0; index < num; index++)
|
|
|
|
{
|
|
|
|
SNAP_ITEM item;
|
|
|
|
const void *data = snap_get_item(snaptype, index, &item);
|
|
|
|
|
|
|
|
if(item.type == NETEVENTTYPE_DAMAGEIND)
|
|
|
|
{
|
|
|
|
NETEVENT_DAMAGEIND *ev = (NETEVENT_DAMAGEIND *)data;
|
|
|
|
gameclient.effects->damage_indicator(vec2(ev->x, ev->y), get_direction(ev->angle));
|
|
|
|
}
|
|
|
|
else if(item.type == NETEVENTTYPE_EXPLOSION)
|
|
|
|
{
|
|
|
|
NETEVENT_EXPLOSION *ev = (NETEVENT_EXPLOSION *)data;
|
|
|
|
gameclient.effects->explosion(vec2(ev->x, ev->y));
|
|
|
|
}
|
2008-10-17 11:23:21 +00:00
|
|
|
else if(item.type == NETEVENTTYPE_HAMMERHIT)
|
|
|
|
{
|
|
|
|
NETEVENT_HAMMERHIT *ev = (NETEVENT_HAMMERHIT *)data;
|
|
|
|
gameclient.effects->hammerhit(vec2(ev->x, ev->y));
|
|
|
|
}
|
2008-08-27 15:48:50 +00:00
|
|
|
else if(item.type == NETEVENTTYPE_SPAWN)
|
|
|
|
{
|
|
|
|
NETEVENT_SPAWN *ev = (NETEVENT_SPAWN *)data;
|
|
|
|
gameclient.effects->playerspawn(vec2(ev->x, ev->y));
|
|
|
|
}
|
|
|
|
else if(item.type == NETEVENTTYPE_DEATH)
|
|
|
|
{
|
|
|
|
NETEVENT_DEATH *ev = (NETEVENT_DEATH *)data;
|
|
|
|
gameclient.effects->playerdeath(vec2(ev->x, ev->y), ev->cid);
|
|
|
|
}
|
|
|
|
else if(item.type == NETEVENTTYPE_SOUNDWORLD)
|
|
|
|
{
|
|
|
|
NETEVENT_SOUNDWORLD *ev = (NETEVENT_SOUNDWORLD *)data;
|
2008-08-29 05:34:18 +00:00
|
|
|
gameclient.sounds->play(SOUNDS::CHN_WORLD, ev->soundid, 1.0f, vec2(ev->x, ev->y));
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void GAMECLIENT::on_snapshot()
|
|
|
|
{
|
2009-01-11 15:51:43 +00:00
|
|
|
new_tick = true;
|
|
|
|
|
2008-08-27 15:48:50 +00:00
|
|
|
// clear out the invalid pointers
|
|
|
|
mem_zero(&gameclient.snap, sizeof(gameclient.snap));
|
2008-09-23 07:43:41 +00:00
|
|
|
snap.local_cid = -1;
|
2008-08-27 15:48:50 +00:00
|
|
|
|
|
|
|
// secure snapshot
|
|
|
|
{
|
|
|
|
int num = snap_num_items(SNAP_CURRENT);
|
|
|
|
for(int index = 0; index < num; index++)
|
|
|
|
{
|
|
|
|
SNAP_ITEM item;
|
|
|
|
void *data = snap_get_item(SNAP_CURRENT, index, &item);
|
|
|
|
if(netobj_validate(item.type, data, item.datasize) != 0)
|
|
|
|
{
|
|
|
|
if(config.debug)
|
|
|
|
dbg_msg("game", "invalidated index=%d type=%d (%s) size=%d id=%d", index, item.type, netobj_get_name(item.type), item.datasize, item.id);
|
|
|
|
snap_invalidate_item(SNAP_CURRENT, index);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
process_events();
|
|
|
|
|
|
|
|
if(config.dbg_stress)
|
|
|
|
{
|
2008-12-19 11:41:17 +00:00
|
|
|
if((client_tick()%100) == 0)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2008-12-19 11:41:17 +00:00
|
|
|
char message[64];
|
|
|
|
int msglen = rand()%(sizeof(message)-1);
|
|
|
|
for(int i = 0; i < msglen; i++)
|
|
|
|
message[i] = 'a'+(rand()%('z'-'a'));
|
|
|
|
message[msglen] = 0;
|
|
|
|
|
2008-08-27 15:48:50 +00:00
|
|
|
NETMSG_CL_SAY msg;
|
2008-12-19 11:41:17 +00:00
|
|
|
msg.team = rand()&1;
|
|
|
|
msg.message = message;
|
2008-08-27 15:48:50 +00:00
|
|
|
msg.pack(MSGFLAG_VITAL);
|
|
|
|
client_send_msg();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-09-23 07:43:41 +00:00
|
|
|
// go trough all the items in the snapshot and gather the info we want
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2008-09-23 07:43:41 +00:00
|
|
|
snap.team_size[0] = snap.team_size[1] = 0;
|
|
|
|
|
2008-08-27 15:48:50 +00:00
|
|
|
int num = snap_num_items(SNAP_CURRENT);
|
|
|
|
for(int i = 0; i < num; i++)
|
|
|
|
{
|
|
|
|
SNAP_ITEM item;
|
|
|
|
const void *data = snap_get_item(SNAP_CURRENT, i, &item);
|
|
|
|
|
2008-10-08 20:47:56 +00:00
|
|
|
if(item.type == NETOBJTYPE_CLIENT_INFO)
|
|
|
|
{
|
|
|
|
const NETOBJ_CLIENT_INFO *info = (const NETOBJ_CLIENT_INFO *)data;
|
|
|
|
int cid = item.id;
|
|
|
|
ints_to_str(&info->name0, 6, clients[cid].name);
|
|
|
|
ints_to_str(&info->skin0, 6, clients[cid].skin_name);
|
|
|
|
|
|
|
|
clients[cid].use_custom_color = info->use_custom_color;
|
|
|
|
clients[cid].color_body = info->color_body;
|
|
|
|
clients[cid].color_feet = info->color_feet;
|
|
|
|
|
|
|
|
// prepare the info
|
|
|
|
if(clients[cid].skin_name[0] == 'x' || clients[cid].skin_name[1] == '_')
|
|
|
|
str_copy(clients[cid].skin_name, "default", 64);
|
|
|
|
|
|
|
|
clients[cid].skin_info.color_body = skins->get_color(clients[cid].color_body);
|
|
|
|
clients[cid].skin_info.color_feet = skins->get_color(clients[cid].color_feet);
|
|
|
|
clients[cid].skin_info.size = 64;
|
|
|
|
|
|
|
|
// find new skin
|
|
|
|
clients[cid].skin_id = gameclient.skins->find(clients[cid].skin_name);
|
|
|
|
if(clients[cid].skin_id < 0)
|
2009-01-21 21:00:06 +00:00
|
|
|
{
|
|
|
|
clients[cid].skin_id = gameclient.skins->find("default");
|
|
|
|
if(clients[cid].skin_id < 0)
|
|
|
|
clients[cid].skin_id = 0;
|
|
|
|
}
|
2008-10-08 20:47:56 +00:00
|
|
|
|
|
|
|
if(clients[cid].use_custom_color)
|
|
|
|
clients[cid].skin_info.texture = gameclient.skins->get(clients[cid].skin_id)->color_texture;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
clients[cid].skin_info.texture = gameclient.skins->get(clients[cid].skin_id)->org_texture;
|
|
|
|
clients[cid].skin_info.color_body = vec4(1,1,1,1);
|
|
|
|
clients[cid].skin_info.color_feet = vec4(1,1,1,1);
|
|
|
|
}
|
|
|
|
|
2009-01-11 14:48:38 +00:00
|
|
|
clients[cid].update_render_info();
|
|
|
|
gameclient.snap.num_players++;
|
2008-10-08 20:47:56 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
else if(item.type == NETOBJTYPE_PLAYER_INFO)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
|
|
|
const NETOBJ_PLAYER_INFO *info = (const NETOBJ_PLAYER_INFO *)data;
|
|
|
|
|
2008-09-23 07:43:41 +00:00
|
|
|
clients[info->cid].team = info->team;
|
|
|
|
snap.player_infos[info->cid] = info;
|
2008-08-27 15:48:50 +00:00
|
|
|
|
|
|
|
if(info->local)
|
|
|
|
{
|
2008-09-23 07:43:41 +00:00
|
|
|
snap.local_cid = item.id;
|
|
|
|
snap.local_info = info;
|
2008-09-09 15:50:41 +00:00
|
|
|
|
|
|
|
if (info->team == -1)
|
2008-09-23 07:43:41 +00:00
|
|
|
snap.spectate = true;
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
2008-09-01 18:17:01 +00:00
|
|
|
|
|
|
|
// calculate team-balance
|
|
|
|
if(info->team != -1)
|
2008-09-23 07:43:41 +00:00
|
|
|
snap.team_size[info->team]++;
|
2008-09-01 18:17:01 +00:00
|
|
|
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
2008-09-23 07:43:41 +00:00
|
|
|
else if(item.type == NETOBJTYPE_CHARACTER)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2008-09-23 07:43:41 +00:00
|
|
|
const void *old = snap_find_item(SNAP_PREV, NETOBJTYPE_CHARACTER, item.id);
|
|
|
|
if(old)
|
|
|
|
{
|
|
|
|
snap.characters[item.id].active = true;
|
|
|
|
snap.characters[item.id].prev = *((const NETOBJ_CHARACTER *)old);
|
|
|
|
snap.characters[item.id].cur = *((const NETOBJ_CHARACTER *)data);
|
2009-01-11 15:51:43 +00:00
|
|
|
|
2008-09-23 07:43:41 +00:00
|
|
|
if(snap.characters[item.id].prev.tick)
|
|
|
|
evolve(&snap.characters[item.id].prev, client_prevtick());
|
|
|
|
if(snap.characters[item.id].cur.tick)
|
|
|
|
evolve(&snap.characters[item.id].cur, client_tick());
|
|
|
|
}
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
2008-09-23 07:43:41 +00:00
|
|
|
else if(item.type == NETOBJTYPE_GAME)
|
|
|
|
snap.gameobj = (NETOBJ_GAME *)data;
|
|
|
|
else if(item.type == NETOBJTYPE_FLAG)
|
|
|
|
snap.flags[item.id%2] = (const NETOBJ_FLAG *)data;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// setup local pointers
|
|
|
|
if(snap.local_cid >= 0)
|
|
|
|
{
|
|
|
|
SNAPSTATE::CHARACTERINFO *c = &snap.characters[snap.local_cid];
|
|
|
|
if(c->active)
|
|
|
|
{
|
|
|
|
snap.local_character = &c->cur;
|
|
|
|
snap.local_prev_character = &c->prev;
|
|
|
|
local_character_pos = vec2(snap.local_character->x, snap.local_character->y);
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
|
|
|
}
|
2008-11-16 13:58:27 +00:00
|
|
|
else
|
|
|
|
snap.spectate = true;
|
2009-01-11 10:40:14 +00:00
|
|
|
|
|
|
|
TUNING_PARAMS standard_tuning;
|
|
|
|
SERVER_INFO current_server_info;
|
|
|
|
client_serverinfo(¤t_server_info);
|
|
|
|
if(current_server_info.gametype[0] != '0')
|
|
|
|
{
|
|
|
|
if(strcmp(current_server_info.gametype, "DM") != 0 && strcmp(current_server_info.gametype, "TDM") != 0 && strcmp(current_server_info.gametype, "CTF") != 0)
|
|
|
|
servermode = SERVERMODE_MOD;
|
|
|
|
else if(memcmp(&standard_tuning, &tuning, sizeof(TUNING_PARAMS)) == 0)
|
|
|
|
servermode = SERVERMODE_PURE;
|
|
|
|
else
|
|
|
|
servermode = SERVERMODE_PUREMOD;
|
|
|
|
}
|
|
|
|
|
2008-08-27 15:48:50 +00:00
|
|
|
|
2008-09-23 07:43:41 +00:00
|
|
|
// update render info
|
2008-08-27 15:48:50 +00:00
|
|
|
for(int i = 0; i < MAX_CLIENTS; i++)
|
2008-09-23 07:43:41 +00:00
|
|
|
clients[i].update_render_info();
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void GAMECLIENT::on_predict()
|
|
|
|
{
|
2008-09-23 07:43:41 +00:00
|
|
|
// store the previous values so we can detect prediction errors
|
2008-08-27 15:48:50 +00:00
|
|
|
CHARACTER_CORE before_prev_char = predicted_prev_char;
|
|
|
|
CHARACTER_CORE before_char = predicted_char;
|
|
|
|
|
2008-09-23 07:43:41 +00:00
|
|
|
// we can't predict without our own id or own character
|
|
|
|
if(snap.local_cid == -1 || !snap.characters[snap.local_cid].active)
|
|
|
|
return;
|
2008-11-16 15:10:57 +00:00
|
|
|
|
|
|
|
// don't predict anything if we are paused
|
|
|
|
if(snap.gameobj && snap.gameobj->paused)
|
|
|
|
{
|
|
|
|
if(snap.local_character)
|
|
|
|
predicted_char.read(snap.local_character);
|
|
|
|
if(snap.local_prev_character)
|
|
|
|
predicted_prev_char.read(snap.local_prev_character);
|
|
|
|
return;
|
|
|
|
}
|
2008-09-23 07:43:41 +00:00
|
|
|
|
2008-08-27 15:48:50 +00:00
|
|
|
// repredict character
|
|
|
|
WORLD_CORE world;
|
|
|
|
world.tuning = tuning;
|
|
|
|
|
|
|
|
// search for players
|
2008-09-23 07:43:41 +00:00
|
|
|
for(int i = 0; i < MAX_CLIENTS; i++)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2008-09-23 07:43:41 +00:00
|
|
|
if(!snap.characters[i].active)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
gameclient.clients[i].predicted.world = &world;
|
|
|
|
world.characters[i] = &gameclient.clients[i].predicted;
|
|
|
|
gameclient.clients[i].predicted.read(&snap.characters[i].cur);
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// predict
|
|
|
|
for(int tick = client_tick()+1; tick <= client_predtick(); tick++)
|
|
|
|
{
|
|
|
|
// fetch the local
|
2008-09-23 07:43:41 +00:00
|
|
|
if(tick == client_predtick() && world.characters[snap.local_cid])
|
|
|
|
predicted_prev_char = *world.characters[snap.local_cid];
|
2008-08-27 15:48:50 +00:00
|
|
|
|
|
|
|
// first calculate where everyone should move
|
|
|
|
for(int c = 0; c < MAX_CLIENTS; c++)
|
|
|
|
{
|
|
|
|
if(!world.characters[c])
|
|
|
|
continue;
|
|
|
|
|
|
|
|
mem_zero(&world.characters[c]->input, sizeof(world.characters[c]->input));
|
2008-09-23 07:43:41 +00:00
|
|
|
if(snap.local_cid == c)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
|
|
|
// apply player input
|
|
|
|
int *input = client_get_input(tick);
|
|
|
|
if(input)
|
|
|
|
world.characters[c]->input = *((NETOBJ_PLAYER_INPUT*)input);
|
2008-09-23 07:43:41 +00:00
|
|
|
world.characters[c]->tick(true);
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
2008-09-23 07:43:41 +00:00
|
|
|
else
|
|
|
|
world.characters[c]->tick(false);
|
2008-08-27 15:48:50 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// move all players and quantize their data
|
|
|
|
for(int c = 0; c < MAX_CLIENTS; c++)
|
|
|
|
{
|
|
|
|
if(!world.characters[c])
|
|
|
|
continue;
|
|
|
|
|
|
|
|
world.characters[c]->move();
|
|
|
|
world.characters[c]->quantize();
|
|
|
|
}
|
|
|
|
|
2008-09-23 07:43:41 +00:00
|
|
|
// check if we want to trigger effects
|
2008-08-27 15:48:50 +00:00
|
|
|
if(tick > last_new_predicted_tick)
|
|
|
|
{
|
|
|
|
last_new_predicted_tick = tick;
|
2009-01-11 15:51:43 +00:00
|
|
|
new_predicted_tick = true;
|
2008-08-27 15:48:50 +00:00
|
|
|
|
2008-09-23 07:43:41 +00:00
|
|
|
if(snap.local_cid != -1 && world.characters[snap.local_cid])
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2008-09-23 07:43:41 +00:00
|
|
|
vec2 pos = world.characters[snap.local_cid]->pos;
|
|
|
|
int events = world.characters[snap.local_cid]->triggered_events;
|
2009-01-11 15:51:43 +00:00
|
|
|
if(events&COREEVENT_GROUND_JUMP) gameclient.sounds->play_and_record(SOUNDS::CHN_WORLD, SOUND_PLAYER_JUMP, 1.0f, pos);
|
|
|
|
|
|
|
|
/*if(events&COREEVENT_AIR_JUMP)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
|
|
|
gameclient.effects->air_jump(pos);
|
2009-01-11 15:51:43 +00:00
|
|
|
gameclient.sounds->play_and_record(SOUNDS::CHN_WORLD, SOUND_PLAYER_AIRJUMP, 1.0f, pos);
|
|
|
|
}*/
|
|
|
|
|
2008-08-27 15:48:50 +00:00
|
|
|
//if(events&COREEVENT_HOOK_LAUNCH) snd_play_random(CHN_WORLD, SOUND_HOOK_LOOP, 1.0f, pos);
|
|
|
|
//if(events&COREEVENT_HOOK_ATTACH_PLAYER) snd_play_random(CHN_WORLD, SOUND_HOOK_ATTACH_PLAYER, 1.0f, pos);
|
2009-01-11 15:51:43 +00:00
|
|
|
if(events&COREEVENT_HOOK_ATTACH_GROUND) gameclient.sounds->play_and_record(SOUNDS::CHN_WORLD, SOUND_HOOK_ATTACH_GROUND, 1.0f, pos);
|
|
|
|
if(events&COREEVENT_HOOK_HIT_NOHOOK) gameclient.sounds->play_and_record(SOUNDS::CHN_WORLD, SOUND_HOOK_NOATTACH, 1.0f, pos);
|
2008-08-27 15:48:50 +00:00
|
|
|
//if(events&COREEVENT_HOOK_RETRACT) snd_play_random(CHN_WORLD, SOUND_PLAYER_JUMP, 1.0f, pos);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-09-23 07:43:41 +00:00
|
|
|
if(tick == client_predtick() && world.characters[snap.local_cid])
|
|
|
|
predicted_char = *world.characters[snap.local_cid];
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
|
|
|
|
2008-09-23 07:43:41 +00:00
|
|
|
if(config.debug && config.cl_predict && predicted_tick == client_predtick())
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2008-11-15 13:29:32 +00:00
|
|
|
NETOBJ_CHARACTER_CORE before = {0}, now = {0}, before_prev = {0}, now_prev = {0};
|
2008-09-23 07:43:41 +00:00
|
|
|
before_char.write(&before);
|
2008-11-15 13:29:32 +00:00
|
|
|
before_prev_char.write(&before_prev);
|
2008-09-23 07:43:41 +00:00
|
|
|
predicted_char.write(&now);
|
2008-11-15 13:29:32 +00:00
|
|
|
predicted_prev_char.write(&now_prev);
|
2008-08-27 15:48:50 +00:00
|
|
|
|
2008-09-23 07:43:41 +00:00
|
|
|
if(mem_comp(&before, &now, sizeof(NETOBJ_CHARACTER_CORE)) != 0)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2008-09-23 07:43:41 +00:00
|
|
|
dbg_msg("client", "prediction error");
|
|
|
|
for(unsigned i = 0; i < sizeof(NETOBJ_CHARACTER_CORE)/sizeof(int); i++)
|
|
|
|
if(((int *)&before)[i] != ((int *)&now)[i])
|
|
|
|
{
|
2008-11-15 13:29:32 +00:00
|
|
|
dbg_msg("", "\t%d %d %d (%d %d)", i, ((int *)&before)[i], ((int *)&now)[i], ((int *)&before_prev)[i], ((int *)&now_prev)[i]);
|
2008-09-23 07:43:41 +00:00
|
|
|
}
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
predicted_tick = client_predtick();
|
|
|
|
}
|
|
|
|
|
|
|
|
void GAMECLIENT::CLIENT_DATA::update_render_info()
|
|
|
|
{
|
|
|
|
render_info = skin_info;
|
|
|
|
|
|
|
|
// force team colors
|
|
|
|
if(gameclient.snap.gameobj && gameclient.snap.gameobj->flags&GAMEFLAG_TEAMS)
|
|
|
|
{
|
|
|
|
const int team_colors[2] = {65387, 10223467};
|
|
|
|
if(team >= 0 || team <= 1)
|
|
|
|
{
|
|
|
|
render_info.texture = gameclient.skins->get(skin_id)->color_texture;
|
|
|
|
render_info.color_body = gameclient.skins->get_color(team_colors[team]);
|
|
|
|
render_info.color_feet = gameclient.skins->get_color(team_colors[team]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void GAMECLIENT::send_switch_team(int team)
|
|
|
|
{
|
|
|
|
NETMSG_CL_SETTEAM msg;
|
|
|
|
msg.team = team;
|
|
|
|
msg.pack(MSGFLAG_VITAL);
|
|
|
|
client_send_msg();
|
|
|
|
}
|
|
|
|
|
|
|
|
void GAMECLIENT::send_info(bool start)
|
|
|
|
{
|
|
|
|
if(start)
|
|
|
|
{
|
|
|
|
NETMSG_CL_STARTINFO msg;
|
|
|
|
msg.name = config.player_name;
|
|
|
|
msg.skin = config.player_skin;
|
|
|
|
msg.use_custom_color = config.player_use_custom_color;
|
|
|
|
msg.color_body = config.player_color_body;
|
|
|
|
msg.color_feet = config.player_color_feet;
|
2008-10-19 09:10:55 +00:00
|
|
|
msg.pack(MSGFLAG_VITAL);
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
NETMSG_CL_CHANGEINFO msg;
|
|
|
|
msg.name = config.player_name;
|
|
|
|
msg.skin = config.player_skin;
|
|
|
|
msg.use_custom_color = config.player_use_custom_color;
|
|
|
|
msg.color_body = config.player_color_body;
|
|
|
|
msg.color_feet = config.player_color_feet;
|
|
|
|
msg.pack(MSGFLAG_VITAL);
|
|
|
|
}
|
|
|
|
client_send_msg();
|
|
|
|
}
|
|
|
|
|
|
|
|
void GAMECLIENT::send_kill(int client_id)
|
|
|
|
{
|
|
|
|
NETMSG_CL_KILL msg;
|
|
|
|
msg.pack(MSGFLAG_VITAL);
|
|
|
|
client_send_msg();
|
|
|
|
}
|
2008-08-31 13:36:30 +00:00
|
|
|
|
|
|
|
void GAMECLIENT::con_team(void *result, void *user_data)
|
|
|
|
{
|
|
|
|
((GAMECLIENT*)user_data)->send_switch_team(console_arg_int(result, 0));
|
|
|
|
}
|
|
|
|
|
|
|
|
void GAMECLIENT::con_kill(void *result, void *user_data)
|
|
|
|
{
|
|
|
|
((GAMECLIENT*)user_data)->send_kill(-1);
|
|
|
|
}
|