-
-
Notifications
You must be signed in to change notification settings - Fork 99
Expand file tree
/
Copy pathCalamityNetcode.cs
More file actions
142 lines (126 loc) · 4.77 KB
/
CalamityNetcode.cs
File metadata and controls
142 lines (126 loc) · 4.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
using System;
using System.Collections.Generic;
using System.IO;
using CalamityMod.Packets;
using Microsoft.Xna.Framework;
using Terraria;
using Terraria.DataStructures;
using Terraria.ID;
using Terraria.ModLoader;
namespace CalamityMod
{
public class CalamityNetcode : ModSystem
{
private static List<CalamityPacket> _PacketHandlers = [];
internal static ushort RegisterHandler(CalamityPacket handler)
{
var id = (ushort)_PacketHandlers.Count;
_PacketHandlers.Add(handler);
return id;
}
internal static void WriteHandlerNetID(BinaryWriter packet, ushort netID)
{
if (_PacketHandlers.Count > 256)
packet.Write(netID);
else
packet.Write((byte)netID);
}
internal static ushort ReadHandlerNetID(BinaryReader packet)
{
if (_PacketHandlers.Count > 256)
return packet.ReadUInt16();
else
return packet.ReadByte();
}
public override void OnModUnload()
{
_PacketHandlers = null;
}
public static void HandlePacket(Mod mod, BinaryReader reader, int whoAmI)
{
try
{
var netID = ReadHandlerNetID(reader);
var packetHandler = _PacketHandlers[netID];
if (packetHandler is not null)
{
packetHandler.HandlePacket(reader, whoAmI);
}
else
{
//
// Default case: with no idea how long the packet is, we can't safely read data.
// Throw an exception now instead of allowing the network stream to corrupt.
//
CalamityMod.Log.Error($"Failed to parse Calamity packet: No Calamity packet exists with ID {netID}.");
throw new Exception("Failed to parse Calamity packet: Invalid Calamity packet ID.");
}
}
catch (Exception e)
{
if (e is EndOfStreamException eose)
CalamityMod.Log.Error("Failed to parse Calamity packet: Packet was too short, missing data, or otherwise corrupt.", eose);
else if (e is ObjectDisposedException ode)
CalamityMod.Log.Error("Failed to parse Calamity packet: Packet reader disposed or destroyed.", ode);
else if (e is IOException ioe)
CalamityMod.Log.Error("Failed to parse Calamity packet: An unknown I/O error occurred.", ioe);
else
throw; // this either will crash the game or be caught by TML's packet policing
}
}
public static void SyncWorld()
{
if (Main.dedServ)
NetMessage.SendData(MessageID.WorldData);
}
/// <summary>
/// Shorthand Method for SyncNPC
/// <code>
/// This Equals to:
///
/// if (Main.dedServ and npc != null)
/// NetMessage.SendData(MessageID.SyncNPC, ...)
/// </code>
/// </summary>
public static void SyncNPC(NPC npcToSync, int toClient = -1, int ignoreClient = -1)
{
if (!Main.dedServ)
return;
if (npcToSync is null)
return;
var npcWhoAmI = npcToSync.whoAmI;
if (npcWhoAmI < 0 || npcWhoAmI >= Main.maxNPCs)
return;
NetMessage.SendData(MessageID.SyncNPC, toClient, ignoreClient, null, npcWhoAmI);
}
/// <summary>
/// Shorthand Method for SyncNPC
/// <code>
/// This Equals to:
///
/// if (Main.dedServ and npcWhoAmI in valid range)
/// NetMessage.SendData(MessageID.SyncNPC, ...)
/// </code>
/// </summary>
public static void SyncNPC(int npcWhoAmI, int toClient = -1, int ignoreClient = -1)
{
if (!Main.dedServ)
return;
if (npcWhoAmI < 0 || npcWhoAmI >= Main.maxNPCs)
return;
NetMessage.SendData(MessageID.SyncNPC, toClient, ignoreClient, null, npcWhoAmI);
}
public static void NewNPC_ClientSide(Vector2 spawnPosition, int npcType, Player player)
{
if (Main.netMode == NetmodeID.SinglePlayer)
{
NPC.NewNPC(new EntitySource_WorldEvent(), (int)spawnPosition.X, (int)spawnPosition.Y, npcType, Target: player.whoAmI);
return;
}
else if (Main.netMode == NetmodeID.MultiplayerClient)
{
SpawnNPCOnPlayerPacket.Send(player, (int)spawnPosition.X, (int)spawnPosition.Y, npcType);
}
}
}
}