-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
NetMessage Class Documentation
This page lists methods pertaining to the NetMessage class. You can consult this page to get a better understanding of how NetMessage works. If you want to create custom netcode for your mod, this page is not relevant, see Basic netcode and Intermediate netcode for that.
Some of this page's contents may contain outdated 1.3 information.
Index |
---|
Fields |
Methods |
NetMessage.SendData() |
NetMessage
doesn't use very many fields due to most of the information being stored in its MessageBuffer
instances.
Field | Type | Description |
---|---|---|
buffer | MessageBuffer[257] | Where all outgoing/incoming netcode data is stored. Index 256 corresponds to this client's NetMessage uses, the rest of the indices are directly tied to each player in Main.player[] and client in Netplay.Clients[] . |
_currentPlayerDeathReason | PlayerDeathReason | Used when sending player hurt/kill netcode data. |
All netcode data is sent via the SendData()
method. However, NetMessage
does have several other methods for more specific purposes.
Sends a text packet to the client player with the given playerId
.
Like SendChatMessageToClient()
, but the packet is sent to all players and, optionally, ignores a certain player.
Sends a text packet from this client's player to the server.
public static void SendData(int msgType, int remoteClient = -1, int ignoreClient = -1, NetworkText text = null, int number = 0, float number2 = 0f, float number3 = 0f, float number4 = 0f, int number5 = 0, int number6 = 0, int number7 = 0)
Sends netcode data from this client to the server or vice versa. Covered in more detail in the next section.
public static void SendObjectPlacment(int whoAmi, int x, int y, int type, int style, int alternative, int random, int direction)
Shorthand for NetMessage.SendData(MessageID.PlaceObject, remoteClient, ignoreClient, null, x, y, type, style, alternative, random, direction);
.
remoteClient
is -1 and ignoreClient
is whoAmi
if this message is sent from the server and vice versa if this message is sent from a client.
public static void SendTemporaryAnimation(int whoAmi, int animationType, int tileType, int xCoord, int yCoord)
Shorthand for NetMessage.SendData(MessageID.TemporaryAnimation, whoAmi, -1, null, animationType, tileType, xCoord, yCoord, 0, 0, 0);
.
public static void SendTileRange(int whoAmi, int tileX, int tileY, int xSize, int ySize, TileChangeType changeType = TileChangeType.None)
Use this method to update a certain area of tiles. Has more control over the specified area than SendTileSquare()
.
Shorthand for NetMessage.SendData(MessageID.TileSquare, whoAmi, -1, null, number, tileX, tileY, 0f, (int)changeType, 0, 0);
.
(tileX, tileY) is the top-left corner of the tile square.
number
is set to the max of xSize
and ySize
.
public static void SendTileSquare(int whoAmi, int tileX, int tileY, int size, TileChangeType changeType = TileChangeType.None)
Use this method to update a certain area of tiles.
Shorthand for NetMessage.SendData(MessageID.TileSquare, whoAmi, -1, null, size, tileX - num, tileY - num, 0f, (int)changeType, 0, 0);
.
(tileX, tileY) is the center for the tile square.
num
is set to (size - 1) / 2
.
The "center" is biased towards the top-left of the tile square. For example, passing in 10, 10, 4
for tileX, tileY, size
will have the top-left tile in the square be at (9, 9). However, passing in 10, 10, 5
for tileX, tileY, size
will have the top-left tile in the square be at (8, 8), which makes sense since the square has odd-numbered edges.
Informs a certain client of the Travelling Merchant's current shop.
If this game is a server instance, this method is a shorthand for NetMessage.SendData(MessageID.TravelMerchantItems, remoteClient, -1, null, 0, 0f, 0f, 0f, 0, 0, 0);
. Otherwise, it does nothing.
Informs all clients or a specific client of the current Angler quest. If this game isn't a server instance, this method does nothing.
Useful for loading a specific section of the map for multiplayer purposes. Sections are 200 by 150 tile "chunks" of the world map.
If this game isn't a server instance, this method does nothing.
Otherwise, if the given section of the map isn't loaded for the client Netplay.Clients[whoAmi]
, the section is loaded and all NPCs inside the section send their info to that client.
For each client, if the tile at Main.tile[x, y]
is in one of the client's loaded sections of the map, said client is informed that that tile's liquid properties were changed.
public static void SendData(int msgType, int remoteClient = -1, int ignoreClient = -1, NetworkText text = null, int number = 0, float number2 = 0f, float number3 = 0f, float number4 = 0f, int number5 = 0, int number6 = 0, int number7 = 0)
NetMessage.SendData()
is the God method for NetMessage, meaning it does anything and everything for sending netcode data. Below is the documentation for each valid message type, their names, and what data is sent:
Unused. Plain and simple.
The first step of client connection to a server.
Client state: 0 ->1
Vanilla sends the version string $"Terraria{Main.curRelease}"
. tModLoader sends the version string $"{ModLoader.versionedName}"
instead.
If the client is banned or the client's version string does not match the server's version string, the client is immediately kicked with the appropriate message.
If the server has a password, the client sends a MessageID.RequestPassword message. If the server does not have a password, the client sends a MessageID.LoadPlayer message instead.
If the server accepts vanilla clients and the client sent a vanilla version string, tModLoader flags the client as a vanilla client and communicates using an unmodified protocol.
If the client is not flagged as a vanilla client, the client sends a MessageID.SyncMods message instead of a MessageID.LoadPlayer message.
Type(s) | Size | Description |
---|---|---|
byte | 1 | MessageID.ClientHello |
string | ? | ModLoader.versionedName |
byte, string | ? | NetMessage.SendData, message type MessageID.Kick; only sent if the client is banned, the client's version number doesn't match the server's version number or if the client is using a vanilla client and ModNet.AllowVanillaClients is false |
byte, short, ? | ? | NetMessage.SendData, message type MessageID.LoadPlayer; only sent if the server doesn't use a password |
? | ? | NetMessage.SendData, message type MessageID.RequestPassword; only sent if the server uses a password |
Kicks the client player whose player.whoAmI
equals remoteClient
with the given reason text
.
Type(s) | Size | Description |
---|---|---|
byte | 1 | MessageID.Kick |
byte, string | ? | Information about the BinaryWriter used for preparing data to send as well as the text reason provided for the kick |
The next two steps of client connection to a server.
Client state: 1 ->2
The client sends MessageID.SyncPlayer, MessageID.ClientUUID, MessageID.PlayerHealth, MessageID.PlayerMana, MessageID.PlayerBuffs and various MessageID.SyncEquipment messages.
The final MessageID.SyncEquipment messages are sent for the player's main inventory, armor/accessories, equipped dyes, miscellaneous accessories, miscellaneous dyes, Piggy Bank inventory, Safe inventory, trash item slot and Defender's Forge inventory.
tModLoader then calls PlayerHooks.SyncPlayer()
.
The client then sends a MessageID.RequestWorldInfo message.
Client state: 2 ->3
Type(s) | Size | Description |
---|---|---|
byte |
1 | MessageID.LoadPlayer |
byte |
1 | remoteClient; the client's player.whoAmI
|
? | ? | NetMessage.SendData, message type MessageID.SyncPlayer |
? | ? | NetMessage.SendData, message type MessageID.ClientUUID |
? | ? | NetMessage.SendData, message type MessageID.PlayerHealth |
? | ? | NetMessage.SendData, message type MessageID.PlayerMana |
? | ? | NetMessage.SendData, message type MessageID.PlayerBuffs |
byte , short , ? |
7 + modded data | NetMessage.SendData, message type MessageID.SyncEquipment; called for each item in the client player's main inventory |
byte , short , ? |
7 + modded data | NetMessage.SendData, message type MessageID.SyncEquipment; called for each item in the client player's armor and accessory slots |
byte , short , ? |
7 + modded data | NetMessage.SendData, message type MessageID.SyncEquipment; called for each item in the client player's equipped dye slots |
byte , short , ? |
7 + modded data | NetMessage.SendData, message type MessageID.SyncEquipment; called for each item in the client player's miscellaneous accessory slots (pet, light pet, hook, minecart, mount) |
byte , short , ? |
7 + modded data | NetMessage.SendData, message type MessageID.SyncEquipment; called for each item in the client player's miscellaneous dye slots (for the miscellaneous accessories) |
byte , short , ? |
7 + modded data | NetMessage.SendData, message type MessageID.SyncEquipment; called for each item in the client player's Piggy Bank inventory |
byte , short , ? |
7 + modded data | NetMessage.SendData, message type MessageID.SyncEquipment; called for each item in the client player's Safe inventory |
byte , short , ? |
7 + modded data | NetMessage.SendData, message type MessageID.SyncEquipment; called for the client player's trash item slot |
byte , short , ? |
7 + modded data | NetMessage.SendData, message type MessageID.SyncEquipment; called for each item in the client player's Defender's Forge inventory |
none | 0 | NetMessage.SendData, message type MessageID.RequestWorldInfo |
Sends information abount a player.
The number
parameter is the player to sync information from.
Type(s) | Size | Description |
---|---|---|
byte |
1 |
number , the player.whoAmI to sync information from, cast to byte
|
byte |
1 |
player.skinVariant , cast to byte
|
byte |
1 |
player.hair , cast to byte
|
string |
? | player.name |
int |
4 |
player.hairDye , only if vanilla clients are allowed |
byte |
4 |
player.hairDye , only if vanilla clients are not allowed, cast to byte
|
ushort |
2 |
player.hideVisibleAccessory , normally a bool[] but sent as a ushort using bitshift wizardry |
BitsByte |
1 | player.hideMisc |
byte |
1 | player.hideMisc |
Color |
3 |
player.hairColor , written as 3 byte s of the color's .R , .G and .B values |
Color |
3 |
player.skinColor , written as 3 byte s of the color's .R , .G and .B values |
Color |
3 |
player.eyeColor , written as 3 byte s of the color's .R , .G and .B values |
Color |
3 |
player.shirtColor , written as 3 byte s of the color's .R , .G and .B values |
Color |
3 |
player.underShirtColor , written as 3 byte s of the color's .R , .G and .B values |
Color |
3 |
player.pantsColor , written as 3 byte s of the color's .R , .G and .B values |
Color |
3 |
player.shoeColor , written as 3 byte s of the color's .R , .G and .B values |
BitsByte |
1 |
player.difficulty and player.extraAccessory sent as a BitsByte
|
BitsByte |
1 |
player.UsingBiomeTorches , player.happyFunTorchTime , player.unlockedBiomeTorches , player.unlockedSuperCart and player.enabledSuperCart sent as a BitsByte . |
BitsByte |
1 |
player.usedAegisCrystal , player.usedAegisFruit , player.usedArcaneCrystal , player.usedGalaxyPearl , player.usedGummyWorm , player.usedAmbrosia and player.ateArtisanBread sent as a BitsByte . |
Sends information about a slot in one of the player's inventory arrays.
The slot to process is determined by the following table:
Indices | Inventory |
---|---|
0..58 |
player.inventory (Main inventory slots) |
59..78 |
player.armor (vanilla armor, accessory and vanity slots) |
79..88 |
player.dye (vanilla dye slots) |
89..93 |
player.miscEquips (pet, light pet, hook, minecart, mount slots) |
94..98 |
player.miscDyes (vanilla dye slots for miscEquips items) |
99..138 |
player.bank (Piggy Bank slots) |
139..178 |
player.bank2 (Safe slots) |
179 |
player.trashItem (Trash slot) |
180..219 |
player.bank3 (Defender's Forge slots) |
220.. |
player.bank4 (Void Vault slots) |
The number
parameter is the player whoAmI
to retrieve information from and the number2
parameter is which slot to sync.
For ease of use, here's a list of constants that can be used to make using this message more readable:
public const int SyncMainInventory = 0;
public const int SyncArmorAndEquips = 59;
public const int SyncArmorDyes = 79;
public const int SyncMiscEquips = 89;
public const int SyncMiscEquipDyes = 94;
public const int SyncPiggyBank = 99;
public const int SyncSafe = 139;
public const int SyncTraskSlot = 179;
public const int SyncDefendersForge = 180;
public const int SyncVoidVault = 220;
Examples:
// Given a player "player" ...
// ... sync the 5th item in the player's main inventory
NetMessage.SendData(MessageID.SyncEquipment, number: player.whoAmI, number2: SyncMainInventory + 4);
// ... sync the 11th item in the player's piggy bank
NetMessage.SendData(MessageID.SyncEquipment, number: player.whoAmI, number2: SyncPiggyBank + 10);
NOTE: There is no bounds check for providing a slot beyond 260 (SyncVoidVault
+ 40 capacity), so this message will throw an exception if the slot is too large.
Furthermore, this message does not support syncing modded accessory slots.
// TODO
Sends information about the world to the server and/or other clients.
Use this MessageID
whenever anything about the world has changed, including, but not limited to, the time of day and weather.
Type(s) | Size | Description |
---|---|---|
int |
4 | Main.time |
byte |
1 | A BitsByte set to the values of Main.dayTime , Main.bloodMoon and Main.eclipse
|
byte |
1 | Main.moonPhase |
short |
2 | Main.maxTilesX |
short |
2 | Main.maxTilesY |
short |
2 | Main.spawnTileX |
short |
2 | Main.spawnTileY |
short |
2 | Main.worldSurface |
short |
2 | Main.rockLayer |
int |
4 | Main.worldID |
string |
? | Main.worldName |
byte[] |
? | The return value of Main.ActiveWorldFileData.UniqueId.ToByteArray()
|
ulong |
8 | Main.ActiveFileData.WorldGeneratorVersion |
byte |
1 | Main.moonType |
byte |
1 | WorldGen.treeBG |
byte |
1 | WorldGen.corruptBG |
byte |
1 | WorldGen.snowBG |
byte |
1 | WorldGen.hallowBG |
byte |
1 | WorldGen.crimsonBG |
byte |
1 | WorldGen.desertBG |
byte |
1 | WorldGen.oceanBG |
byte |
1 | Main.iceBackStyle |
byte |
1 | Main.jungleBackStyle |
byte |
1 | Main.hellBackStyle |
float |
4 | Main.windSpeedSet |
byte |
1 | Main.numClouds |
int |
12 | The contents of Main.treeX[]
|
byte |
4 | The contents of Main.treeStyle[] , each cast to byte
|
int |
12 | The contents of Main.caveBackX[]
|
byte |
4 | The contents of Main.caveBackStyle[] , each cast to byte
|
float |
4 | Main.maxRaining |
byte |
1 | A BitsByte set to the values of WorldGen.shadowOrbSmashed , NPC.downedBoss1 , NPC.downedBoss2 , NPC.downedBoss3 , Main.hardMode , NPC.downedClown and NPC.downedPlantBoss
|
byte |
1 | A BitsByte set to the values of NPC.downedMechBoss1 , NPC.downedMechBoss2 , NPC.downedMechBoss3 , NPC.downedMechBossAny , Main.cloudBGActive >= 1f , WorldGen.crimson , Main.pumpkinMoon and Main.snowMoon
|
byte |
1 | A BitsByte set to the values of Main.expertMode , Main.fastForwardTime , Main.slimeRain , NPC.downedSlimeKing , NPC.downedQueenBee , NPC.downedFishron , NPC.downedMartian and NPC.downedAncientCultist
|
byte |
1 | A BitsByte set to the values of NPC.downedMoonlord , NPC.downedHalloweenKing , NPC.downedHalloweenTree , NPC.downedChristmasIceQueen , NPC.downedChristmasSantank , NPC.downedChristmasTree , NPC.downedGolemBoss and BirthdayParty.PartyIsUp
|
byte |
1 | A BitsByte set to the values of NPC.downedPirates , NPC.downedFrost , NPC.downedGoblins , Sandstorm.Happening , DD2Event.Ongoing , DD2Event.DownedInvasionT1 , DD2Event.DownedInvasionT2 and DD2Event.DownedInvasionT3
|
sbyte |
1 | Main.invasionType |
? | ? | The result of calling WorldIO.SendModData(BinaryWriter) . ModSystem.NetSend(BinaryWriter) is called here. |
ulong |
8 | If SocialAPI.Network isn't null , then the result of SocialAPI.Network.GetLobbyId() is written. Otherwise, a 0 is written instead. |
float |
4 | Sandstorm.IntendedSeverity |
Sending this net message has the following side effect:
-
Main.maxRaining
is set to0f
before it is written to theBinaryWriter
ifMain.raining
isfalse
.
// TODO
// TODO
// TODO
Deprecated. Framing happens as needed after TileSection is sent.
// TODO
// TODO
// TODO
Unused. Plain and simple.
// TODO
// TODO
Unused. Plain and simple.
Not sure why main menu information would need to be sent through a server anyway.
// TODO
// TODO
Sends the information of the dropped item Main.item[number]
. If the target item is not active
, then this MessageID can be used to inform other clients that this item has despawned.
The number2
parameter is used when sending the message from the server in Item.NewItem()
for if noGrabDelay
is true. Otherwise, it can just be ignored.
Example:
int item = Item.NewItem(/* args */);
// Code that directly modifies Main.item[item] here...
if(Main.netMode != NetmodeID.Singleplayer)
NetMessage.SendData(MessageID.SyncItem, number: item);
// TODO
// TODO
Unused. Plain and simple.
Most likely unused due to it using an item's damage and knockback directly without any of the usual variance.
Obsolete. Either use the chat message methods in NetMessage
or use the NetTextModule
class.
Obsolete. Use MessageID.PlayerHurtV2 instead.
// TODO
// TODO
// TODO
// TODO
// TODO
Syncs the item at Main.chest[number].item[number2]
. This message is usually sent within MessageID.ChestUpdates
, but it still functions normally by itself.
Example:
Point16 position = /* some tile position */;
//FindByGuessing searches the nearby tiles within a 3x3 area with the target position at the center
//The call will return the index of whatever chest had this target position inside of its 2x2 tile bounds
int chest = Chest.FindByGuessing(position.X, position.Y);
if(chest > -1){
Item item = Main.chest[chest].item[20] = new Item();
item.SetDefaults(ItemID.DirtBlock);
item.stack = 20;
if(Main.netMode != NetmodeID.Singleplayer)
NetMessage.SendData(MessageID.SyncChestItem, number: chest, number2: 20, number3: 0);
}
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
Obsolete. Use MessageID.PlayerDeathV2 instead.
// TODO
// TODO
// TODO
Obsolete. Use MessageID.NetModules instead.
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
Plays harp or bell sound based on held item at player position. Main.harpNote = pitch
for the pitch.
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
Used by the projectile orbs from the Spectre Hood armor set bonus. Increases the player's life and displays the combat text on other clients.
number
is the Player.whoAmI
of the player to heal and number2
is how much to heal the player by.
Nothing happens on the receiving client's end if number2
is not greater than zero.
Example:
// This example showcases a projectile healing its owner player in its AI:
int plr = Projectile.owner;
Player player = Main.player[plr];
if (plr == Main.myPlayer && !player.moonLeech) {
int amount = 50;
// Player.Heal() should not be used here since it broadcasts an extra HealEffect call
player.statLife += amount;
if (player.statLife > player.statLifeMax2)
player.statLife = player.statLifeMax2;
player.HealEffect(amount, broadcast: false);
NetMessage.SendData(MessageID.SpiritHeal, number: plr, number2: amount);
}
NOTE: This message ID is not restricted to projectiles. You can use it to simply sync a player health increase in general as well.
Unused. Plain and simple.
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
Attempts to send a tile entity's data, if the ID provided exists. The data is sent via TileEntity.Write(BinaryWriter, TileEntity, bool)
, which calls ModTileEntity.NetSend(BinaryWriter, bool)
.
Example:
Point16 tilePosition = new Point16(i, j);
ModTileEntity entity = ModContent.GetInstance<SomeModTileEntity>();
//If the given position does not have an entity on it, place one and send a net message
if(entity.Find(tilePosition.X, tilePosition.Y) < 0){
int id = entity.Place(tilePosition.X, tilePosition.Y);
if(Main.netMode == NetmodeID.MultiplayerClient)
NetMessage.SendData(MessageID.TileEntitySharing, remoteClient: -1, ignoreClient: Main.myPlayer, number: id);
}
If the ID no longer exists in the client that sends the message (via TileEntity.ByID.Remove(int)
), but it does exist on the other clients, the tile entity will be removed on those clients.
Example:
Point16 tilePosition = new Point16(i, j);
if(TileEntity.ByPosition.TryGetValue(tilePosition, out TileEntity entity)){
//Assumes that the TileEntity is actually a ModTileEntity, which should be the case if you're using this code
ModTileEntity existing = entity as ModTileEntity;
//Kill an entity if it exists at (i, j)
existing.Kill(i, j);
//Send a net message
if(Main.netMode == NetmodeID.MultiplayerClient)
NetMessage.SendData(MessageID.TileEntitySharing, remoteClient: -1, ignoreClient: Main.myPlayer, existing.ID);
}
// TODO
// TODO
// TODO
// TODO
// TODO
Syncs Main.npc[number].extraValue
by setting it to number2
and, on clients, plays the "ping" sound at the world position (number3, number4)
.
Example:
//"npc" is an NPC instance and "position" is a Vector2 where the "pickup" visuals should be displayed
int givenCoins = 50; //50 copper coins
npc.extraValue += givenCoins;
if(Main.netMode == NetmodeID.Singleplayer)
npc.moneyPing(position);
else
NetMessage.SendData(MessageID.SendExtraValue, number: npc.whoAmI, number2: givenCoins, number3: position.X, number4: position.Y);
// TODO
Unused. Plain and simple.
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
No, that's not a typo. The constant is actually called CrystalInvasionWipeAllTheThingsss
.
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
// TODO
Identical to MessageID.SyncItem (21), except also syncs Item.shimmered and Item.shimmerTime
Checks (number) with 3 results
Item.ShimmerEffect(new Vector2(number2, number3));
Main.LocalPlayer.AddCoinLuck(new Vector2(number2, number3), number4);
Main.npc[number2].SetNetShimmerEffect();
// TODO
// TODO
The total number of MessageIDs in vanilla.
// TODO
// TODO
// TODO
// TODO