freeso/TSOClient/tso.simantics/NetPlay/Model/Commands/VMNetDeleteObjectCmd.cs

155 lines
6.3 KiB
C#

using System.IO;
using FSO.SimAntics.Model;
using FSO.SimAntics.Model.TSOPlatform;
using FSO.SimAntics.Model.Platform;
namespace FSO.SimAntics.NetPlay.Model.Commands
{
public class VMNetDeleteObjectCmd : VMNetCommandBodyAbstract
{
public short ObjectID;
public uint ObjectPID;
public bool CleanupAll;
public bool Verified;
public bool Success;
public DeleteMode Mode = DeleteMode.Delete;
public override bool Execute(VM vm, VMAvatar caller)
{
if (Mode == DeleteMode.Delete)//ObjectPID == 0) //only has value when this is an inventory move.
{
VMEntity obj = vm.GetObjectById(ObjectID);
if (obj == null || (!vm.TS1 && caller == null)) return false;
var value = (obj.PersistID != 0 || vm.TS1) ? obj.MultitileGroup.Price : 0;
obj.ExecuteEntryPoint(12, vm.Context, true);
obj.Delete(CleanupAll, vm.Context);
// If we're the server, tell the global link to give their money back.
if (vm.GlobalLink != null)
{
vm.GlobalLink.PerformTransaction(vm, false, uint.MaxValue, caller?.PersistID ?? uint.MaxValue,
value,
(bool success, int transferAmount, uint uid1, uint budget1, uint uid2, uint budget2) =>
{
});
}
vm.SignalChatEvent(new VMChatEvent(caller, VMChatEventType.Arch,
caller?.Name ?? "Unknown",
vm.GetUserIP(caller?.PersistID ?? 0),
"deleted " + obj.ToString()
));
}
else
{
//inventory move. Just delete the object.
VMEntity obj = vm.GetObjectByPersist(ObjectPID);
if (obj == null) return false;
if (Success)
{
if (((VMTSOObjectState)obj.TSOState).OwnerID == vm.MyUID)
{
//if the owner is here, tell them this object is now in their inventory.
//if they're elsewhere, they'll see it the next time their inventory updates.
//Inventory accesses are not by index, but PID, and straight to DB... so this won't cause any race conditions.
vm.MyInventory.Add(new VMInventoryItem()
{
ObjectPID = ObjectPID,
GUID = (obj.MasterDefinition?.GUID) ?? obj.Object.OBJ.GUID,
Name = obj.MultitileGroup.Name,
Value = (uint)obj.MultitileGroup.Price,
Graphic = (ushort)obj.GetValue(VMStackObjectVariable.Graphic),
DynFlags1 = obj.DynamicSpriteFlags,
DynFlags2 = obj.DynamicSpriteFlags2,
});
}
vm.Context.ObjectQueries.RemoveMultitilePersist(vm, obj.PersistID);
foreach (var o in obj.MultitileGroup.Objects) o.PersistID = 0; //no longer representative of the object in db.
obj.Delete(CleanupAll, vm.Context);
vm.SignalChatEvent(new VMChatEvent(caller, VMChatEventType.Arch,
caller?.Name ?? "disconnected user",
vm.GetUserIP(caller.PersistID),
"sent " + obj.ToString() + " back to the inventory of its owner."
));
} else
{
//something bad happened. just unlock the object.
foreach (var o in obj.MultitileGroup.Objects)
((VMGameObject)o).Disabled &= VMGameObjectDisableFlags.TransactionIncomplete;
}
}
return true;
}
public override bool Verify(VM vm, VMAvatar caller)
{
if (Verified) return true;
ObjectPID = 0;
VMEntity obj = vm.GetObjectById(ObjectID);
if (!vm.TS1)
{
Mode = vm.PlatformState.Validator.GetDeleteMode(Mode, caller, obj);
if (Mode == DeleteMode.Disallowed) return false;
if (caller.AvatarState.Permissions == VMTSOAvatarPermissions.Admin)
{
VMNetLockCmd.LockObj(vm, obj);
return true; //admins can always deete
}
}
else if (vm.Context.Cheats.MoveObjects) //for ts1 moveobjects cheat
return true;
if (obj == null || (obj is VMAvatar) || obj.IsUserMovable(vm.Context, true) != VMPlacementError.Success) return false;
if ((((VMGameObject)obj).Disabled & VMGameObjectDisableFlags.TransactionIncomplete) > 0) return false; //can't delete objects mid trasaction...
VMNetLockCmd.LockObj(vm, obj);
if (Mode == DeleteMode.Delete)
{
//straight up delete this object. another check will be done at the execution stage.
return true;
} else
{
//send to the owner's inventory
ObjectPID = obj.PersistID; //we don't want to accidentally delete the wrong object - so use its real persist id.
vm.GlobalLink.MoveToInventory(vm, obj.MultitileGroup, (bool success, uint pid) =>
{
Success = success;
Verified = true;
vm.ForwardCommand(this);
});
return false;
}
}
#region VMSerializable Members
public override void SerializeInto(BinaryWriter writer)
{
base.SerializeInto(writer);
writer.Write(ObjectID);
writer.Write(ObjectPID);
writer.Write(CleanupAll);
writer.Write(Success);
writer.Write((byte)Mode);
}
public override void Deserialize(BinaryReader reader)
{
base.Deserialize(reader);
ObjectID = reader.ReadInt16();
ObjectPID = reader.ReadUInt32();
CleanupAll = reader.ReadBoolean();
Success = reader.ReadBoolean();
Mode = (DeleteMode)reader.ReadByte();
}
#endregion
}
}