PSO2SERVER/Server/Models/PSOObject.cs
2024-12-06 21:49:29 +08:00

151 lines
4.6 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Runtime.Remoting.Messaging;
using System.Text;
using PSO2SERVER.Database;
using PSO2SERVER.Protocol;
using PSO2SERVER.Zone;
namespace PSO2SERVER.Models
{
public class PSOObject
{
public struct PSOObjectThing
{
public uint Data;
public PSOObjectThing(uint data)
{
Data = data;
}
}
public ObjectHeader Header { get; set; }
public PSOLocation Position { get; set; }
public string Name { get; set; }
public uint ThingFlag { get; set; }
public PSOObjectThing[] Things { get; set; }
public virtual byte[] GenerateSpawnBlob()
{
PacketWriter writer = new PacketWriter();
writer.WriteStruct(Header);
writer.WritePosition(Position);
writer.Seek(2, SeekOrigin.Current); // Padding I guess...
writer.WriteFixedLengthASCII(Name, 0x34);
writer.Write(ThingFlag);
writer.Write(Things.Length);
foreach (PSOObjectThing thing in Things)
{
writer.WriteStruct(thing);
}
return writer.ToArray();
}
internal static PSOObject FromPacketBin(byte[] v)
{
PacketReader reader = new PacketReader(v);
PSOObject obj = new PSOObject();
reader.ReadStruct<PacketHeader>(); //Skip over header
obj.Header = reader.ReadStruct<ObjectHeader>();
obj.Position = reader.ReadEntityPosition();
reader.ReadUInt16(); // Seek 2
obj.Name = reader.ReadFixedLengthAscii(0x34);
obj.ThingFlag = reader.ReadUInt32();
uint thingCount = reader.ReadUInt32();
obj.Things = new PSOObjectThing[thingCount];
for (int i = 0; i < thingCount; i++)
{
obj.Things[i] = reader.ReadStruct<PSOObjectThing>();
}
return obj;
}
internal static PSOObject FromDBObject(GameObject dbObject)
{
PSOObject psoObj = new PSOObject();
psoObj.Header = new ObjectHeader((uint)dbObject.ObjectID, ObjectType.Object);
psoObj.Name = dbObject.ObjectName;
psoObj.Position = new PSOLocation(dbObject.RotX, dbObject.RotY, dbObject.RotZ, dbObject.RotW, dbObject.PosX, dbObject.PosY, dbObject.PosZ);
int thingCount = dbObject.ObjectFlags.Length / 4; // I hope this will work
psoObj.Things = new PSOObjectThing[thingCount];
for(int i = 0; i < psoObj.Things.Length; i++)
{
psoObj.Things[i] = new PSOObjectThing(BitConverter.ToUInt32(dbObject.ObjectFlags, 4 * i)); // This should work?
}
return psoObj;
}
}
public class PSONPC : PSOObject
{
public unsafe struct NPC {
public ObjectHeader objHeader;
public PSOLocation objPosition;
public ushort unk1;
public string objName;
public uint unk2;
public fixed byte unk3[0x0C];
public ushort unk4;
public ushort unk5;
public uint unk6;
public uint unk7;
public uint unk8;
public uint unk9;
public uint unk10;
public uint unk11;
public uint unk12;
public string unk13; //Ascii
}
public override byte[] GenerateSpawnBlob()
{
NPC npc = new NPC
{
objHeader = Header,
objPosition = Position,
objName = Name,
unk8 = 1101004800,
unk12 = 1,
unk13 = "",
};
PacketWriter writer = new PacketWriter();
writer.WriteStruct(Header);
writer.WritePosition(Position);
writer.Write((UInt16)0);
writer.WriteFixedLengthASCII(Name, 0x20);
writer.Write(0); // Padding?
writer.Write(new byte[0xC]); // Unknown, usually zero
writer.Write((UInt16)0);
writer.Write((UInt16)0);
writer.Write((UInt32)0);
writer.Write((UInt32)0);
writer.Write((UInt32)1101004800); // Always this
writer.Write((UInt32)0);
writer.Write((UInt32)0);
writer.Write((UInt32)0);
writer.Write((UInt32)1);
writer.WriteMagic(1, 0x9FCD, 0xE7);
writer.Write((UInt32)0);
return writer.ToArray();
}
}
}