📄 sv_main.java
字号:
* This has to be done before the world logic, because player processing * happens outside RunWorldFrame. */ public static void SV_PrepWorldFrame() { edict_t ent; int i; for (i = 0; i < GameBase.num_edicts; i++) { ent = GameBase.g_edicts[i]; // events only last for a single message ent.s.event = 0; } } /** * SV_RunGameFrame. */ public static void SV_RunGameFrame() { if (Globals.host_speeds.value != 0) Globals.time_before_game = Timer.Milliseconds(); // we always need to bump framenum, even if we // don't run the world, otherwise the delta // compression can get confused when a client // has the "current" frame SV_INIT.sv.framenum++; SV_INIT.sv.time = SV_INIT.sv.framenum * 100; // don't run if paused if (0 == SV_MAIN.sv_paused.value || SV_MAIN.maxclients.value > 1) { GameBase.G_RunFrame(); // never get more than one tic behind if (SV_INIT.sv.time < SV_INIT.svs.realtime) { if (SV_MAIN.sv_showclamp.value != 0) Com.Printf("sv highclamp\n"); SV_INIT.svs.realtime = SV_INIT.sv.time; } } if (Globals.host_speeds.value != 0) Globals.time_after_game = Timer.Milliseconds(); } /** * SV_Frame. */ public static void SV_Frame(long msec) { Globals.time_before_game = Globals.time_after_game = 0; // if server is not active, do nothing if (!SV_INIT.svs.initialized) return; SV_INIT.svs.realtime += msec; // keep the random time dependent Lib.rand(); // check timeouts SV_CheckTimeouts(); // get packets from clients SV_ReadPackets(); //if (Game.g_edicts[1] !=null) // Com.p("player at:" + Lib.vtofsbeaty(Game.g_edicts[1].s.origin )); // move autonomous things around if enough time has passed if (0 == SV_MAIN.sv_timedemo.value && SV_INIT.svs.realtime < SV_INIT.sv.time) { // never let the time get too far off if (SV_INIT.sv.time - SV_INIT.svs.realtime > 100) { if (SV_MAIN.sv_showclamp.value != 0) Com.Printf("sv lowclamp\n"); SV_INIT.svs.realtime = SV_INIT.sv.time - 100; } NET.Sleep(SV_INIT.sv.time - SV_INIT.svs.realtime); return; } // update ping based on the last known frame from all clients SV_CalcPings(); // give the clients some timeslices SV_GiveMsec(); // let everything in the world think and move SV_RunGameFrame(); // send messages back to the clients that had packets read this frame SV_SEND.SV_SendClientMessages(); // save the entire world state if recording a serverdemo SV_ENTS.SV_RecordDemoMessage(); // send a heartbeat to the master if needed Master_Heartbeat(); // clear teleport flags, etc for next frame SV_PrepWorldFrame(); } public static void Master_Heartbeat() { String string; int i; // pgm post3.19 change, cvar pointer not validated before dereferencing if (Globals.dedicated == null || 0 == Globals.dedicated.value) return; // only dedicated servers send heartbeats // pgm post3.19 change, cvar pointer not validated before dereferencing if (null == SV_MAIN.public_server || 0 == SV_MAIN.public_server.value) return; // a private dedicated game // check for time wraparound if (SV_INIT.svs.last_heartbeat > SV_INIT.svs.realtime) SV_INIT.svs.last_heartbeat = SV_INIT.svs.realtime; if (SV_INIT.svs.realtime - SV_INIT.svs.last_heartbeat < SV_MAIN.HEARTBEAT_SECONDS * 1000) return; // not time to send yet SV_INIT.svs.last_heartbeat = SV_INIT.svs.realtime; // send the same string that we would give for a status OOB command string = SV_StatusString(); // send to group master for (i = 0; i < Defines.MAX_MASTERS; i++) if (SV_MAIN.master_adr[i].port != 0) { Com.Printf("Sending heartbeat to " + NET.AdrToString(SV_MAIN.master_adr[i]) + "\n"); Netchan.OutOfBandPrint(Defines.NS_SERVER, SV_MAIN.master_adr[i], "heartbeat\n" + string); } } /** * Master_Shutdown, Informs all masters that this server is going down. */ public static void Master_Shutdown() { int i; // pgm post3.19 change, cvar pointer not validated before dereferencing if (null == Globals.dedicated || 0 == Globals.dedicated.value) return; // only dedicated servers send heartbeats // pgm post3.19 change, cvar pointer not validated before dereferencing if (null == SV_MAIN.public_server || 0 == SV_MAIN.public_server.value) return; // a private dedicated game // send to group master for (i = 0; i < Defines.MAX_MASTERS; i++) if (SV_MAIN.master_adr[i].port != 0) { if (i > 0) Com.Printf("Sending heartbeat to " + NET.AdrToString(SV_MAIN.master_adr[i]) + "\n"); Netchan.OutOfBandPrint(Defines.NS_SERVER, SV_MAIN.master_adr[i], "shutdown"); } } /** * Pull specific info from a newly changed userinfo string into a more C * freindly form. */ public static void SV_UserinfoChanged(client_t cl) { String val; int i; // call prog code to allow overrides PlayerClient.ClientUserinfoChanged(cl.edict, cl.userinfo); // name for C code cl.name = Info.Info_ValueForKey(cl.userinfo, "name"); // mask off high bit //TODO: masking for german umlaute //for (i=0 ; i<sizeof(cl.name) ; i++) // cl.name[i] &= 127; // rate command val = Info.Info_ValueForKey(cl.userinfo, "rate"); if (val.length() > 0) { i = Lib.atoi(val); cl.rate = i; if (cl.rate < 100) cl.rate = 100; if (cl.rate > 15000) cl.rate = 15000; } else cl.rate = 5000; // msg command val = Info.Info_ValueForKey(cl.userinfo, "msg"); if (val.length() > 0) { cl.messagelevel = Lib.atoi(val); } } /** * Only called at quake2.exe startup, not for each game */ public static void SV_Init() { SV_CCMDS.SV_InitOperatorCommands(); //ok. SV_MAIN.rcon_password = Cvar.Get("rcon_password", "", 0); Cvar.Get("skill", "1", 0); Cvar.Get("deathmatch", "0", Defines.CVAR_LATCH); Cvar.Get("coop", "0", Defines.CVAR_LATCH); Cvar.Get("dmflags", "" + Defines.DF_INSTANT_ITEMS, Defines.CVAR_SERVERINFO); Cvar.Get("fraglimit", "0", Defines.CVAR_SERVERINFO); Cvar.Get("timelimit", "0", Defines.CVAR_SERVERINFO); Cvar.Get("cheats", "0", Defines.CVAR_SERVERINFO | Defines.CVAR_LATCH); Cvar.Get("protocol", "" + Defines.PROTOCOL_VERSION, Defines.CVAR_SERVERINFO | Defines.CVAR_NOSET); SV_MAIN.maxclients = Cvar.Get("maxclients", "1", Defines.CVAR_SERVERINFO | Defines.CVAR_LATCH); SV_MAIN.hostname = Cvar.Get("hostname", "noname", Defines.CVAR_SERVERINFO | Defines.CVAR_ARCHIVE); SV_MAIN.timeout = Cvar.Get("timeout", "125", 0); SV_MAIN.zombietime = Cvar.Get("zombietime", "2", 0); SV_MAIN.sv_showclamp = Cvar.Get("showclamp", "0", 0); SV_MAIN.sv_paused = Cvar.Get("paused", "0", 0); SV_MAIN.sv_timedemo = Cvar.Get("timedemo", "0", 0); SV_MAIN.sv_enforcetime = Cvar.Get("sv_enforcetime", "0", 0); SV_MAIN.allow_download = Cvar.Get("allow_download", "1", Defines.CVAR_ARCHIVE); SV_MAIN.allow_download_players = Cvar.Get("allow_download_players", "0", Defines.CVAR_ARCHIVE); SV_MAIN.allow_download_models = Cvar.Get("allow_download_models", "1", Defines.CVAR_ARCHIVE); SV_MAIN.allow_download_sounds = Cvar.Get("allow_download_sounds", "1", Defines.CVAR_ARCHIVE); SV_MAIN.allow_download_maps = Cvar.Get("allow_download_maps", "1", Defines.CVAR_ARCHIVE); SV_MAIN.sv_noreload = Cvar.Get("sv_noreload", "0", 0); SV_MAIN.sv_airaccelerate = Cvar.Get("sv_airaccelerate", "0", Defines.CVAR_LATCH); SV_MAIN.public_server = Cvar.Get("public", "0", 0); SV_MAIN.sv_reconnect_limit = Cvar.Get("sv_reconnect_limit", "3", Defines.CVAR_ARCHIVE); SZ.Init(Globals.net_message, Globals.net_message_buffer, Globals.net_message_buffer.length); } /** * Used by SV_Shutdown to send a final message to all connected clients * before the server goes down. The messages are sent immediately, not just * stuck on the outgoing message list, because the server is going to * totally exit after returning from this function. */ public static void SV_FinalMessage(String message, boolean reconnect) { int i; client_t cl; SZ.Clear(Globals.net_message); MSG.WriteByte(Globals.net_message, Defines.svc_print); MSG.WriteByte(Globals.net_message, Defines.PRINT_HIGH); MSG.WriteString(Globals.net_message, message); if (reconnect) MSG.WriteByte(Globals.net_message, Defines.svc_reconnect); else MSG.WriteByte(Globals.net_message, Defines.svc_disconnect); // send it twice // stagger the packets to crutch operating system limited buffers for (i = 0; i < SV_INIT.svs.clients.length; i++) { cl = SV_INIT.svs.clients[i]; if (cl.state >= Defines.cs_connected) Netchan.Transmit(cl.netchan, Globals.net_message.cursize, Globals.net_message.data); } for (i = 0; i < SV_INIT.svs.clients.length; i++) { cl = SV_INIT.svs.clients[i]; if (cl.state >= Defines.cs_connected) Netchan.Transmit(cl.netchan, Globals.net_message.cursize, Globals.net_message.data); } } /** * Called when each game quits, before Sys_Quit or Sys_Error. */ public static void SV_Shutdown(String finalmsg, boolean reconnect) { if (SV_INIT.svs.clients != null) SV_FinalMessage(finalmsg, reconnect); Master_Shutdown(); SV_GAME.SV_ShutdownGameProgs(); // free current level if (SV_INIT.sv.demofile != null) try { SV_INIT.sv.demofile.close(); } catch (IOException e) { e.printStackTrace(); } SV_INIT.sv = new server_t(); Globals.server_state = SV_INIT.sv.state; if (SV_INIT.svs.demofile != null) try { SV_INIT.svs.demofile.close(); } catch (IOException e1) { e1.printStackTrace(); } SV_INIT.svs = new server_static_t(); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -