/// <summary> /// CL_SignonReply /// /// An svc_signonnum has been received, perform a client side setup /// </summary> static void SignonReply() { Con.DPrint("CL_SignonReply: {0}\n", cls.signon); switch (cls.signon) { case 1: cls.message.WriteByte(Protocol.clc_stringcmd); cls.message.WriteString("prespawn"); break; case 2: cls.message.WriteByte(Protocol.clc_stringcmd); cls.message.WriteString(String.Format("name \"{0}\"\n", _Name.String)); cls.message.WriteByte(Protocol.clc_stringcmd); cls.message.WriteString(String.Format("color {0} {1}\n", ((int)_Color.Value) >> 4, ((int)_Color.Value) & 15)); cls.message.WriteByte(Protocol.clc_stringcmd); cls.message.WriteString("spawn " + cls.spawnparms); break; case 3: cls.message.WriteByte(Protocol.clc_stringcmd); cls.message.WriteString("begin"); Cache.Report(); // print remaining memory break; case 4: Scr.EndLoadingPlaque(); // allow normal screen updates break; } }
/// <summary> /// Host_Error /// This shuts down both the client and server /// </summary> public static void Error(string error, params object[] args) { _ErrorDepth++; try { if (_ErrorDepth > 1) { Sys.Error("Host_Error: recursively entered. " + error, args); } Scr.EndLoadingPlaque(); // reenable screen updates string message = (args.Length > 0 ? String.Format(error, args) : error); Con.Print("Host_Error: {0}\n", message); if (Server.sv.active) { ShutdownServer(false); } if (Client.cls.state == cactive_t.ca_dedicated) { Sys.Error("Host_Error: {0}\n", message); // dedicated servers exit } Client.Disconnect(); Client.cls.demonum = -1; throw new EndGameException(); // longjmp (host_abortserver, 1); } finally { _ErrorDepth--; } }
/// <summary> /// Con_Printf /// </summary> public static void Print(string fmt, params object[] args) { string msg = (args.Length > 0 ? String.Format(fmt, args) : fmt); // log all messages to file if (_DebugLog) { DebugLog(msg); } if (!_IsInitialized) { return; } if (Client.cls.state == cactive_t.ca_dedicated) { return; // no graphics mode } // write it to the scrollable buffer Print(msg); // update the screen if the console is displayed if (Client.cls.signon != Client.SIGNONS && !Scr.IsDisabledForLoading) { Scr.UpdateScreen(); } }
// Host_Map_f // // handle a // map <servername> // command from the console. Active clients are kicked off. static void Map_f() { if (Cmd.Source != cmd_source_t.src_command) { return; } Client.cls.demonum = -1; // stop demo loop in case this fails Client.Disconnect(); ShutdownServer(false); Key.Destination = keydest_t.key_game; // remove console or menu Scr.BeginLoadingPlaque(); Client.cls.mapstring = Cmd.JoinArgv() + "\n"; Server.svs.serverflags = 0; // haven't completed an episode yet string name = Cmd.Argv(1); Server.SpawnServer(name); if (!Server.IsActive) { return; } if (Client.cls.state != cactive_t.ca_dedicated) { Client.cls.spawnparms = Cmd.JoinArgv(); Cmd.ExecuteString("connect local", cmd_source_t.src_command); } }
public static void Init(quakeparms_t parms) { _Params = parms; Cache.Init(1024 * 1024 * 16); // debug Cbuf.Init(); Cmd.Init(); View.Init(); Chase.Init(); InitVCR(parms); Common.Init(parms.basedir, parms.argv); InitLocal(); Wad.LoadWadFile("gfx.wad"); Key.Init(); Con.Init(); Menu.Init(); Progs.Init(); Mod.Init(); Net.Init(); Server.Init(); //Con.Print("Exe: "__TIME__" "__DATE__"\n"); //Con.Print("%4.1f megabyte heap\n",parms->memsize/ (1024*1024.0)); Render.InitTextures(); // needed even for dedicated servers if (Client.cls.state != cactive_t.ca_dedicated) { _BasePal = Common.LoadFile("gfx/palette.lmp"); if (_BasePal == null) { Sys.Error("Couldn't load gfx/palette.lmp"); } _ColorMap = Common.LoadFile("gfx/colormap.lmp"); if (_ColorMap == null) { Sys.Error("Couldn't load gfx/colormap.lmp"); } // on non win32, mouse comes before video for security reasons Input.Init(); Vid.Init(_BasePal); Drawer.Init(); Scr.Init(); Render.Init(); Sound.Init(); CDAudio.Init(); Sbar.Init(); Client.Init(); } Cbuf.InsertText("exec quake.rc\n"); _IsInitialized = true; Con.DPrint("========Quake Initialized=========\n"); }
/// <summary> /// CL_NextDemo /// /// Called to play the next demo in the demo loop /// </summary> public static void NextDemo() { if (cls.demonum == -1) { return; // don't play demos } Scr.BeginLoadingPlaque(); if (String.IsNullOrEmpty(cls.demos[cls.demonum]) || cls.demonum == MAX_DEMOS) { cls.demonum = 0; if (String.IsNullOrEmpty(cls.demos[cls.demonum])) { Con.Print("No demos listed with startdemos\n"); cls.demonum = -1; return; } } Cbuf.InsertText(String.Format("playdemo {0}\n", cls.demos[cls.demonum])); cls.demonum++; }
/// <summary> /// Con_ToggleConsole_f /// </summary> public static void ToggleConsole_f() { if (Key.Destination == keydest_t.key_console) { if (Client.cls.state == cactive_t.ca_connected) { Key.Destination = keydest_t.key_game; Key.Lines[Key.EditLine][1] = '\0'; // clear any typing Key.LinePos = 1; } else { MenuBase.MainMenu.Show(); } } else { Key.Destination = keydest_t.key_console; } Scr.EndLoadingPlaque(); Array.Clear(_Times, 0, _Times.Length); }
static float _LastMsg; // static float lastmsg from CL_KeepaliveMessage /// <summary> /// CL_ParseServerMessage /// </summary> static void ParseServerMessage() { // // if recording demos, copy the message out // if (_ShowNet.Value == 1) { Con.Print("{0} ", Net.Message.Length); } else if (_ShowNet.Value == 2) { Con.Print("------------------\n"); } cl.onground = false; // unless the server says otherwise // // parse the message // Net.Reader.Reset(); int i; while (true) { if (Net.Reader.IsBadRead) { Host.Error("CL_ParseServerMessage: Bad server message"); } int cmd = Net.Reader.ReadByte(); if (cmd == -1) { ShowNet("END OF MESSAGE"); return; // end of message } // if the high bit of the command byte is set, it is a fast update if ((cmd & 128) != 0) { ShowNet("fast update"); ParseUpdate(cmd & 127); continue; } ShowNet(_SvcStrings[cmd]); // other commands switch (cmd) { default: Host.Error("CL_ParseServerMessage: Illegible server message\n"); break; case Protocol.svc_nop: break; case Protocol.svc_time: cl.mtime[1] = cl.mtime[0]; cl.mtime[0] = Net.Reader.ReadFloat(); break; case Protocol.svc_clientdata: i = Net.Reader.ReadShort(); ParseClientData(i); break; case Protocol.svc_version: i = Net.Reader.ReadLong(); if (i != Protocol.PROTOCOL_VERSION) { Host.Error("CL_ParseServerMessage: Server is protocol {0} instead of {1}\n", i, Protocol.PROTOCOL_VERSION); } break; case Protocol.svc_disconnect: Host.EndGame("Server disconnected\n"); break; case Protocol.svc_print: Con.Print(Net.Reader.ReadString()); break; case Protocol.svc_centerprint: Scr.CenterPrint(Net.Reader.ReadString()); break; case Protocol.svc_stufftext: Cbuf.AddText(Net.Reader.ReadString()); break; case Protocol.svc_damage: View.ParseDamage(); break; case Protocol.svc_serverinfo: ParseServerInfo(); Scr.vid.recalc_refdef = true; // leave intermission full screen break; case Protocol.svc_setangle: cl.viewangles.X = Net.Reader.ReadAngle(); cl.viewangles.Y = Net.Reader.ReadAngle(); cl.viewangles.Z = Net.Reader.ReadAngle(); break; case Protocol.svc_setview: cl.viewentity = Net.Reader.ReadShort(); break; case Protocol.svc_lightstyle: i = Net.Reader.ReadByte(); if (i >= QDef.MAX_LIGHTSTYLES) { Sys.Error("svc_lightstyle > MAX_LIGHTSTYLES"); } _LightStyle[i].map = Net.Reader.ReadString(); break; case Protocol.svc_sound: ParseStartSoundPacket(); break; case Protocol.svc_stopsound: i = Net.Reader.ReadShort(); Sound.StopSound(i >> 3, i & 7); break; case Protocol.svc_updatename: Sbar.Changed(); i = Net.Reader.ReadByte(); if (i >= cl.maxclients) { Host.Error("CL_ParseServerMessage: svc_updatename > MAX_SCOREBOARD"); } cl.scores[i].name = Net.Reader.ReadString(); break; case Protocol.svc_updatefrags: Sbar.Changed(); i = Net.Reader.ReadByte(); if (i >= cl.maxclients) { Host.Error("CL_ParseServerMessage: svc_updatefrags > MAX_SCOREBOARD"); } cl.scores[i].frags = Net.Reader.ReadShort(); break; case Protocol.svc_updatecolors: Sbar.Changed(); i = Net.Reader.ReadByte(); if (i >= cl.maxclients) { Host.Error("CL_ParseServerMessage: svc_updatecolors > MAX_SCOREBOARD"); } cl.scores[i].colors = Net.Reader.ReadByte(); NewTranslation(i); break; case Protocol.svc_particle: Render.ParseParticleEffect(); break; case Protocol.svc_spawnbaseline: i = Net.Reader.ReadShort(); // must use CL_EntityNum() to force cl.num_entities up ParseBaseline(EntityNum(i)); break; case Protocol.svc_spawnstatic: ParseStatic(); break; case Protocol.svc_temp_entity: ParseTempEntity(); break; case Protocol.svc_setpause: { cl.paused = Net.Reader.ReadByte() != 0; if (cl.paused) { CDAudio.Pause(); } else { CDAudio.Resume(); } } break; case Protocol.svc_signonnum: i = Net.Reader.ReadByte(); if (i <= cls.signon) { Host.Error("Received signon {0} when at {1}", i, cls.signon); } cls.signon = i; SignonReply(); break; case Protocol.svc_killedmonster: cl.stats[QStats.STAT_MONSTERS]++; break; case Protocol.svc_foundsecret: cl.stats[QStats.STAT_SECRETS]++; break; case Protocol.svc_updatestat: i = Net.Reader.ReadByte(); if (i < 0 || i >= QStats.MAX_CL_STATS) { Sys.Error("svc_updatestat: {0} is invalid", i); } cl.stats[i] = Net.Reader.ReadLong(); break; case Protocol.svc_spawnstaticsound: ParseStaticSound(); break; case Protocol.svc_cdtrack: cl.cdtrack = Net.Reader.ReadByte(); cl.looptrack = Net.Reader.ReadByte(); if ((cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1)) { CDAudio.Play((byte)cls.forcetrack, true); } else { CDAudio.Play((byte)cl.cdtrack, true); } break; case Protocol.svc_intermission: cl.intermission = 1; cl.completed_time = (int)cl.time; Scr.vid.recalc_refdef = true; // go to full screen break; case Protocol.svc_finale: cl.intermission = 2; cl.completed_time = (int)cl.time; Scr.vid.recalc_refdef = true; // go to full screen Scr.CenterPrint(Net.Reader.ReadString()); break; case Protocol.svc_cutscene: cl.intermission = 3; cl.completed_time = (int)cl.time; Scr.vid.recalc_refdef = true; // go to full screen Scr.CenterPrint(Net.Reader.ReadString()); break; case Protocol.svc_sellscreen: Cmd.ExecuteString("help", cmd_source_t.src_command); break; } } }
/// <summary> /// _Datagram_Connect /// </summary> qsocket_t InternalConnect(string host) { // see if we can resolve the host name EndPoint sendaddr = Net.LanDriver.GetAddrFromName(host); if (sendaddr == null) { return(null); } Socket newsock = Net.LanDriver.OpenSocket(0); if (newsock == null) { return(null); } qsocket_t sock = Net.NewSocket(); if (sock == null) { goto ErrorReturn2; } sock.socket = newsock; sock.landriver = Net.LanDriverLevel; // connect to the host if (Net.LanDriver.Connect(newsock, sendaddr) == -1) { goto ErrorReturn; } // send the connection request Con.Print("trying...\n"); Scr.UpdateScreen(); double start_time = Net.Time; int ret = 0; for (int reps = 0; reps < 3; reps++) { Net.Message.Clear(); // save space for the header, filled in later Net.Message.WriteLong(0); Net.Message.WriteByte(CCReq.CCREQ_CONNECT); Net.Message.WriteString("QUAKE"); Net.Message.WriteByte(Net.NET_PROTOCOL_VERSION); Common.WriteInt(Net.Message.Data, 0, Common.BigLong(NetFlags.NETFLAG_CTL | (Net.Message.Length & NetFlags.NETFLAG_LENGTH_MASK))); //*((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); Net.LanDriver.Write(newsock, Net.Message.Data, Net.Message.Length, sendaddr); Net.Message.Clear(); EndPoint readaddr = new IPEndPoint(IPAddress.Any, 0); do { ret = Net.Message.FillFrom(newsock, ref readaddr); // if we got something, validate it if (ret > 0) { // is it from the right place? if (sock.LanDriver.AddrCompare(readaddr, sendaddr) != 0) { #if DEBUG Con.Print("wrong reply address\n"); Con.Print("Expected: {0}\n", StrAddr(sendaddr)); Con.Print("Received: {0}\n", StrAddr(readaddr)); Scr.UpdateScreen(); #endif ret = 0; continue; } if (ret < sizeof(int)) { ret = 0; continue; } Net.Reader.Reset(); int control = Common.BigLong(Net.Reader.ReadLong());// BigLong(*((int *)net_message.data)); //MSG_ReadLong(); if (control == -1) { ret = 0; continue; } if ((control & (~NetFlags.NETFLAG_LENGTH_MASK)) != NetFlags.NETFLAG_CTL) { ret = 0; continue; } if ((control & NetFlags.NETFLAG_LENGTH_MASK) != ret) { ret = 0; continue; } } }while ((ret == 0) && (Net.SetNetTime() - start_time) < 2.5); if (ret > 0) { break; } Con.Print("still trying...\n"); Scr.UpdateScreen(); start_time = Net.SetNetTime(); } string reason = String.Empty; if (ret == 0) { reason = "No Response"; Con.Print("{0}\n", reason); Menu.ReturnReason = reason; goto ErrorReturn; } if (ret == -1) { reason = "Network Error"; Con.Print("{0}\n", reason); Menu.ReturnReason = reason; goto ErrorReturn; } ret = Net.Reader.ReadByte(); if (ret == CCRep.CCREP_REJECT) { reason = Net.Reader.ReadString(); Con.Print(reason); Menu.ReturnReason = reason; goto ErrorReturn; } if (ret == CCRep.CCREP_ACCEPT) { IPEndPoint ep = (IPEndPoint)sendaddr; sock.addr = new IPEndPoint(ep.Address, ep.Port); Net.LanDriver.SetSocketPort(sock.addr, Net.Reader.ReadLong()); } else { reason = "Bad Response"; Con.Print("{0}\n", reason); Menu.ReturnReason = reason; goto ErrorReturn; } sock.address = Net.LanDriver.GetNameFromAddr(sendaddr); Con.Print("Connection accepted\n"); sock.lastMessageTime = Net.SetNetTime(); // switch the connection to the specified address if (Net.LanDriver.Connect(newsock, sock.addr) == -1) { reason = "Connect to Game failed"; Con.Print("{0}\n", reason); Menu.ReturnReason = reason; goto ErrorReturn; } Menu.ReturnOnError = false; return(sock); ErrorReturn: Net.FreeSocket(sock); ErrorReturn2: Net.LanDriver.CloseSocket(newsock); if (Menu.ReturnOnError && Menu.ReturnMenu != null) { Menu.ReturnMenu.Show(); Menu.ReturnOnError = false; } return(null); }
// _Host_Frame // //Runs all active servers static void InternalFrame(double time) { // keep the random time dependent Sys.Random(); // decide the simulation time if (!FilterTime(time)) { return; // don't run too fast, or packets will flood out } // get new key events Sys.SendKeyEvents(); // allow mice or other external controllers to add commands Input.Commands(); // process console commands Cbuf.Execute(); Net.Poll(); // if running the server locally, make intentions now if (Server.sv.active) { Client.SendCmd(); } //------------------- // // server operations // //------------------- // check for commands typed to the host GetConsoleCommands(); if (Server.sv.active) { ServerFrame(); } //------------------- // // client operations // //------------------- // if running the server remotely, send intentions now after // the incoming messages have been read if (!Server.sv.active) { Client.SendCmd(); } _Time += FrameTime; // fetch results from server if (Client.cls.state == cactive_t.ca_connected) { Client.ReadFromServer(); } // update video if (_Speeds.Value != 0) { _Time1 = Sys.GetFloatTime(); } Scr.UpdateScreen(); if (_Speeds.Value != 0) { _Time2 = Sys.GetFloatTime(); } // update audio if (Client.cls.signon == Client.SIGNONS) { Sound.Update(ref Render.Origin, ref Render.ViewPn, ref Render.ViewRight, ref Render.ViewUp); Client.DecayLights(); } else { Sound.Update(ref Common.ZeroVector, ref Common.ZeroVector, ref Common.ZeroVector, ref Common.ZeroVector); } CDAudio.Update(); if (_Speeds.Value != 0) { int pass1 = (int)((_Time1 - _Time3) * 1000); _Time3 = Sys.GetFloatTime(); int pass2 = (int)((_Time2 - _Time1) * 1000); int pass3 = (int)((_Time3 - _Time2) * 1000); Con.Print("{0,3} tot {1,3} server {2,3} gfx {3,3} snd\n", pass1 + pass2 + pass3, pass1, pass2, pass3); } _FrameCount++; }
// void SCR_UpdateScreen (void); // This is called every frame, and can also be called explicitly to flush // text to the screen. // // WARNING: be very careful calling this from elsewhere, because the refresh // needs almost the entire 256k of stack space! public static void UpdateScreen() { if (BlockDrawing || !_IsInitialized || _InUpdate) { return; } _InUpdate = true; try { if (MainForm.Instance != null) { if ((MainForm.Instance.VSync == VSyncMode.On) != Vid.Wait) { MainForm.Instance.VSync = (Vid.Wait ? VSyncMode.On : VSyncMode.Off); } } _VidDef.numpages = 2 + (int)_glTripleBuffer.Value; CopyTop = false; _CopyEverything = false; if (IsDisabledForLoading) { if ((Host.RealTime - _DisabledTime) > 60) { IsDisabledForLoading = false; Con.Print("Load failed.\n"); } else { return; } } if (!Con.IsInitialized) { return; // not initialized yet } BeginRendering(); // // determine size of refresh window // if (_OldFov != _Fov.Value) { _OldFov = _Fov.Value; _VidDef.recalc_refdef = true; } if (_OldScreenSize != _ViewSize.Value) { _OldScreenSize = _ViewSize.Value; _VidDef.recalc_refdef = true; } if (_VidDef.recalc_refdef) { CalcRefdef(); } // // do 3D refresh drawing, and then update the screen // SetUpToDrawConsole(); View.RenderView(); Set2D(); // // draw any areas not covered by the refresh // Scr.TileClear(); if (_DrawDialog) { Sbar.Draw(); Drawer.FadeScreen(); DrawNotifyString(); _CopyEverything = true; } else if (_DrawLoading) { DrawLoading(); Sbar.Draw(); } else if (Client.cl.intermission == 1 && Key.Destination == keydest_t.key_game) { Sbar.IntermissionOverlay(); } else if (Client.cl.intermission == 2 && Key.Destination == keydest_t.key_game) { Sbar.FinaleOverlay(); CheckDrawCenterString(); } else { if (View.Crosshair > 0) { Drawer.DrawCharacter(_VRect.x + _VRect.width / 2, _VRect.y + _VRect.height / 2, '+'); } //Drawer.DrawString(8, vid.height - Sbar.SBAR_HEIGHT, $"{Math.Round(1.0 / Host.FrameTime)}fps"); ; DrawRam(); DrawNet(); DrawTurtle(); DrawPause(); CheckDrawCenterString(); Sbar.Draw(); DrawConsole(); Menu.Draw(); } View.UpdatePalette(); EndRendering(); } finally { _InUpdate = false; } }
/// <summary> /// Key_Console /// Interactive line editing and console scrollback /// </summary> static void KeyConsole(int key) { if (key == K_ENTER) { string line = new String(_Lines[_EditLine]).TrimEnd('\0', ' '); string cmd = line.Substring(1); Cbuf.AddText(cmd); // skip the > Cbuf.AddText("\n"); Con.Print("{0}\n", line); _EditLine = (_EditLine + 1) & 31; _HistoryLine = _EditLine; _Lines[_EditLine][0] = ']'; Key.LinePos = 1; if (Client.cls.state == cactive_t.ca_disconnected) { Scr.UpdateScreen(); // force an update, because the command } // may take some time return; } if (key == K_TAB) { // command completion string txt = new String(_Lines[_EditLine], 1, MAXCMDLINE - 1).TrimEnd('\0', ' '); string[] cmds = Cmd.Complete(txt); string[] vars = Cvar.CompleteName(txt); string match = null; if (cmds != null) { if (cmds.Length > 1 || vars != null) { Con.Print("\nCommands:\n"); foreach (string s in cmds) { Con.Print(" {0}\n", s); } } else { match = cmds[0]; } } if (vars != null) { if (vars.Length > 1 || cmds != null) { Con.Print("\nVariables:\n"); foreach (string s in vars) { Con.Print(" {0}\n", s); } } else if (match == null) { match = vars[0]; } } if (!String.IsNullOrEmpty(match)) { int len = Math.Min(match.Length, MAXCMDLINE - 3); for (int i = 0; i < len; i++) { _Lines[_EditLine][i + 1] = match[i]; } Key.LinePos = len + 1; _Lines[_EditLine][Key.LinePos] = ' '; Key.LinePos++; _Lines[_EditLine][Key.LinePos] = '\0'; return; } } if (key == K_BACKSPACE || key == K_LEFTARROW) { if (Key.LinePos > 1) { Key.LinePos--; } return; } if (key == K_UPARROW) { do { _HistoryLine = (_HistoryLine - 1) & 31; } while (_HistoryLine != _EditLine && (_Lines[_HistoryLine][1] == 0)); if (_HistoryLine == _EditLine) { _HistoryLine = (_EditLine + 1) & 31; } Array.Copy(_Lines[_HistoryLine], _Lines[_EditLine], MAXCMDLINE); Key.LinePos = 0; while (_Lines[_EditLine][Key.LinePos] != '\0' && Key.LinePos < MAXCMDLINE) { Key.LinePos++; } return; } if (key == K_DOWNARROW) { if (_HistoryLine == _EditLine) { return; } do { _HistoryLine = (_HistoryLine + 1) & 31; }while (_HistoryLine != _EditLine && (_Lines[_HistoryLine][1] == '\0')); if (_HistoryLine == _EditLine) { _Lines[_EditLine][0] = ']'; Key.LinePos = 1; } else { Array.Copy(_Lines[_HistoryLine], _Lines[_EditLine], MAXCMDLINE); Key.LinePos = 0; while (_Lines[_EditLine][Key.LinePos] != '\0' && Key.LinePos < MAXCMDLINE) { Key.LinePos++; } } return; } if (key == K_PGUP || key == K_MWHEELUP) { Con.BackScroll += 2; if (Con.BackScroll > Con.TotalLines - (Scr.vid.height >> 3) - 1) { Con.BackScroll = Con.TotalLines - (Scr.vid.height >> 3) - 1; } return; } if (key == K_PGDN || key == K_MWHEELDOWN) { Con.BackScroll -= 2; if (Con.BackScroll < 0) { Con.BackScroll = 0; } return; } if (key == K_HOME) { Con.BackScroll = Con.TotalLines - (Scr.vid.height >> 3) - 1; return; } if (key == K_END) { Con.BackScroll = 0; return; } if (key < 32 || key > 127) { return; // non printable } if (Key.LinePos < MAXCMDLINE - 1) { _Lines[_EditLine][Key.LinePos] = (char)key; Key.LinePos++; _Lines[_EditLine][Key.LinePos] = '\0'; } }
/// <summary> /// Host_Reconnect_f /// This command causes the client to wait for the signon messages again. /// This is sent just before a server changes levels /// </summary> static void Reconnect_f() { Scr.BeginLoadingPlaque(); Client.cls.signon = 0; // need new connection messages }