📄 sv_ccmds.java
字号:
/*Copyright (C) 1997-2001 Id Software, Inc.This program is free software; you can redistribute it and/ormodify it under the terms of the GNU General Public Licenseas published by the Free Software Foundation; either version 2of the License, or (at your option) any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*/// Created on 18.01.2004 by RST.// $Id: SV_CCMDS.java,v 1.15 2005/12/03 19:45:42 salomo Exp $package jake2.server;import jake2.Defines;import jake2.Globals;import jake2.game.Cmd;import jake2.game.EndianHandler;import jake2.game.GameSVCmds;import jake2.game.GameSave;import jake2.game.Info;import jake2.game.cvar_t;import jake2.qcommon.CM;import jake2.qcommon.Com;import jake2.qcommon.Cvar;import jake2.qcommon.FS;import jake2.qcommon.MSG;import jake2.qcommon.Netchan;import jake2.qcommon.SZ;import jake2.qcommon.netadr_t;import jake2.qcommon.sizebuf_t;import jake2.qcommon.xcommand_t;import jake2.sys.NET;import jake2.sys.Sys;import jake2.util.Lib;import jake2.util.QuakeFile;import jake2.util.Vargs;import java.io.File;import java.io.FileNotFoundException;import java.io.IOException;import java.io.RandomAccessFile;import java.util.Calendar;public class SV_CCMDS { /* =============================================================================== OPERATOR CONSOLE ONLY COMMANDS These commands can only be entered from stdin or by a remote operator datagram =============================================================================== */ /* ==================== SV_SetMaster_f Specify a list of master servers ==================== */ public static void SV_SetMaster_f() { int i, slot; // only dedicated servers send heartbeats if (Globals.dedicated.value == 0) { Com.Printf("Only dedicated servers use masters.\n"); return; } // make sure the server is listed public Cvar.Set("public", "1"); for (i = 1; i < Defines.MAX_MASTERS; i++) SV_MAIN.master_adr[i] = new netadr_t(); slot = 1; // slot 0 will always contain the id master for (i = 1; i < Cmd.Argc(); i++) { if (slot == Defines.MAX_MASTERS) break; if (!NET.StringToAdr(Cmd.Argv(i), SV_MAIN.master_adr[i])) { Com.Printf("Bad address: " + Cmd.Argv(i) + "\n"); continue; } if (SV_MAIN.master_adr[slot].port == 0) SV_MAIN.master_adr[slot].port = Defines.PORT_MASTER; Com.Printf("Master server at " + NET.AdrToString(SV_MAIN.master_adr[slot]) + "\n"); Com.Printf("Sending a ping.\n"); Netchan.OutOfBandPrint(Defines.NS_SERVER, SV_MAIN.master_adr[slot], "ping"); slot++; } SV_INIT.svs.last_heartbeat = -9999999; } /* ================== SV_SetPlayer Sets sv_client and sv_player to the player with idnum Cmd.Argv(1) ================== */ public static boolean SV_SetPlayer() { client_t cl; int i; int idnum; String s; if (Cmd.Argc() < 2) return false; s = Cmd.Argv(1); // numeric values are just slot numbers if (s.charAt(0) >= '0' && s.charAt(0) <= '9') { idnum = Lib.atoi(Cmd.Argv(1)); if (idnum < 0 || idnum >= SV_MAIN.maxclients.value) { Com.Printf("Bad client slot: " + idnum + "\n"); return false; } SV_MAIN.sv_client = SV_INIT.svs.clients[idnum]; SV_USER.sv_player = SV_MAIN.sv_client.edict; if (0 == SV_MAIN.sv_client.state) { Com.Printf("Client " + idnum + " is not active\n"); return false; } return true; } // check for a name match for (i = 0; i < SV_MAIN.maxclients.value; i++) { cl = SV_INIT.svs.clients[i]; if (0 == cl.state) continue; if (0 == Lib.strcmp(cl.name, s)) { SV_MAIN.sv_client = cl; SV_USER.sv_player = SV_MAIN.sv_client.edict; return true; } } Com.Printf("Userid " + s + " is not on the server\n"); return false; } /* =============================================================================== SAVEGAME FILES =============================================================================== */ public static void remove(String name) { try { new File(name).delete(); } catch (Exception e) { } } /** Delete save files save/(number)/. */ public static void SV_WipeSavegame(String savename) { String name, s; Com.DPrintf("SV_WipeSaveGame(" + savename + ")\n"); name = FS.Gamedir() + "/save/" + savename + "/server.ssv"; remove(name); name = FS.Gamedir() + "/save/" + savename + "/game.ssv"; remove(name); name = FS.Gamedir() + "/save/" + savename + "/*.sav"; File f = Sys.FindFirst(name, 0, 0); while (f != null) { f.delete(); f = Sys.FindNext(); } Sys.FindClose(); name = FS.Gamedir() + "/save/" + savename + "/*.sv2"; f = Sys.FindFirst(name, 0, 0); while (f != null) { f.delete(); f = Sys.FindNext(); } Sys.FindClose(); } /* ================ CopyFile ================ */ public static void CopyFile(String src, String dst) { RandomAccessFile f1, f2; int l = -1; byte buffer[] = new byte[65536]; //Com.DPrintf("CopyFile (" + src + ", " + dst + ")\n"); try { f1 = new RandomAccessFile(src, "r"); } catch (Exception e) { return; } try { f2 = new RandomAccessFile(dst, "rw"); } catch (Exception e) { try { f1.close(); } catch (IOException e1) { e1.printStackTrace(); } return; } while (true) { try { l = f1.read(buffer, 0, 65536); } catch (IOException e1) { e1.printStackTrace(); } if (l == -1) break; try { f2.write(buffer, 0, l); } catch (IOException e2) { e2.printStackTrace(); } } try { f1.close(); } catch (IOException e1) { e1.printStackTrace(); } try { f2.close(); } catch (IOException e2) { e2.printStackTrace(); } } /* ================ SV_CopySaveGame ================ */ public static void SV_CopySaveGame(String src, String dst) { //char name[MAX_OSPATH], name2[MAX_OSPATH]; int l, len; File found; String name, name2; Com.DPrintf("SV_CopySaveGame(" + src + "," + dst + ")\n"); SV_WipeSavegame(dst); // copy the savegame over name = FS.Gamedir() + "/save/" + src + "/server.ssv"; name2 = FS.Gamedir() + "/save/" + dst + "/server.ssv"; FS.CreatePath(name2); CopyFile(name, name2); name = FS.Gamedir() + "/save/" + src + "/game.ssv"; name2 = FS.Gamedir() + "/save/" + dst + "/game.ssv"; CopyFile(name, name2); String name1 = FS.Gamedir() + "/save/" + src + "/"; len = name1.length(); name = FS.Gamedir() + "/save/" + src + "/*.sav"; found = Sys.FindFirst(name, 0, 0); while (found != null) { name = name1 + found.getName(); name2 = FS.Gamedir() + "/save/" + dst + "/" + found.getName(); CopyFile(name, name2); // change sav to sv2 name = name.substring(0, name.length() - 3) + "sv2"; name2 = name2.substring(0, name2.length() - 3) + "sv2"; CopyFile(name, name2); found = Sys.FindNext(); } Sys.FindClose(); } /* ============== SV_WriteLevelFile ============== */ public static void SV_WriteLevelFile() { String name; QuakeFile f; Com.DPrintf("SV_WriteLevelFile()\n"); name = FS.Gamedir() + "/save/current/" + SV_INIT.sv.name + ".sv2"; try { f = new QuakeFile(name, "rw"); for (int i = 0; i < Defines.MAX_CONFIGSTRINGS; i++) f.writeString(SV_INIT.sv.configstrings[i]); CM.CM_WritePortalState(f); f.close(); } catch (Exception e) { Com.Printf("Failed to open " + name + "\n"); e.printStackTrace(); } name = FS.Gamedir() + "/save/current/" + SV_INIT.sv.name + ".sav"; GameSave.WriteLevel(name); } /* ============== SV_ReadLevelFile ============== */ public static void SV_ReadLevelFile() { //char name[MAX_OSPATH]; String name; QuakeFile f; Com.DPrintf("SV_ReadLevelFile()\n"); name = FS.Gamedir() + "/save/current/" + SV_INIT.sv.name + ".sv2"; try { f = new QuakeFile(name, "r"); for (int n = 0; n < Defines.MAX_CONFIGSTRINGS; n++) SV_INIT.sv.configstrings[n] = f.readString(); CM.CM_ReadPortalState(f); f.close(); } catch (IOException e1) { Com.Printf("Failed to open " + name + "\n"); e1.printStackTrace(); } name = FS.Gamedir() + "/save/current/" + SV_INIT.sv.name + ".sav"; GameSave.ReadLevel(name); } /* ============== SV_WriteServerFile ============== */ public static void SV_WriteServerFile(boolean autosave) { QuakeFile f; cvar_t var; String filename, name, string, comment; Com.DPrintf("SV_WriteServerFile(" + (autosave ? "true" : "false") + ")\n"); filename = FS.Gamedir() + "/save/current/server.ssv"; try { f = new QuakeFile(filename, "rw"); if (!autosave) { Calendar c = Calendar.getInstance(); comment = Com.sprintf( "%2i:%2i %2i/%2i ", new Vargs().add(c.get(Calendar.HOUR_OF_DAY)).add(c.get(Calendar.MINUTE)).add( c.get(Calendar.MONTH) + 1).add( c.get(Calendar.DAY_OF_MONTH))); comment += SV_INIT.sv.configstrings[Defines.CS_NAME]; } else { // autosaved comment = "ENTERING " + SV_INIT.sv.configstrings[Defines.CS_NAME]; } f.writeString(comment); f.writeString(SV_INIT.svs.mapcmd); // write the mapcmd // write all CVAR_LATCH cvars // these will be things like coop, skill, deathmatch, etc for (var = Globals.cvar_vars; var != null; var = var.next) { if (0 == (var.flags & Defines.CVAR_LATCH)) continue; if (var.name.length() >= Defines.MAX_OSPATH - 1 || var.string.length() >= 128 - 1) { Com.Printf("Cvar too long: " + var.name + " = " + var.string + "\n"); continue; } name = var.name; string = var.string; try { f.writeString(name); f.writeString(string); } catch (IOException e2) { } } // rst: for termination. f.writeString(null); f.close(); } catch (Exception e) { Com.Printf("Couldn't write " + filename + "\n"); } // write game state filename = FS.Gamedir() + "/save/current/game.ssv"; GameSave.WriteGame(filename, autosave); } /* ============== SV_ReadServerFile ============== */ public static void SV_ReadServerFile() { String filename="", name = "", string, comment, mapcmd; try { QuakeFile f; mapcmd = ""; Com.DPrintf("SV_ReadServerFile()\n"); filename = FS.Gamedir() + "/save/current/server.ssv"; f = new QuakeFile(filename, "r"); // read the comment field comment = f.readString(); // read the mapcmd mapcmd = f.readString(); // read all CVAR_LATCH cvars // these will be things like coop, skill, deathmatch, etc while (true) { name = f.readString(); if (name == null) break; string = f.readString(); Com.DPrintf("Set " + name + " = " + string + "\n"); Cvar.ForceSet(name, string); } f.close(); // start a new game fresh with new cvars SV_INIT.SV_InitGame(); SV_INIT.svs.mapcmd = mapcmd; // read game state filename = FS.Gamedir() + "/save/current/game.ssv"; GameSave.ReadGame(filename); } catch (Exception e) { Com.Printf("Couldn't read file " + filename + "\n"); e.printStackTrace(); } } //========================================================= /* ================== SV_DemoMap_f Puts the server in demo mode on a specific map/cinematic ================== */ public static void SV_DemoMap_f() { SV_INIT.SV_Map(true, Cmd.Argv(1), false); } /* ================== SV_GameMap_f Saves the state of the map just being exited and goes to a new map. If the initial character of the map string is '*', the next map is in a new unit, so the current savegame directory is cleared of map files. Example: *inter.cin+jail Clears the archived maps, plays the inter.cin cinematic, then goes to map jail.bsp. ================== */ public static void SV_GameMap_f() { String map; int i; client_t cl; boolean savedInuse[]; if (Cmd.Argc() != 2) { Com.Printf("USAGE: gamemap <map>\n"); return; } Com.DPrintf("SV_GameMap(" + Cmd.Argv(1) + ")\n"); FS.CreatePath(FS.Gamedir() + "/save/current/"); // check for clearing the current savegame map = Cmd.Argv(1); if (map.charAt(0) == '*') { // wipe all the *.sav files SV_WipeSavegame("current"); } else { // save the map just exited if (SV_INIT.sv.state == Defines.ss_game) { // clear all the client inuse flags before saving so that // when the level is re-entered, the clients will spawn // at spawn points instead of occupying body shells
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -