public override bool Tick(VM vm) { if (vm.SpeedMultiplier == 0) { return(true); } //try to read a new tick from the stream bool success = false; if (Reader.BaseStream.Position < Reader.BaseStream.Length - 1) { try { var tick = new VMNetTick(); tick.Deserialize(Reader); InternalTick(vm, tick); TickID = tick.TickID; success = true; } catch { //might be incomplete, but that shouldn't crash the program. just assume there are no more commands. } } if (!success) { InternalTick(vm, new VMNetTick() { Commands = new List <VMNetCommand>(), TickID = ++TickID, RandomSeed = vm.Context.RandomSeed }); } return(true); }
private void SendOneOff(NetworkClient client, VMNetTick tick) //uh, this is a little silly. { var ticks = new VMNetTickList { Ticks = new List <VMNetTick>() { tick }, ImmediateMode = true }; byte[] data; using (var stream = new MemoryStream()) { using (var writer = new BinaryWriter(stream)) { ticks.SerializeInto(writer); } data = stream.ToArray(); } using (var stream = new PacketStream((byte)ProtocolAbstractionLibraryD.PacketType.VM_PACKET, 0)) { stream.WriteHeader(); stream.WriteInt32(data.Length + (int)PacketHeaders.UNENCRYPTED); stream.WriteBytes(data); client.Send(stream.ToArray()); } }
public override bool Tick(VM vm) { HandleClients(); lock (QueuedCmds) { var tick = new VMNetTick(); tick.Commands = new List <VMNetCommand>(QueuedCmds); tick.TickID = TickID++; tick.RandomSeed = vm.Context.RandomSeed; InternalTick(vm, tick); QueuedCmds.Clear(); TickBuffer.Add(tick); if (TickBuffer.Count >= TICKS_PER_PACKET) { lock (ClientsToSync) { SendTickBuffer(); SendState(vm); } } } return(true); }
protected void InternalTick(VM vm, VMNetTick tick) { if (!tick.ImmediateMode && (tick.Commands.Count == 0 || !(tick.Commands[0].Command is VMStateSyncCmd)) && vm.Context.RandomSeed != tick.RandomSeed) { if (DesyncCooldown == 0) { System.Console.WriteLine("DESYNC - Requested state from host"); vm.SendCommand(new VMRequestResyncCmd()); DesyncCooldown = 30 * 30; } else { System.Console.WriteLine("WARN - DESYNC - Too soon to try again!"); } } vm.Context.RandomSeed = tick.RandomSeed; bool doTick = !tick.ImmediateMode; foreach (var cmd in tick.Commands) { if (cmd.Command is VMStateSyncCmd) { if (LastTick + 1 != tick.TickID) { System.Console.WriteLine("Jump to tick " + tick.TickID); } doTick = false; } var caller = vm.GetAvatarByPersist(cmd.Command.ActorUID); cmd.Command.Execute(vm, caller); } if (tick.TickID < LastTick) { System.Console.WriteLine("Tick wrong! Got " + tick.TickID + ", Missed " + ((int)tick.TickID - (LastTick + 1))); } else if (doTick && vm.Context.Ready) { if (tick.TickID > LastTick + 1) { System.Console.WriteLine("Tick wrong! Got " + tick.TickID + ", Missed " + ((int)tick.TickID - (LastTick + 1))); } #if VM_DESYNC_DEBUG vm.Trace.NewTick(tick.TickID); #endif vm.InternalTick(tick.TickID); if (DesyncCooldown > 0) { DesyncCooldown--; } } LastTick = tick.TickID; }
public override bool Tick(VM vm) { HandleClients(); lock (QueuedCmds) { //verify the queued commands. Remove ones which fail (or defer til later) for (int i = 0; i < QueuedCmds.Count; i++) { var caller = vm.GetObjectByPersist(QueuedCmds[i].Command.ActorUID); if (!(caller is VMAvatar)) { caller = null; } if (!QueuedCmds[i].Command.Verify(vm, (VMAvatar)caller)) { QueuedCmds.RemoveAt(i--); } else if (QueuedCmds[i].Type == VMCommandType.SimJoin) { var cmd = (VMNetSimJoinCmd)QueuedCmds[i].Command; if (cmd.Client != null) { lock (ClientToUID) { ClientToUID.Add(cmd.Client, cmd.ActorUID); UIDtoClient.Add(cmd.ActorUID, cmd.Client); } } } } var tick = new VMNetTick(); tick.Commands = new List <VMNetCommand>(QueuedCmds); tick.TickID = TickID++; tick.RandomSeed = vm.Context.RandomSeed; QueuedCmds.Clear(); InternalTick(vm, tick); TickBuffer.Add(tick); if (TickBuffer.Count >= TICKS_PER_PACKET) { lock (ClientsToSync) { SendTickBuffer(); SendState(vm); } } } return(true); }
protected void InternalTick(VM vm, VMNetTick tick) { if (!tick.ImmediateMode && (tick.Commands.Count == 0 || !(tick.Commands[0].Command is VMStateSyncCmd)) && vm.Context.RandomSeed != tick.RandomSeed) { if (DesyncCooldown == 0) { System.Console.WriteLine("DESYNC - Requested state from host"); vm.SendCommand(new VMRequestResyncCmd()); DesyncCooldown = 30 * 3; } else { System.Console.WriteLine("WARN - DESYNC - Too soon to try again!"); } ExceptionOnDesync = true; } vm.Context.RandomSeed = tick.RandomSeed; bool doTick = !tick.ImmediateMode; foreach (var cmd in tick.Commands) { if (cmd.Command is VMStateSyncCmd) { doTick = false; } var caller = vm.GetObjectByPersist(cmd.Command.ActorUID); if (!(caller is VMAvatar)) { caller = null; } cmd.Command.Execute(vm, (VMAvatar)caller); } if (doTick && vm.Context.Ready) { vm.InternalTick(); if (DesyncCooldown > 0) { DesyncCooldown--; } } }
protected void InternalTick(VM vm, VMNetTick tick) { if ((tick.Commands.Count == 0 || !(tick.Commands[0].Command is VMStateSyncCmd)) && vm.Context.RandomSeed != tick.RandomSeed) { if (DesyncCooldown == 0) { System.Console.WriteLine("DESYNC - Requested state from host"); vm.SendCommand(new VMRequestResyncCmd()); DesyncCooldown = 30 * 3; } else { System.Console.WriteLine("WARN - DESYNC - Too soon to try again!"); } ExceptionOnDesync = true; } vm.Context.RandomSeed = tick.RandomSeed; bool doTick = true; foreach (var cmd in tick.Commands) { if (cmd.Command is VMStateSyncCmd) { doTick = false; } cmd.Command.Execute(vm); } if (doTick) { vm.InternalTick(); } if (DesyncCooldown > 0) { DesyncCooldown--; } }
public override bool Tick(VM vm) { HandleClients(vm); //copy the queue when we can acquire a lock List <VMNetCommand> cmdQueue; lock (QueuedCmds) { cmdQueue = new List <VMNetCommand>(QueuedCmds); QueuedCmds.Clear(); } //verify the queued commands. Remove ones which fail (or defer til later) for (int i = 0; i < cmdQueue.Count; i++) { var caller = vm.GetAvatarByPersist(cmdQueue[i].Command.ActorUID); if (!cmdQueue[i].Command.Verify(vm, caller)) { cmdQueue.RemoveAt(i--); } } var tick = new VMNetTick(); tick.Commands = new List <VMNetCommand>(cmdQueue); tick.TickID = TickID; if (vm.SpeedMultiplier > 0) { tick.TickID = TickID++; } tick.RandomSeed = vm.Context.RandomSeed; cmdQueue.Clear(); InternalTick(vm, tick); if (LastDesyncPcts.Count == 6 && LastDesyncPcts.Average() > 0.5f) { vm.SignalChatEvent(new VMChatEvent(null, VMChatEventType.Debug, "Automatic self resync - " + LastDesyncPcts.Count + " desyncs close by with an average of " + (LastDesyncPcts.Average() * 100) + "% affected.")); LastDesyncPcts.Clear(); SelfResync = true; } if (SelfResync) { SelfResync = false; var save = vm.Save(); vm.Load(save); vm.EODHost.SelfResync(); } TickBuffer.Add(tick); if (TickBuffer.Count >= TICKS_PER_PACKET) { lock (ClientsToSync) { SendTickBuffer(); SendState(vm); } } return(true); }
public bool AsyncBreak; //if protected void InternalTick(VM vm, VMNetTick tick) { CurrentTick = tick.TickID; if (CurrentTick > GreatestTick) { GreatestTick = CurrentTick; } if (!tick.ImmediateMode && (tick.Commands.Count == 0 || !(tick.Commands[0].Command is VMStateSyncCmd)) && vm.Context.RandomSeed != tick.RandomSeed) { if (DesyncCooldown == 0) { System.Console.WriteLine("DESYNC - Requested state from host"); if (DesyncTick == 0) { DesyncTick = CurrentTick - 1; } vm.SendCommand(new VMRequestResyncCmd()); DesyncCooldown = 30 * 30; } else { System.Console.WriteLine("WARN - DESYNC - Expected " + tick.RandomSeed + ", was at " + vm.Context.RandomSeed); } } if (RecordStream != null) { RecordTick(tick); } vm.Context.RandomSeed = tick.RandomSeed; AsyncBreak = false; bool doTick = !tick.ImmediateMode; foreach (var cmd in tick.Commands) { if (cmd.Command is VMStateSyncCmd && ((VMStateSyncCmd)cmd.Command).Run) { if (LastTick + 1 != tick.TickID) { System.Console.WriteLine("Jump to tick " + tick.TickID); } if (!(this is VMFSORDriver)) { doTick = false; //something weird here. this can break loading from saves casually - but must not be active for resyncs. } //disable just for fsor playback } var caller = vm.GetAvatarByPersist(cmd.Command.ActorUID); Executing = cmd; cmd.Command.Execute(vm, caller); Executing = null; if (vm.FSOVAsyncLoading) { tick.Commands.Remove(cmd); //don't worry about modifying an enumerated collection - we are exiting anyways. AsyncBreak = true; return; } } if (tick.TickID < LastTick) { System.Console.WriteLine("Tick wrong! Got " + tick.TickID + ", Missed " + ((int)tick.TickID - (LastTick + 1))); } else if (doTick && vm.Context.Ready) { if (tick.TickID > LastTick + 1) { System.Console.WriteLine("Tick wrong! Got " + tick.TickID + ", Missed " + ((int)tick.TickID - (LastTick + 1))); } vm.Trace?.NewTick(tick.TickID); vm.InternalTick(tick.TickID); if (DesyncCooldown > 0) { DesyncCooldown--; } } LastTick = tick.TickID; }
public void RecordTick(VMNetTick tick) { tick.SerializeInto(RecordStream); }
public override bool Tick(VM vm) { HandleClients(vm); //copy the queue when we can acquire a lock List <VMNetCommand> cmdQueue; lock (QueuedCmds) { cmdQueue = new List <VMNetCommand>(QueuedCmds); QueuedCmds.Clear(); } //verify the queued commands. Remove ones which fail (or defer til later) for (int i = 0; i < cmdQueue.Count; i++) { var caller = vm.GetAvatarByPersist(cmdQueue[i].Command.ActorUID); if (!cmdQueue[i].Command.Verify(vm, caller)) { cmdQueue.RemoveAt(i--); } } var tick = new VMNetTick(); tick.Commands = new List <VMNetCommand>(cmdQueue); if (vm.SpeedMultiplier > 0) { tick.TickID = TickID++; } tick.RandomSeed = vm.Context.RandomSeed; cmdQueue.Clear(); InternalTick(vm, tick); TickBuffer.Add(tick); lock (ClientsToSyncLater) { if (LastResyncCooldown > 0) { LastResyncCooldown--; } else if (ClientsToSyncLater.Count > 0) { lock (ClientsToSync) { foreach (var client in ClientsToSyncLater) { ClientsToSync.Add(client); } ClientsToSyncLater.Clear(); } LastResyncCooldown = CLIENT_RESYNC_COOLDOWN; } } if (TickBuffer.Count >= TICKS_PER_PACKET) { lock (ClientsToSync) { SendTickBuffer(); SendState(vm); } } return(true); }
protected void InternalTick(VM vm, VMNetTick tick) { if (!tick.ImmediateMode && (tick.Commands.Count == 0 || !(tick.Commands[0].Command is VMStateSyncCmd)) && vm.Context.RandomSeed != tick.RandomSeed) { if (DesyncCooldown == 0) { System.Console.WriteLine("DESYNC - Requested state from host"); vm.SendCommand(new VMRequestResyncCmd()); DesyncCooldown = 30 * 30; } else { System.Console.WriteLine("WARN - DESYNC - Too soon to try again!"); } } if (RecordStream != null) { RecordTick(tick); } vm.Context.RandomSeed = tick.RandomSeed; bool doTick = !tick.ImmediateMode; foreach (var cmd in tick.Commands) { if (cmd.Command is VMStateSyncCmd && ((VMStateSyncCmd)cmd.Command).Run) { if (LastTick + 1 != tick.TickID) { System.Console.WriteLine("Jump to tick " + tick.TickID); } if (!(this is VMFSORDriver)) { doTick = false; //something weird here. this can break loading from saves casually - but must not be active for resyncs. } //disable just for fsor playback } var caller = vm.GetAvatarByPersist(cmd.Command.ActorUID); cmd.Command.Execute(vm, caller); } if (tick.TickID < LastTick) { System.Console.WriteLine("Tick wrong! Got " + tick.TickID + ", Missed " + ((int)tick.TickID - (LastTick + 1))); } else if (doTick && vm.Context.Ready) { if (tick.TickID > LastTick + 1) { System.Console.WriteLine("Tick wrong! Got " + tick.TickID + ", Missed " + ((int)tick.TickID - (LastTick + 1))); } #if VM_DESYNC_DEBUG vm.Trace.NewTick(tick.TickID); #endif vm.InternalTick(tick.TickID); if (DesyncCooldown > 0) { DesyncCooldown--; } } LastTick = tick.TickID; }