Merge ingame_help into master

This commit is contained in:
TheManii 2016-04-07 22:25:58 -07:00
commit fc07d2e24d
12 changed files with 1268 additions and 600 deletions

View File

@ -0,0 +1,680 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;
using System.Threading;
using FFXIVClassic_Lobby_Server.common;
using FFXIVClassic_Map_Server.dataobjects;
using FFXIVClassic_Lobby_Server.packets;
using System.IO;
using FFXIVClassic_Map_Server.packets.send.actor;
using FFXIVClassic_Map_Server;
using FFXIVClassic_Map_Server.packets.send;
using FFXIVClassic_Map_Server.dataobjects.chara;
using FFXIVClassic_Map_Server.Actors;
using FFXIVClassic_Map_Server.lua;
using FFXIVClassic_Map_Server.actors.chara.player;
using FFXIVClassic_Map_Server.Properties;
namespace FFXIVClassic_Lobby_Server
{
class CommandProcessor
{
private Dictionary<uint, ConnectedPlayer> mConnectedPlayerList;
private static WorldManager mWorldManager = Server.getWorldManager();
private static Dictionary<uint, Item> gamedataItems = Server.getItemGamedataList();
// For the moment, this is the only predefined item
// TODO: make a list/enum in the future so that items can be given by name, instead of by id
const UInt32 ITEM_GIL = 1000001;
public CommandProcessor(Dictionary<uint, ConnectedPlayer> playerList)
{
mConnectedPlayerList = playerList;
}
public void sendPacket(ConnectedPlayer client, string path)
{
BasePacket packet = new BasePacket(path);
if (client != null)
{
packet.replaceActorID(client.actorID);
client.queuePacket(packet);
}
else
{
foreach (KeyValuePair<uint, ConnectedPlayer> entry in mConnectedPlayerList)
{
packet.replaceActorID(entry.Value.actorID);
entry.Value.queuePacket(packet);
}
}
}
public void changeProperty(uint id, uint value, string target)
{
SetActorPropetyPacket changeProperty = new SetActorPropetyPacket(target);
changeProperty.setTarget(target);
changeProperty.addInt(id, value);
changeProperty.addTarget();
foreach (KeyValuePair<uint, ConnectedPlayer> entry in mConnectedPlayerList)
{
SubPacket changePropertyPacket = changeProperty.buildPacket((entry.Value.actorID), (entry.Value.actorID));
BasePacket packet = BasePacket.createPacket(changePropertyPacket, true, false);
packet.debugPrintPacket();
entry.Value.queuePacket(packet);
}
}
public void doMusic(ConnectedPlayer client, string music)
{
ushort musicId;
if (music.ToLower().StartsWith("0x"))
musicId = Convert.ToUInt16(music, 16);
else
musicId = Convert.ToUInt16(music);
if (client != null)
client.queuePacket(BasePacket.createPacket(SetMusicPacket.buildPacket(client.actorID, musicId, 1), true, false));
else
{
foreach (KeyValuePair<uint, ConnectedPlayer> entry in mConnectedPlayerList)
{
BasePacket musicPacket = BasePacket.createPacket(SetMusicPacket.buildPacket(entry.Value.actorID, musicId, 1), true, false);
entry.Value.queuePacket(musicPacket);
}
}
}
/// <summary>
/// Teleports player to a location on a predefined list
/// </summary>
/// <param name="client">The current player</param>
/// <param name="entranceId">Predefined list: &lt;ffxiv_database&gt;\server_zones_spawnlocations</param>
public void doWarp(ConnectedPlayer client, string entranceId)
{
uint id;
try
{
if (entranceId.ToLower().StartsWith("0x"))
id = Convert.ToUInt32(entranceId, 16);
else
id = Convert.ToUInt32(entranceId);
}
catch(FormatException e)
{return;}
FFXIVClassic_Map_Server.WorldManager.ZoneEntrance ze = mWorldManager.getZoneEntrance(id);
if (ze == null)
return;
if (client != null)
mWorldManager.DoZoneChange(client.getActor(), ze.zoneId, ze.privateAreaName, ze.spawnType, ze.spawnX, ze.spawnY, ze.spawnZ, 0.0f);
else
{
foreach (KeyValuePair<uint, ConnectedPlayer> entry in mConnectedPlayerList)
{
mWorldManager.DoZoneChange(entry.Value.getActor(), ze.zoneId, ze.privateAreaName, ze.spawnType, ze.spawnX, ze.spawnY, ze.spawnZ, 0.0f);
}
}
}
public void doWarp(ConnectedPlayer client, string zone, string privateArea, string sx, string sy, string sz)
{
uint zoneId;
float x,y,z;
x = Single.Parse(sx);
y = Single.Parse(sy);
z = Single.Parse(sz);
if (zone == null)
{
if (client != null)
mWorldManager.DoZoneChange(client.getActor(), 0, privateArea, 0x2, x, y, z, 0.0f);
}
else
{
if (zone.ToLower().StartsWith("0x"))
zoneId = Convert.ToUInt32(zone, 16);
else
zoneId = Convert.ToUInt32(zone);
if (mWorldManager.GetZone(zoneId) == null)
{
if (client != null)
client.queuePacket(BasePacket.createPacket(SendMessagePacket.buildPacket(client.actorID, client.actorID, SendMessagePacket.MESSAGE_TYPE_GENERAL_INFO, "", "Zone does not exist or setting isn't valid."), true, false));
Log.error("Zone does not exist or setting isn't valid.");
}
if (client != null)
mWorldManager.DoZoneChange(client.getActor(), zoneId, privateArea, 0x2, x, y, z, 0.0f);
else
{
foreach (KeyValuePair<uint, ConnectedPlayer> entry in mConnectedPlayerList)
{
mWorldManager.DoZoneChange(entry.Value.getActor(), zoneId, privateArea, 0x2, x, y, z, 0.0f);
}
}
}
}
public void printPos(ConnectedPlayer client)
{
if (client != null)
{
Player p = client.getActor();
client.queuePacket(BasePacket.createPacket(SendMessagePacket.buildPacket(client.actorID, client.actorID, SendMessagePacket.MESSAGE_TYPE_GENERAL_INFO, "", String.Format("{0}\'s position: ZoneID: {1}, X: {2}, Y: {3}, Z: {4}, Rotation: {5}", p.customDisplayName, p.zoneId, p.positionX, p.positionY, p.positionZ, p.rotation)), true, false));
}
else
{
foreach (KeyValuePair<uint, ConnectedPlayer> entry in mConnectedPlayerList)
{
Player p = entry.Value.getActor();
Log.info(String.Format("{0}\'s position: ZoneID: {1}, X: {2}, Y: {3}, Z: {4}, Rotation: {5}", p.customDisplayName, p.zoneId, p.positionX, p.positionY, p.positionZ, p.rotation));
}
}
}
private void setGraphic(ConnectedPlayer client, uint slot, uint wId, uint eId, uint vId, uint cId)
{
if (client != null)
{
Player p = client.getActor();
p.graphicChange(slot, wId, eId, vId, cId);
p.sendAppearance();
}
else
{
foreach (KeyValuePair<uint, ConnectedPlayer> entry in mConnectedPlayerList)
{
Player p = entry.Value.getActor();
p.graphicChange(slot, wId, eId, vId, cId);
p.sendAppearance();
}
}
}
private void giveItem(ConnectedPlayer client, uint itemId, int quantity)
{
if (client != null)
{
Player p = client.getActor();
p.getInventory(Inventory.NORMAL).addItem(itemId, quantity);
}
else
{
foreach (KeyValuePair<uint, ConnectedPlayer> entry in mConnectedPlayerList)
{
Player p = entry.Value.getActor();
p.getInventory(Inventory.NORMAL).addItem(itemId, quantity);
}
}
}
private void giveItem(ConnectedPlayer client, uint itemId, int quantity, ushort type)
{
if (client != null)
{
Player p = client.getActor();
if (p.getInventory(type) != null)
p.getInventory(type).addItem(itemId, quantity);
}
else
{
foreach (KeyValuePair<uint, ConnectedPlayer> entry in mConnectedPlayerList)
{
Player p = entry.Value.getActor();
if (p.getInventory(type) != null)
p.getInventory(type).addItem(itemId, quantity);
}
}
}
private void removeItem(ConnectedPlayer client, uint itemId, int quantity)
{
if (client != null)
{
Player p = client.getActor();
p.getInventory(Inventory.NORMAL).removeItem(itemId, quantity);
}
else
{
foreach (KeyValuePair<uint, ConnectedPlayer> entry in mConnectedPlayerList)
{
Player p = entry.Value.getActor();
p.getInventory(Inventory.NORMAL).removeItem(itemId, quantity);
}
}
}
private void removeItem(ConnectedPlayer client, uint itemId, int quantity, ushort type)
{
if (client != null)
{
Player p = client.getActor();
if (p.getInventory(type) != null)
p.getInventory(type).removeItem(itemId, quantity);
}
else
{
foreach (KeyValuePair<uint, ConnectedPlayer> entry in mConnectedPlayerList)
{
Player p = entry.Value.getActor();
if (p.getInventory(type) != null)
p.getInventory(type).removeItem(itemId, quantity);
}
}
}
private void giveCurrency(ConnectedPlayer client, uint itemId, int quantity)
{
if (client != null)
{
Player p = client.getActor();
p.getInventory(Inventory.CURRENCY).addItem(itemId, quantity);
}
else
{
foreach (KeyValuePair<uint, ConnectedPlayer> entry in mConnectedPlayerList)
{
Player p = entry.Value.getActor();
p.getInventory(Inventory.CURRENCY).addItem(itemId, quantity);
}
}
}
// TODO: make removeCurrency() remove all quantity of a currency if quantity_to_remove > quantity_in_inventory instead of silently failing
private void removeCurrency(ConnectedPlayer client, uint itemId, int quantity)
{
if (client != null)
{
Player p = client.getActor();
p.getInventory(Inventory.CURRENCY).removeItem(itemId, quantity);
}
else
{
foreach (KeyValuePair<uint, ConnectedPlayer> entry in mConnectedPlayerList)
{
Player p = entry.Value.getActor();
p.getInventory(Inventory.CURRENCY).removeItem(itemId, quantity);
}
}
}
private void giveKeyItem(ConnectedPlayer client, uint itemId)
{
if (client != null)
{
Player p = client.getActor();
p.getInventory(Inventory.KEYITEMS).addItem(itemId, 1);
}
else
{
foreach (KeyValuePair<uint, ConnectedPlayer> entry in mConnectedPlayerList)
{
Player p = entry.Value.getActor();
p.getInventory(Inventory.KEYITEMS).addItem(itemId, 1);
}
}
}
private void removeKeyItem(ConnectedPlayer client, uint itemId)
{
if (client != null)
{
Player p = client.getActor();
p.getInventory(Inventory.KEYITEMS).removeItem(itemId, 1);
}
else
{
foreach (KeyValuePair<uint, ConnectedPlayer> entry in mConnectedPlayerList)
{
Player p = entry.Value.getActor();
p.getInventory(Inventory.KEYITEMS).removeItem(itemId, 1);
}
}
}
/// <summary>
/// We only use the default options for SendMessagePacket.
/// May as well make it less unwieldly to view
/// </summary>
/// <param name="client"></param>
/// <param name="message"></param>
private void sendMessage(ConnectedPlayer client, String message)
{
if (client != null)
client.getActor().queuePacket(SendMessagePacket.buildPacket(client.actorID, client.actorID, SendMessagePacket.MESSAGE_TYPE_GENERAL_INFO, "", message));
}
internal bool doCommand(string input, ConnectedPlayer client)
{
input.Trim();
if (input.StartsWith("!"))
input = input.Substring(1);
String[] split = input.Split(' ');
split = split.Select(temp => temp.ToLower()).ToArray(); // Ignore case on commands
split = split.Where(temp => temp != "").ToArray(); // strips extra whitespace from commands
// Debug
//sendMessage(client, string.Join(",", split));
if (split.Length >= 1)
{
#region !help
if (split[0].Equals("help"))
{
if (split.Length == 1)
{
sendMessage(client, Resources.CPhelp);
}
if (split.Length == 2)
{
if (split[1].Equals("mypos"))
sendMessage(client, Resources.CPmypos);
else if (split[1].Equals("music"))
sendMessage(client, Resources.CPmusic);
else if (split[1].Equals("warp"))
sendMessage(client, Resources.CPwarp);
else if (split[1].Equals("givecurrency"))
sendMessage(client, Resources.CPgivecurrency);
else if (split[1].Equals("giveitem"))
sendMessage(client, Resources.CPgiveitem);
else if (split[1].Equals("givekeyitem"))
sendMessage(client, Resources.CPgivekeyitem);
else if (split[1].Equals("removecurrency"))
sendMessage(client, Resources.CPremovecurrency);
else if (split[1].Equals("removeitem"))
sendMessage(client, Resources.CPremoveitem);
else if (split[1].Equals("removekeyitem"))
sendMessage(client, Resources.CPremovekeyitem);
else if (split[1].Equals("reloaditems"))
sendMessage(client, Resources.CPreloaditems);
else if (split[1].Equals("reloadzones"))
sendMessage(client, Resources.CPreloadzones);
/*
else if (split[1].Equals("property"))
sendMessage(client, Resources.CPproperty);
else if (split[1].Equals("property2"))
sendMessage(client, Resources.CPproperty2);
else if (split[1].Equals("sendpacket"))
sendMessage(client, Resources.CPsendpacket);
else if (split[1].Equals("setgraphic"))
sendMessage(client, Resources.CPsetgraphic);
*/
}
return true;
}
#endregion
#region !mypos
else if (split[0].Equals("mypos"))
{
try
{
printPos(client);
return true;
}
catch (Exception e)
{
Log.error("Could not load packet: " + e);
}
}
#endregion
#region !reloadzones
else if (split[0].Equals("reloadzones"))
{
if (client != null)
{
Log.info(String.Format("Got request to reset zone: {0}", client.getActor().zoneId));
client.getActor().zone.clear();
client.getActor().zone.addActorToZone(client.getActor());
client.getActor().sendInstanceUpdate();
client.queuePacket(BasePacket.createPacket(SendMessagePacket.buildPacket(client.actorID, client.actorID, SendMessagePacket.MESSAGE_TYPE_GENERAL_INFO, "", String.Format("Reseting zone {0}...", client.getActor().zoneId)), true, false));
}
mWorldManager.reloadZone(client.getActor().zoneId);
return true;
}
#endregion
#region !reloaditems
else if (split[0].Equals("reloaditems"))
{
Log.info(String.Format("Got request to reload item gamedata"));
sendMessage(client, "Reloading Item Gamedata...");
gamedataItems.Clear();
gamedataItems = Database.getItemGamedata();
Log.info(String.Format("Loaded {0} items.", gamedataItems.Count));
sendMessage(client, String.Format("Loaded {0} items.", gamedataItems.Count));
return true;
}
#endregion
#region !sendpacket
else if (split[0].Equals("sendpacket"))
{
if (split.Length < 2)
return false;
try
{
sendPacket(client, "./packets/" + split[1]);
return true;
}
catch (Exception e)
{
Log.error("Could not load packet: " + e);
}
}
#endregion
#region !graphic
else if (split[0].Equals("graphic"))
{
try
{
if (split.Length == 6)
setGraphic(client, UInt32.Parse(split[1]), UInt32.Parse(split[2]), UInt32.Parse(split[3]), UInt32.Parse(split[4]), UInt32.Parse(split[5]));
return true;
}
catch (Exception e)
{
Log.error("Could not give item.");
}
}
#endregion
#region !giveitem
else if (split[0].Equals("giveitem"))
{
try
{
if (split.Length == 2)
giveItem(client, UInt32.Parse(split[1]), 1);
else if (split.Length == 3)
giveItem(client, UInt32.Parse(split[1]), Int32.Parse(split[2]));
else if (split.Length == 4)
giveItem(client, UInt32.Parse(split[1]), Int32.Parse(split[2]), UInt16.Parse(split[3]));
return true;
}
catch (Exception e)
{
Log.error("Could not give item.");
}
}
#endregion
#region !removeitem
else if (split[0].Equals("removeitem"))
{
if (split.Length < 2)
return false;
try
{
if (split.Length == 2)
removeItem(client, UInt32.Parse(split[1]), 1);
else if (split.Length == 3)
removeItem(client, UInt32.Parse(split[1]), Int32.Parse(split[2]));
else if (split.Length == 4)
removeItem(client, UInt32.Parse(split[1]), Int32.Parse(split[2]), UInt16.Parse(split[3]));
return true;
}
catch (Exception e)
{
Log.error("Could not remove item.");
}
}
#endregion
#region !givekeyitem
else if (split[0].Equals("givekeyitem"))
{
try
{
if (split.Length == 2)
giveKeyItem(client, UInt32.Parse(split[1]));
}
catch (Exception e)
{
Log.error("Could not give keyitem.");
}
}
#endregion
#region !removekeyitem
else if (split[0].Equals("removekeyitem"))
{
if (split.Length < 2)
return false;
try
{
if (split.Length == 2)
removeKeyItem(client, UInt32.Parse(split[1]));
return true;
}
catch (Exception e)
{
Log.error("Could not remove keyitem.");
}
}
#endregion
#region !givecurrency
else if (split[0].Equals("givecurrency"))
{
try
{
if (split.Length == 2)
giveCurrency(client, ITEM_GIL, Int32.Parse(split[1]));
else if (split.Length == 3)
giveCurrency(client, UInt32.Parse(split[1]), Int32.Parse(split[2]));
}
catch (Exception e)
{
Log.error("Could not give currency.");
}
}
#endregion
#region !removecurrency
else if (split[0].Equals("removecurrency"))
{
if (split.Length < 2)
return false;
try
{
if (split.Length == 2)
removeCurrency(client, ITEM_GIL, Int32.Parse(split[1]));
else if (split.Length == 3)
removeCurrency(client, UInt32.Parse(split[1]), Int32.Parse(split[2]));
return true;
}
catch (Exception e)
{
Log.error("Could not remove currency.");
}
}
#endregion
#region !music
else if (split[0].Equals("music"))
{
if (split.Length < 2)
return false;
try
{
doMusic(client, split[1]);
return true;
}
catch (Exception e)
{
Log.error("Could not change music: " + e);
}
}
#endregion
#region !warp
else if (split[0].Equals("warp"))
{
if (split.Length == 2) // Predefined list
doWarp(client, split[1]);
else if (split.Length == 4) // X/Y/Z
doWarp(client, null, null, split[1], split[2], split[3]);
else if (split.Length == 5) // Zone + X/Y/Z
doWarp(client, split[1], null, split[2], split[3], split[4]);
else if (split.Length == 6) // Zone + instance + X/Y/Z
doWarp(client, split[1], split[2], split[3], split[4], split[5]);
return true;
}
#endregion
#region !property
else if (split[0].Equals("property"))
{
if (split.Length == 4)
{
changeProperty(Utils.MurmurHash2(split[1], 0), Convert.ToUInt32(split[2], 16), split[3]);
}
return true;
}
#endregion
#region !property2
else if (split[0].Equals("property2"))
{
if (split.Length == 4)
{
changeProperty(Convert.ToUInt32(split[1], 16), Convert.ToUInt32(split[2], 16), split[3]);
}
return true;
}
#endregion
}
return false;
}
}
}

View File

@ -708,7 +708,7 @@ namespace FFXIVClassic_Lobby_Server
player.getInventory(Inventory.NORMAL).initList(getInventory(player, 0, Inventory.NORMAL));
player.getInventory(Inventory.KEYITEMS).initList(getInventory(player, 0, Inventory.KEYITEMS));
player.getInventory(Inventory.CURRANCY).initList(getInventory(player, 0, Inventory.CURRANCY));
player.getInventory(Inventory.CURRENCY).initList(getInventory(player, 0, Inventory.CURRENCY));
player.getInventory(Inventory.BAZAAR).initList(getInventory(player, 0, Inventory.BAZAAR));
player.getInventory(Inventory.MELDREQUEST).initList(getInventory(player, 0, Inventory.MELDREQUEST));
player.getInventory(Inventory.LOOT).initList(getInventory(player, 0, Inventory.LOOT));

View File

@ -79,6 +79,7 @@
<Compile Include="actors\StaticActors.cs" />
<Compile Include="actors\world\WorldMaster.cs" />
<Compile Include="ClientConnection.cs" />
<Compile Include="CommandProcessor.cs" />
<Compile Include="common\Bitfield.cs" />
<Compile Include="common\Blowfish.cs" />
<Compile Include="common\EfficientHashTables.cs" />
@ -250,6 +251,11 @@
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="lua\LuaUtils.cs" />
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Server.cs" />
<Compile Include="utils\ActorPropertyPacketUtil.cs" />
<Compile Include="utils\CharacterUtils.cs" />
@ -261,7 +267,12 @@
<None Include="App.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup />
<ItemGroup>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>PublicResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>xcopy "$(SolutionDir)data" "$(SolutionDir)$(ProjectName)\$(OutDir)" /E /C /D</PostBuildEvent>

View File

@ -39,6 +39,7 @@ namespace FFXIVClassic_Lobby_Server
class PacketProcessor
{
Server mServer;
CommandProcessor cp;
Dictionary<uint, ConnectedPlayer> mPlayers;
List<ClientConnection> mConnections;
@ -47,6 +48,7 @@ namespace FFXIVClassic_Lobby_Server
mPlayers = playerList;
mConnections = connectionList;
mServer = server;
cp = new CommandProcessor(playerList);
}
public void processPacket(ClientConnection client, BasePacket packet)
@ -186,7 +188,7 @@ namespace FFXIVClassic_Lobby_Server
subpacket.debugPrintSubPacket();
client.queuePacket(_0x2Packet.buildPacket(player.actorID), true, false);
Server.GetWorldManager().DoLogin(player.getActor());
Server.getWorldManager().DoLogin(player.getActor());
break;
@ -198,7 +200,7 @@ namespace FFXIVClassic_Lobby_Server
if (chatMessage.message.StartsWith("!"))
{
if (mServer.doCommand(chatMessage.message, player))
if (cp.doCommand(chatMessage.message, player))
continue;
}
@ -265,7 +267,7 @@ namespace FFXIVClassic_Lobby_Server
if (ownerActor == null)
{
//Is it a instance actor?
ownerActor = Server.GetWorldManager().GetActorInWorld(player.getActor().eventCurrentOwner);
ownerActor = Server.getWorldManager().GetActorInWorld(player.getActor().eventCurrentOwner);
if (ownerActor == null)
{
//Is it a Director?
@ -296,7 +298,7 @@ namespace FFXIVClassic_Lobby_Server
Actor updateOwnerActor = Server.getStaticActors(player.getActor().eventCurrentOwner);
if (updateOwnerActor == null)
{
updateOwnerActor = Server.GetWorldManager().GetActorInWorld(player.getActor().eventCurrentOwner);
updateOwnerActor = Server.getWorldManager().GetActorInWorld(player.getActor().eventCurrentOwner);
if (player.getActor().currentDirector != null && player.getActor().eventCurrentOwner == player.getActor().currentDirector.actorId)
updateOwnerActor = player.getActor().currentDirector;

View File

@ -68,12 +68,13 @@ namespace FFXIVClassic_Lobby_Server
if (startServer)
{
Server server = new Server();
CommandProcessor cp = new CommandProcessor(server.getConnectedPlayerList());
server.startServer();
while (true)
{
String input = Console.ReadLine();
server.doCommand(input, null);
cp.doCommand(input, null);
}
}

View File

@ -0,0 +1,256 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace FFXIVClassic_Map_Server.Properties {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
public class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
public static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("FFXIVClassic_Map_Server.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
public static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to Adds the specified currency to the current player&apos;s inventory
///
///*Syntax: givecurrency &lt;quantity&gt;
/// givecurrency &lt;quantity&gt; &lt;type&gt;
///&lt;type&gt; is the specific type of currency desired, defaults to gil if no type specified.
/// </summary>
public static string CPgivecurrency {
get {
return ResourceManager.GetString("CPgivecurrency", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Adds the specified items to the current player&apos;s inventory
///
///*Syntax: giveitem &lt;item id&gt;
/// giveitem &lt;item id&gt; &lt;quantity&gt;
/// giveitem &lt;item id&gt; &lt;quantity&gt; &lt;type&gt;
///&lt;item id&gt; is the item&apos;s specific id as defined in the server database
///&lt;type&gt; is the type as defined in the server database (defaults to standard item if not specified).
/// </summary>
public static string CPgiveitem {
get {
return ResourceManager.GetString("CPgiveitem", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Adds the specified key item to the current player&apos;s inventory
///
///*Syntax: givekeyitem &lt;item id&gt;
///&lt;item id&gt; is the key item&apos;s specific id as defined in the server database.
/// </summary>
public static string CPgivekeyitem {
get {
return ResourceManager.GetString("CPgivekeyitem", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Use !help(command) for details
///
///Available commands:
///Standard: mypos, music, warp
///Server Administration: givecurrency, giveitem, givekeyitem, removecurrency, removekeyitem, reloaditems, reloadzones.
/// </summary>
public static string CPhelp {
get {
return ResourceManager.GetString("CPhelp", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Changes the currently playing background music
///
///*Syntax: music &lt;music id&gt;
///&lt;music id&gt; is the key item&apos;s specific id as defined in the server database.
/// </summary>
public static string CPmusic {
get {
return ResourceManager.GetString("CPmusic", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Prints out your current location
///
///*Note: The X/Y/Z coordinates do not correspond to the coordinates listed in the in-game map, they are based on the underlying game data.
/// </summary>
public static string CPmypos {
get {
return ResourceManager.GetString("CPmypos", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to *Syntax: property &lt;value 1&gt; &lt;value 2&gt; &lt;value 3&gt;.
/// </summary>
public static string CPproperty {
get {
return ResourceManager.GetString("CPproperty", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to *Syntax: property2 &lt;value 1&gt; &lt;value 2&gt; &lt;value 3&gt;.
/// </summary>
public static string CPproperty2 {
get {
return ResourceManager.GetString("CPproperty2", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Reloads the current item data from the database.
/// </summary>
public static string CPreloaditems {
get {
return ResourceManager.GetString("CPreloaditems", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Reloads the current zone data from the database.
/// </summary>
public static string CPreloadzones {
get {
return ResourceManager.GetString("CPreloadzones", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Removes the specified currency from the current player&apos;s inventory
///
///*Syntax: removecurrency &lt;quantity&gt;
/// removecurrency &lt;quantity&gt; &lt;type&gt;
///&lt;type&gt; is the specific type of currency desired, defaults to gil if no type specified.
/// </summary>
public static string CPremovecurrency {
get {
return ResourceManager.GetString("CPremovecurrency", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Removes the specified items to the current player&apos;s inventory
///
///*Syntax: removeitem &lt;itemid&gt;
/// removeitem &lt;itemid&gt; &lt;quantity&gt;
///&lt;item id&gt; is the item&apos;s specific id as defined in the server database.
/// </summary>
public static string CPremoveitem {
get {
return ResourceManager.GetString("CPremoveitem", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Removes the specified key item to the current player&apos;s inventory
///
///*Syntax: removekeyitem &lt;itemid&gt;
///&lt;item id&gt; is the key item&apos;s specific id as defined in the server database.
/// </summary>
public static string CPremovekeyitem {
get {
return ResourceManager.GetString("CPremovekeyitem", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Server sends a special packet to the client
///
///*Syntax: sendpacket &lt;path to packet&gt;
///&lt;Path to packet&gt; is the path to the packet, starting in &lt;map server install location&gt;\packet.
/// </summary>
public static string CPsendpacket {
get {
return ResourceManager.GetString("CPsendpacket", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Overrides the currently displayed character equipment in a specific slot
///
///*Note: Similar to Glamours in FFXIV:ARR, the overridden graphics are purely cosmetic, they do not affect the underlying stats of whatever is equipped on that slot
///
///*Syntax: sendpacket &lt;slot&gt; &lt;wid&gt; &lt;eid&gt; &lt;vid&gt; &lt;cid&gt;
///&lt;w/e/v/c id&gt; are as defined in the client game data.
/// </summary>
public static string CPsetgraphic {
get {
return ResourceManager.GetString("CPsetgraphic", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Teleports the player to the specified location
///
///*Syntax: warp &lt;location list&gt;
/// warp &lt;X coordinate&gt; &lt;Y coordinate&gt; &lt;Z coordinate&gt;
/// warp &lt;zone id&gt; &lt;X coordinate&gt; &lt;Y coordinate&gt; &lt;Z coordinate&gt;
/// warp &lt;zone id&gt; &lt;instance&gt; &lt;X coordinate&gt; &lt;Y coordinate&gt; &lt;Z coordinate&gt;
///&lt;location list&gt; is a pre-defined list of locations from the server database
///&lt;zone id&gt; is the zone&apos;s id as defined in the server database
///&lt;instance&gt; is an instanced copy of the desired zone that&apos;s only visible to the current player.
/// </summary>
public static string CPwarp {
get {
return ResourceManager.GetString("CPwarp", resourceCulture);
}
}
}
}

View File

@ -0,0 +1,217 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="CPgivecurrency" xml:space="preserve">
<value>Adds the specified currency to the current player's inventory
*Syntax: givecurrency &lt;quantity&gt;
givecurrency &lt;quantity&gt; &lt;type&gt;
&lt;type&gt; is the specific type of currency desired, defaults to gil if no type specified</value>
</data>
<data name="CPgiveitem" xml:space="preserve">
<value>Adds the specified items to the current player's inventory
*Syntax: giveitem &lt;item id&gt;
giveitem &lt;item id&gt; &lt;quantity&gt;
giveitem &lt;item id&gt; &lt;quantity&gt; &lt;type&gt;
&lt;item id&gt; is the item's specific id as defined in the server database
&lt;type&gt; is the type as defined in the server database (defaults to standard item if not specified)</value>
</data>
<data name="CPgivekeyitem" xml:space="preserve">
<value>Adds the specified key item to the current player's inventory
*Syntax: givekeyitem &lt;item id&gt;
&lt;item id&gt; is the key item's specific id as defined in the server database</value>
</data>
<data name="CPhelp" xml:space="preserve">
<value>Use !help(command) for details
Available commands:
Standard: mypos, music, warp
Server Administration: givecurrency, giveitem, givekeyitem, removecurrency, removekeyitem, reloaditems, reloadzones</value>
</data>
<data name="CPmusic" xml:space="preserve">
<value>Changes the currently playing background music
*Syntax: music &lt;music id&gt;
&lt;music id&gt; is the key item's specific id as defined in the server database</value>
</data>
<data name="CPmypos" xml:space="preserve">
<value>Prints out your current location
*Note: The X/Y/Z coordinates do not correspond to the coordinates listed in the in-game map, they are based on the underlying game data</value>
</data>
<data name="CPproperty" xml:space="preserve">
<value>*Syntax: property &lt;value 1&gt; &lt;value 2&gt; &lt;value 3&gt;</value>
</data>
<data name="CPproperty2" xml:space="preserve">
<value>*Syntax: property2 &lt;value 1&gt; &lt;value 2&gt; &lt;value 3&gt;</value>
</data>
<data name="CPreloaditems" xml:space="preserve">
<value>Reloads the current item data from the database</value>
</data>
<data name="CPreloadzones" xml:space="preserve">
<value>Reloads the current zone data from the database</value>
</data>
<data name="CPremovecurrency" xml:space="preserve">
<value>Removes the specified currency from the current player's inventory
*Syntax: removecurrency &lt;quantity&gt;
removecurrency &lt;quantity&gt; &lt;type&gt;
&lt;type&gt; is the specific type of currency desired, defaults to gil if no type specified</value>
</data>
<data name="CPremoveitem" xml:space="preserve">
<value>Removes the specified items to the current player's inventory
*Syntax: removeitem &lt;itemid&gt;
removeitem &lt;itemid&gt; &lt;quantity&gt;
&lt;item id&gt; is the item's specific id as defined in the server database</value>
</data>
<data name="CPremovekeyitem" xml:space="preserve">
<value>Removes the specified key item to the current player's inventory
*Syntax: removekeyitem &lt;itemid&gt;
&lt;item id&gt; is the key item's specific id as defined in the server database</value>
</data>
<data name="CPsendpacket" xml:space="preserve">
<value>Server sends a special packet to the client
*Syntax: sendpacket &lt;path to packet&gt;
&lt;Path to packet&gt; is the path to the packet, starting in &lt;map server install location&gt;\packet</value>
</data>
<data name="CPsetgraphic" xml:space="preserve">
<value>Overrides the currently displayed character equipment in a specific slot
*Note: Similar to Glamours in FFXIV:ARR, the overridden graphics are purely cosmetic, they do not affect the underlying stats of whatever is equipped on that slot
*Syntax: sendpacket &lt;slot&gt; &lt;wid&gt; &lt;eid&gt; &lt;vid&gt; &lt;cid&gt;
&lt;w/e/v/c id&gt; are as defined in the client game data</value>
</data>
<data name="CPwarp" xml:space="preserve">
<value>Teleports the player to the specified location
*Syntax: warp &lt;location list&gt;
warp &lt;X coordinate&gt; &lt;Y coordinate&gt; &lt;Z coordinate&gt;
warp &lt;zone id&gt; &lt;X coordinate&gt; &lt;Y coordinate&gt; &lt;Z coordinate&gt;
warp &lt;zone id&gt; &lt;instance&gt; &lt;X coordinate&gt; &lt;Y coordinate&gt; &lt;Z coordinate&gt;
&lt;location list&gt; is a pre-defined list of locations from the server database
&lt;zone id&gt; is the zone's id as defined in the server database
&lt;instance&gt; is an instanced copy of the desired zone that's only visible to the current player</value>
</data>
</root>

View File

@ -22,9 +22,9 @@ namespace FFXIVClassic_Lobby_Server
{
class Server
{
public const int FFXIV_MAP_PORT = 54992;
public const int BUFFER_SIZE = 0xFFFF; //Max basepacket size is 0xFFFF
public const int BACKLOG = 100;
public const int FFXIV_MAP_PORT = 54992;
public const int BUFFER_SIZE = 0xFFFF; //Max basepacket size is 0xFFFF
public const int BACKLOG = 100;
public const int HEALTH_THREAD_SLEEP_TIME = 5;
public const string STATIC_ACTORS_PATH = "./staticactors.bin";
@ -33,7 +33,7 @@ namespace FFXIVClassic_Lobby_Server
private Socket mServerSocket;
private Dictionary<uint,ConnectedPlayer> mConnectedPlayerList = new Dictionary<uint,ConnectedPlayer>();
private Dictionary<uint, ConnectedPlayer> mConnectedPlayerList = new Dictionary<uint, ConnectedPlayer>();
private List<ClientConnection> mConnectionList = new List<ClientConnection>();
private LuaEngine mLuaEngine = new LuaEngine();
@ -83,10 +83,10 @@ namespace FFXIVClassic_Lobby_Server
mConnectionHealthThread.Name = "MapThread:Health";
//mConnectionHealthThread.Start();
mStaticActors = new StaticActors(STATIC_ACTORS_PATH);
mStaticActors = new StaticActors(STATIC_ACTORS_PATH);
gamedataItems = Database.getItemGamedata();
Log.info(String.Format("Loaded {0} items.",gamedataItems.Count));
Log.info(String.Format("Loaded {0} items.", gamedataItems.Count));
mWorldManager = new WorldManager(this);
mWorldManager.LoadZoneList();
@ -95,8 +95,9 @@ namespace FFXIVClassic_Lobby_Server
IPEndPoint serverEndPoint = new System.Net.IPEndPoint(IPAddress.Parse(ConfigConstants.OPTIONS_BINDIP), FFXIV_MAP_PORT);
try{
mServerSocket = new System.Net.Sockets.Socket(serverEndPoint.Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
try
{
mServerSocket = new System.Net.Sockets.Socket(serverEndPoint.Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
}
catch (Exception e)
{
@ -145,8 +146,8 @@ namespace FFXIVClassic_Lobby_Server
private void acceptCallback(IAsyncResult result)
{
ClientConnection conn = null;
Socket socket = (System.Net.Sockets.Socket)result.AsyncState;
Socket socket = (System.Net.Sockets.Socket)result.AsyncState;
try
{
@ -168,8 +169,8 @@ namespace FFXIVClassic_Lobby_Server
catch (SocketException)
{
if (conn != null)
{
{
lock (mConnectionList)
{
mConnectionList.Remove(conn);
@ -180,7 +181,7 @@ namespace FFXIVClassic_Lobby_Server
catch (Exception)
{
if (conn != null)
{
{
lock (mConnectionList)
{
mConnectionList.Remove(conn);
@ -224,7 +225,7 @@ namespace FFXIVClassic_Lobby_Server
lock (mConnectionList)
{
mConnectionList.Remove(conn);
}
}
if (conn.connType == BasePacket.TYPE_ZONE)
Log.conn(String.Format("{0} has disconnected.", conn.owner == 0 ? conn.getAddress() : "User " + conn.owner));
return;
@ -241,37 +242,37 @@ namespace FFXIVClassic_Lobby_Server
int offset = 0;
//Build packets until can no longer or out of data
while(true)
{
BasePacket basePacket = buildPacket(ref offset, conn.buffer, bytesRead);
//If can't build packet, break, else process another
if (basePacket == null)
break;
else
mProcessor.processPacket(conn, basePacket);
}
//Not all bytes consumed, transfer leftover to beginning
while (true)
{
BasePacket basePacket = buildPacket(ref offset, conn.buffer, bytesRead);
//If can't build packet, break, else process another
if (basePacket == null)
break;
else
mProcessor.processPacket(conn, basePacket);
}
//Not all bytes consumed, transfer leftover to beginning
if (offset < bytesRead)
Array.Copy(conn.buffer, offset, conn.buffer, 0, bytesRead - offset);
conn.lastPartialSize = bytesRead - offset;
//Build any queued subpackets into basepackets and send
conn.flushQueuedSendPackets();
if (offset < bytesRead)
//Need offset since not all bytes consumed
conn.flushQueuedSendPackets();
if (offset < bytesRead)
//Need offset since not all bytes consumed
conn.socket.BeginReceive(conn.buffer, bytesRead - offset, conn.buffer.Length - (bytesRead - offset), SocketFlags.None, new AsyncCallback(receiveCallback), conn);
else
//All bytes consumed, full buffer available
else
//All bytes consumed, full buffer available
conn.socket.BeginReceive(conn.buffer, 0, conn.buffer.Length, SocketFlags.None, new AsyncCallback(receiveCallback), conn);
}
else
{
Log.conn(String.Format("{0} has disconnected.", conn.owner == 0 ? conn.getAddress() : "User " + conn.owner));
Log.conn(String.Format("{0} has disconnected.", conn.owner == 0 ? conn.getAddress() : "User " + conn.owner));
lock (mConnectionList)
{
mConnectionList.Remove(conn);
@ -279,15 +280,15 @@ namespace FFXIVClassic_Lobby_Server
}
}
catch (SocketException)
{
{
if (conn.socket != null)
{
Log.conn(String.Format("{0} has disconnected.", conn.owner == 0 ? conn.getAddress() : "User " + conn.owner));
Log.conn(String.Format("{0} has disconnected.", conn.owner == 0 ? conn.getAddress() : "User " + conn.owner));
lock (mConnectionList)
{
mConnectionList.Remove(conn);
}
}
}
}
}
@ -325,532 +326,23 @@ namespace FFXIVClassic_Lobby_Server
}
return newPacket;
}
}
#endregion
public void sendPacket(ConnectedPlayer client, string path)
{
BasePacket packet = new BasePacket(path);
if (client != null)
{
packet.replaceActorID(client.actorID);
client.queuePacket(packet);
}
else
{
foreach (KeyValuePair<uint, ConnectedPlayer> entry in mConnectedPlayerList)
{
packet.replaceActorID(entry.Value.actorID);
entry.Value.queuePacket(packet);
}
}
public static WorldManager getWorldManager()
{
return mWorldManager;
}
public void changeProperty(uint id, uint value, string target)
{
SetActorPropetyPacket changeProperty = new SetActorPropetyPacket(target);
changeProperty.setTarget(target);
changeProperty.addInt(id, value);
changeProperty.addTarget();
foreach (KeyValuePair<uint, ConnectedPlayer> entry in mConnectedPlayerList)
{
SubPacket changePropertyPacket = changeProperty.buildPacket((entry.Value.actorID), (entry.Value.actorID));
BasePacket packet = BasePacket.createPacket(changePropertyPacket, true, false);
packet.debugPrintPacket();
entry.Value.queuePacket(packet);
}
}
public void doMusic(ConnectedPlayer client, string music)
{
ushort musicId;
if (music.ToLower().StartsWith("0x"))
musicId = Convert.ToUInt16(music, 16);
else
musicId = Convert.ToUInt16(music);
if (client != null)
client.queuePacket(BasePacket.createPacket(SetMusicPacket.buildPacket(client.actorID, musicId, 1), true, false));
else
{
foreach (KeyValuePair<uint, ConnectedPlayer> entry in mConnectedPlayerList)
{
BasePacket musicPacket = BasePacket.createPacket(SetMusicPacket.buildPacket(entry.Value.actorID, musicId, 1), true, false);
entry.Value.queuePacket(musicPacket);
}
}
}
public void doWarp(ConnectedPlayer client, string entranceId)
{
uint id;
try
{
if (entranceId.ToLower().StartsWith("0x"))
id = Convert.ToUInt32(entranceId, 16);
else
id = Convert.ToUInt32(entranceId);
}
catch(FormatException e)
{return;}
FFXIVClassic_Map_Server.WorldManager.ZoneEntrance ze = mWorldManager.getZoneEntrance(id);
if (ze == null)
return;
if (client != null)
mWorldManager.DoZoneChange(client.getActor(), ze.zoneId, ze.privateAreaName, ze.spawnType, ze.spawnX, ze.spawnY, ze.spawnZ, 0.0f);
else
{
foreach (KeyValuePair<uint, ConnectedPlayer> entry in mConnectedPlayerList)
{
mWorldManager.DoZoneChange(entry.Value.getActor(), ze.zoneId, ze.privateAreaName, ze.spawnType, ze.spawnX, ze.spawnY, ze.spawnZ, 0.0f);
}
}
}
public void doWarp(ConnectedPlayer client, string zone, string privateArea, string sx, string sy, string sz)
{
uint zoneId;
float x,y,z;
if (zone.ToLower().StartsWith("0x"))
zoneId = Convert.ToUInt32(zone, 16);
else
zoneId = Convert.ToUInt32(zone);
if (mWorldManager.GetZone(zoneId) == null)
{
if (client != null)
client.queuePacket(BasePacket.createPacket(SendMessagePacket.buildPacket(client.actorID, client.actorID, SendMessagePacket.MESSAGE_TYPE_GENERAL_INFO, "", "Zone does not exist or setting isn't valid."), true, false));
Log.error("Zone does not exist or setting isn't valid.");
}
x = Single.Parse(sx);
y = Single.Parse(sy);
z = Single.Parse(sz);
if (client != null)
mWorldManager.DoZoneChange(client.getActor(), zoneId, privateArea, 0x2, x, y, z, 0.0f);
else
{
foreach (KeyValuePair<uint, ConnectedPlayer> entry in mConnectedPlayerList)
{
mWorldManager.DoZoneChange(entry.Value.getActor(), zoneId, privateArea, 0x2, x, y, z, 0.0f);
}
}
}
public static WorldManager GetWorldManager()
{
return mWorldManager;
}
public void printPos(ConnectedPlayer client)
{
if (client != null)
{
Player p = client.getActor();
client.queuePacket(BasePacket.createPacket(SendMessagePacket.buildPacket(client.actorID, client.actorID, SendMessagePacket.MESSAGE_TYPE_GENERAL_INFO, "", String.Format("Position: {1}, {2}, {3}, {4}", p.customDisplayName, p.positionX, p.positionY, p.positionZ, p.rotation)), true, false));
}
else
{
foreach (KeyValuePair<uint, ConnectedPlayer> entry in mConnectedPlayerList)
{
Player p = entry.Value.getActor();
Log.info(String.Format("{0} position: {1}, {2}, {3}, {4}", p.customDisplayName, p.positionX, p.positionY, p.positionZ, p.rotation));
}
}
}
private void setGraphic(ConnectedPlayer client, uint slot, uint wId, uint eId, uint vId, uint cId)
{
if (client != null)
{
Player p = client.getActor();
p.graphicChange(slot, wId, eId, vId, cId);
p.sendAppearance();
}
else
{
foreach (KeyValuePair<uint, ConnectedPlayer> entry in mConnectedPlayerList)
{
Player p = entry.Value.getActor();
p.graphicChange(slot, wId, eId, vId, cId);
p.sendAppearance();
}
}
}
private void giveItem(ConnectedPlayer client, uint itemId, int quantity)
{
if (client != null)
{
Player p = client.getActor();
p.getInventory(Inventory.NORMAL).addItem(itemId, quantity);
}
else
{
foreach (KeyValuePair<uint, ConnectedPlayer> entry in mConnectedPlayerList)
{
Player p = entry.Value.getActor();
p.getInventory(Inventory.NORMAL).addItem(itemId, quantity);
}
}
}
private void giveItem(ConnectedPlayer client, uint itemId, int quantity, ushort type)
{
if (client != null)
{
Player p = client.getActor();
if (p.getInventory(type) != null)
p.getInventory(type).addItem(itemId, quantity);
}
else
{
foreach (KeyValuePair<uint, ConnectedPlayer> entry in mConnectedPlayerList)
{
Player p = entry.Value.getActor();
if (p.getInventory(type) != null)
p.getInventory(type).addItem(itemId, quantity);
}
}
}
private void removeItem(ConnectedPlayer client, uint itemId, int quantity)
{
if (client != null)
{
Player p = client.getActor();
p.getInventory(Inventory.NORMAL).removeItem(itemId, quantity);
}
else
{
foreach (KeyValuePair<uint, ConnectedPlayer> entry in mConnectedPlayerList)
{
Player p = entry.Value.getActor();
p.getInventory(Inventory.NORMAL).removeItem(itemId, quantity);
}
}
}
private void removeItem(ConnectedPlayer client, uint itemId, int quantity, ushort type)
{
if (client != null)
{
Player p = client.getActor();
if (p.getInventory(type) != null)
p.getInventory(type).removeItem(itemId, quantity);
}
else
{
foreach (KeyValuePair<uint, ConnectedPlayer> entry in mConnectedPlayerList)
{
Player p = entry.Value.getActor();
if (p.getInventory(type) != null)
p.getInventory(type).removeItem(itemId, quantity);
}
}
}
private void giveCurrancy(ConnectedPlayer client, uint itemId, int quantity)
{
if (client != null)
{
Player p = client.getActor();
p.getInventory(Inventory.CURRANCY).addItem(itemId, quantity);
}
else
{
foreach (KeyValuePair<uint, ConnectedPlayer> entry in mConnectedPlayerList)
{
Player p = entry.Value.getActor();
p.getInventory(Inventory.CURRANCY).addItem(itemId, quantity);
}
}
}
private void removeCurrancy(ConnectedPlayer client, uint itemId, int quantity)
{
if (client != null)
{
Player p = client.getActor();
p.getInventory(Inventory.CURRANCY).removeItem(itemId, quantity);
}
else
{
foreach (KeyValuePair<uint, ConnectedPlayer> entry in mConnectedPlayerList)
{
Player p = entry.Value.getActor();
p.getInventory(Inventory.CURRANCY).removeItem(itemId, quantity);
}
}
}
private void giveKeyItem(ConnectedPlayer client, uint itemId)
{
if (client != null)
{
Player p = client.getActor();
p.getInventory(Inventory.KEYITEMS).addItem(itemId, 1);
}
else
{
foreach (KeyValuePair<uint, ConnectedPlayer> entry in mConnectedPlayerList)
{
Player p = entry.Value.getActor();
p.getInventory(Inventory.KEYITEMS).addItem(itemId, 1);
}
}
}
private void removeKeyItem(ConnectedPlayer client, uint itemId)
{
if (client != null)
{
Player p = client.getActor();
p.getInventory(Inventory.KEYITEMS).removeItem(itemId, 1);
}
else
{
foreach (KeyValuePair<uint, ConnectedPlayer> entry in mConnectedPlayerList)
{
Player p = entry.Value.getActor();
p.getInventory(Inventory.KEYITEMS).removeItem(itemId, 1);
}
}
}
internal bool doCommand(string input, ConnectedPlayer client)
{
input.Trim();
if (input.StartsWith("!"))
input = input.Substring(1);
String[] split = input.Split(' ');
if (split.Length >= 1)
{
if (split[0].Equals("mypos"))
{
try
{
printPos(client);
return true;
}
catch (Exception e)
{
Log.error("Could not load packet: " + e);
}
}
else if (split[0].Equals("resetzone"))
{
if (client != null)
{
Log.info(String.Format("Got request to reset zone: {0}", client.getActor().zoneId));
client.getActor().zone.clear();
client.getActor().zone.addActorToZone(client.getActor());
client.getActor().sendInstanceUpdate();
client.queuePacket(BasePacket.createPacket(SendMessagePacket.buildPacket(client.actorID, client.actorID, SendMessagePacket.MESSAGE_TYPE_GENERAL_INFO, "", String.Format("Resting zone {0}...", client.getActor().zoneId)), true, false));
}
mWorldManager.reloadZone(client.getActor().zoneId);
return true;
}
else if (split[0].Equals("reloaditems"))
{
Log.info(String.Format("Got request to reload item gamedata"));
if (client != null)
client.getActor().queuePacket(SendMessagePacket.buildPacket(client.actorID, client.actorID, SendMessagePacket.MESSAGE_TYPE_GENERAL_INFO, "", "Reloading Item Gamedata..."));
gamedataItems.Clear();
gamedataItems = Database.getItemGamedata();
Log.info(String.Format("Loaded {0} items.", gamedataItems.Count));
if (client != null)
client.getActor().queuePacket(SendMessagePacket.buildPacket(client.actorID, client.actorID, SendMessagePacket.MESSAGE_TYPE_GENERAL_INFO, "", String.Format("Loaded {0} items.", gamedataItems.Count)));
return true;
}
else if (split[0].Equals("sendpacket"))
{
if (split.Length < 2)
return false;
try
{
sendPacket(client, "./packets/" + split[1]);
return true;
}
catch (Exception e)
{
Log.error("Could not load packet: " + e);
}
}
else if (split[0].Equals("graphic"))
{
try
{
if (split.Length == 6)
setGraphic(client, UInt32.Parse(split[1]), UInt32.Parse(split[2]), UInt32.Parse(split[3]), UInt32.Parse(split[4]), UInt32.Parse(split[5]));
return true;
}
catch (Exception e)
{
Log.error("Could not give item.");
}
}
else if (split[0].Equals("giveitem"))
{
try
{
if (split.Length == 2)
giveItem(client, UInt32.Parse(split[1]), 1);
else if (split.Length == 3)
giveItem(client, UInt32.Parse(split[1]), Int32.Parse(split[2]));
else if (split.Length == 4)
giveItem(client, UInt32.Parse(split[1]), Int32.Parse(split[2]), UInt16.Parse(split[3]));
return true;
}
catch (Exception e)
{
Log.error("Could not give item.");
}
}
else if (split[0].Equals("removeitem"))
{
if (split.Length < 2)
return false;
try
{
if (split.Length == 2)
removeItem(client, UInt32.Parse(split[1]), 1);
else if (split.Length == 3)
removeItem(client, UInt32.Parse(split[1]), Int32.Parse(split[2]));
else if (split.Length == 4)
removeItem(client, UInt32.Parse(split[1]), Int32.Parse(split[2]), UInt16.Parse(split[3]));
return true;
}
catch (Exception e)
{
Log.error("Could not remove item.");
}
}
else if (split[0].Equals("givekeyitem"))
{
try
{
if (split.Length == 2)
giveKeyItem(client, UInt32.Parse(split[1]));
}
catch (Exception e)
{
Log.error("Could not give keyitem.");
}
}
else if (split[0].Equals("removekeyitem"))
{
if (split.Length < 2)
return false;
try
{
if (split.Length == 2)
removeKeyItem(client, UInt32.Parse(split[1]));
return true;
}
catch (Exception e)
{
Log.error("Could not remove keyitem.");
}
}
else if (split[0].Equals("givecurrancy"))
{
try
{
if (split.Length == 2)
giveCurrancy(client, UInt32.Parse(split[1]), 1);
else if (split.Length == 3)
giveCurrancy(client, UInt32.Parse(split[1]), Int32.Parse(split[2]));
}
catch (Exception e)
{
Log.error("Could not give currancy.");
}
}
else if (split[0].Equals("removecurrancy"))
{
if (split.Length < 2)
return false;
try
{
if (split.Length == 2)
removeCurrancy(client, UInt32.Parse(split[1]), 1);
else if (split.Length == 3)
removeCurrancy(client, UInt32.Parse(split[1]), Int32.Parse(split[2]));
return true;
}
catch (Exception e)
{
Log.error("Could not remove currancy.");
}
}
else if (split[0].Equals("music"))
{
if (split.Length < 2)
return false;
try
{
doMusic(client, split[1]);
return true;
}
catch (Exception e)
{
Log.error("Could not change music: " + e);
}
}
else if (split[0].Equals("warp"))
{
if (split.Length == 2)
doWarp(client, split[1]);
else if (split.Length == 5)
doWarp(client, split[1], null, split[2], split[3], split[4]);
else if (split.Length == 6)
doWarp(client, split[1], split[2], split[3], split[4], split[5]);
return true;
}
else if (split[0].Equals("property"))
{
if (split.Length == 4)
{
changeProperty(Utils.MurmurHash2(split[1], 0), Convert.ToUInt32(split[2], 16), split[3]);
}
return true;
}
else if (split[0].Equals("property2"))
{
if (split.Length == 4)
{
changeProperty(Convert.ToUInt32(split[1], 16), Convert.ToUInt32(split[2], 16), split[3]);
}
return true;
}
}
return false;
}
public Dictionary<uint, ConnectedPlayer> getConnectedPlayerList()
{
return mConnectedPlayerList;
}
public static Dictionary<uint, Item> getItemGamedataList()
{
return gamedataItems;
}
}
}
}

View File

@ -372,26 +372,35 @@ namespace FFXIVClassic_Map_Server
}
//Add player to new zone and update
Area newArea;
if (destinationPrivateArea == null)
newArea = GetZone(destinationZoneId);
Area newArea;
if (destinationZoneId != 0)
{
if (destinationPrivateArea == null)
newArea = GetZone(destinationZoneId);
else
newArea = GetZone(destinationZoneId).getPrivateArea(destinationPrivateArea, 0);
}
else
newArea = GetZone(destinationZoneId).getPrivateArea(destinationPrivateArea, 0);
{
if (destinationPrivateArea == null)
newArea = GetZone(player.zoneId);
else
newArea = GetZone(player.zoneId).getPrivateArea(destinationPrivateArea, 0);
}
//This server does not contain that zoneId
if (newArea == null)
return;
newArea.addActorToZone(player);
//Update player actor's properties
player.zoneId = newArea.actorId;
player.zone = newArea;
player.positionX = spawnX;
player.positionY = spawnY;
player.positionZ = spawnZ;
player.rotation = spawnRotation;
newArea.addActorToZone(player);
//Update player actor's properties
player.zoneId = newArea.actorId;
player.zone = newArea;
player.positionX = spawnX;
player.positionY = spawnY;
player.positionZ = spawnZ;
player.rotation = spawnRotation;
//Send packets
player.playerSession.queuePacket(DeleteAllActorsPacket.buildPacket(player.actorId), true, false);

View File

@ -49,7 +49,7 @@ namespace FFXIVClassic_Map_Server.Actors
{
List<LuaParam> lParams;
Player player = Server.GetWorldManager().GetPCInWorld(playerActorId);
Player player = Server.getWorldManager().GetPCInWorld(playerActorId);
lParams = LuaEngine.doActorOnInstantiate(player, this);
if (lParams == null)

View File

@ -18,7 +18,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
public const ushort LOOT = 0x0004; //Max 0xA
public const ushort MELDREQUEST = 0x0005; //Max 0x04
public const ushort BAZAAR = 0x0007; //Max 0x0A
public const ushort CURRANCY = 0x0063; //Max 0x140
public const ushort CURRENCY = 0x0063; //Max 0x140
public const ushort KEYITEMS = 0x0064; //Max 0x500
public const ushort EQUIPMENT = 0x00FE; //Max 0x23
public const ushort EQUIPMENT_OTHERPLAYER = 0x00F9; //Max 0x23
@ -132,7 +132,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
{
Database.setQuantity(owner, slot, inventoryCode, list[slot].quantity);
if (inventoryCode != CURRANCY && inventoryCode != KEYITEMS)
if (inventoryCode != CURRENCY && inventoryCode != KEYITEMS)
sendInventoryPackets(list[slot]);
}
@ -144,13 +144,13 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
list.Add(addedItem);
if (inventoryCode != CURRANCY && inventoryCode != KEYITEMS)
if (inventoryCode != CURRENCY && inventoryCode != KEYITEMS)
sendInventoryPackets(addedItem);
quantityCount -= gItem.maxStack;
}
if (inventoryCode == CURRANCY || inventoryCode == KEYITEMS)
if (inventoryCode == CURRENCY || inventoryCode == KEYITEMS)
sendFullInventory();
owner.queuePacket(InventorySetEndPacket.buildPacket(owner.actorId));

View File

@ -43,7 +43,7 @@ namespace FFXIVClassic_Map_Server.lua
Script script = new Script();
((ScriptLoaderBase)script.Options.ScriptLoader).ModulePaths = new string[] { "./scripts/?", "./scripts/?.lua" };
script.Globals["getStaticActor"] = (Func<string, Actor>)Server.getStaticActors;
script.Globals["getWorldMaster"] = (Func<Actor>)Server.GetWorldManager().GetActor;
script.Globals["getWorldMaster"] = (Func<Actor>)Server.getWorldManager().GetActor;
script.Globals["getItemGamedata"] = (Func<uint, Item>)Server.getItemGamedata;
script.DoFile(luaPath);
DynValue result = script.Call(script.Globals["onInstantiate"], target);
@ -82,9 +82,9 @@ namespace FFXIVClassic_Map_Server.lua
{
Script script = new Script();
((ScriptLoaderBase)script.Options.ScriptLoader).ModulePaths = new string[] { "./scripts/?", "./scripts/?.lua" };
script.Globals["getWorldManager"] = (Func<WorldManager>)Server.GetWorldManager;
script.Globals["getWorldManager"] = (Func<WorldManager>)Server.getWorldManager;
script.Globals["getStaticActor"] = (Func<string, Actor>)Server.getStaticActors;
script.Globals["getWorldMaster"] = (Func<Actor>)Server.GetWorldManager().GetActor;
script.Globals["getWorldMaster"] = (Func<Actor>)Server.getWorldManager().GetActor;
script.Globals["getItemGamedata"] = (Func<uint, Item>)Server.getItemGamedata;
script.DoFile(luaPath);
@ -125,9 +125,9 @@ namespace FFXIVClassic_Map_Server.lua
{
Script script = new Script();
((ScriptLoaderBase)script.Options.ScriptLoader).ModulePaths = new string[] { "./scripts/?", "./scripts/?.lua" };
script.Globals["getWorldManager"] = (Func<WorldManager>)Server.GetWorldManager;
script.Globals["getWorldManager"] = (Func<WorldManager>)Server.getWorldManager;
script.Globals["getStaticActor"] = (Func<string, Actor>)Server.getStaticActors;
script.Globals["getWorldMaster"] = (Func<Actor>)Server.GetWorldManager().GetActor;
script.Globals["getWorldMaster"] = (Func<Actor>)Server.getWorldManager().GetActor;
script.Globals["getItemGamedata"] = (Func<uint, Item>)Server.getItemGamedata;
script.DoFile(luaPath);
@ -158,9 +158,9 @@ namespace FFXIVClassic_Map_Server.lua
{
Script script = new Script();
((ScriptLoaderBase)script.Options.ScriptLoader).ModulePaths = new string[] { "./scripts/?", "./scripts/?.lua" };
script.Globals["getWorldManager"] = (Func<WorldManager>)Server.GetWorldManager;
script.Globals["getWorldManager"] = (Func<WorldManager>)Server.getWorldManager;
script.Globals["getStaticActor"] = (Func<string, Actor>)Server.getStaticActors;
script.Globals["getWorldMaster"] = (Func<Actor>)Server.GetWorldManager().GetActor;
script.Globals["getWorldMaster"] = (Func<Actor>)Server.getWorldManager().GetActor;
script.Globals["getItemGamedata"] = (Func<uint, Item>)Server.getItemGamedata;
script.DoFile(luaPath);
@ -175,9 +175,9 @@ namespace FFXIVClassic_Map_Server.lua
{
Script script = new Script();
((ScriptLoaderBase)script.Options.ScriptLoader).ModulePaths = new string[] { "./scripts/?", "./scripts/?.lua" };
script.Globals["getWorldManager"] = (Func<WorldManager>)Server.GetWorldManager;
script.Globals["getWorldManager"] = (Func<WorldManager>)Server.getWorldManager;
script.Globals["getStaticActor"] = (Func<string, Actor>)Server.getStaticActors;
script.Globals["getWorldMaster"] = (Func<Actor>)Server.GetWorldManager().GetActor;
script.Globals["getWorldMaster"] = (Func<Actor>)Server.getWorldManager().GetActor;
script.Globals["getItemGamedata"] = (Func<uint, Item>)Server.getItemGamedata;
script.DoFile(FILEPATH_PLAYER);