Move netmodule handling into handlers namespace

Add handler for teleport pylons, and permission for teleport pylons
This commit is contained in:
Chris 2020-06-02 12:59:14 +09:30
parent 4d1fd54a7c
commit 48d610d33f
9 changed files with 401 additions and 152 deletions

View file

@ -0,0 +1,113 @@
using System.Collections.Generic;
using System.IO;
using System.IO.Streams;
using static TShockAPI.GetDataHandlers;
namespace TShockAPI.Handlers.NetModules
{
/// <summary>
/// Provides handling for the Creative Power net module. Checks permissions on all creative powers
/// </summary>
public class CreativePowerHandler : INetModuleHandler
{
/// <summary>
/// The power type being activated
/// </summary>
public CreativePowerTypes PowerType { get; set; }
/// <summary>
/// Reads the power type from the stream
/// </summary>
/// <param name="data"></param>
public void Deserialize(MemoryStream data)
{
PowerType = (CreativePowerTypes)data.ReadInt16();
}
/// <summary>
/// Determines if the player has permission to use the power type
/// </summary>
/// <param name="player"></param>
/// <param name="rejectPacket"></param>
public void HandlePacket(TSPlayer player, out bool rejectPacket)
{
if (!CheckPermission(PowerType, player))
{
rejectPacket = true;
return;
}
rejectPacket = false;
}
/// <summary>
/// Determines if a player has permission to use a specific creative power
/// </summary>
/// <param name="powerType"></param>
/// <param name="player"></param>
/// <returns></returns>
public static bool CheckPermission(CreativePowerTypes powerType, TSPlayer player)
{
if (!PowerToPermissionMap.ContainsKey(powerType))
{
TShock.Log.ConsoleDebug("CreativePowerHandler received permission check request for unknown creative power");
return false;
}
string permission = PowerToPermissionMap[powerType];
if (!player.HasPermission(permission))
{
player.SendErrorMessage("You do not have permission to {0}.", PermissionToDescriptionMap[permission]);
return false;
}
return true;
}
/// <summary>
/// Maps creative powers to permission nodes
/// </summary>
public static Dictionary<CreativePowerTypes, string> PowerToPermissionMap = new Dictionary<CreativePowerTypes, string>
{
{ CreativePowerTypes.FreezeTime, Permissions.journey_timefreeze },
{ CreativePowerTypes.SetDawn, Permissions.journey_timeset },
{ CreativePowerTypes.SetNoon, Permissions.journey_timeset },
{ CreativePowerTypes.SetDusk, Permissions.journey_timeset },
{ CreativePowerTypes.SetMidnight, Permissions.journey_timeset },
{ CreativePowerTypes.Godmode, Permissions.journey_godmode },
{ CreativePowerTypes.WindStrength, Permissions.journey_windstrength },
{ CreativePowerTypes.RainStrength, Permissions.journey_rainstrength },
{ CreativePowerTypes.TimeSpeed, Permissions.journey_timespeed },
{ CreativePowerTypes.RainFreeze, Permissions.journey_rainfreeze },
{ CreativePowerTypes.WindFreeze, Permissions.journey_windfreeze },
{ CreativePowerTypes.IncreasePlacementRange, Permissions.journey_placementrange },
{ CreativePowerTypes.WorldDifficulty, Permissions.journey_setdifficulty },
{ CreativePowerTypes.BiomeSpreadFreeze, Permissions.journey_biomespreadfreeze },
{ CreativePowerTypes.SetSpawnRate, Permissions.journey_setspawnrate },
};
/// <summary>
/// Maps journey mode permission nodes to descriptions of what the permission allows
/// </summary>
public static Dictionary<string, string> PermissionToDescriptionMap = new Dictionary<string, string>
{
{ Permissions.journey_timefreeze, "freeze the time of the server" },
{ Permissions.journey_timeset, "modify the time of the server" },
{ Permissions.journey_timeset, "modify the time of the server" },
{ Permissions.journey_timeset, "modify the time of the server" },
{ Permissions.journey_timeset, "modify the time of the server" },
{ Permissions.journey_godmode, "toggle godmode" },
{ Permissions.journey_windstrength, "modify the wind strength of the server" },
{ Permissions.journey_rainstrength, "modify the rain strength of the server" },
{ Permissions.journey_timespeed, "modify the time speed of the server" },
{ Permissions.journey_rainfreeze, "freeze the rain strength of the server" },
{ Permissions.journey_windfreeze, "freeze the wind strength of the server" },
{ Permissions.journey_placementrange, "modify the tile placement range of your character" },
{ Permissions.journey_setdifficulty, "modify the world difficulty of the server" },
{ Permissions.journey_biomespreadfreeze, "freeze the biome spread of the server" },
{ Permissions.journey_setspawnrate, "modify the NPC spawn rate of the server" },
};
}
}

View file

@ -0,0 +1,75 @@
using System.IO;
using System.IO.Streams;
using Terraria.GameContent.NetModules;
using Terraria.Net;
namespace TShockAPI.Handlers.NetModules
{
/// <summary>
/// Handles creative unlock requests
/// </summary>
public class CreativeUnlocksHandler : INetModuleHandler
{
/// <summary>
/// An unknown field. If this does not have a value of '0' the packet should be rejected.
/// </summary>
public byte UnknownField { get; set; }
/// <summary>
/// ID of the item being sacrificed
/// </summary>
public ushort ItemId { get; set; }
/// <summary>
/// Stack size of the item being sacrificed
/// </summary>
public ushort Amount { get; set; }
/// <summary>
/// Reads the unlock data from the stream
/// </summary>
/// <param name="data"></param>
public void Deserialize(MemoryStream data)
{
UnknownField = data.ReadInt8();
if (UnknownField == 0)
{
ItemId = data.ReadUInt16();
Amount = data.ReadUInt16();
}
}
/// <summary>
/// Determines if the unlock is valid and the player has permission to perform the unlock.
/// Syncs unlock status if the packet is accepted
/// </summary>
/// <param name="player"></param>
/// <param name="rejectPacket"></param>
public void HandlePacket(TSPlayer player, out bool rejectPacket)
{
if (UnknownField != 0)
{
TShock.Log.ConsoleDebug(
"CreativeUnlocksNetModuleHandler received non-vanilla unlock request. Random field value: {0} from {1}",
UnknownField,
player.Name
);
rejectPacket = true;
return;
}
if (!player.HasPermission(Permissions.journey_contributeresearch))
{
player.SendErrorMessage("You do not have permission to contribute research.");
rejectPacket = true;
return;
}
var totalSacrificed = TShock.ResearchDatastore.SacrificeItem(ItemId, Amount, player);
var response = NetCreativeUnlocksModule.SerializeItemSacrifice(ItemId, totalSacrificed);
NetManager.Instance.Broadcast(response);
rejectPacket = false;
}
}
}

View file

@ -0,0 +1,23 @@
using System.IO;
namespace TShockAPI.Handlers.NetModules
{
/// <summary>
/// Describes a handler for a net module
/// </summary>
public interface INetModuleHandler
{
/// <summary>
/// Reads the net module's data from the given stream
/// </summary>
/// <param name="data"></param>
void Deserialize(MemoryStream data);
/// <summary>
/// Provides handling for the packet and determines if it should be accepted or rejected
/// </summary>
/// <param name="player"></param>
/// <param name="rejectPacket"></param>
void HandlePacket(TSPlayer player, out bool rejectPacket);
}
}

View file

@ -0,0 +1,75 @@
using System;
using Terraria;
using static TShockAPI.GetDataHandlers;
namespace TShockAPI.Handlers.NetModules
{
/// <summary>
/// Handles packet 82 - Load Net Module packets
/// </summary>
public class NetModulePacketHandler : IPacketHandler<LoadNetModuleEventArgs>
{
/// <summary>
/// Invoked when a load net module packet is received. This method picks a <see cref="INetModuleHandler"/> based on the
/// net module type being loaded, then forwards the data to the chosen handler to process
/// </summary>
/// <param name="sender"></param>
/// <param name="args"></param>
public void OnReceive(object sender, LoadNetModuleEventArgs args)
{
INetModuleHandler handler;
switch (args.ModuleType)
{
case NetModulesTypes.CreativePowers:
{
handler = new CreativePowerHandler();
break;
}
case NetModulesTypes.CreativeUnlocksPlayerReport:
{
if (!Main.GameModeInfo.IsJourneyMode)
{
TShock.Log.ConsoleDebug(
"NetModuleHandler received attempt to unlock sacrifice while not in journey mode from",
args.Player.Name
);
args.Handled = true;
return;
}
handler = new CreativeUnlocksHandler();
break;
}
case NetModulesTypes.TeleportPylon:
{
handler = new PylonHandler();
break;
}
default:
{
// As of 1.4.x.x, this is now used for more things:
// NetCreativePowersModule
// NetCreativePowerPermissionsModule
// NetLiquidModule
// NetParticlesModule
// NetPingModule
// NetTeleportPylonModule
// NetTextModule
// I (particles) have disabled the original return here, which means that we need to
// handle this more. In the interm, this unbreaks parts of vanilla. Originally
// we just blocked this because it was a liquid exploit.
args.Handled = false;
return;
}
}
handler.Deserialize(args.Data);
handler.HandlePacket(args.Player, out bool rejectPacket);
args.Handled = rejectPacket;
}
}
}

View file

@ -0,0 +1,62 @@
using System.IO;
using System.IO.Streams;
using Terraria.GameContent;
using static Terraria.GameContent.NetModules.NetTeleportPylonModule;
namespace TShockAPI.Handlers.NetModules
{
/// <summary>
/// Handles a pylon net module
/// </summary>
public class PylonHandler : INetModuleHandler
{
/// <summary>
/// Event occuring
/// </summary>
public SubPacketType PylonEventType { get; set; }
/// <summary>
/// Tile X coordinate of the pylon
/// </summary>
public short TileX { get; set; }
/// <summary>
/// Tile Y coordinate of the pylon
/// </summary>
public short TileY { get; set; }
/// <summary>
/// Type of Pylon
/// </summary>
public TeleportPylonType PylonType { get; set; }
/// <summary>
/// Reads the pylon data from the net module
/// </summary>
/// <param name="data"></param>
public void Deserialize(MemoryStream data)
{
PylonEventType = (SubPacketType)data.ReadInt8();
TileX = data.ReadInt16();
TileY = data.ReadInt16();
PylonType = (TeleportPylonType)data.ReadInt8();
}
/// <summary>
/// Rejects a pylon teleport request if the player does not have permission
/// </summary>
/// <param name="player"></param>
/// <param name="rejectPacket"></param>
public void HandlePacket(TSPlayer player, out bool rejectPacket)
{
if (PylonEventType == SubPacketType.PlayerRequestsTeleport)
{
if (!player.HasPermission(Permissions.pylon))
{
rejectPacket = true;
player.SendErrorMessage("You do not have permission to teleport with pylons.");
return;
}
}
rejectPacket = false;
}
}
}