Browse Source

Initial code commit.

pull/2/head
atom0s 8 years ago
parent
commit
ed8319177b
  1. 221
      .gitignore
  2. 22
      Servo.sln
  3. 52
      Source/Chat.cpp
  4. 438
      Source/Chat.hpp
  5. 79
      Source/CommandParser.h
  6. 5
      Source/Exports.def
  7. 97
      Source/Servo.h
  8. 202
      Source/Servo.vcproj
  9. 114
      Source/Servo.vcxproj
  10. BIN
      Source/libzmq.lib
  11. 594
      Source/main.cpp
  12. 416
      Source/zeromq/include/zmq.h
  13. 105
      Source/zeromq/include/zmq_utils.h
  14. 566
      Source/zmq.hpp

221
.gitignore vendored

@ -0,0 +1,221 @@
# ---> VisualStudio
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
build/
bld/
[Bb]in/
[Oo]bj/
# Visual Studio 2015 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# DNX
project.lock.json
artifacts/
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opensdf
*.sdf
*.cachefile
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# Windows Azure Build Output
csx/
*.build.csdef
# Windows Store app package directory
AppPackages/
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others
ClientBin/
[Ss]tyle[Cc]op.*
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.pfx
*.publishsettings
node_modules/
orleans.codegen.cs
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
*.mdf
*.ldf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
/Ashita.exp
/Ashita.lib

22
Servo.sln

@ -0,0 +1,22 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.30110.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Servo", "Source\Servo.vcxproj", "{19191E0E-AA6C-4BAB-800E-06ADFCB1ED5B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{19191E0E-AA6C-4BAB-800E-06ADFCB1ED5B}.Debug|Win32.ActiveCfg = Debug|Win32
{19191E0E-AA6C-4BAB-800E-06ADFCB1ED5B}.Debug|Win32.Build.0 = Debug|Win32
{19191E0E-AA6C-4BAB-800E-06ADFCB1ED5B}.Release|Win32.ActiveCfg = Release|Win32
{19191E0E-AA6C-4BAB-800E-06ADFCB1ED5B}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

52
Source/Chat.cpp

@ -0,0 +1,52 @@
#include "Chat.hpp"
namespace Chat{
void Log::putAutoTransOpen()
{
s.put('\xFF');
s.put('\xEF');
s.put('\x27');
}
void Log::putAutoTransClose()
{
s.put('\xFF');
s.put('\xEF');
s.put('\x28');
}
IAutoTrans Log::Region(unsigned char RegionID)
{
IAutoTrans i;
i.x = m_Ashita->GetResourceManager()->GetString("regions", RegionID, 0);
return i;
}
IAutoTrans Log::Zone(unsigned int ZoneID)
{
IAutoTrans i;
i.x = m_Ashita->GetResourceManager()->GetString("areas",ZoneID,0);
return i;
}
IAutoTrans Log::Keyitem(unsigned int ID)
{
IAutoTrans i;
i.x = m_Ashita->GetResourceManager()->GetString("keyitems",ID,0);
return i;
}
Log::Log() : m_Ashita(NULL)
{
mode = RecvdSay;
s = std::ostringstream();
}
Log::~Log()
{
}
void Log::SetCore(IAshitaCore* mAshitaCore)
{
m_Ashita = mAshitaCore;
}
};

438
Source/Chat.hpp

@ -0,0 +1,438 @@
#include <stdint.h>
#include <sstream>
#include <string>
#include "G:/Code/git.ashita.atom0s.com/Ashita v3/Ashita-src/build/plugins/ADK/Ashita.h"
#include <iostream>
namespace Chat
{
//typedef const char* IAutoTrans;
struct IAutoTrans{
const char* x;
};
enum Mode : short
{
// Info mostly taken from http://www.ffevo.net/wiki/index.php/ChatIDs
//----------------------
// Common "Chat" Modes
//----------------------
Unknown = 0, // Catch all. Do not use...it sometimes breaks the chat log.
SentSay = 0x1, // Outgoing Say
SentSay2 = 0x2, // Outgoing Say
SentTell = 0x4, // Outgoing Tell
SentParty = 0x5, // Outgoing Party
SentLinkShell = 0x6, // Outgoing Linkshell
SentEmote = 0x7, // Outgoing Emote, untargetted
RecvdSay = 0x9, // Incoming Say
RecvdSay2 = 0xA, // Incoming Say
RcvdTell = 0xC, // Incoming Tell
RcvdParty = 0xD, // Incoming Party (thanks Vanion for the correction!)
RcvdLinkShell = 0xE, // Incoming Linkshell
SentEmoteTo = 0xF, // Outgoing Emote, targeted
Echo = 0xCE, // Echo
//----------------------
// Action Modes
//----------------------
ActCallHelp = 0x10, // Call for Help!
ActFriendReq = 0x12, // Sent Friend Request
ActCastMagic = 0x13, //
ActHitDamage = 0x14, //
ActMiss = 0x15, //
ActDrained = 0x16, //
ActPTHitAbsorbed = 0x17, //
ActPTRecoverHP = 0x18, //
ActPTHitDamage = 0x19, //
ActPTMiss = 0x1A, //
ActPTDrained = 0x1B, //
ActDamaged = 0x1C, //
ActAvoidDamage = 0x1D, //
ActRecoverHealth = 0x1E, //
ActRecoverHP = 0x1F, //
ActPTDamaged = 0x20, //
ActPTAvoidDamage = 0x21, //
ActPCGainHealth = 0x22, //
ActPTHealedOther = 0x23, //
ActDefeats = 0x24, //
ActPCDeath = 0x25, //
ActDeath = 0x26, //
ActPTDeath = 0x27, //
ActPCDamage = 0x28, //
ActPCMiss = 0x29, //
ActPCRecoverHealth = 0x2A, //
ActPCHealsPC = 0x2B, //
ActPCDefeated = 0x2C, //
//----------------------
// Special Action Modes
//----------------------
SAct = 0x32, //
SActPT = 0x33, //
SActPC = 0x34, //
SActRecvdBenefit = 0x38, //
SActRecvdDetriment = 0x39, //
SActNoEffect = 0x3B, //
SActPTRecvdBenefit = 0x3C, //
SActPTRecvdDetriment = 0x3D,//
SActPTNoEffect = 0x3F, // Needs confirmation
SActPCRecvdBenefit = 0x40, //
SActPCRecvdDetriment = 0x41,//
SActPCNoEffect = 0x43, //
SActPTResisted = 0x44, //
SActOtherResisted = 0x45, //
SActSAttUse = 0x65, //
SActOtherBenefit = 0x6F, //
SActOtherDetriment = 0x70, //
SActOtherMissed = 0x72, //
SActSpellEffect = 0xBB, //
//----------------------
// Item Modes
//----------------------
ItemRecvdEffect = 0x51, //
ItemPCUsed = 0x55, //
ItemPCUsed2 = 0x5A, //
ItemLearnedSpell = 0x5B, //
//----------------------
// Mob Special Action Modes
//----------------------
MobActSAttUse = 0x64, //
MobActDetriment = 0x66, //
MobActSAttEvaded = 0x68, //
MobActSAttAoE = 0x69, //
MobActSupport = 0x6A, //
MobActDrain = 0x6B, //
MobActRAttMissed = 0x6D, //
MobActSAttInit = 0x6E, //
//----------------------
// System Message Modes
//----------------------
Sys1 = 0x79, // Target out of range, AH & synth feedback, Item feedback, trade feedback
Sys2 = 0x7A, // Entity chasing out of range, entity intimidated, raise, paralyzed, cannot see entity,
// casting interrupted, cannot attack, target already claimed, no exp gained
Sys3 = 0x7B, // Sneak/invis wearing, wait longer to perform action, chat not sent/recvd
SysObtainedItem = 0x7F, //
SysSkillGained = 0x81, //
SysExpLvlMerit = 0x83, //
SysInvitedToParty = 0x87, //
SysLogoutCountdown = 0x88, //
SysBazaar = 0x8A, //
SysTimePlayed = 0x8B, //
SysClock = 0x8C, //
SysDynamisWarning = 0x8D, //
SysTaunts = 0x8E, //
SysTutorialMoogle = 0x90, //
SysCaughtFish = 0x92, //
Sys4 = 0x94, // Digging/Fishing/Door/Ballista Feedback, Mission Gil Reward, Accepted Mission, Receive
// Mission Key Item, Gained Conquest Points
SysTimeRestriction = 0x95, //
SysTutorialNPC = 0x98, //
SysCommandError = 0x9D, // Also /help output
SysConquestUpdate = 0xA1, //
SysNeedKey = 0xBE, //
Sys5 = 0xBF, // Effect wears off, Detriment wears off, no longer stunned, fall to level
SysMOTD = 0xC8, // Also recast times (but not /recast feedback)
SysSearchComment = 0xCC, //
SysLinkshellMOTD = 0xCD, //
SysExamined = 0xD0, //
//----------------------
// Alliance Action Modes
//----------------------
AllyHealAlly = 0xA2, //
AllyDamage = 0xA3, //
AllyMiss = 0xA4, //
AllyDefeats = 0xA6, //
AllyDefeated = 0xA7, //
AllySAct = 0xA8, //
AllyNoEffect = 0xAA, //
AllyItemUse = 0xAB, //
AllyRecvdDetriment = 0xAE, //
AllyRecvdBenefit = 0xAF, //
AllyRecvdDetrimentAoE = 0xB6,//
AllyDamaged = 0xB9, //
AllyEvades = 0xBA, //
//----------------------
// NPC Action Modes
//----------------------
NPCSAct = 0xB1, //
NPCActDetriment = 0xB5, //
//----------------------
// Unknown or Unused Modes
//----------------------
SentYell = 0x03,
RecvdYell = 0x11,
//0x3
//0x8
//0xB
//0x11
//0x2D-0x31
//0x35-0x37
//0x3A
//0x3E
//0x42
//0x46-0x50
//0x52-0x54
//0x56-0x59
//0x5C-0x63
//0x67
//0x6C
//0x71
//0x73-0x78
//0x7C-0x7E
//0x80
//0x82
//0x84-0x86
//0x89
//0x8F
//0x91
//0x93
//0x96
//0x97
//0x99-0x9C
//0x9E-0xA0
//0xA5
//0xA9
//0xAC
//0xAD
//0xB0
//0xB2-0xB4
//0xB7
//0xB8
//0xBC
//0xBD
//0xC0-0xC7
//0xC9-0xCB
//0xCF
//0xD1-0xFF
};
enum Format {
LineBreak,// = 0x07, // Inserts an inline line break (does not flush)
Reset,// = 0x1E01,
Green,// = 0x1E02,
Blue,// = 0x1E03,
Purple,// = 0x1E05,
Aqua,// = 0x1E06,
Peach,// = 0x1E07,
White,// = 0x1E1A,
Gray,// = 0x1E1B,
Lilac,// = 0x1E3A,
BlueWhite,// = 0x1E3C,
InvisibleBlue,// = 0x1E62, // Ridiculously hard to read
Red,// = 0x1E69,
Yellow,// = 0x1E6E,
RoyalBlue,// = 0x1E71,
Invisible,// = 0x1E86, // This one really is invisible as far as I can tell
GreenWhite,// = 0x1E96,
SageGreen,// = 0x1EA0,
AutoTransOpen,// = 0xFFEF27,
AutoTransClose,// = 0xFFEF28,
EnterToContinue,// = 0x7F3101 // Waits one second before making prompt available. Can alter the last byte to change the timing.
};
enum Control
{
flush, //Flush the output to chat log and clears the buffer
clear, //Clears the buffer without writing it out
};
class Log{
private:
Mode mode;
std::ostringstream s;
IAshitaCore* m_Ashita;
void putAutoTransOpen();
void putAutoTransClose();
public:
Log &operator<<(Chat::Mode x)
{
mode = x;
return *this;
}
Log &operator<<(Chat::Format x)
{
switch (x)
{
case LineBreak:
s.put('\x07');
break;
case Reset:
s.put('\x1E');
s.put('\x01');
break;
case Green:
s.put('\x1E');
s.put('\x02');
break;
case Blue:
s.put('\x1E');
s.put('\x03');
break;
case Purple:
s.put('\x1E');
s.put('\x05');
break;
case Aqua:
s.put('\x1E');
s.put('\x06');
break;
case Peach:
s.put('\x1E');
s.put('\x07');
break;
case White:
s.put('\x1E');
s.put('\x1A');
break;
case Gray:
s.put('\x1E');
s.put('\x1B');
break;
case Lilac:
s.put('\x1E');
s.put('\x3A');
break;
case BlueWhite:
s.put('\x1E');
s.put('\x3C');
break;
case InvisibleBlue:
s.put('\x1E');
s.put('\x62');
break;
case Red:
s.put('\x1E');
s.put('\x69');
break;
case Yellow:
s.put('\x1E');
s.put('\x6E');
break;
case RoyalBlue:
s.put('\x1E');
s.put('\x71');
break;
case Invisible:
s.put('\x1E');
s.put('\x86');
break;
case GreenWhite:
s.put('\x1E');
s.put('\x96');
break;
case SageGreen:
s.put('\x1E');
s.put('\xA0');
break;
case AutoTransOpen:
putAutoTransOpen();
break;
case AutoTransClose:
putAutoTransClose();
break;
case EnterToContinue:
s.put('\x7F');
s.put('\x31');
s.put('\x01');
break;
}
return *this;
}
Log &operator<<(ISpell* x)
{
putAutoTransOpen();
s << x->Name;
putAutoTransClose();
return *this;
}
Log &operator<<(IAbility* x)
{
putAutoTransOpen();
s << x->Name;
putAutoTransClose();
return *this;
}
Log &operator<<(IItem* x)
{
putAutoTransOpen();
s << x->Name;
putAutoTransClose();
return *this;
}
Log &operator<<(Chat::IAutoTrans x)
{
putAutoTransOpen();
s << x.x;
putAutoTransClose();
return *this;
}
Log &operator<<(Chat::Control x)
{
switch(x)
{
case Control::flush:
m_Ashita->GetChatManager()->AddChatMessage(mode,s.str().c_str());
case Control::clear:
s = std::ostringstream();
break;
}
return *this;
}
Log &operator<<(const char* &x)
{
s << x;
return *this;
}
Log &operator<<(std::string &x)
{
s << x;
return *this;
}
Log &operator<<(const char x[])
{
s << x;
return *this;
}
Log();
~Log();
IAutoTrans Region(unsigned char RegionID);
IAutoTrans Zone(unsigned int ZoneID);
IAutoTrans Keyitem(unsigned int ID);
void SetCore(IAshitaCore* mAshitaCore);
};
};

79
Source/CommandParser.h

@ -0,0 +1,79 @@
#include <vector>
#include <stdint.h>
class CommandParser
{
private:
std::vector<char*> thisList;
uint8_t argC;
uint8_t argIdx;
public:
CommandParser()
{}
~CommandParser()
{}
void InputCommand(const char* szBuffer);
bool GetFirstCommand(std::string*);
bool GetCommandAt(unsigned int,std::string*);
bool GetNextCommand(std::string*);
bool GetRemainingCommands(std::string*);
unsigned int GetArgCount();
};
void CommandParser::InputCommand(const char* szBuffer)
{
thisList.clear();
argIdx = 0;
argC = 0;
uint8_t span = 0;
char* szTemp = const_cast<char*>(szBuffer);
char* tokenBuf;
for(char* substr = strtok_s(szTemp, " ",&tokenBuf);substr; substr = strtok_s(NULL, " ",&tokenBuf))
{
thisList.push_back(substr);
argC += 1;
}
}
bool CommandParser::GetFirstCommand(std::string* sReturn)
{
argIdx = 0;
return GetNextCommand(&*sReturn);
}
bool CommandParser::GetCommandAt(unsigned int idx, std::string* sReturn)
{
argIdx = idx;
return GetNextCommand(&*sReturn);
}
bool CommandParser::GetNextCommand(std::string* sReturn)
{
if(argIdx < argC)
{
*sReturn = thisList[argIdx];
argIdx += 1;
return true;
}
return false;
}
bool CommandParser::GetRemainingCommands(std::string* sReturn)
{
bool retVal = false;
*sReturn = "";
while(argIdx < argC)
{
sReturn->append(thisList[argIdx]);
sReturn->append(1,'\x20');
argIdx += 1;
retVal = true;
}
return retVal;
}
unsigned int CommandParser::GetArgCount()
{
return argC;
}

5
Source/Exports.def

@ -0,0 +1,5 @@
LIBRARY "Servo"
EXPORTS
GetInterfaceVersion
CreatePluginInfo
CreatePlugin

97
Source/Servo.h

@ -0,0 +1,97 @@
#ifndef __ASHITA_SERVO_H_INCLUDED__
#define __ASHITA_SERVO_H_INCLUDED__
#if defined (_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <deque>
#include <atomic>
#include <thread>
#include <mutex>
#include "zmq.hpp"
#include "G:/Code/git.ashita.atom0s.com/Ashita v3/Ashita-src/build/plugins/ADK/Ashita.h"
#include "CommandParser.h"
#include "Chat.hpp"
plugininfo_t* g_PluginInfo = NULL;
#pragma comment(lib,"libzmq.lib")
struct auto_follow
{
unsigned int unknown_ptr;
unsigned int TargetIndex;
unsigned int TargetID;
float DirectionX;
float DirectionY;
float DirectionZ;
float unknown_float; // 1 -- Deals with collision (CXiCollisionActor)
unsigned int unknown_ptr2;
unsigned int FollowIndex;
unsigned int FollowID;
unsigned char CameraMode; // 0 = third-person - 1 = first-person
unsigned char AutoRun;
};
namespace ServoMode {
enum Mode { Standby, Server, Client };
};
class Servo : IPlugin
{
private:
IAshitaCore* m_AshitaCore;
Chat::Log log;
std::string me;
auto_follow* StructPointer;
zmq::context_t zContext;
std::mutex lock;
std::atomic_bool connected;
std::atomic_bool follow;
std::atomic_bool zoning;
std::vector<std::string> groups;
std::thread conn;
std::thread pos;
std::deque<std::string> buffer;
std::atomic<ServoMode::Mode> state;
std::string servAddr;
std::mutex lservAddr;
std::string StringSub(std::string, std::string, std::string);
CommandParser* cmdParse;
void formatCommand(std::string* command);
void SendCommand(std::string command);
void RecvCommand(std::string* command);
void SetState(ServoMode::Mode mode);
void Sync(std::string host);
void WalkTo(float x, float y);
//Threads
void Serv();
void ServPos();
void Client();
void Follow();
public:
Servo() {}
~Servo() {}
plugininfo_t GetPluginInfo(void) override;
bool Initialize(IAshitaCore* ashitaCore, ILogManager* log, uint32_t dwPluginId) override;
void Release(void) override;
bool HandleCommand(const char* pszCommand, int nCommandType) override;
bool Direct3DInitialize(IDirect3DDevice8* lpDevice) override;
void Direct3DRender(void) override;
bool HandleIncomingPacket(uint16_t id, uint32_t size, void* data, void* modified, bool blocked) override;
bool HandleOutgoingPacket(uint16_t id, uint32_t size, void* data, void* modified, bool blocked) override;
};
#endif //__ASHITA_SERVO_H_INCLUDED__

202
Source/Servo.vcproj

@ -0,0 +1,202 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="Servo"
ProjectGUID="{EA36DE2F-4E69-4FF6-A007-AA919DBD6E43}"
RootNamespace="Servo"
Keyword="Win32Proj"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;SERVO_EXPORTS"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
ModuleDefinitionFile="exports.def"
GenerateDebugInformation="true"
SubSystem="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;SERVO_EXPORTS"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath=".\Exports.def"
>
</File>
<File
RelativePath=".\main.cpp"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath=".\Servo.h"
>
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

114
Source/Servo.vcxproj

@ -0,0 +1,114 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{19191E0E-AA6C-4BAB-800E-06ADFCB1ED5B}</ProjectGuid>
<RootNamespace>Servo</RootNamespace>
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
<PlatformToolset>v140_xp</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140_xp</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>$(SolutionDir)$(Configuration)\Plugins\</OutDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;SERVO_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<AdditionalIncludeDirectories>zeromq\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<ExceptionHandling>Async</ExceptionHandling>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<ModuleDefinitionFile>Exports.def</ModuleDefinitionFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<TargetMachine>MachineX86</TargetMachine>
<IgnoreSpecificDefaultLibraries>libci.lib</IgnoreSpecificDefaultLibraries>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<Optimization>Full</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;SERVO_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>false</FunctionLevelLinking>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<AdditionalIncludeDirectories>zeromq\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<ExceptionHandling>Async</ExceptionHandling>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<StringPooling>true</StringPooling>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<TargetMachine>MachineX86</TargetMachine>
<IgnoreSpecificDefaultLibraries>libci.lib</IgnoreSpecificDefaultLibraries>
<ModuleDefinitionFile>Exports.def</ModuleDefinitionFile>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<None Include="Exports.def" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="Chat.cpp" />
<ClCompile Include="main.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="Chat.hpp" />
<ClInclude Include="Servo.h" />
<ClInclude Include="CommandParser.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

BIN
Source/libzmq.lib

Binary file not shown.

594
Source/main.cpp

@ -0,0 +1,594 @@
#include "Servo.h"
#include <sstream>
#pragma comment(lib, "Psapi.lib")
#include <Psapi.h>
#include <algorithm>
#include <functional>
#include <cctype>
#include <locale>
// trim from start (in place)
static inline void ltrim(std::string &s) {
s.erase(s.begin(), std::find_if(s.begin(), s.end(),
std::not1(std::ptr_fun<int, int>(std::isspace))));
}
// trim from end (in place)
static inline void rtrim(std::string &s) {
s.erase(std::find_if(s.rbegin(), s.rend(),
std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
}
// trim from both ends (in place)
static inline void trim(std::string &s) {
ltrim(s);
rtrim(s);
}
// trim from start (copying)
static inline std::string ltrimmed(std::string s) {
ltrim(s);
return s;
}
// trim from end (copying)
static inline std::string rtrimmed(std::string s) {
rtrim(s);
return s;
}
// trim from both ends (copying)
static inline std::string trimmed(std::string s) {
trim(s);
return s;
}
std::string Servo::StringSub(std::string instring, std::string subin, std::string subout)
{
if (instring.find(subin) != std::string::npos)
return(instring.replace(instring.find(subin), subin.length(), subout));
else
return instring;
}
void Servo::formatCommand(std::string* command)
{
std::stringstream id;
id << m_AshitaCore->GetDataManager()->GetTarget()->GetTargetServerId();
*command = StringSub(*command, "[me]", m_AshitaCore->GetDataManager()->GetParty()->GetMemberName(0));
*command = StringSub(*command, "[p0]", m_AshitaCore->GetDataManager()->GetParty()->GetMemberName(0));
*command = StringSub(*command, "[p1]", m_AshitaCore->GetDataManager()->GetParty()->GetMemberName(1));
*command = StringSub(*command, "[p2]", m_AshitaCore->GetDataManager()->GetParty()->GetMemberName(2));
*command = StringSub(*command, "[p3]", m_AshitaCore->GetDataManager()->GetParty()->GetMemberName(3));
*command = StringSub(*command, "[p4]", m_AshitaCore->GetDataManager()->GetParty()->GetMemberName(4));
*command = StringSub(*command, "[p5]", m_AshitaCore->GetDataManager()->GetParty()->GetMemberName(5));
*command = StringSub(*command, "[t]", id.str());
}
void Servo::SendCommand(std::string command)
{
while (!lock.try_lock())
std::this_thread::sleep_for(std::chrono::milliseconds(20));
buffer.push_back(command);
lock.unlock();
}
void Servo::WalkTo(float x, float z)
{
if (zoning)
return;
auto myX = m_AshitaCore->GetDataManager()->GetEntity()->GetLocalX(m_AshitaCore->GetDataManager()->GetParty()->GetMemberTargetIndex(0));
auto myZ = m_AshitaCore->GetDataManager()->GetEntity()->GetLocalZ(m_AshitaCore->GetDataManager()->GetParty()->GetMemberTargetIndex(0));
auto myStatus = m_AshitaCore->GetDataManager()->GetEntity()->GetStatus(m_AshitaCore->GetDataManager()->GetParty()->GetMemberTargetIndex(0));
float dist = sqrt(pow((myX - x), 2.0f) + pow((myZ - z), 2.0f));
if (dist > 1.5f && (myStatus == 0 || myStatus == 5))
{
if (StructPointer->AutoRun != 1)
StructPointer->AutoRun = 1;
StructPointer->DirectionX = x - myX;
StructPointer->DirectionZ = z - myZ;
StructPointer->DirectionY = 0;
}
else
StructPointer->AutoRun = 0;
}
void Servo::RecvCommand(std::string* command)
{
command->erase();
if (lock.try_lock())
{
if (!buffer.empty())
{
command->swap(buffer.front());
buffer.pop_front();
}
lock.unlock();
}
}
void Servo::SetState(ServoMode::Mode mode)
{
ServoMode::Mode prevState = state;
state = ServoMode::Mode::Standby;
follow = false;
zoning = false;
connected = false;
if (prevState != ServoMode::Mode::Standby)
{
conn.join();
pos.join();
}
while (!buffer.empty())
buffer.pop_front();
state = mode;
}
void Servo::Sync(std::string host)
{
me = m_AshitaCore->GetDataManager()->GetParty()->GetMemberName(0);
log << Chat::Format::RoyalBlue << "Servo started in client mode, connected to: ";
while (!lservAddr.try_lock())
std::this_thread::sleep_for(std::chrono::milliseconds(50));
if (host != "")
{
servAddr = host;
log << servAddr;
}
else
{
servAddr = "";
log << "localhost";
}
lservAddr.unlock();
SetState(ServoMode::Mode::Client);
conn.swap(std::thread(&Servo::Client, this));
pos.swap(std::thread(&Servo::Follow, this));
log << Chat::Control::flush;
}
bool Servo::Initialize(IAshitaCore* ashitaCore, ILogManager* logManager, uint32_t dwPluginId)
{
this->m_AshitaCore = ashitaCore;
this->m_PluginId = dwPluginId;
// Obtain the base module information..
MODULEINFO mod = { 0 };
if (!::GetModuleInformation(::GetCurrentProcess(), ::GetModuleHandle("FFXiMain.dll"), &mod, sizeof(MODULEINFO)))
return false;
// Cast the data and scan for the pattern..
std::vector<uint8_t> data((uint8_t*)(uintptr_t)mod.lpBaseOfDll, (uint8_t*)(uintptr_t)mod.lpBaseOfDll + mod.SizeOfImage);
unsigned char* Pointer = (unsigned char*)Ashita::Memory::FindPattern(std::ref(data), (uintptr_t)mod.lpBaseOfDll, "8BCDE87F7????F8B0D7F7F7F7FE87F7F7F7F8BF885??750CB9", 0, 0);
StructPointer = NULL;
if (Pointer != NULL)
{
Pointer += 25;
StructPointer = (auto_follow*)(*((DWORD*)Pointer));
}
if (StructPointer)
{
StructPointer->DirectionX;
StructPointer->DirectionZ;
StructPointer->AutoRun;
}
cmdParse = new CommandParser;
state = ServoMode::Mode::Standby;
lservAddr.lock();
servAddr = "";
lservAddr.unlock();
me = "";
follow = false;
zoning = false;
zContext = zmq::context_t(1);
conn = std::thread();
pos = std::thread();
log.SetCore(m_AshitaCore);
log << Chat::Mode::Echo;
return 1;
}
void Servo::Serv()
{
zmq::socket_t publisher(zContext, ZMQ_PUB);
std::string hostmask = "tcp://";
while (!lservAddr.try_lock())
std::this_thread::sleep_for(std::chrono::milliseconds(50));
if (!servAddr.empty())
hostmask.append(servAddr);
else
hostmask.append("127.0.0.1");
lservAddr.unlock();
hostmask.append(":56556");
publisher.bind(hostmask.c_str());
connected = true;
while (connected) {
while (!lock.try_lock())
std::this_thread::sleep_for(std::chrono::milliseconds(50));
if (!buffer.empty())
{
auto it = buffer.begin();
zmq::message_t message(it->length() + 1);
strcpy_s((char*)message.data(), (size_t)(it->length() + 1), it->c_str());
buffer.pop_front();
lock.unlock();
publisher.send(message, ZMQ_DONTWAIT);
}
else
lock.unlock();
std::this_thread::sleep_for(std::chrono::milliseconds(20));
}
publisher.close();
}
void Servo::ServPos()
{
zmq::socket_t publisher(zContext, ZMQ_PUB);
std::string hostmask = "tcp://";
while (!lservAddr.try_lock())
std::this_thread::sleep_for(std::chrono::milliseconds(50));
if (!servAddr.empty())
hostmask.append(servAddr);
else
hostmask.append("127.0.0.1");
lservAddr.unlock();
hostmask.append(":56557");
publisher.bind(hostmask.c_str());
if (!connected)
std::this_thread::sleep_for(std::chrono::milliseconds(100));
while (connected) {
if (!zoning && m_AshitaCore->GetDataManager()->GetParty()->GetMemberTargetIndex(0))
{
auto myX = m_AshitaCore->GetDataManager()->GetEntity()->GetLocalX(m_AshitaCore->GetDataManager()->GetParty()->GetMemberTargetIndex(0));
auto myZ = m_AshitaCore->GetDataManager()->GetEntity()->GetLocalZ(m_AshitaCore->GetDataManager()->GetParty()->GetMemberTargetIndex(0));
std::stringstream ss;
ss << m_AshitaCore->GetDataManager()->GetParty()->GetMemberZone(0) << " " << myX << " " << myZ;
zmq::message_t message(strlen(ss.str().c_str()) + 1);
strcpy_s((char*)message.data(), strlen(ss.str().c_str()) + 1, ss.str().c_str());
publisher.send(message, ZMQ_DONTWAIT);
}
std::this_thread::sleep_for(std::chrono::milliseconds(200));
}
publisher.close();
}
void Servo::Client()
{
std::string host = "tcp://";
while (!lservAddr.try_lock())
std::this_thread::sleep_for(std::chrono::milliseconds(50));
if (!servAddr.empty())
host.append(servAddr);
else
host.append("localhost");
lservAddr.unlock();
host.append(":56556");
zmq::socket_t subscriber(zContext, ZMQ_SUB);
subscriber.connect(host.c_str());
subscriber.setsockopt(ZMQ_SUBSCRIBE, me.c_str(), me.size());
for (auto it = groups.begin(); it != groups.end(); ++it)
subscriber.setsockopt(ZMQ_SUBSCRIBE, it->c_str(), it->size());
subscriber.setsockopt(ZMQ_SUBSCRIBE, "::", 2);
subscriber.setsockopt(ZMQ_SUBSCRIBE, ":SERVOFUNC:", 11);
connected = true;
while (connected)
{
zmq::message_t update;
while (subscriber.recv(&update, ZMQ_DONTWAIT) == false)
{
if (connected)
std::this_thread::sleep_for(std::chrono::milliseconds(20));
else
break;
}
std::string s(static_cast<char*>(update.data()));
if (!s.empty())
{
while (!lock.try_lock())
std::this_thread::sleep_for(std::chrono::milliseconds(50));
buffer.push_back(s);
lock.unlock();
}
std::this_thread::sleep_for(std::chrono::milliseconds(20));
}
subscriber.close();
}
void Servo::Follow()
{
std::string host = "tcp://";
while (!lservAddr.try_lock())
std::this_thread::sleep_for(std::chrono::milliseconds(50));
if (!servAddr.empty())
host.append(servAddr);
else
host.append("localhost");
lservAddr.unlock();
host.append(":56557");
zmq::socket_t subscriber(zContext, ZMQ_SUB);
subscriber.connect(host.c_str());
subscriber.setsockopt(ZMQ_SUBSCRIBE, "", 0);
if (!connected)
std::this_thread::sleep_for(std::chrono::milliseconds(100));
while (connected)
{
zmq::message_t update;
while (follow)
{
update = zmq::message_t();
while (subscriber.recv(&update, ZMQ_DONTWAIT) == false)
{
if (connected)
std::this_thread::sleep_for(std::chrono::milliseconds(50));
else
break;
}
std::stringstream ss(static_cast<char*>(update.data()));
if (!ss.str().empty())
{
float WARPX, WARPY;
short zoneid;
ss >> zoneid >> WARPX >> WARPY;
if (zoneid == m_AshitaCore->GetDataManager()->GetParty()->GetMemberZone(0))
WalkTo(WARPX, WARPY);
else
StructPointer->AutoRun = 0; // If no longer sharing the same zone, stop running (will trigger after the server char has arrived in the new area, so there is some delay)
}
std::this_thread::sleep_for(std::chrono::milliseconds(50));
}
while (subscriber.recv(&update, ZMQ_DONTWAIT) == false)
{
if (connected & !follow)
std::this_thread::sleep_for(std::chrono::milliseconds(50));
else
break;
}
update.data(); // Discard data when not following.
std::this_thread::sleep_for(std::chrono::milliseconds(500));
}
subscriber.close();
}
void Servo::Release()
{
SetState(ServoMode::Mode::Standby);
zContext.close();
delete cmdParse;
}
plugininfo_t Servo::GetPluginInfo(void)
{
return (*g_PluginInfo);
}
bool Servo::HandleCommand(const char* szCommand, int iType)
{
if (iType == 0)
{
return false;
}
char szClean[1024];
if (iType != -2)
m_AshitaCore->GetChatManager()->ParseAutoTranslate(szCommand, szClean, 1024, false);
else
strncpy_s(szClean, szCommand, 1024);
std::string arg;
cmdParse->InputCommand(szClean);
cmdParse->GetFirstCommand(&arg);
if (arg == "/servo")
{
cmdParse->GetNextCommand(&arg);
if (arg == "on")
{
log << Chat::Format::RoyalBlue << "Servo started in server mode, with a hostmask of: ";
while (!lservAddr.try_lock())
std::this_thread::sleep_for(std::chrono::milliseconds(50));
if (cmdParse->GetNextCommand(&arg))
{
servAddr = arg;
log << servAddr;
}
else
{
servAddr = "";
log << "localhost";
}
lservAddr.unlock();
SetState(ServoMode::Mode::Server);
conn.swap(std::thread(&Servo::Serv, this));
pos.swap(std::thread(&Servo::ServPos, this));
log << Chat::Control::flush;
}
else if (arg == "sync")
{
if (!cmdParse->GetNextCommand(&arg))
arg = "";
Sync(arg);
}
else if (arg == "off")
{
SetState(ServoMode::Mode::Standby);
log << Chat::Format::RoyalBlue << "Servo set to standy!" << Chat::Control::flush;
}
else if (arg == "command" || arg == "send")
{
if (cmdParse->GetRemainingCommands(&arg))
{
arg = ":: " + arg;
formatCommand(&arg);
SendCommand(arg);
}
}
else if (arg == "sendto")
{
if (cmdParse->GetRemainingCommands(&arg))
{
formatCommand(&arg);
SendCommand(arg);
}
}
else if (arg == "followme")
{
if (state.load() == ServoMode::Mode::Server)
{
if (!cmdParse->GetNextCommand(&arg))
{
if (arg == "on")
SendCommand(":SERVOFUNC: FOLLOWON");
else if (arg == "off")
SendCommand(":SERVOFUNC: FOLLOWOFF");
}
else
SendCommand(":SERVOFUNC: FOLLOW");
}
}
else if (arg == "follow")
{
if (state.load() == ServoMode::Mode::Client)
{
if (!cmdParse->GetNextCommand(&arg))
{
if (arg == "on")
follow = true;
else if (arg == "off")
follow = false;
}
else
follow = follow ? false : true;
}
}
else if (arg == "addgroup")
{
std::string group;
cmdParse->GetNextCommand(&group);
groups.push_back(group);
if (state == ServoMode::Mode::Client)
Sync(servAddr);
}
else if (arg == "delgroup")
{
bool changed = false;
std::string group;
cmdParse->GetNextCommand(&group);
for (auto it = groups.begin(); it != groups.end();)
{
if (*it == group)
{
changed = true;
it = groups.erase(it);
}
else
++it;
}
if (state == ServoMode::Mode::Client && changed)
Sync(servAddr);
}
return true;
}
return false;
}
bool Servo::Direct3DInitialize(IDirect3DDevice8* mDevice)
{
return true;
}
void Servo::Direct3DRender()
{
if (state.load() == ServoMode::Mode::Client)
{
std::string commandtype;
std::string incommand;
RecvCommand(&incommand);
if (!incommand.empty())
{
commandtype = incommand.substr(0, incommand.find_first_of(" "));
incommand = incommand.substr(incommand.find_first_of(" ") + 1);
if (commandtype != ":SERVOFUNC:")
{
auto cmd = incommand;
trim(cmd);
m_AshitaCore->GetChatManager()->QueueCommand(cmd.c_str(), (int32_t)Ashita::CommandInputType::Menu);
}
else
{
if (incommand == "FOLLOWON")
follow = true;
else if (incommand == "FOLLOWOFF")
follow = false;
else if (incommand == "FOLLOW")
follow = follow ? false : true;
}
}
}
}
bool Servo::HandleOutgoingPacket(uint16_t id, uint32_t size, void* data, void* modified, bool blocked)
{
if (id == 0x5E)
zoning = true;
return false;
}
bool Servo::HandleIncomingPacket(uint16_t id, uint32_t size, void* data, void* modified, bool blocked)
{
if (id == 0x0A)
zoning = false;
return false;
}
__declspec(dllexport) double __stdcall GetInterfaceVersion(void)
{
return ASHITA_INTERFACE_VERSION;
}
__declspec(dllexport) void __stdcall CreatePluginInfo(plugininfo_t* lpBuffer)
{
g_PluginInfo = lpBuffer;
strcpy_s(g_PluginInfo->Name, sizeof(g_PluginInfo->Name), "Servo");
strcpy_s(g_PluginInfo->Author, sizeof(g_PluginInfo->Author), "bluekirby0");
g_PluginInfo->InterfaceVersion = ASHITA_INTERFACE_VERSION;
g_PluginInfo->PluginVersion = 3.00f;
g_PluginInfo->Priority = 0;
}
__declspec(dllexport) IPlugin* __stdcall CreatePlugin(void)
{
return (IPlugin*)new Servo();
}

416
Source/zeromq/include/zmq.h

@ -0,0 +1,416 @@
/*
Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file
This file is part of 0MQ.
0MQ is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
0MQ is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*************************************************************************
NOTE to contributors. This file comprises the principal public contract
for ZeroMQ API users (along with zmq_utils.h). Any change to this file
supplied in a stable release SHOULD not break existing applications.
In practice this means that the value of constants must not change, and
that old values may not be reused for new constants.
*************************************************************************
*/
#ifndef __ZMQ_H_INCLUDED__
#define __ZMQ_H_INCLUDED__
/* Version macros for compile-time API version detection */
#define ZMQ_VERSION_MAJOR 4
#define ZMQ_VERSION_MINOR 0
#define ZMQ_VERSION_PATCH 3
#define ZMQ_MAKE_VERSION(major, minor, patch) \
((major) * 10000 + (minor) * 100 + (patch))
#define ZMQ_VERSION \
ZMQ_MAKE_VERSION(ZMQ_VERSION_MAJOR, ZMQ_VERSION_MINOR, ZMQ_VERSION_PATCH)
#ifdef __cplusplus
extern "C" {
#endif
#if !defined _WIN32_WCE
#include <errno.h>
#endif
#include <stddef.h>
#include <stdio.h>
#if defined _WIN32
#include <winsock2.h>
#endif
/* Handle DSO symbol visibility */
#if defined _WIN32
# if defined ZMQ_STATIC
# define ZMQ_EXPORT
# elif defined DLL_EXPORT
# define ZMQ_EXPORT __declspec(dllexport)
# else
# define ZMQ_EXPORT __declspec(dllimport)
# endif
#else
# if defined __SUNPRO_C || defined __SUNPRO_CC
# define ZMQ_EXPORT __global
# elif (defined __GNUC__ && __GNUC__ >= 4) || defined __INTEL_COMPILER
# define ZMQ_EXPORT __attribute__ ((visibility("default")))
# else
# define ZMQ_EXPORT
# endif
#endif
/* Define integer types needed for event interface */
#if defined ZMQ_HAVE_SOLARIS || defined ZMQ_HAVE_OPENVMS
# include <inttypes.h>
#elif defined _MSC_VER && _MSC_VER < 1600
# ifndef int32_t
typedef __int32 int32_t;
# endif
# ifndef uint16_t
typedef unsigned __int16 uint16_t;
# endif
# ifndef uint8_t
typedef unsigned __int8 uint8_t;
# endif
#else
# include <stdint.h>
#endif
/******************************************************************************/
/* 0MQ errors. */
/******************************************************************************/
/* A number random enough not to collide with different errno ranges on */
/* different OSes. The assumption is that error_t is at least 32-bit type. */
#define ZMQ_HAUSNUMERO 156384712
/* On Windows platform some of the standard POSIX errnos are not defined. */
#ifndef ENOTSUP
#define ENOTSUP (ZMQ_HAUSNUMERO + 1)
#endif
#ifndef EPROTONOSUPPORT
#define EPROTONOSUPPORT (ZMQ_HAUSNUMERO + 2)
#endif
#ifndef ENOBUFS
#define ENOBUFS (ZMQ_HAUSNUMERO + 3)
#endif
#ifndef ENETDOWN
#define ENETDOWN (ZMQ_HAUSNUMERO + 4)
#endif
#ifndef EADDRINUSE
#define EADDRINUSE (ZMQ_HAUSNUMERO + 5)
#endif
#ifndef EADDRNOTAVAIL
#define EADDRNOTAVAIL (ZMQ_HAUSNUMERO + 6)
#endif
#ifndef ECONNREFUSED
#define ECONNREFUSED (ZMQ_HAUSNUMERO + 7)
#endif
#ifndef EINPROGRESS
#define EINPROGRESS (ZMQ_HAUSNUMERO + 8)
#endif
#ifndef ENOTSOCK
#define ENOTSOCK (ZMQ_HAUSNUMERO + 9)
#endif
#ifndef EMSGSIZE
#define EMSGSIZE (ZMQ_HAUSNUMERO + 10)
#endif
#ifndef EAFNOSUPPORT
#define EAFNOSUPPORT (ZMQ_HAUSNUMERO + 11)
#endif
#ifndef ENETUNREACH
#define ENETUNREACH (ZMQ_HAUSNUMERO + 12)
#endif
#ifndef ECONNABORTED
#define ECONNABORTED (ZMQ_HAUSNUMERO + 13)
#endif
#ifndef ECONNRESET
#define ECONNRESET (ZMQ_HAUSNUMERO + 14)
#endif
#ifndef ENOTCONN
#define ENOTCONN (ZMQ_HAUSNUMERO + 15)
#endif
#ifndef ETIMEDOUT
#define ETIMEDOUT (ZMQ_HAUSNUMERO + 16)
#endif
#ifndef EHOSTUNREACH
#define EHOSTUNREACH (ZMQ_HAUSNUMERO + 17)
#endif
#ifndef ENETRESET
#define ENETRESET (ZMQ_HAUSNUMERO + 18)
#endif
/* Native 0MQ error codes. */
#define EFSM (ZMQ_HAUSNUMERO + 51)
#define ENOCOMPATPROTO (ZMQ_HAUSNUMERO + 52)
#define ETERM (ZMQ_HAUSNUMERO + 53)
#define EMTHREAD (ZMQ_HAUSNUMERO + 54)
/* Run-time API version detection */
ZMQ_EXPORT void zmq_version (int *major, int *minor, int *patch);
/* This function retrieves the errno as it is known to 0MQ library. The goal */
/* of this function is to make the code 100% portable, including where 0MQ */
/* compiled with certain CRT library (on Windows) is linked to an */
/* application that uses different CRT library. */
ZMQ_EXPORT int zmq_errno (void);
/* Resolves system errors and 0MQ errors to human-readable string. */
ZMQ_EXPORT const char *zmq_strerror (int errnum);
/******************************************************************************/
/* 0MQ infrastructure (a.k.a. context) initialisation & termination. */
/******************************************************************************/
/* New API */
/* Context options */
#define ZMQ_IO_THREADS 1
#define ZMQ_MAX_SOCKETS 2
/* Default for new contexts */
#define ZMQ_IO_THREADS_DFLT 1
#define ZMQ_MAX_SOCKETS_DFLT 1023
ZMQ_EXPORT void *zmq_ctx_new (void);
ZMQ_EXPORT int zmq_ctx_term (void *context);
ZMQ_EXPORT int zmq_ctx_shutdown (void *ctx_);
ZMQ_EXPORT int zmq_ctx_set (void *context, int option, int optval);
ZMQ_EXPORT int zmq_ctx_get (void *context, int option);
/* Old (legacy) API */
ZMQ_EXPORT void *zmq_init (int io_threads);
ZMQ_EXPORT int zmq_term (void *context);
ZMQ_EXPORT int zmq_ctx_destroy (void *context);
/******************************************************************************/
/* 0MQ message definition. */
/******************************************************************************/
typedef struct zmq_msg_t {unsigned char _ [32];} zmq_msg_t;
typedef void (zmq_free_fn) (void *data, void *hint);
ZMQ_EXPORT int zmq_msg_init (zmq_msg_t *msg);
ZMQ_EXPORT int zmq_msg_init_size (zmq_msg_t *msg, size_t size);
ZMQ_EXPORT int zmq_msg_init_data (zmq_msg_t *msg, void *data,
size_t size, zmq_free_fn *ffn, void *hint);
ZMQ_EXPORT int zmq_msg_send (zmq_msg_t *msg, void *s, int flags);
ZMQ_EXPORT int zmq_msg_recv (zmq_msg_t *msg, void *s, int flags);
ZMQ_EXPORT int zmq_msg_close (zmq_msg_t *msg);
ZMQ_EXPORT int zmq_msg_move (zmq_msg_t *dest, zmq_msg_t *src);
ZMQ_EXPORT int zmq_msg_copy (zmq_msg_t *dest, zmq_msg_t *src);
ZMQ_EXPORT void *zmq_msg_data (zmq_msg_t *msg);
ZMQ_EXPORT size_t zmq_msg_size (zmq_msg_t *msg);
ZMQ_EXPORT int zmq_msg_more (zmq_msg_t *msg);
ZMQ_EXPORT int zmq_msg_get (zmq_msg_t *msg, int option);
ZMQ_EXPORT int zmq_msg_set (zmq_msg_t *msg, int option, int optval);
/******************************************************************************/
/* 0MQ socket definition. */
/******************************************************************************/
/* Socket types. */
#define ZMQ_PAIR 0
#define ZMQ_PUB 1
#define ZMQ_SUB 2
#define ZMQ_REQ 3
#define ZMQ_REP 4
#define ZMQ_DEALER 5
#define ZMQ_ROUTER 6
#define ZMQ_PULL 7
#define ZMQ_PUSH 8
#define ZMQ_XPUB 9
#define ZMQ_XSUB 10
#define ZMQ_STREAM 11
/* Deprecated aliases */
#define ZMQ_XREQ ZMQ_DEALER
#define ZMQ_XREP ZMQ_ROUTER
/* Socket options. */
#define ZMQ_AFFINITY 4
#define ZMQ_IDENTITY 5
#define ZMQ_SUBSCRIBE 6
#define ZMQ_UNSUBSCRIBE 7
#define ZMQ_RATE 8
#define ZMQ_RECOVERY_IVL 9
#define ZMQ_SNDBUF 11
#define ZMQ_RCVBUF 12
#define ZMQ_RCVMORE 13
#define ZMQ_FD 14
#define ZMQ_EVENTS 15
#define ZMQ_TYPE 16
#define ZMQ_LINGER 17
#define ZMQ_RECONNECT_IVL 18
#define ZMQ_BACKLOG 19
#define ZMQ_RECONNECT_IVL_MAX 21
#define ZMQ_MAXMSGSIZE 22
#define ZMQ_SNDHWM 23
#define ZMQ_RCVHWM 24
#define ZMQ_MULTICAST_HOPS 25
#define ZMQ_RCVTIMEO 27
#define ZMQ_SNDTIMEO 28
#define ZMQ_LAST_ENDPOINT 32
#define ZMQ_ROUTER_MANDATORY 33
#define ZMQ_TCP_KEEPALIVE 34
#define ZMQ_TCP_KEEPALIVE_CNT 35
#define ZMQ_TCP_KEEPALIVE_IDLE 36
#define ZMQ_TCP_KEEPALIVE_INTVL 37
#define ZMQ_TCP_ACCEPT_FILTER 38
#define ZMQ_IMMEDIATE 39
#define ZMQ_XPUB_VERBOSE 40
#define ZMQ_ROUTER_RAW 41
#define ZMQ_IPV6 42
#define ZMQ_MECHANISM 43
#define ZMQ_PLAIN_SERVER 44
#define ZMQ_PLAIN_USERNAME 45
#define ZMQ_PLAIN_PASSWORD 46
#define ZMQ_CURVE_SERVER 47
#define ZMQ_CURVE_PUBLICKEY 48
#define ZMQ_CURVE_SECRETKEY 49
#define ZMQ_CURVE_SERVERKEY 50
#define ZMQ_PROBE_ROUTER 51
#define ZMQ_REQ_CORRELATE 52
#define ZMQ_REQ_RELAXED 53
#define ZMQ_CONFLATE 54
#define ZMQ_ZAP_DOMAIN 55
/* Message options */
#define ZMQ_MORE 1
/* Send/recv options. */
#define ZMQ_DONTWAIT 1
#define ZMQ_SNDMORE 2
/* Security mechanisms */
#define ZMQ_NULL 0
#define ZMQ_PLAIN 1
#define ZMQ_CURVE 2
/* Deprecated options and aliases */
#define ZMQ_IPV4ONLY 31
#define ZMQ_DELAY_ATTACH_ON_CONNECT ZMQ_IMMEDIATE
#define ZMQ_NOBLOCK ZMQ_DONTWAIT
#define ZMQ_FAIL_UNROUTABLE ZMQ_ROUTER_MANDATORY
#define ZMQ_ROUTER_BEHAVIOR ZMQ_ROUTER_MANDATORY
/******************************************************************************/
/* 0MQ socket events and monitoring */
/******************************************************************************/
/* Socket transport events (tcp and ipc only) */
#define ZMQ_EVENT_CONNECTED 1
#define ZMQ_EVENT_CONNECT_DELAYED 2
#define ZMQ_EVENT_CONNECT_RETRIED 4
#define ZMQ_EVENT_LISTENING 8
#define ZMQ_EVENT_BIND_FAILED 16
#define ZMQ_EVENT_ACCEPTED 32
#define ZMQ_EVENT_ACCEPT_FAILED 64
#define ZMQ_EVENT_CLOSED 128
#define ZMQ_EVENT_CLOSE_FAILED 256
#define ZMQ_EVENT_DISCONNECTED 512
#define ZMQ_EVENT_MONITOR_STOPPED 1024
#define ZMQ_EVENT_ALL ( ZMQ_EVENT_CONNECTED | ZMQ_EVENT_CONNECT_DELAYED | \
ZMQ_EVENT_CONNECT_RETRIED | ZMQ_EVENT_LISTENING | \
ZMQ_EVENT_BIND_FAILED | ZMQ_EVENT_ACCEPTED | \
ZMQ_EVENT_ACCEPT_FAILED | ZMQ_EVENT_CLOSED | \
ZMQ_EVENT_CLOSE_FAILED | ZMQ_EVENT_DISCONNECTED | \
ZMQ_EVENT_MONITOR_STOPPED)
/* Socket event data */
typedef struct {
uint16_t event; // id of the event as bitfield
int32_t value ; // value is either error code, fd or reconnect interval
} zmq_event_t;
ZMQ_EXPORT void *zmq_socket (void *, int type);
ZMQ_EXPORT int zmq_close (void *s);
ZMQ_EXPORT int zmq_setsockopt (void *s, int option, const void *optval,
size_t optvallen);
ZMQ_EXPORT int zmq_getsockopt (void *s, int option, void *optval,
size_t *optvallen);
ZMQ_EXPORT int zmq_bind (void *s, const char *addr);
ZMQ_EXPORT int zmq_connect (void *s, const char *addr);
ZMQ_EXPORT int zmq_unbind (void *s, const char *addr);
ZMQ_EXPORT int zmq_disconnect (void *s, const char *addr);
ZMQ_EXPORT int zmq_send (void *s, const void *buf, size_t len, int flags);
ZMQ_EXPORT int zmq_send_const (void *s, const void *buf, size_t len, int flags);
ZMQ_EXPORT int zmq_recv (void *s, void *buf, size_t len, int flags);
ZMQ_EXPORT int zmq_socket_monitor (void *s, const char *addr, int events);
ZMQ_EXPORT int zmq_sendmsg (void *s, zmq_msg_t *msg, int flags);
ZMQ_EXPORT int zmq_recvmsg (void *s, zmq_msg_t *msg, int flags);
/* Experimental */
struct iovec;
ZMQ_EXPORT int zmq_sendiov (void *s, struct iovec *iov, size_t count, int flags);
ZMQ_EXPORT int zmq_recviov (void *s, struct iovec *iov, size_t *count, int flags);
/******************************************************************************/
/* I/O multiplexing. */
/******************************************************************************/
#define ZMQ_POLLIN 1
#define ZMQ_POLLOUT 2
#define ZMQ_POLLERR 4
typedef struct
{
void *socket;
#if defined _WIN32
SOCKET fd;
#else
int fd;
#endif
short events;
short revents;
} zmq_pollitem_t;
#define ZMQ_POLLITEMS_DFLT 16
ZMQ_EXPORT int zmq_poll (zmq_pollitem_t *items, int nitems, long timeout);
/* Built-in message proxy (3-way) */
ZMQ_EXPORT int zmq_proxy (void *frontend, void *backend, void *capture);
/* Encode a binary key as printable text using ZMQ RFC 32 */
ZMQ_EXPORT char *zmq_z85_encode (char *dest, uint8_t *data, size_t size);
/* Encode a binary key from printable text per ZMQ RFC 32 */
ZMQ_EXPORT uint8_t *zmq_z85_decode (uint8_t *dest, char *string);
/* Deprecated aliases */
#define ZMQ_STREAMER 1
#define ZMQ_FORWARDER 2
#define ZMQ_QUEUE 3
/* Deprecated method */
ZMQ_EXPORT int zmq_device (int type, void *frontend, void *backend);
#undef ZMQ_EXPORT
#ifdef __cplusplus
}
#endif
#endif

105
Source/zeromq/include/zmq_utils.h

@ -0,0 +1,105 @@
/*
Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file
This file is part of 0MQ.
0MQ is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
0MQ is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __ZMQ_UTILS_H_INCLUDED__
#define __ZMQ_UTILS_H_INCLUDED__
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/* Define integer types needed for event interface */
#if defined ZMQ_HAVE_SOLARIS || defined ZMQ_HAVE_OPENVMS
# include <inttypes.h>
#elif defined _MSC_VER && _MSC_VER < 1600
# ifndef int32_t
typedef __int32 int32_t;
# endif
# ifndef uint16_t
typedef unsigned __int16 uint16_t;
# endif
#else
# include <stdint.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* Handle DSO symbol visibility */
#if defined _WIN32
# if defined ZMQ_STATIC
# define ZMQ_EXPORT
# elif defined DLL_EXPORT
# define ZMQ_EXPORT __declspec(dllexport)
# else
# define ZMQ_EXPORT __declspec(dllimport)
# endif
#else
# if defined __SUNPRO_C || defined __SUNPRO_CC
# define ZMQ_EXPORT __global
# elif (defined __GNUC__ && __GNUC__ >= 4) || defined __INTEL_COMPILER
# define ZMQ_EXPORT __attribute__ ((visibility("default")))
# else
# define ZMQ_EXPORT
# endif
#endif
/* These functions are documented by man pages */
/* Encode data with Z85 encoding. Returns encoded data */
ZMQ_EXPORT char *zmq_z85_encode (char *dest, uint8_t *data, size_t size);
/* Decode data with Z85 encoding. Returns decoded data */
ZMQ_EXPORT uint8_t *zmq_z85_decode (uint8_t *dest, char *string);
/* Generate z85-encoded public and private keypair with libsodium. */
/* Returns 0 on success. */
ZMQ_EXPORT int zmq_curve_keypair (char *z85_public_key, char *z85_secret_key);
typedef void (zmq_thread_fn) (void*);
/* These functions are not documented by man pages */
/* Helper functions are used by perf tests so that they don't have to care */
/* about minutiae of time-related functions on different OS platforms. */
/* Starts the stopwatch. Returns the handle to the watch. */
ZMQ_EXPORT void *zmq_stopwatch_start (void);
/* Stops the stopwatch. Returns the number of microseconds elapsed since */
/* the stopwatch was started. */
ZMQ_EXPORT unsigned long zmq_stopwatch_stop (void *watch_);
/* Sleeps for specified number of seconds. */
ZMQ_EXPORT void zmq_sleep (int seconds_);
/* Start a thread. Returns a handle to the thread. */
ZMQ_EXPORT void *zmq_threadstart (zmq_thread_fn* func, void* arg);
/* Wait for thread to complete then free up resources. */
ZMQ_EXPORT void zmq_threadclose (void* thread);
#undef ZMQ_EXPORT
#ifdef __cplusplus
}
#endif
#endif

566
Source/zmq.hpp

@ -0,0 +1,566 @@
/*
Copyright (c) 2009-2011 250bpm s.r.o.
Copyright (c) 2011 Botond Ballo
Copyright (c) 2007-2009 iMatix Corporation
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#ifndef __ZMQ_HPP_INCLUDED__
#define __ZMQ_HPP_INCLUDED__
#include <zmq.h>
#include <algorithm>
#include <cassert>
#include <cstring>
#include <string>
#include <exception>
// Detect whether the compiler supports C++11 rvalue references.
#if (defined(__GNUC__) && (__GNUC__ > 4 || \
(__GNUC__ == 4 && __GNUC_MINOR__ > 2)) && \
defined(__GXX_EXPERIMENTAL_CXX0X__))
#define ZMQ_HAS_RVALUE_REFS
#define ZMQ_DELETED_FUNCTION = delete
#elif defined(__clang__)
#if __has_feature(cxx_rvalue_references)
#define ZMQ_HAS_RVALUE_REFS
#endif
#if __has_feature(cxx_deleted_functions)
#define ZMQ_DELETED_FUNCTION = delete
#else
#define ZMQ_DELETED_FUNCTION
#endif
#elif defined(_MSC_VER) && (_MSC_VER >= 1600)
#define ZMQ_HAS_RVALUE_REFS
#define ZMQ_DELETED_FUNCTION
#else
#define ZMQ_DELETED_FUNCTION
#endif
#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(3, 3, 0)
#define ZMQ_NEW_MONITOR_EVENT_LAYOUT
#endif
// In order to prevent unused variable warnings when building in non-debug
// mode use this macro to make assertions.
#ifndef NDEBUG
# define ZMQ_ASSERT(expression) assert(expression)
#else
# define ZMQ_ASSERT(expression) (void)(expression)
#endif
namespace zmq
{
typedef zmq_free_fn free_fn;
typedef zmq_pollitem_t pollitem_t;
class error_t : public std::exception
{
public:
error_t () : errnum (zmq_errno ()) {}
virtual const char *what () const throw ()
{
return zmq_strerror (errnum);
}
int num () const
{
return errnum;
}
private:
int errnum;
};
inline int poll (zmq_pollitem_t *items_, int nitems_, long timeout_ = -1)
{
int rc = zmq_poll (items_, nitems_, timeout_);
if (rc < 0)
throw error_t ();
return rc;
}
inline void proxy (void *frontend, void *backend, void *capture)
{
int rc = zmq_proxy (frontend, backend, capture);
if (rc != 0)
throw error_t ();
}
inline void version (int *major_, int *minor_, int *patch_)
{
zmq_version (major_, minor_, patch_);
}
class message_t
{
friend class socket_t;
public:
inline message_t ()
{
int rc = zmq_msg_init (&msg);
if (rc != 0)
throw error_t ();
}
inline explicit message_t (size_t size_)
{
int rc = zmq_msg_init_size (&msg, size_);
if (rc != 0)
throw error_t ();
}
inline message_t (void *data_, size_t size_, free_fn *ffn_,
void *hint_ = NULL)
{
int rc = zmq_msg_init_data (&msg, data_, size_, ffn_, hint_);
if (rc != 0)
throw error_t ();
}
#ifdef ZMQ_HAS_RVALUE_REFS
inline message_t (message_t &&rhs) : msg (rhs.msg)
{
int rc = zmq_msg_init (&rhs.msg);
if (rc != 0)
throw error_t ();
}
inline message_t &operator = (message_t &&rhs)
{
std::swap (msg, rhs.msg);
return *this;
}
#endif
inline ~message_t ()
{
int rc = zmq_msg_close (&msg);
ZMQ_ASSERT (rc == 0);
}
inline void rebuild ()
{
int rc = zmq_msg_close (&msg);
if (rc != 0)
throw error_t ();
rc = zmq_msg_init (&msg);
if (rc != 0)
throw error_t ();
}
inline void rebuild (size_t size_)
{
int rc = zmq_msg_close (&msg);
if (rc != 0)
throw error_t ();
rc = zmq_msg_init_size (&msg, size_);
if (rc != 0)
throw error_t ();
}
inline void rebuild (void *data_, size_t size_, free_fn *ffn_,
void *hint_ = NULL)
{
int rc = zmq_msg_close (&msg);
if (rc != 0)
throw error_t ();
rc = zmq_msg_init_data (&msg, data_, size_, ffn_, hint_);
if (rc != 0)
throw error_t ();
}
inline void move (message_t *msg_)
{
int rc = zmq_msg_move (&msg, &(msg_->msg));
if (rc != 0)
throw error_t ();
}
inline void copy (message_t *msg_)
{
int rc = zmq_msg_copy (&msg, &(msg_->msg));
if (rc != 0)
throw error_t ();
}
inline bool more ()
{
int rc = zmq_msg_more (&msg);
return rc != 0;
}
inline void *data ()
{
return zmq_msg_data (&msg);
}
inline const void* data () const
{
return zmq_msg_data (const_cast<zmq_msg_t*>(&msg));
}
inline size_t size () const
{
return zmq_msg_size (const_cast<zmq_msg_t*>(&msg));
}
private:
// The underlying message
zmq_msg_t msg;
// Disable implicit message copying, so that users won't use shared
// messages (less efficient) without being aware of the fact.
message_t (const message_t&);
void operator = (const message_t&);
};
class context_t
{
friend class socket_t;
public:
inline context_t ()
{
ptr = zmq_ctx_new ();
if (ptr == NULL)
throw error_t ();
}
inline explicit context_t (int io_threads_)
{
ptr = zmq_ctx_new ();
if (ptr == NULL)
throw error_t ();
int rc = zmq_ctx_set (ptr, ZMQ_IO_THREADS, io_threads_);
ZMQ_ASSERT (rc == 0);
}
#ifdef ZMQ_HAS_RVALUE_REFS
inline context_t (context_t &&rhs) : ptr (rhs.ptr)
{
rhs.ptr = NULL;
}
inline context_t &operator = (context_t &&rhs)
{
std::swap (ptr, rhs.ptr);
return *this;
}
#endif
inline ~context_t ()
{
close();
}
inline void close()
{
if (ptr == NULL)
return;
int rc = zmq_ctx_destroy (ptr);
ZMQ_ASSERT (rc == 0);
ptr = NULL;
}
// Be careful with this, it's probably only useful for
// using the C api together with an existing C++ api.
// Normally you should never need to use this.
inline operator void* ()
{
return ptr;
}
private:
void *ptr;
context_t (const context_t&);
void operator = (const context_t&);
};
class socket_t
{
friend class monitor_t;
public:
inline socket_t (context_t &context_, int type_)
{
ctxptr = context_.ptr;
ptr = zmq_socket (context_.ptr, type_);
if (ptr == NULL)
throw error_t ();
}
#ifdef ZMQ_HAS_RVALUE_REFS
inline socket_t(socket_t&& rhs) : ptr(rhs.ptr)
{
rhs.ptr = NULL;
}
inline socket_t& operator=(socket_t&& rhs)
{
std::swap(ptr, rhs.ptr);
return *this;
}
#endif
inline ~socket_t ()
{
close();
}
inline operator void* ()
{
return ptr;
}
inline void close()
{
if(ptr == NULL)
// already closed
return ;
int rc = zmq_close (ptr);
ZMQ_ASSERT (rc == 0);
ptr = 0 ;
}
inline void setsockopt (int option_, const void *optval_,
size_t optvallen_)
{
int rc = zmq_setsockopt (ptr, option_, optval_, optvallen_);
if (rc != 0)
throw error_t ();
}
inline void getsockopt (int option_, void *optval_,
size_t *optvallen_)
{
int rc = zmq_getsockopt (ptr, option_, optval_, optvallen_);
if (rc != 0)
throw error_t ();
}
inline void bind (const char *addr_)
{
int rc = zmq_bind (ptr, addr_);
if (rc != 0)
throw error_t ();
}
inline void unbind (const char *addr_)
{
int rc = zmq_unbind (ptr, addr_);
if (rc != 0)
throw error_t ();
}
inline void connect (const char *addr_)
{
int rc = zmq_connect (ptr, addr_);
if (rc != 0)
throw error_t ();
}
inline void disconnect (const char *addr_)
{
int rc = zmq_disconnect (ptr, addr_);
if (rc != 0)
throw error_t ();
}
inline bool connected()
{
return(ptr != NULL);
}
inline size_t send (const void *buf_, size_t len_, int flags_ = 0)
{
int nbytes = zmq_send (ptr, buf_, len_, flags_);
if (nbytes >= 0)
return (size_t) nbytes;
if (zmq_errno () == EAGAIN)
return 0;
throw error_t ();
}
inline bool send (message_t &msg_, int flags_ = 0)
{
int nbytes = zmq_msg_send (&(msg_.msg), ptr, flags_);
if (nbytes >= 0)
return true;
if (zmq_errno () == EAGAIN)
return false;
throw error_t ();
}
inline size_t recv (void *buf_, size_t len_, int flags_ = 0)
{
int nbytes = zmq_recv (ptr, buf_, len_, flags_);
if (nbytes >= 0)
return (size_t) nbytes;
if (zmq_errno () == EAGAIN)
return 0;
throw error_t ();
}
inline bool recv (message_t *msg_, int flags_ = 0)
{
int nbytes = zmq_msg_recv (&(msg_->msg), ptr, flags_);
if (nbytes >= 0)
return true;
if (zmq_errno () == EAGAIN)
return false;
throw error_t ();
}
private:
void *ptr;
void *ctxptr;
socket_t (const socket_t&) ZMQ_DELETED_FUNCTION;
void operator = (const socket_t&) ZMQ_DELETED_FUNCTION;
};
class monitor_t
{
public:
monitor_t() : socketPtr(NULL) {}
virtual ~monitor_t() {}
void monitor(socket_t &socket, const char *addr_, int events = ZMQ_EVENT_ALL)
{
int rc = zmq_socket_monitor(socket.ptr, addr_, events);
if (rc != 0)
throw error_t ();
socketPtr = socket.ptr;
void *s = zmq_socket (socket.ctxptr, ZMQ_PAIR);
assert (s);
rc = zmq_connect (s, addr_);
assert (rc == 0);
on_monitor_started();
while (true) {
zmq_msg_t eventMsg;
zmq_msg_init (&eventMsg);
rc = zmq_recvmsg (s, &eventMsg, 0);
if (rc == -1 && zmq_errno() == ETERM)
break;
assert (rc != -1);
zmq_event_t* event = static_cast<zmq_event_t*>(zmq_msg_data (&eventMsg));
#ifdef ZMQ_NEW_MONITOR_EVENT_LAYOUT
zmq_msg_t addrMsg;
zmq_msg_init (&addrMsg);
rc = zmq_recvmsg (s, &addrMsg, 0);
if (rc == -1 && zmq_errno() == ETERM)
break;
assert (rc != -1);
const char* str = static_cast<const char*>(zmq_msg_data (&addrMsg));
std::string address(str, str + zmq_msg_size(&addrMsg));
zmq_msg_close (&addrMsg);
#else
// Bit of a hack, but all events in the zmq_event_t union have the same layout so this will work for all event types.
std::string address = event->data.connected.addr;
#endif
#ifdef ZMQ_EVENT_MONITOR_STOPPED
if (event->event == ZMQ_EVENT_MONITOR_STOPPED)
break;
#endif
switch (event->event) {
case ZMQ_EVENT_CONNECTED:
on_event_connected(*event, address.c_str());
break;
case ZMQ_EVENT_CONNECT_DELAYED:
on_event_connect_delayed(*event, address.c_str());
break;
case ZMQ_EVENT_CONNECT_RETRIED:
on_event_connect_retried(*event, address.c_str());
break;
case ZMQ_EVENT_LISTENING:
on_event_listening(*event, address.c_str());
break;
case ZMQ_EVENT_BIND_FAILED:
on_event_bind_failed(*event, address.c_str());
break;
case ZMQ_EVENT_ACCEPTED:
on_event_accepted(*event, address.c_str());
break;
case ZMQ_EVENT_ACCEPT_FAILED:
on_event_accept_failed(*event, address.c_str());
break;
case ZMQ_EVENT_CLOSED:
on_event_closed(*event, address.c_str());
break;
case ZMQ_EVENT_CLOSE_FAILED:
on_event_close_failed(*event, address.c_str());
break;
case ZMQ_EVENT_DISCONNECTED:
on_event_disconnected(*event, address.c_str());
break;
default:
on_event_unknown(*event, address.c_str());
break;
}
zmq_msg_close (&eventMsg);
}
zmq_close (s);
socketPtr = NULL;
}
#ifdef ZMQ_EVENT_MONITOR_STOPPED
void abort()
{
if (socketPtr)
zmq_socket_monitor(socketPtr, NULL, 0);
}
#endif
virtual void on_monitor_started() {}
virtual void on_event_connected(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; }
virtual void on_event_connect_delayed(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; }
virtual void on_event_connect_retried(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; }
virtual void on_event_listening(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; }
virtual void on_event_bind_failed(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; }
virtual void on_event_accepted(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; }
virtual void on_event_accept_failed(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; }
virtual void on_event_closed(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; }
virtual void on_event_close_failed(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; }
virtual void on_event_disconnected(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; }
virtual void on_event_unknown(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; }
private:
void* socketPtr;
};
}
#endif
Loading…
Cancel
Save