diff --git a/GameControl/GlobalAPI/define.go b/GameControl/GlobalAPI/define.go deleted file mode 100644 index c207d0633..000000000 --- a/GameControl/GlobalAPI/define.go +++ /dev/null @@ -1,25 +0,0 @@ -package GlobalAPI - -import ( - "phoenixbuilder/GameControl/ResourcesControlCenter" - "phoenixbuilder/minecraft/protocol/packet" -) - -// 描述客户端的基本信息 -type BotInfo struct { - BotName string // 客户端的游戏昵称 - BotIdentity string // 客户端的唯一标识符 [当前还未使用] - BotUniqueID int64 // 客户端的唯一 ID [当前还未使用] - BotRunTimeID uint64 // 客户端的运行时 ID -} - -// 用于 PhoenixBuilder 与租赁服交互。 -// 此结构体下的实现将允许您与租赁服进行交互操作,例如打开容器等 -type GlobalAPI struct { - // 用于向租赁服发送数据包的函数 - WritePacket func(packet.Packet) error - // 存储客户端的基本信息 - BotInfo BotInfo - // PhoenixBuilder 的各类公用资源 - Resources *ResourcesControlCenter.Resources -} diff --git a/GameControl/GlobalAPI/getQuerytargetInfo.go b/GameControl/GlobalAPI/getQuerytargetInfo.go deleted file mode 100644 index a3dc2f40c..000000000 --- a/GameControl/GlobalAPI/getQuerytargetInfo.go +++ /dev/null @@ -1,116 +0,0 @@ -package GlobalAPI - -import ( - "encoding/json" - "fmt" - "phoenixbuilder/minecraft/protocol/packet" -) - -// 用于描述单个 querytarget 结果的结构体 -type QuerytargetInfo struct { - Dimension byte - Position [3]float32 - UniqueId string - YRot float32 -} - -// 解析 querytarget 命令的返回值为列表,因为同一时刻可以查询多个实体的相关数据。 -// 列表内单个数据的数据类型为 QuerytargetInfo 结构体 -func (g *GlobalAPI) ParseQuerytargetInfo(pk packet.CommandOutput) ([]QuerytargetInfo, error) { - ans := []QuerytargetInfo{} - // 初始化 - if pk.SuccessCount <= 0 || len(pk.OutputMessages[0].Parameters) <= 0 { - return []QuerytargetInfo{}, nil - } - // 如果命令失败或者未能找到任何可以解析的信息 - datas := pk.OutputMessages[0].Parameters[0] - var datasDecodeAns []interface{} - err := json.Unmarshal([]byte(datas), &datasDecodeAns) - if err != nil { - return []QuerytargetInfo{}, fmt.Errorf("ParseQuerytargetInfo: %v", err) - } - // 解析 JSON 数据 - for _, value := range datasDecodeAns { - newStruct := QuerytargetInfo{} - // 初始化 - val, normal := value.(map[string]interface{}) - if !normal { - return []QuerytargetInfo{}, fmt.Errorf("ParseQuerytargetInfo: Could not convert value into map[string]interface{}; value = %#v", value) - } - // 将列表中的被遍历元素解析为 map[string]interface{} - _, ok := val["dimension"] - if !ok { - return []QuerytargetInfo{}, fmt.Errorf("ParseQuerytargetInfo: Crashed in val[\"dimension\"]; val = %#v", val) - } - dimension, normal := val["dimension"].(float64) - if !normal { - return []QuerytargetInfo{}, fmt.Errorf("ParseQuerytargetInfo: Crashed in val[\"dimension\"]; val = %#v", val) - } - newStruct.Dimension = byte(dimension) - // dimension - _, ok = val["position"] - if !ok { - return []QuerytargetInfo{}, fmt.Errorf("ParseQuerytargetInfo: Crashed in val[\"position\"]; val = %#v", val) - } - position, normal := val["position"].(map[string]interface{}) - if normal { - _, ok := position["x"] - if !ok { - return []QuerytargetInfo{}, fmt.Errorf("ParseQuerytargetInfo: Crashed in val[\"position\"][\"x\"]; val[\"position\"] = %#v", position) - } - x, normal := position["x"].(float64) - if !normal { - return []QuerytargetInfo{}, fmt.Errorf("ParseQuerytargetInfo: Crashed in val[\"position\"][\"x\"]; val[\"position\"] = %#v", position) - } - newStruct.Position = [3]float32{float32(x), 0, 0} - // posx - _, ok = position["y"] - if !ok { - return []QuerytargetInfo{}, fmt.Errorf("ParseQuerytargetInfo: Crashed in val[\"position\"][\"y\"]; val[\"position\"] = %#v", position) - } - y, normal := position["y"].(float64) - if !normal { - return []QuerytargetInfo{}, fmt.Errorf("ParseQuerytargetInfo: Crashed in val[\"position\"][\"y\"]; val[\"position\"] = %#v", position) - } - newStruct.Position[1] = float32(y) - // posy - _, ok = position["z"] - if !ok { - return []QuerytargetInfo{}, fmt.Errorf("ParseQuerytargetInfo: Crashed in val[\"position\"][\"z\"]; val[\"position\"] = %#v", position) - } - z, normal := position["z"].(float64) - if !normal { - return []QuerytargetInfo{}, fmt.Errorf("ParseQuerytargetInfo: Crashed in val[\"position\"][\"z\"]; val[\"position\"] = %#v", position) - } - newStruct.Position[2] = float32(z) - // posz - } else { - return []QuerytargetInfo{}, fmt.Errorf("ParseQuerytargetInfo: Crashed in val[\"position\"]; val = %#v", val) - } - // position - _, ok = val["uniqueId"] - if !ok { - return []QuerytargetInfo{}, fmt.Errorf("ParseQuerytargetInfo: Crashed in val[\"uniqueId\"]; val = %#v", val) - } - uniqueId, normal := val["uniqueId"].(string) - if !normal { - return []QuerytargetInfo{}, fmt.Errorf("ParseQuerytargetInfo: Crashed in val[\"uniqueId\"]; val = %#v", val) - } - newStruct.UniqueId = uniqueId - // uniqueId - _, ok = val["yRot"] - if !ok { - return []QuerytargetInfo{}, fmt.Errorf("ParseQuerytargetInfo: Crashed in val[\"yRot\"]; val = %#v", val) - } - yRot, normal := val["yRot"].(float64) - if !normal { - return []QuerytargetInfo{}, fmt.Errorf("ParseQuerytargetInfo: Crashed in val[\"yRot\"]; val = %#v", val) - } - newStruct.YRot = float32(yRot) - // yRot - ans = append(ans, newStruct) - // append struct - } - return ans, nil - // 返回值 -} diff --git a/GameControl/GlobalAPI/sendcommand.go b/GameControl/GlobalAPI/sendcommand.go deleted file mode 100644 index 3894161dc..000000000 --- a/GameControl/GlobalAPI/sendcommand.go +++ /dev/null @@ -1,119 +0,0 @@ -package GlobalAPI - -import ( - "fmt" - "phoenixbuilder/minecraft/protocol" - "phoenixbuilder/minecraft/protocol/packet" - - "github.com/google/uuid" -) - -// 向租赁服发送 Sizukana 命令且无视返回值。 -// 当 sendDimensionalCmd 为真时, -// 将使用 execute 更换命令执行环境为机器人所在的环境 -func (g *GlobalAPI) SendSettingsCommand( - command string, - sendDimensionalCmd bool, -) error { - if sendDimensionalCmd { - command = fmt.Sprintf( - `execute @a[name="%v"] ~ ~ ~ %v`, - g.BotInfo.BotName, - command, - ) - } - err := g.WritePacket(&packet.SettingsCommand{ - CommandLine: command, - SuppressOutput: true, - }) - if err != nil { - return fmt.Errorf("SendSettingsCommand: %v", err) - } - return nil -} - -// 以 origin 的身份向租赁服发送命令且无视返回值。 -// 属于私有实现 -func (g *GlobalAPI) sendCommandPrivate( - command string, - uniqueId uuid.UUID, - origin uint32, -) error { - requestId, _ := uuid.Parse("96045347-a6a3-4114-94c0-1bc4cc561694") - err := g.WritePacket(&packet.CommandRequest{ - CommandLine: command, - CommandOrigin: protocol.CommandOrigin{ - Origin: origin, - UUID: uniqueId, - RequestID: requestId.String(), - }, - Internal: false, - UnLimited: false, - }) - if err != nil { - return fmt.Errorf("sendCommandPrivate: %v", err) - } - return nil -} - -// 以 origin 的身份向租赁服发送命令并且取得响应体。 -// 属于私有实现 -func (g *GlobalAPI) sendCMDWithRespPrivate( - command string, - origin uint32, -) (packet.CommandOutput, error) { - uniqueId := generateUUID() - err := g.Resources.Command.WriteRequest(uniqueId) - if err != nil { - return packet.CommandOutput{}, fmt.Errorf("sendCMDWithRespPrivate: %v", err) - } - // 写入请求到等待队列 - err = g.sendCommandPrivate(command, uniqueId, origin) - if err != nil { - return packet.CommandOutput{}, fmt.Errorf("sendCMDWithRespPrivate: %v", err) - } - // 发送命令 - ans, err := g.Resources.Command.LoadResponceAndDelete(uniqueId) - if err != nil { - return packet.CommandOutput{}, fmt.Errorf("sendCMDWithRespPrivate: %v", err) - } - // 等待租赁服响应命令请求并取得命令请求的返回值 - return ans, nil - // 返回值 -} - -// 以玩家的身份向租赁服发送命令且无视返回值 -func (g *GlobalAPI) SendCommand(command string, uniqueId uuid.UUID) error { - err := g.sendCommandPrivate(command, uniqueId, protocol.CommandOriginPlayer) - if err != nil { - return fmt.Errorf("SendCommand: %v", err) - } - return nil -} - -// 向租赁服发送 WS 命令且无视返回值 -func (g *GlobalAPI) SendWSCommand(command string, uniqueId uuid.UUID) error { - err := g.sendCommandPrivate(command, uniqueId, protocol.CommandOriginAutomationPlayer) - if err != nil { - return fmt.Errorf("SendWSCommand: %v", err) - } - return nil -} - -// 以玩家的身份向租赁服发送命令且获取返回值 -func (g *GlobalAPI) SendCommandWithResponce(command string) (packet.CommandOutput, error) { - resp, err := g.sendCMDWithRespPrivate(command, protocol.CommandOriginPlayer) - if err != nil { - return packet.CommandOutput{}, fmt.Errorf("SendCommandWithResponce: %v", err) - } - return resp, nil -} - -// 向租赁服发送 WS 命令且获取返回值 -func (g *GlobalAPI) SendWSCommandWithResponce(command string) (packet.CommandOutput, error) { - resp, err := g.sendCMDWithRespPrivate(command, protocol.CommandOriginAutomationPlayer) - if err != nil { - return packet.CommandOutput{}, fmt.Errorf("SendWSCommandWithResponce: %v", err) - } - return resp, nil -} diff --git a/Makefile b/Makefile index c0d93ab48..fede29be2 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: current all current-v8 current-arm64-executable ios-executable ios-v8-executable ios-lib ish-executable macos macos-v8 android-executable-armv7 android-executable-arm64 android-executable-x86_64 android-executable-x86 windows-executable windows-executable-x86 windows-executable-x86_64 freebsd-executable freebsd-executable-x86 freebsd-executable-x86_64 freebsd-executable-arm64 netbsd-executable netbsd-executable-x86 netbsd-executable-x86_64 netbsd-executable-arm64 netbsd-executable netbsd-executable-x86 netbsd-executable-x86_64 netbsd-executable-arm64 openwrt-mt7620-mipsel_24kc +.PHONY: current all current-v8 current-arm64-executable ios-executable ios-v8-executable ish-executable macos macos-v8 android-executable-armv7 android-executable-arm64 android-executable-x86_64 android-executable-x86 windows-executable windows-executable-x86 windows-executable-x86_64 freebsd-executable freebsd-executable-x86 freebsd-executable-x86_64 freebsd-executable-arm64 netbsd-executable netbsd-executable-x86 netbsd-executable-x86_64 netbsd-executable-arm64 netbsd-executable netbsd-executable-x86 netbsd-executable-x86_64 netbsd-executable-arm64 openwrt-mt7620-mipsel_24kc TARGETS:=build/ current current-no-readline current-v8 PACKAGETARGETS:= ifeq ($(shell uname | grep "Darwin" > /dev/null ; echo $${?}),0) @@ -6,13 +6,13 @@ ifeq ($(shell uname -m | grep -E "iPhone|iPad|iPod" > /dev/null ; echo $${?}),0) IOS_STRIP=/usr/bin/strip LIPO=/usr/bin/lipo LDID=/usr/bin/ldid -TARGETS:=${TARGETS} ios-executable ios-v8-executable ios-lib +TARGETS:=${TARGETS} ios-executable ios-v8-executable else IOS_STRIP=$(shell xcrun --sdk iphoneos -f strip) IOS_OBJCOPY=$(shell xcrun --sdk iphoneos -f objcopy) LDID=ldid2 LIPO=/usr/bin/lipo -TARGETS:=${TARGETS} macos ios-v8-executable ios-executable ios-lib +TARGETS:=${TARGETS} macos ios-v8-executable ios-executable endif PACKAGETARGETS:=${PACKAGETARGETS} package/ios else @@ -30,7 +30,7 @@ endif ### *-----------------------------------* ### ifneq (${THEOS},) - TARGETS:=${TARGETS} ios-executable ios-lib ios-v8-executable macos macos-v8 + TARGETS:=${TARGETS} ios-executable ios-v8-executable macos macos-v8 PACKAGETARGETS:=${PACKAGETARGETS} package/ios endif ifneq ($(wildcard ${HOME}/android-ndk-r20b),) @@ -77,7 +77,6 @@ current-v8: build/phoenixbuilder-v8 current-arm64-executable: build/phoenixbuilder-aarch64 ios-executable: build/phoenixbuilder-ios-executable ios-v8-executable: build/phoenixbuilder-v8-ios-executable -ios-lib: build/phoenixbuilder-ios-static.a ish-executable: build/phoenixbuilder-ish-executable macos: build/phoenixbuilder-macos macos-v8: build/phoenixbuilder-v8-macos @@ -144,8 +143,6 @@ build/phoenixbuilder-v8: build/ ${SRCS_GO} CGO_CFLAGS=${CGO_DEF}" -DWITH_V8" CGO_ENABLED=1 go build -tags "with_v8 ${APPEND_GO_TAGS}" -trimpath -ldflags "-s -w" -o build/phoenixbuilder-v8 build/libexternal_functions_provider.so: build/ io/external_functions_provider/provider.c gcc -shared io/external_functions_provider/provider.c -o build/libexternal_functions_provider.so -build/phoenixbuilder-static.a: build/ build/libexternal_functions_provider.so ${SRCS_GO} - CGO_CFLAGS=${CGO_DEF} CGO_LDFLAGS="-Lbuild -lexternal_functions_provider" CGO_ENABLED=1 go build -trimpath -buildmode=c-archive -ldflags "-s -w" -tags "no_readline,is_tweak ${APPEND_GO_TAGS}" -o build/phoenixbuilder-static.a build/phoenixbuilder-aarch64: build/ ${SRCS_GO} cd depends/stub&&make clean&&make CC=/usr/bin/aarch64-linux-gnu-gcc&&cd - GODEBUG=madvdontneed=1 CGO_CFLAGS=${CGO_DEF} CC=/usr/bin/aarch64-linux-gnu-gcc CGO_ENABLED=1 GOARCH=arm64 go build -tags use_aarch64_linux_rl -trimpath -ldflags "-s -w" -o build/phoenixbuilder-aarch64 @@ -159,8 +156,6 @@ build/phoenixbuilder-v8-ios-executable: build/ ${SRCS_GO} ${LDID} -Sios-ent.xml build/phoenixbuilder-v8-ios-executable build/libexternal_functions_provider.dylib: build/ io/external_functions_provider/provider.c `pwd`/archs/ios.sh io/external_functions_provider/provider.c -shared -o build/libexternal_functions_provider.dylib -build/phoenixbuilder-ios-static.a: build/ build/libexternal_functions_provider.dylib ${SRCS_GO} - CGO_CFLAGS=${CGO_DEF} CGO_LDFLAGS="-Lbuild -lexternal_functions_provider" CC=`pwd`/archs/ios.sh CGO_ENABLED=1 GOOS=ios GOARCH=arm64 go build -buildmode=c-archive -trimpath -ldflags "-s -w -extar ${THEOS}/toolchain/linux/iphone/bin/ar" -tags is_tweak,no_readline -o build/phoenixbuilder-ios-static.a build/phoenixbuilder-ish-executable: build/ ${SRCS_GO} cd depends/stub&&make clean&&make CC="${HOME}/i686-unknown-linux-musl/bin/i686-unknown-linux-musl-gcc --sysroot=`pwd`/../buildroot/ish -L`pwd`/../buildroot/ish/usr/lib" && cd - GODEBUG=madvdontneed=1 CGO_CFLAGS=${CGO_DEF} CC="${HOME}/i686-unknown-linux-musl/bin/i686-unknown-linux-musl-gcc --sysroot=`pwd`/depends/buildroot/ish" CGO_ENABLED=1 GOOS=linux GOARCH=386 go build -tags "ish" -trimpath -ldflags "-s -w" -o build/phoenixbuilder-ish-executable diff --git a/docs/bdump/bdump.md b/docs/bdump/bdump.md index b85dd2234..716c15f51 100644 --- a/docs/bdump/bdump.md +++ b/docs/bdump/bdump.md @@ -1,45 +1,43 @@ # BDump File Format -BDump v3 is a file format for storing Minecraft's structures. It is made of different commands that indicate the constructing process. +BDump v3 is a file format for storing Minecraft's structures, which is made of a set of commands indicating the constructing process. -By writing the ids that represent each blocks in a specific order is a workable plan that reduces the file size, but this would allow a large amount of unexpected air blocks that increasing the file size so we implemented a new format which has a pointer that indicates where the "brush" is, the file is a set of commands that tells the "brush" how to move, and where to place blocks. Within this file format, air blocks can be simply skipped by a move command so files can be smaller. +By writing the IDs of each blocks in a specific order is a workable plan for reducing the file size, but this would leave a large amount of unexpected air blocks increasing the file size. Therefore this format holding a pointer indicating the position of the "brush" is implemented. ## Basic File Structure -BDump v3 file's extension is `.bdx`, and the general header of it is `BD@`, which stands for that the file was compressed with brotli compression algorithm (the compress quality phoenixbuilder uses is 6). Note that there's also a header `BDZ` that stands for the file was compressed with gzip compression algorithm, which is no longer supported by PhoenixBuilder today since it has been deprecated for a long time and it's hard to find this type's file again. We define such kind of header as "compression header" and the content after it is compressed with the compression algorithm it indicates. +BDump v3 file's recommended extension is `.bdx`, whose general header is `BD@`, standing for a compression in `brotli` algorithm (default compressing quality: 6). Note that the header `BDZ` standing for a `gzip` compressed file is also possible, but is no longer supported by PhoenixBuilder since it has been deprecated for a long time and it's hard to find this type's file again. The content after the compression header is the data compressed with the compression algorithm it indicates. -> Tip: BDump v2's extension is `.bdp` and the header is `BDMPS\0\x02\0`. +> Note: BDump v2's extension is `.bdp` and the header is `BDMPS\0\x02\0`. -The header of the compressed content is `BDX\0`, and the author's player name that terminated with `\0` is followed right after it. Then the content after it is the command with arguments that written one-by-one tightly. Each command id would take 1 byte of space, like what an `unsigned char` do. +The header of the compressed content is `BDX\0`, and the author's player name terminated by `\0` following right after it (deprecated). The content after it is the command with arguments that written one-by-one tightly. Each command id would take 1 byte of space, like what an `unsigned char` do. -All the operations depend a `Vec3` value that represents the current position of the "brush". +All the operations depend on a shared `Vec3` value representing the current position of the "brush". -Let's see the list of commands first. +The list of commands is shown below. > Note: Integers would be written in **big endian**. > -> What is the difference of little endian and big endian? -> > For example, an int32 number in little endian, `1`, is `01 00 00 00` in the memory, and the memory of an int32 number `1` in big endian is `00 00 00 01`. Type definition: -* {int}: a number that can be positive, negative or zero. -* {unsigned int}: a number that can be positive or zero. -* `char`: an {int} value with 1 byte long. -* `unsigned char`: an {unsigned int} value with 1 byte long. -* `short`: an {int} value with 2 bytes long. -* `unsigned short`: an {unsigned int} value with 2 bytes long. -* `int32_t`: an {int} value with 4 bytes long. -* `uint32_t`: an {unsigned int} value with 4 bytes long. -* `char *`: a string that terminated with `\0` (encoding is utf-8). +* {int}: an integer that can be positive, negative or zero. +* {unsigned int}: an integer that can be positive or zero. +* `char`: an 1-byte-long {int} value. +* `unsigned char`: an 1-byte-long {unsigned int} value. +* `short`/`int16_t`: a 2-byte-long {int} value. +* `unsigned short`/`uint16_t`: a 2-byte-long {unsigned int} value. +* `int32_t`: a 4-byte-long {int} value. +* `uint32_t`: a 4-byte-long {unsigned int} value. +* `char *`: a string terminated by `\0` (utf-8 encoded). * `int`: alias of `int32_t` * `unsigned int`: alias of `uint32_t` -* `bool`: a value that can be either `true(1)` or `false(0)`, 1 byte long. +* `bool`: an 1-byte-long value that can be either `true(1)` or `false(0)`. | ID | Internal name | Description | Arguments | | ----------------- | --------------------------------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | -| 1 | `CreateConstantString` | Add the specified string to the palette, and the ID of the string is sorted in the term of the command called, e.g. the ID when assigning the first string given is `0`, and the ID of the second time is `1`. The maximum count of strings is `65536`. | `char *constantString` | +| 1 | `CreateConstantString` | Add the specified string to the palette, whose ID is sorted by the order of having the command called, e.g. the ID of the first constant string given is `0`, and the ID of the second one is `1`. The maximum count of strings is `65536`. | `char *constantString` | | 2 | **DEPRECATED and REMOVED** | - | - | | 3 | **DEPRECATED and REMOVED** | - | - | | 4 | **DEPRECATED and REMOVED** | - | - | @@ -83,7 +81,7 @@ Type definition: | 88, `'X'`, `0x58` | `Terminate` | Stop reading. Note that although the general end is "XE" (2 bytes long), a 'X' (1 byte long) character is enough. | - | | 90, `0x5A` | `isSigned` (fake command) | A command that functions a little different with other commands, its argument is the previous byte of it, would only appear in the end of the file. An invalid signature would prevent PhoenixBuilder from constructing the structure. See paragraph `Signing` for reference. | `unsigned char signatureSize` | -The list above is all the commands of the bdump v4 till 2022-1-29. +The list above is all the commands of the bdump v4 till June 26th of 2023. For the `struct ChestData` data format: diff --git a/fastbuilder/args/args.c b/fastbuilder/args/args.c index 11674f204..ca13af0aa 100644 --- a/fastbuilder/args/args.c +++ b/fastbuilder/args/args.c @@ -8,6 +8,13 @@ #include #endif #include +#include +#ifdef WIN32 +#ifndef __MINGW32__ +#error "This file uses gcc-specific features, please consider switching to mingw gcc." +#endif +#include +#endif #ifndef FB_VERSION #define FB_VERSION "(CUSTOMIZED)" @@ -16,37 +23,41 @@ #warning "It seems that you're building PhoenixBuilder with plain `go build` command, it is highly recommended to use `make current` instead." #endif +struct go_string { + char *buf; + uint64_t length; +}; + +#define EMPTY_GOSTRING {"",0} + char args_isDebugMode=0; -char args_disableHashCheck=0; -char replaced_auth_server=0; -char *newAuthServer; -char args_muteWorldChat=0; -char args_noPyRpc=1; -char use_startup_script=0; -char *startup_script; -char specified_server=0; -char *server_code; -char *server_password=""; -char custom_token=0; -char *token_content; -char *externalListenAddr=""; -char *capture_output_file=""; +char args_disableVersionCheck=0; +struct go_string newAuthServer={ + "wss://api.fastbuilder.pro:2053/", + 31 +}; +struct go_string startup_script=EMPTY_GOSTRING; +struct go_string server_code=EMPTY_GOSTRING; +struct go_string server_password=EMPTY_GOSTRING; +struct go_string token_content=EMPTY_GOSTRING; +struct go_string externalListenAddr=EMPTY_GOSTRING; +struct go_string capture_output_file=EMPTY_GOSTRING; char args_no_readline=0; -char *pack_scripts=""; -char *pack_scripts_out=""; +struct go_string pack_scripts=EMPTY_GOSTRING; +struct go_string pack_scripts_out=EMPTY_GOSTRING; char enable_omega_system=0; -char *custom_gamename=""; +struct go_string custom_gamename=EMPTY_GOSTRING; char ingame_response=0; extern void custom_script_engine_const(const char *key, const char *val); extern void do_suppress_se_const(const char *key); +// TODO: Localizations via Gettext/Glibc intl void print_help(const char *self_name) { printf("%s [options]\n",self_name); printf("\t--debug: Run in debug mode.\n"); printf("\t-A , --auth-server=: Use the specified authentication server, instead of the default one.\n"); printf("\t--no-update-check: Suppress update notifications.\n"); - printf("\t-M, --no-world-chat: Ignore world chat on client side.\n"); printf("\t--force-pyrpc: Enable the PyRpcPacket interaction, client will be kicked automatically by netease's rental server.\n"); #ifdef WITH_V8 printf("\t-S, --script=<*.js>: run a .js script at start\n"); @@ -73,22 +84,6 @@ void print_help(const char *self_name) { printf("\t\t--version-plain: Show the version of this program.\n"); } -char *get_fb_version() { -#ifdef FBGUI_VERSION - return FB_VERSION "@" FBGUI_VERSION " (" FB_COMMIT ")"; -#else - return FB_VERSION " (" FB_COMMIT ")"; -#endif -} - -char *get_fb_plain_version() { -#ifdef FBGUI_VERSION - return FBGUI_VERSION; -#else - return FB_VERSION; -#endif -} - char *commit_hash() { return FB_COMMIT_LONG; } @@ -118,12 +113,29 @@ void read_token(char *token_path) { fseek(file,0,SEEK_END); size_t flen=ftell(file); fseek(file,0,SEEK_SET); - token_content=malloc(flen+1); - token_content[flen]=0; - fread(token_content, 1, flen, file); + token_content.length=flen; + token_content.buf=malloc(flen); + fread(token_content.buf, 1, flen, file); fclose(file); } +void quickmake(struct go_string **target_ptr) { + size_t length=strlen(optarg); + char *data=malloc(length); + memcpy(data, optarg, length); + *target_ptr=malloc(16); + (*target_ptr)->buf=data; + (*target_ptr)->length=length; +} + +void quickset(struct go_string *target_ptr) { + size_t length=strlen(optarg); + char *data=malloc(length); + memcpy(data, optarg, length); + target_ptr->buf=data; + target_ptr->length=length; +} + void quickcopy(char **target_ptr) { size_t length=strlen(optarg)+1; *target_ptr=malloc(length); @@ -230,10 +242,11 @@ int _parse_args(int argc, char **argv) { args_isDebugMode=1; break; case 3: - args_disableHashCheck=1; + args_disableVersionCheck=1; break; case 5: - args_noPyRpc=0; + fprintf(stderr, "--force-pyrpc not available\n"); + return 10; break; case 6: fprintf(stderr, "--no-nbt option is no longer available.\n"); @@ -274,13 +287,13 @@ int _parse_args(int argc, char **argv) { args_no_readline=1; break; case 18: - quickcopy(&pack_scripts); + quickset(&pack_scripts); break; case 19: - quickcopy(&pack_scripts_out); + quickset(&pack_scripts_out); break; case 20: - quickcopy(&capture_output_file); + quickset(&capture_output_file); break; case 23: ingame_response=1; @@ -294,38 +307,29 @@ int _parse_args(int argc, char **argv) { print_help(argv[0]); return 0; case 'A': - replaced_auth_server=1; - quickcopy(&newAuthServer); - break; - case 'M': - args_muteWorldChat=1; + quickset(&newAuthServer); break; case 'S': #ifndef WITH_V8 fprintf(stderr,"-S, --script option isn't available: No V8 linked for this version.\n"); return 10; #endif - use_startup_script=1; - quickcopy(&startup_script); + quickset(&startup_script); break; case 'c': - specified_server=1; - quickcopy(&server_code); + quickset(&server_code); break; case 'p': - specified_server=1; - quickcopy(&server_password); + quickset(&server_password); break; case 't': - custom_token=1; read_token(optarg); break; case 'T': - custom_token=1; - quickcopy(&token_content); + quickset(&token_content); break; case 'E': - quickcopy(&externalListenAddr); + quickset(&externalListenAddr); break; case 'v': print_version(1); @@ -334,7 +338,7 @@ int _parse_args(int argc, char **argv) { enable_omega_system=1; break; case 'N': - quickcopy(&custom_gamename); + quickset(&custom_gamename); break; default: print_help(argv[0]); @@ -344,10 +348,74 @@ int _parse_args(int argc, char **argv) { return -1; } -void parse_args(int argc, char **argv) { +struct go_string args_var_fbversion_struct={ + FB_VERSION " (" FB_COMMIT ")", + sizeof(FB_VERSION " (" FB_COMMIT ")")-1 +}; + +/* +// Go uses a different ABI than C, which would use BX for the 2nd return, +// and we couldn't do that w/o asm. +struct go_string *args_func_authServer() { + if(!newAuthServer) { + static struct go_string original_auth_server={ + "wss://api.fastbuilder.pro:2053/", + 31 + }; + return &original_auth_server; + } + return newAuthServer; +}*/ + +struct go_string args_var_fbplainversion_struct={ + FB_VERSION, + sizeof(FB_VERSION)-1 +}; + +struct go_string args_fb_commit_struct={ + FB_COMMIT, + sizeof(FB_COMMIT)-1 +}; + +int args_has_specified_server() { + return server_code.length!=0; +} + +int args_specified_token() { + return token_content.length!=0; +} + +#ifndef WIN32 +__attribute__((constructor)) static void parse_args(int argc, char **argv) { int ec; if((ec=_parse_args(argc,argv))!=-1) { exit(ec); } return; } +#else +__attribute__((constructor)) static void parse_args_win32() { + int argc; + char **argv; + wchar_t **ugly_argv=CommandLineToArgvW(GetCommandLineW(), &argc); + argv=malloc(sizeof(char*)*argc); + for(int i=0;i \n", os.Args[0]) os.Exit(1) } - file, err:=os.Open(os.Args[1]) - if err!=nil { + file, err := os.Open(os.Args[1]) + if err != nil { fmt.Printf("Failed to open input file: %v\n", err) os.Exit(2) } - output_file, err:=os.OpenFile(os.Args[2], os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644) - if err!=nil { + output_file, err := os.OpenFile(os.Args[2], os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644) + if err != nil { panic(err) } defer output_file.Close() defer file.Close() header_byte := []byte{0} - _, err=io.ReadAtLeast(file, header_byte, 1) - if err!=nil { + _, err = io.ReadAtLeast(file, header_byte, 1) + if err != nil { panic(err) } - if header_byte[0]=='{' { - bf:=&bytes.Buffer{} - _, err=bf.ReadFrom(file) - if err!=nil { + if header_byte[0] == '{' { + bf := &bytes.Buffer{} + _, err = bf.ReadFrom(file) + if err != nil { panic(err) } - json_str:=string(append([]byte{'{'},bf.Bytes()...)) - gvmap:=map[string]interface{} {} - err=json.Unmarshal([]byte(json_str), &gvmap) - if err!=nil { + json_str := string(append([]byte{'{'}, bf.Bytes()...)) + gvmap := map[string]interface{}{} + err = json.Unmarshal([]byte(json_str), &gvmap) + if err != nil { panic(err) } construct(gvmap, output_file) - }else if header_byte[0]=='B' { - header_byte=make([]byte, 2) - _, err=io.ReadAtLeast(file, header_byte, 2) - if err!=nil { + } else if header_byte[0] == 'B' { + header_byte = make([]byte, 2) + _, err = io.ReadAtLeast(file, header_byte, 2) + if err != nil { panic(err) } - if string(header_byte)!="D@" { + if string(header_byte) != "D@" { fmt.Printf("Not a Brotli-Compressed BDump file.\n") os.Exit(3) } @@ -58,4 +58,4 @@ func main() { } fmt.Printf("Invalid input file\n") os.Exit(3) -} \ No newline at end of file +} diff --git a/fastbuilder/bdump/bdump.go b/fastbuilder/bdump/bdump.go index 2011b3333..8156c3724 100644 --- a/fastbuilder/bdump/bdump.go +++ b/fastbuilder/bdump/bdump.go @@ -18,8 +18,6 @@ type BDump struct { } /* -// Important note: Things under this file is what currently used, -// and actually bdump.go isn't under use now. if(i.cmd=="addToBlockPalette"){ writebuf(1,1); writebuf(i.blockName+"\0"); diff --git a/fastbuilder/bdump/blockNBT/CommandBlock.go b/fastbuilder/bdump/blockNBT/CommandBlock.go deleted file mode 100644 index 03d183d7d..000000000 --- a/fastbuilder/bdump/blockNBT/CommandBlock.go +++ /dev/null @@ -1,269 +0,0 @@ -package blockNBT - -import ( - "fmt" - "phoenixbuilder/fastbuilder/commands_generator" - "phoenixbuilder/fastbuilder/types" - "phoenixbuilder/minecraft/protocol/packet" -) - -// CommandBlockDatas 结构体用于描述命令方块的 NBT 在被解析后的数据 -type CommandBlockDatas struct { - Command string // Command(TAG_String) = "" - CustomName string // CustomName(TAG_String) = "" - LastOutput string // LastOutput(TAG_String) = "" - TickDelay int32 // TickDelay(TAG_Int) = 0 - ExecuteOnFirstTick bool // ExecuteOnFirstTick(TAG_Byte) = 1 - TrackOutput bool // TrackOutput(TAG_Byte) = 1 - ConditionalMode bool // conditionalMode(TAG_Byte) = 0 - Auto bool // auto(TAG_Byte) = 1 -} - -// CommandBlock 结构体用于描述一个完整的命令方块数据 -type CommandBlock struct { - // 该方块实体的详细数据 - Package *Package - // 命令方块数据 - CommandBlockDatas CommandBlockDatas - // 为向下兼容而设,因为旧方法下不需要放置命令方块 - NeedToPlaceBlock bool -} - -// 从 c.Package.Block.NBT 提取命令方块数据并保存在 c.CommandBlockDatas 中 -func (c *CommandBlock) Decode() error { - var normal bool = false - var command string = "" - var customName string = "" - var lastOutput string = "" - var tickDelay int32 = int32(0) - var executeOnFirstTick bool = true - var trackOutput bool = true - var conditionalMode bool = false - var auto bool = true - // 初始化 - _, ok := c.Package.Block.NBT["Command"] - if ok { - command, normal = c.Package.Block.NBT["Command"].(string) - if !normal { - return fmt.Errorf("Decode: Crashed in c.Package.Block.NBT[\"Command\"]; c.Package.Block.NBT = %#v", c.Package.Block.NBT) - } - } - // Command - _, ok = c.Package.Block.NBT["CustomName"] - if ok { - customName, normal = c.Package.Block.NBT["CustomName"].(string) - if !normal { - return fmt.Errorf("Decode: Crashed in c.Package.Block.NBT[\"CustomName\"]; c.Package.Block.NBT = %#v", c.Package.Block.NBT) - } - } - // CustomName - _, ok = c.Package.Block.NBT["LastOutput"] - if ok { - lastOutput, normal = c.Package.Block.NBT["LastOutput"].(string) - if !normal { - return fmt.Errorf("Decode: Crashed in c.Package.Block.NBT[\"LastOutput\"]; c.Package.Block.NBT = %#v", c.Package.Block.NBT) - } - } - // LastOutput - _, ok = c.Package.Block.NBT["TickDelay"] - if ok { - tickDelay, normal = c.Package.Block.NBT["TickDelay"].(int32) - if !normal { - return fmt.Errorf("Decode: Crashed in c.Package.Block.NBT[\"TickDelay\"]; c.Package.Block.NBT = %#v", c.Package.Block.NBT) - } - } - // TickDelay - _, ok = c.Package.Block.NBT["ExecuteOnFirstTick"] - if ok { - got, normal := c.Package.Block.NBT["ExecuteOnFirstTick"].(byte) - if !normal { - return fmt.Errorf("Decode: Crashed in c.Package.Block.NBT[\"ExecuteOnFirstTick\"]; c.Package.Block.NBT = %#v", c.Package.Block.NBT) - } - if got == byte(0) { - executeOnFirstTick = false - } else { - executeOnFirstTick = true - } - } - // ExecuteOnFirstTick - _, ok = c.Package.Block.NBT["TrackOutput"] - if ok { - got, normal := c.Package.Block.NBT["TrackOutput"].(byte) - if !normal { - return fmt.Errorf("Decode: Crashed in c.Package.Block.NBT[\"TrackOutput\"]; c.Package.Block.NBT = %#v", c.Package.Block.NBT) - } - if got == byte(0) { - trackOutput = false - } else { - trackOutput = true - } - } - // TrackOutput - _, ok = c.Package.Block.NBT["conditionalMode"] - if ok { - got, normal := c.Package.Block.NBT["conditionalMode"].(byte) - if !normal { - return fmt.Errorf("Decode: Crashed in c.Package.Block.NBT[\"conditionalMode\"]; c.Package.Block.NBT = %#v", c.Package.Block.NBT) - } - if got == byte(0) { - conditionalMode = false - } else { - conditionalMode = true - } - } - // conditionalMode - _, ok = c.Package.Block.NBT["auto"] - if ok { - got, normal := c.Package.Block.NBT["auto"].(byte) - if !normal { - return fmt.Errorf("Decode: Crashed in c.Package.Block.NBT[\"auto\"]; c.Package.Block.NBT = %#v", c.Package.Block.NBT) - } - if got == byte(0) { - auto = false - } else { - auto = true - } - } - // auto - c.CommandBlockDatas = CommandBlockDatas{ - Command: command, - CustomName: customName, - LastOutput: lastOutput, - TickDelay: tickDelay, - ExecuteOnFirstTick: executeOnFirstTick, - TrackOutput: trackOutput, - ConditionalMode: conditionalMode, - Auto: auto, - } - return nil - // return -} - -// 放置一个命令方块(可选)并写入命令方块数据 -func (c *CommandBlock) WriteDatas() error { - var mode uint32 = packet.CommandBlockImpulse - // 初始化 - if c.NeedToPlaceBlock { - if c.Package.Datas.Settings.ExcludeCommands || c.Package.Datas.FastMode { - err := c.Package.API.SetBlockFastly(c.Package.Datas.Position, c.Package.Block.Name, c.Package.Datas.StatesString) - if err != nil { - return fmt.Errorf("WriteDatas: %v", err) - } - // 如果要求仅放置命令方块亦或以快速模式放置命令方块 - } else { - err := c.Package.API.SetBlock(c.Package.Datas.Position, c.Package.Block.Name, c.Package.Datas.StatesString) - if err != nil { - return fmt.Errorf("WriteDatas: %v", err) - } - // 普通情形 - } - } - // 放置命令方块 - if c.Package.Datas.Settings.ExcludeCommands { - return nil - } - // 如果不要求写入命令方块数据 - err := c.Package.API.SendSettingsCommand(fmt.Sprintf("tp %d %d %d", c.Package.Datas.Position[0], c.Package.Datas.Position[1], c.Package.Datas.Position[2]), true) - if err != nil { - return fmt.Errorf("WriteDatas: %v", err) - } - // 传送机器人到命令方块位置 - if c.Package.Block.Name == "chain_command_block" { - mode = packet.CommandBlockChain - } else if c.Package.Block.Name == "repeating_command_block" { - mode = packet.CommandBlockRepeating - } - // 确定命令方块的类型 - if c.Package.Datas.Settings.InvalidateCommands { - c.CommandBlockDatas.Command = "# " + c.CommandBlockDatas.Command - } - // 如果需要对命令无效化处理 - err = c.Package.API.WritePacket(&packet.CommandBlockUpdate{ - Block: true, - Position: c.Package.Datas.Position, - Mode: mode, - NeedsRedstone: !c.CommandBlockDatas.Auto, - Conditional: c.CommandBlockDatas.ConditionalMode, - Command: c.CommandBlockDatas.Command, - LastOutput: c.CommandBlockDatas.LastOutput, - Name: c.CommandBlockDatas.CustomName, - ShouldTrackOutput: c.CommandBlockDatas.TrackOutput, - TickDelay: c.CommandBlockDatas.TickDelay, - ExecuteOnFirstTick: c.CommandBlockDatas.ExecuteOnFirstTick, - }) - if err != nil { - return fmt.Errorf("WriteDatas: %v", err) - } - // 写入命令方块数据 - return nil - // 返回值 -} - -// 以旧方法放置命令方块;主要用于向下兼容,如 operation 36 等 -func (c *CommandBlock) PlaceCommandBlockWithLegacyMethod( - block *types.Module, - cfg *types.MainConfig, -) error { - var blockName string = "command_block" - c.CommandBlockDatas = CommandBlockDatas{ - Command: block.CommandBlockData.Command, - CustomName: block.CommandBlockData.CustomName, - LastOutput: block.CommandBlockData.LastOutput, - TickDelay: block.CommandBlockData.TickDelay, - ExecuteOnFirstTick: block.CommandBlockData.ExecuteOnFirstTick, - TrackOutput: block.CommandBlockData.TrackOutput, - ConditionalMode: block.CommandBlockData.Conditional, - Auto: !block.CommandBlockData.NeedsRedstone, - } - // 初始化 - if block.CommandBlockData.Mode == packet.CommandBlockChain { - blockName = "chain_command_block" - } else if block.CommandBlockData.Mode == packet.CommandBlockRepeating { - blockName = "repeating_command_block" - } - if block.Block == nil { - block.Block = &types.Block{} - block.Block.Name = &blockName - - { - _, err := c.Package.API.SendWSCommandWithResponce("list") - if err != nil { - return fmt.Errorf("PlaceCommandBlockWithLegacyMethod: %v", err) - } - } - // 这么做的目的只是为了保证存在 operation 26 - SetCommandBlockData 的时候, - // 命令方块导入速度不会太快。 - // 不过这个解决方案不是很优雅, - // 但这里并没有 GetBlockUpdateSubscribeMap 类似的实现, - // 所以暂且先这样吧 - - err := c.WriteDatas() - if err != nil { - return fmt.Errorf("PlaceCommandBlockWithLegacyMethod: %v", err) - } - return nil - } - block.Block.Name = &blockName - c.Package.Block.Name = blockName - // 确定命令方块的类型 & 如果是 operation 26 - SetCommandBlockData - request := commands_generator.SetBlockRequest(block, cfg) - if c.Package.Datas.FastMode { - err := c.Package.API.SendSettingsCommand(request, true) - if err != nil { - return fmt.Errorf("PlaceCommandBlockWithLegacyMethod: %v", err) - } - } else { - _, err := c.Package.API.SendWSCommandWithResponce(request) - if err != nil { - return fmt.Errorf("PlaceCommandBlockWithLegacyMethod: %v", err) - } - } - // 放置命令方块 - err := c.WriteDatas() - if err != nil { - return fmt.Errorf("PlaceCommandBlockWithLegacyMethod: %v", err) - } - // 写入命令方块数据 - return nil - // 返回值 -} diff --git a/fastbuilder/bdump/blockNBT/Sign.go b/fastbuilder/bdump/blockNBT/Sign.go deleted file mode 100644 index 0fee0d532..000000000 --- a/fastbuilder/bdump/blockNBT/Sign.go +++ /dev/null @@ -1,219 +0,0 @@ -package blockNBT - -import ( - "fmt" - "phoenixbuilder/GameControl/GlobalAPI" - "phoenixbuilder/minecraft/protocol/packet" -) - -// SignDatas 结构体用于描述告示牌的 NBT 在被解析后的数据 -type SignDatas struct { - TextOwner string // TextOwner(TAG_String) = "" - IgnoreLighting byte // IgnoreLighting(TAG_Byte) = 0 - SignTextColor int32 // SignTextColor(TAG_Int) = 0 - TextIgnoreLegacyBugResolved byte // TextIgnoreLegacyBugResolved(TAG_Byte) = 0 - Text string // Text(TAG_String) = "" -} - -// Sign 结构体用于描述一个完整的告示牌 -type Sign struct { - Package *Package // 该方块实体的详细数据 - SignDatas SignDatas // 告示牌数据 -} - -// 从 s.Package.Block.NBT 提取告示牌数据并保存在 s.SignDatas 中 -func (s *Sign) Decode() error { - var ok bool = false - var normal bool = false - var textOwner string = "" - var ignoreLighting byte = byte(0) - var signTextColor int32 = 0 - var textIgnoreLegacyBugResolved byte = byte(0) - var text string = "" - // 初始化 - _, ok = s.Package.Block.NBT["TextOwner"] - if ok { - textOwner, normal = s.Package.Block.NBT["TextOwner"].(string) - if !normal { - return fmt.Errorf("Decode: Could not parse s.Package.Block.NBT[\"TextOwner\"]; s.Package.Block.NBT = %#v", s.Package.Block.NBT) - } - } - // TextOwner - _, ok = s.Package.Block.NBT["IgnoreLighting"] - if ok { - ignoreLighting, normal = s.Package.Block.NBT["IgnoreLighting"].(byte) - if !normal { - return fmt.Errorf("Decode: Could not parse s.Package.Block.NBT[\"IgnoreLighting\"]; s.Package.Block.NBT = %#v", s.Package.Block.NBT) - } - } - // IgnoreLighting - _, ok = s.Package.Block.NBT["SignTextColor"] - if ok { - signTextColor, normal = s.Package.Block.NBT["SignTextColor"].(int32) - if !normal { - return fmt.Errorf("Decode: Could not parse s.Package.Block.NBT[\"SignTextColor\"]; s.Package.Block.NBT = %#v", s.Package.Block.NBT) - } - } - // SignTextColor - _, ok = s.Package.Block.NBT["TextIgnoreLegacyBugResolved"] - if ok { - textIgnoreLegacyBugResolved, normal = s.Package.Block.NBT["TextIgnoreLegacyBugResolved"].(byte) - if !normal { - return fmt.Errorf("Decode: Could not parse s.Package.Block.NBT[\"TextIgnoreLegacyBugResolved\"]; s.Package.Block.NBT = %#v", s.Package.Block.NBT) - } - } - // TextIgnoreLegacyBugResolved - _, ok = s.Package.Block.NBT["Text"] - if ok { - text, normal = s.Package.Block.NBT["Text"].(string) - if !normal { - return fmt.Errorf("Decode: Could not parse s.Package.Block.NBT[\"Text\"]; s.Package.Block.NBT = %#v", s.Package.Block.NBT) - } - } - // Text - s.SignDatas = SignDatas{ - TextOwner: textOwner, - IgnoreLighting: ignoreLighting, - SignTextColor: signTextColor, - TextIgnoreLegacyBugResolved: textIgnoreLegacyBugResolved, - Text: text, - } - // 写入数据 - return nil - // 返回值 -} - -// 放置一个告示牌并写入告示牌数据 -func (s *Sign) WriteDatas() error { - if s.Package.Datas.FastMode { - err := s.Package.API.SetBlockFastly(s.Package.Datas.Position, s.Package.Block.Name, s.Package.Datas.StatesString) - if err != nil { - return fmt.Errorf("WriteDatas: %v", err) - } - return nil - } - // 放置告示牌(快速导入模式下) - { - err := s.Package.API.SendSettingsCommand(fmt.Sprintf("tp %d %d %d", s.Package.Datas.Position[0], s.Package.Datas.Position[1], s.Package.Datas.Position[2]), true) - if err != nil { - return fmt.Errorf("WriteDatas: %v", err) - } - // 传送机器人到告示牌所在的位置 - err = s.Package.API.SendSettingsCommand( - fmt.Sprintf( - "setblock %d %d %d air", - s.Package.Datas.Position[0], - s.Package.Datas.Position[1], - s.Package.Datas.Position[2], - ), - true, - ) - if err != nil { - return fmt.Errorf("WriteDatas: %v", err) - } - // 清除当前告示牌处的方块。 - // 如果不这么做且原本该处的方块是告示牌的话, - // 那么 NBT 数据将会注入失败 - err = s.Package.API.SendSettingsCommand( - "replaceitem entity @s slot.hotbar 0 oak_sign", - true, - ) - if err != nil { - return fmt.Errorf("WriteDatas: %v", err) - } - // 获取一个告示牌到快捷栏 0 - err = s.Package.API.ChangeSelectedHotbarSlot(0) - if err != nil { - return fmt.Errorf("WriteDatas: %v", err) - } - // 切换手持物品栏到快捷栏 0 - uniqueID, err := s.Package.API.BackupStructure( - GlobalAPI.MCStructure{ - BeginX: s.Package.Datas.Position[0] + 1, - BeginY: s.Package.Datas.Position[1], - BeginZ: s.Package.Datas.Position[2], - SizeX: 1, - SizeY: 1, - SizeZ: 1, - }, - ) - if err != nil { - return fmt.Errorf("WriteDatas: %v", err) - } - /* - 我们会在告示牌的 (~1, ~, ~) 处生成一个玻璃, - 然后点击这个玻璃并指定点击的面是 4 以将手中的告示牌放上去。 - - 这样,我们就可以取得反作弊的认同, - 然后我们就可以向告示牌注入 NBT 数据了。 - - 但在生成玻璃前,我们需要备份这个玻璃原本的方块以方便之后恢复它 - */ - _, err = s.Package.API.SendWSCommandWithResponce( - fmt.Sprintf( - "setblock %d %d %d glass", - s.Package.Datas.Position[0]+1, - s.Package.Datas.Position[1], - s.Package.Datas.Position[2], - ), - ) - if err != nil { - return fmt.Errorf("WriteDatas: %v", err) - } - // 生成上文提到的玻璃 - err = s.Package.API.PlaceBlock( - GlobalAPI.UseItemOnBlocks{ - HotbarSlotID: 0, - BlockPos: [3]int32{ - s.Package.Datas.Position[0] + 1, - s.Package.Datas.Position[1], - s.Package.Datas.Position[2], - }, - BlockName: "minecraft:glass", - BlockStates: map[string]interface{}{}, - }, - 4, - ) - if err != nil { - return fmt.Errorf("WriteDatas: %v", err) - } - // 在玻璃上放置手中的告示牌 - err = s.Package.API.SetBlock(s.Package.Datas.Position, s.Package.Block.Name, s.Package.Datas.StatesString) - if err != nil { - return fmt.Errorf("WriteDatas: %v", err) - } - // 现在玻璃上有了一个告示牌,这是我们刚刚放上去的, - // 但这个告示牌的种类是 oak_sign ,且朝向固定, - // 因此现在我们需要覆写这个告示牌的种类及朝向为正确的形式。 - // 经过测试,覆写操作不会导致 NBT 数据无法注入 - err = s.Package.API.RevertStructure( - uniqueID, - GlobalAPI.BlockPos{ - s.Package.Datas.Position[0] + 1, - s.Package.Datas.Position[1], - s.Package.Datas.Position[2], - }, - ) - if err != nil { - return fmt.Errorf("WriteDatas: %v", err) - } - // 将上文提到的玻璃处的方块恢复为原本的方块 - } - // 放置告示牌 - err := s.Package.API.WritePacket(&packet.BlockActorData{ - Position: s.Package.Datas.Position, - NBTData: map[string]interface{}{ - "TextOwner": s.SignDatas.TextOwner, - "IgnoreLighting": s.SignDatas.IgnoreLighting, - "SignTextColor": s.SignDatas.SignTextColor, - "TextIgnoreLegacyBugResolved": s.SignDatas.TextIgnoreLegacyBugResolved, - "Text": s.SignDatas.Text, - }, - }) - if err != nil { - return fmt.Errorf("WriteDatas: %v", err) - } - // 写入告示牌数据 - return nil - // 返回值 -} diff --git a/fastbuilder/bdump/blockNBT/interface.go b/fastbuilder/bdump/blockNBT/interface.go deleted file mode 100644 index 936fd1ec8..000000000 --- a/fastbuilder/bdump/blockNBT/interface.go +++ /dev/null @@ -1,9 +0,0 @@ -package blockNBT - -// 用于放置方块实体的通用接口 -type GeneralBlockNBT interface { - // 解析 NBT(map[string]interface{}) 为 golang struct - Decode() error - // 放置方块并以合法手段写入方块实体数据 - WriteDatas() error -} diff --git a/fastbuilder/bdump/blockNBT/define.go b/fastbuilder/bdump/block_nbt/block_nbt.go similarity index 57% rename from fastbuilder/bdump/blockNBT/define.go rename to fastbuilder/bdump/block_nbt/block_nbt.go index 8e493dd3a..9cdd8e171 100644 --- a/fastbuilder/bdump/blockNBT/define.go +++ b/fastbuilder/bdump/block_nbt/block_nbt.go @@ -2,10 +2,24 @@ package blockNBT import ( "fmt" - GlobalAPI "phoenixbuilder/GameControl/GlobalAPI" + "phoenixbuilder/fastbuilder/environment/interfaces" "phoenixbuilder/fastbuilder/types" ) +// ------------------------- interface ------------------------- + +/* +GeneralBlockNBT 提供了一个通用的接口, +以便于您可以方便的解析对应的方块实体, +然后放置它并以最大的可能性注入 NBT 数据。 + +该接口实际与下方的 BlockEntity 结构体绑定 +*/ +type GeneralBlockNBT interface { + Decode() error + WriteData() error +} + // ------------------------- general ------------------------- // GeneralBlock 结构体用于描述通用型方块的数据 @@ -18,13 +32,14 @@ type GeneralBlock struct { NBT map[string]interface{} } -// Datas 结构体用于描述一个方块实体的其他附加数据,例如方块的绝对坐标 -type Datas struct { +// AdditionalData 结构体用于描述一个方块实体的其他附加数据,例如方块的绝对坐标 +type AdditionalData struct { // 字符串形式的方块状态,用于在放置方块时使用 - StatesString string + BlockStates string // 方块坐标(绝对坐标) Position [3]int32 // 该方块的类型,例如各式各样的告示牌可以写作 Sign + // TODO: USE ENUM INSTEAD Type string // 此参数应当只被 PhoenixBuilder 使用,除非 Omega 也需要设置一些功能 Settings *types.MainConfig @@ -34,47 +49,25 @@ type Datas struct { Others interface{} } -// Package 是用于包装每个方块实体的结构体 -type Package struct { +// BlockEntity 是用于包装每个方块实体的结构体 +type BlockEntity struct { // 储存执行该方块状态放置所需的 API ,例如发包需要用到的函数等 // 此参数需要外部实现主动赋值, // 主要是为了兼容 Omega 和 PhoenixBuilder 对功能的同时使用 - API *GlobalAPI.GlobalAPI + Interface interfaces.GameInterface // 一个通用型方块的数据,例如名称、方块状态和所携带的 NBT 数据 Block GeneralBlock // 此方块的其他附加数据,例如方块的绝对坐标 - Datas *Datas + AdditionalData AdditionalData } // ------------------------- Container ------------------------- -// 此表描述了可被 replaceitem 生效的容器。 -// key 代表容器的方块名,而 value 则代表此容器放置物品所使用的复合标签或列表 -var SupportContainerPool map[string]string = map[string]string{ - "blast_furnace": "Items", - "lit_blast_furnace": "Items", - "smoker": "Items", - "lit_smoker": "Items", - "furnace": "Items", - "lit_furnace": "Items", - "chest": "Items", - "barrel": "Items", - "trapped_chest": "Items", - "lectern": "book", - "hopper": "Items", - "dispenser": "Items", - "dropper": "Items", - "jukebox": "RecordItem", - "brewing_stand": "Items", - "undyed_shulker_box": "Items", - "shulker_box": "Items", -} - -// 未被支持的容器会被用到以下两个变量 -var NotASupportedContainer string = "Not a supported container" +// 未被支持的容器会被应用此错误信息。 +// 用于 Container.go 中的 ReplaceNBTMapToContainerList 等函数 var ErrNotASupportedContainer error = fmt.Errorf("replaceNBTMapToContainerList: Not a supported container") // 用于 Container.go 中的 ReplaceNBTMapToContainerList 等函数 -var KeyName string = "datas" +var KeyName string = "data" // ------------------------- END ------------------------- diff --git a/fastbuilder/bdump/block_nbt/command_block.go b/fastbuilder/bdump/block_nbt/command_block.go new file mode 100644 index 000000000..b4fa85b5a --- /dev/null +++ b/fastbuilder/bdump/block_nbt/command_block.go @@ -0,0 +1,267 @@ +package blockNBT + +import ( + "fmt" + "phoenixbuilder/fastbuilder/commands_generator" + "phoenixbuilder/fastbuilder/types" + GameInterface "phoenixbuilder/game_control/game_interface" + "phoenixbuilder/minecraft/protocol/packet" +) + +// Parsed Command block NBT data +type CommandBlockData struct { + Command string // Command(TAG_String) = "" + CustomName string // CustomName(TAG_String) = "" + LastOutput string // LastOutput(TAG_String) = "" + TickDelay int32 // TickDelay(TAG_Int) = 0 + ExecuteOnFirstTick bool // ExecuteOnFirstTick(TAG_Byte) = 1 + TrackOutput bool // TrackOutput(TAG_Byte) = 1 + ConditionalMode bool // conditionalMode(TAG_Byte) = 0 + Auto bool // auto(TAG_Byte) = 1 +} + +// CommandBlock 结构体用于描述一个完整的命令方块数据 +type CommandBlock struct { + // 该方块实体的详细数据 + BlockEntity *BlockEntity + CommandBlockData + // 为向下兼容而设,因为旧方法下不需要放置命令方块 + ShouldPlaceBlock bool +} + +// 从 c.Package.Block.NBT 提取命令方块数据并保存在 c.CommandBlockData 中 +func (c *CommandBlock) Decode() error { + var normal bool = false + var command string = "" + var customName string = "" + var lastOutput string = "" + var tickDelay int32 = int32(0) + var executeOnFirstTick bool = true + var trackOutput bool = true + var conditionalMode bool = false + var auto bool = true + // 初始化 + _, ok := c.BlockEntity.Block.NBT["Command"] + if ok { + command, normal = c.BlockEntity.Block.NBT["Command"].(string) + if !normal { + return fmt.Errorf("Decode: Crashed at c.BlockEntity.Block.NBT[\"Command\"]; c.BlockEntity.Block.NBT = %#v", c.BlockEntity.Block.NBT) + } + } + // Command + _, ok = c.BlockEntity.Block.NBT["CustomName"] + if ok { + customName, normal = c.BlockEntity.Block.NBT["CustomName"].(string) + if !normal { + return fmt.Errorf("Decode: Crashed at c.BlockEntity.Block.NBT[\"CustomName\"]; c.Package.Block.NBT = %#v", c.BlockEntity.Block.NBT) + } + } + // CustomName + _, ok = c.BlockEntity.Block.NBT["LastOutput"] + if ok { + lastOutput, normal = c.BlockEntity.Block.NBT["LastOutput"].(string) + if !normal { + return fmt.Errorf("Decode: Crashed at c.BlockEntity.Block.NBT[\"LastOutput\"]; c.BlockEntity.Block.NBT = %#v", c.BlockEntity.Block.NBT) + } + } + // LastOutput + _, ok = c.BlockEntity.Block.NBT["TickDelay"] + if ok { + tickDelay, normal = c.BlockEntity.Block.NBT["TickDelay"].(int32) + if !normal { + return fmt.Errorf("Decode: Crashed in c.Package.Block.NBT[\"TickDelay\"]; c.BlockEntity.Block.NBT = %#v", c.BlockEntity.Block.NBT) + } + } + // TickDelay + _, ok = c.BlockEntity.Block.NBT["ExecuteOnFirstTick"] + if ok { + got, normal := c.BlockEntity.Block.NBT["ExecuteOnFirstTick"].(byte) + if !normal { + return fmt.Errorf("Decode: Crashed at c.BlockEntity.Block.NBT[\"ExecuteOnFirstTick\"]; c.BlockEntity.Block.NBT = %#v", c.BlockEntity.Block.NBT) + } + if got == byte(0) { + executeOnFirstTick = false + } else { + executeOnFirstTick = true + } + } + // ExecuteOnFirstTick + _, ok = c.BlockEntity.Block.NBT["TrackOutput"] + if ok { + got, normal := c.BlockEntity.Block.NBT["TrackOutput"].(byte) + if !normal { + return fmt.Errorf("Decode: Crashed at c.BlockEntity.Block.NBT[\"TrackOutput\"]; c.BlockEntity.Block.NBT = %#v", c.BlockEntity.Block.NBT) + } + if got == byte(0) { + trackOutput = false + } else { + trackOutput = true + } + } + // TrackOutput + _, ok = c.BlockEntity.Block.NBT["conditionalMode"] + if ok { + got, normal := c.BlockEntity.Block.NBT["conditionalMode"].(byte) + if !normal { + return fmt.Errorf("Decode: ERR 106; NBT = %#v", c.BlockEntity.Block.NBT) + } + if got == byte(0) { + conditionalMode = false + } else { + conditionalMode = true + } + } + // conditionalMode + _, ok = c.BlockEntity.Block.NBT["auto"] + if ok { + got, normal := c.BlockEntity.Block.NBT["auto"].(byte) + if !normal { + return fmt.Errorf("Decode: ERR 333; NBT = %#v", c.BlockEntity.Block.NBT) + } + if got == byte(0) { + auto = false + } else { + auto = true + } + } + // auto + c.CommandBlockData = CommandBlockData{ + Command: command, + CustomName: customName, + LastOutput: lastOutput, + TickDelay: tickDelay, + ExecuteOnFirstTick: executeOnFirstTick, + TrackOutput: trackOutput, + ConditionalMode: conditionalMode, + Auto: auto, + } + return nil + // return +} + +// 放置一个命令方块(可选)并写入命令方块数据 +func (c *CommandBlock) WriteData() error { + var mode uint32 = packet.CommandBlockImpulse + gameInterface := c.BlockEntity.Interface.(*GameInterface.GameInterface) + if c.ShouldPlaceBlock { + if c.BlockEntity.AdditionalData.Settings.ExcludeCommands || c.BlockEntity.AdditionalData.FastMode { + err := c.BlockEntity.Interface.SetBlockAsync(c.BlockEntity.AdditionalData.Position, c.BlockEntity.Block.Name, c.BlockEntity.AdditionalData.BlockStates) + if err != nil { + return fmt.Errorf("WriteData: %v", err) + } + // 如果要求仅放置命令方块亦或以快速模式放置命令方块 + } else { + err := c.BlockEntity.Interface.SetBlock(c.BlockEntity.AdditionalData.Position, c.BlockEntity.Block.Name, c.BlockEntity.AdditionalData.BlockStates) + if err != nil { + return fmt.Errorf("WriteData: %v", err) + } + // 普通情形 + } + } + // 放置命令方块 + if c.BlockEntity.AdditionalData.Settings.ExcludeCommands { + return nil + } + // 如果不要求写入命令方块数据 + err := c.BlockEntity.Interface.SendSettingsCommand(fmt.Sprintf("tp %d %d %d", c.BlockEntity.AdditionalData.Position[0], c.BlockEntity.AdditionalData.Position[1], c.BlockEntity.AdditionalData.Position[2]), true) + if err != nil { + return fmt.Errorf("WriteData: %v", err) + } + if c.BlockEntity.Block.Name == "chain_command_block" { + mode = packet.CommandBlockChain + } else if c.BlockEntity.Block.Name == "repeating_command_block" { + mode = packet.CommandBlockRepeating + } + if c.BlockEntity.AdditionalData.Settings.InvalidateCommands { + c.CommandBlockData.Command = "# " + c.CommandBlockData.Command + } + err = gameInterface.WritePacket(&packet.CommandBlockUpdate{ + Block: true, + Position: c.BlockEntity.AdditionalData.Position, + Mode: mode, + NeedsRedstone: !c.CommandBlockData.Auto, + Conditional: c.CommandBlockData.ConditionalMode, + Command: c.CommandBlockData.Command, + LastOutput: c.CommandBlockData.LastOutput, + Name: c.CommandBlockData.CustomName, + ShouldTrackOutput: c.CommandBlockData.TrackOutput, + TickDelay: c.CommandBlockData.TickDelay, + ExecuteOnFirstTick: c.CommandBlockData.ExecuteOnFirstTick, + }) + if err != nil { + return fmt.Errorf("WriteData: %v", err) + } + // 写入命令方块数据 + return nil + // 返回值 +} + +// 以旧方法放置命令方块;主要用于向下兼容,如 operation 36 等 +func (c *CommandBlock) PlaceCommandBlockLegacy( + block *types.Module, + cfg *types.MainConfig, +) error { + var blockName string = "command_block" + c.CommandBlockData = CommandBlockData{ + Command: block.CommandBlockData.Command, + CustomName: block.CommandBlockData.CustomName, + LastOutput: block.CommandBlockData.LastOutput, + TickDelay: block.CommandBlockData.TickDelay, + ExecuteOnFirstTick: block.CommandBlockData.ExecuteOnFirstTick, + TrackOutput: block.CommandBlockData.TrackOutput, + ConditionalMode: block.CommandBlockData.Conditional, + Auto: !block.CommandBlockData.NeedsRedstone, + } + // 初始化 + if block.CommandBlockData.Mode == packet.CommandBlockChain { + blockName = "chain_command_block" + } else if block.CommandBlockData.Mode == packet.CommandBlockRepeating { + blockName = "repeating_command_block" + } + if block.Block == nil { + block.Block = &types.Block{} + block.Block.Name = &blockName + + // TODO: 优化下方的这一段代码 + { + _, err := c.BlockEntity.Interface.(*GameInterface.GameInterface).SendWSCommandWithResponse("list") + if err != nil { + return fmt.Errorf("PlaceCommandBlockLegacy: %v", err) + } + } + // 这么做的目的只是为了保证存在 operation 26 - SetCommandBlockData 的时候, + // 命令方块导入速度不会太快。 + // 不过这个解决方案不是很优雅, + // 但这里并没有 GetBlockUpdateSubscribeMap 类似的实现, + // 所以暂且先这样吧 + + err := c.WriteData() + if err != nil { + return fmt.Errorf("PlaceCommandBlockLegacy: %v", err) + } + return nil + } + block.Block.Name = &blockName + c.BlockEntity.Block.Name = blockName + // 确定命令方块的类型 & 如果是 operation 26 - SetCommandBlockData + request := commands_generator.SetBlockRequest(block, cfg) + if c.BlockEntity.AdditionalData.FastMode { + err := c.BlockEntity.Interface.SendSettingsCommand(request, true) + if err != nil { + return fmt.Errorf("ERR 444eee %v", err) + } + } else { + _, err := c.BlockEntity.Interface.(*GameInterface.GameInterface).SendWSCommandWithResponse(request) + if err != nil { + return fmt.Errorf("ERR 555ccc %v", err) + } + } + // 放置命令方块 + err := c.WriteData() + if err != nil { + return fmt.Errorf("PlaceCommandBlockLegacy: %v", err) + } + // 写入命令方块数据 + return nil + // 返回值 +} diff --git a/fastbuilder/bdump/blockNBT/Container.go b/fastbuilder/bdump/block_nbt/container.go similarity index 84% rename from fastbuilder/bdump/blockNBT/Container.go rename to fastbuilder/bdump/block_nbt/container.go index f3bece508..f4f4ab989 100644 --- a/fastbuilder/bdump/blockNBT/Container.go +++ b/fastbuilder/bdump/block_nbt/container.go @@ -3,6 +3,7 @@ package blockNBT import ( "fmt" "phoenixbuilder/fastbuilder/types" + GameInterface "phoenixbuilder/game_control/game_interface" "phoenixbuilder/mirror/chunk" "strings" ) @@ -17,32 +18,33 @@ type Item struct { // Container 结构体用于描述一个容器 type Container struct { - Package *Package // 该方块实体的详细数据 - Items []Item // 容器内的物品数据 + BlockEntity *BlockEntity // 该方块实体的详细数据 + Items []Item // 容器内的物品数据 } -// 检查一个方块是否是已被支持的有效的容器;这里的“有效”指的是可以被 replaceitem 命令生效的容器。 -// 如果不是已被支持的容器,则返回 var NotASupportedContainer string = "Not a supported container" -func (c *Container) checkIfIsSupportedContainer() string { - value, ok := SupportContainerPool[c.Package.Block.Name] +// 检查一个方块是否是已被支持的有效的容器。 +// 这里的 有效 指的是可以被 replaceitem 命令生效的容器。 +// 如果不是已被支持的容器,则返回长度为 0 的空字符串 +func (c *Container) containerSupported() string { + value, ok := SupportContainerPool[c.BlockEntity.Block.Name] if ok { return value } - return NotASupportedContainer + return "" } // 从容器的 NBT 数据提取物品数据;结果会被替换在 c.Package.Block.NBT[KeyName] 中 func (c *Container) replaceNBTMapToContainerList() error { - key := c.checkIfIsSupportedContainer() - if key == NotASupportedContainer { + key := c.containerSupported() + if len(key) == 0 { return ErrNotASupportedContainer } // 这里是确定一下这个容器是否是我们支持了的容器 - value, ok := c.Package.Block.NBT[key] + value, ok := c.BlockEntity.Block.NBT[key] if !ok { - c.Package.Block.NBT = map[string]interface{}{KeyName: []interface{}{}} + c.BlockEntity.Block.NBT = map[string]interface{}{KeyName: []interface{}{}} } else { - c.Package.Block.NBT = map[string]interface{}{KeyName: value} + c.BlockEntity.Block.NBT = map[string]interface{}{KeyName: value} } // 对于唱片机和讲台这种容器,如果它们没有被放物品的话,那么对应的 key 是找不到的 // 但是这并非是错误 @@ -59,11 +61,11 @@ func (c *Container) Decode() error { return fmt.Errorf("Decode: %v", err) } // 替换 NBT 数据为物品数据 - got, normal := c.Package.Block.NBT[KeyName].([]interface{}) + got, normal := c.BlockEntity.Block.NBT[KeyName].([]interface{}) if !normal { - got, normal := c.Package.Block.NBT[KeyName].(map[string]interface{}) + got, normal := c.BlockEntity.Block.NBT[KeyName].(map[string]interface{}) if !normal { - return fmt.Errorf("Decode: Crashed in c.Package.Block.NBT c.Package.Block.NBT = %#v", c.Package.Block.NBT) + return fmt.Errorf("Decode ERR 67dddddd NBT = %#v", c.BlockEntity.Block.NBT) } correct = append(correct, got) } else { @@ -204,15 +206,15 @@ func (c *Container) Decode() error { } // 放置一个容器并填充物品 -func (c *Container) WriteDatas() error { - err := c.Package.API.SetBlock(c.Package.Datas.Position, c.Package.Block.Name, c.Package.Datas.StatesString) +func (c *Container) WriteData() error { + err := c.BlockEntity.Interface.SetBlock(c.BlockEntity.AdditionalData.Position, c.BlockEntity.Block.Name, c.BlockEntity.AdditionalData.BlockStates) if err != nil { - return fmt.Errorf("WriteDatas: %v", err) + return fmt.Errorf("WriteData: %v", err) } // 放置容器 for _, value := range c.Items { - err := c.Package.API.ReplaceitemToContainer( - c.Package.Datas.Position, + err := c.BlockEntity.Interface.(*GameInterface.GameInterface).ReplaceItemInContainer( + c.BlockEntity.AdditionalData.Position, types.ChestSlot{ Name: value.Name, Count: value.Count, @@ -222,7 +224,7 @@ func (c *Container) WriteDatas() error { "", ) if err != nil { - return fmt.Errorf("WriteDatas: %v", err) + return fmt.Errorf("WriteData: %v", err) } } // 向容器内填充物品 diff --git a/fastbuilder/bdump/blockNBT/Default.go b/fastbuilder/bdump/block_nbt/default.go similarity index 63% rename from fastbuilder/bdump/blockNBT/Default.go rename to fastbuilder/bdump/block_nbt/default.go index 055dbd9ef..3a0441b7f 100644 --- a/fastbuilder/bdump/blockNBT/Default.go +++ b/fastbuilder/bdump/block_nbt/default.go @@ -5,7 +5,7 @@ import "fmt" // Default 结构体用于描述一个完整的方块实体数据。 // 任何未被支持的方块实体都会被重定向为此结构体 type Default struct { - Package *Package // 该方块实体的详细数据 + BlockEntity *BlockEntity // 该方块实体的详细数据 } // 这只是为了保证接口一致而设 @@ -14,8 +14,8 @@ func (d *Default) Decode() error { } // 放置目标方块但不写入方块实体数据 -func (d *Default) WriteDatas() error { - err := d.Package.API.SetBlockFastly(d.Package.Datas.Position, d.Package.Block.Name, d.Package.Datas.StatesString) +func (d *Default) WriteData() error { + err := d.BlockEntity.Interface.SetBlockAsync(d.BlockEntity.AdditionalData.Position, d.BlockEntity.Block.Name, d.BlockEntity.AdditionalData.BlockStates) if err != nil { return fmt.Errorf("placeBlockWithNBTData: %v", err) } diff --git a/fastbuilder/bdump/block_nbt/get_method.go b/fastbuilder/bdump/block_nbt/get_method.go new file mode 100644 index 000000000..e79999793 --- /dev/null +++ b/fastbuilder/bdump/block_nbt/get_method.go @@ -0,0 +1,16 @@ +package blockNBT + +// 取得用于放置目标方块实体的 接口/方法 +func getMethod(block *BlockEntity) GeneralBlockNBT { + switch block.AdditionalData.Type { + case "CommandBlock": + return &CommandBlock{BlockEntity: block, ShouldPlaceBlock: true} + case "Container": + return &Container{BlockEntity: block} + case "Sign": + return &Sign{BlockEntity: block} + default: + return &Default{BlockEntity: block} + // 其他尚且未被支持的方块实体 + } +} diff --git a/fastbuilder/bdump/blockNBT/pool.go b/fastbuilder/bdump/block_nbt/pool.go similarity index 75% rename from fastbuilder/bdump/blockNBT/pool.go rename to fastbuilder/bdump/block_nbt/pool.go index 8b3ec9c5c..a95c52c0e 100644 --- a/fastbuilder/bdump/blockNBT/pool.go +++ b/fastbuilder/bdump/block_nbt/pool.go @@ -19,8 +19,6 @@ var SupportBlocksPool map[string]string = map[string]string{ "hopper": "Container", "dispenser": "Container", "dropper": "Container", - "cauldron": "Container", - "lava_cauldron": "Container", "jukebox": "Container", "brewing_stand": "Container", "undyed_shulker_box": "Container", @@ -69,3 +67,25 @@ var SupportBlocksPool map[string]string = map[string]string{ "warped_hanging_sign": "Sign", // 告示牌 } + +// 此表描述了可被 replaceitem 生效的容器。 +// key 代表容器的方块名,而 value 则代表此容器放置物品所使用的复合标签或列表 +var SupportContainerPool map[string]string = map[string]string{ + "blast_furnace": "Items", + "lit_blast_furnace": "Items", + "smoker": "Items", + "lit_smoker": "Items", + "furnace": "Items", + "lit_furnace": "Items", + "chest": "Items", + "barrel": "Items", + "trapped_chest": "Items", + "lectern": "book", + "hopper": "Items", + "dispenser": "Items", + "dropper": "Items", + "jukebox": "RecordItem", + "brewing_stand": "Items", + "undyed_shulker_box": "Items", + "shulker_box": "Items", +} diff --git a/fastbuilder/bdump/blockNBT/run.go b/fastbuilder/bdump/block_nbt/run.go similarity index 57% rename from fastbuilder/bdump/blockNBT/run.go rename to fastbuilder/bdump/block_nbt/run.go index 01e3a280a..1fab61190 100644 --- a/fastbuilder/bdump/blockNBT/run.go +++ b/fastbuilder/bdump/block_nbt/run.go @@ -2,41 +2,41 @@ package blockNBT import ( "fmt" - GlobalAPI "phoenixbuilder/GameControl/GlobalAPI" + env_interfaces "phoenixbuilder/fastbuilder/environment/interfaces" "phoenixbuilder/fastbuilder/types" "sync" ) -var apiIsUsing sync.Mutex +var interfaceLock sync.Mutex // 带有 NBT 数据放置方块。 // 若你也想参与对于方块实体的其他支持, // 另见 https://github.com/df-mc/dragonfly func PlaceBlockWithNBTData( - api *GlobalAPI.GlobalAPI, + intf env_interfaces.GameInterface, blockInfo *types.Module, - datas *Datas, + additionalData *AdditionalData, ) error { - defer apiIsUsing.Unlock() - apiIsUsing.Lock() + defer interfaceLock.Unlock() + interfaceLock.Lock() // lock(or unlock) api generalBlock, err := parseBlockModule(blockInfo) if err != nil { return fmt.Errorf("PlaceBlockWithNBTData: Failed to place the entity block named %v at (%d,%d,%d), and the error log is %v", *blockInfo.Block.Name, blockInfo.Point.X, blockInfo.Point.Y, blockInfo.Point.Z, err) } // get general block - newRequest := Package{ - API: api, - Block: generalBlock, - Datas: datas, + newRequest := BlockEntity{ + Interface: intf, + Block: generalBlock, + AdditionalData: *additionalData, } - newRequest.Datas.StatesString = blockInfo.Block.BlockStates - newRequest.Datas.Position = [3]int32{int32(blockInfo.Point.X), int32(blockInfo.Point.Y), int32(blockInfo.Point.Z)} - newRequest.Datas.Type = checkIfIsEffectiveNBTBlock(newRequest.Block.Name) + newRequest.AdditionalData.BlockStates = blockInfo.Block.BlockStates + newRequest.AdditionalData.Position = [3]int32{int32(blockInfo.Point.X), int32(blockInfo.Point.Y), int32(blockInfo.Point.Z)} + newRequest.AdditionalData.Type = isNBTBlockSupported(newRequest.Block.Name) // get new request of place nbt block var placeBlockMethod GeneralBlockNBT - if datas.Settings.AssignNBTData || newRequest.Datas.Type == "CommandBlock" { - placeBlockMethod = getMethod(newRequest) + if additionalData.Settings.AssignNBTData || newRequest.AdditionalData.Type == "CommandBlock" { + placeBlockMethod = getMethod(&newRequest) err = placeBlockMethod.Decode() if err != nil { return fmt.Errorf("PlaceBlockWithNBTData: %v", err) @@ -44,11 +44,11 @@ func PlaceBlockWithNBTData( // if the user wants us to assign NBT data, // or the target block is a command block } else { - placeBlockMethod = &Default{Package: &newRequest} + placeBlockMethod = &Default{BlockEntity: &newRequest} // if the user does not want us to assign NBT data } // get method and decode nbt data into golang struct - err = placeBlockMethod.WriteDatas() + err = placeBlockMethod.WriteData() if err != nil { return fmt.Errorf("PlaceBlockWithNBTData: %v", err) } diff --git a/fastbuilder/bdump/block_nbt/sign.go b/fastbuilder/bdump/block_nbt/sign.go new file mode 100644 index 000000000..2f9d44111 --- /dev/null +++ b/fastbuilder/bdump/block_nbt/sign.go @@ -0,0 +1,195 @@ +package blockNBT + +import ( + "fmt" + GameInterface "phoenixbuilder/game_control/game_interface" + "phoenixbuilder/minecraft/protocol/packet" + + "github.com/google/uuid" +) + +// Sign 结构体用于描述一个完整的告示牌 +type Sign struct { + BlockEntity *BlockEntity // 该方块实体的详细数据 +} + +// 我们不再检查用户提供的告示牌的 NBT 是否正确。 +// 我们信任并且永远认为它们是正确且完整的 +func (s *Sign) Decode() error { + return nil +} + +// 放置一个告示牌并写入告示牌数据 +func (s *Sign) WriteData() error { + var uniqueID_1 uuid.UUID + var uniqueID_2 uuid.UUID + // 初始化变量 + if s.BlockEntity.AdditionalData.FastMode { + err := s.BlockEntity.Interface.SetBlockAsync(s.BlockEntity.AdditionalData.Position, s.BlockEntity.Block.Name, s.BlockEntity.AdditionalData.BlockStates) + if err != nil { + return fmt.Errorf("WriteData: %v", err) + } + return nil + } + gameInterface := s.BlockEntity.Interface.(*GameInterface.GameInterface) + // 放置告示牌(快速导入模式下) + { + err := gameInterface.SendSettingsCommand(fmt.Sprintf("tp %d %d %d", s.BlockEntity.AdditionalData.Position[0], s.BlockEntity.AdditionalData.Position[1], s.BlockEntity.AdditionalData.Position[2]), true) + if err != nil { + return fmt.Errorf("WriteData: %v", err) + } + // 传送机器人到告示牌所在的位置 + err = gameInterface.SendSettingsCommand( + fmt.Sprintf( + "setblock %d %d %d air", + s.BlockEntity.AdditionalData.Position[0], + s.BlockEntity.AdditionalData.Position[1], + s.BlockEntity.AdditionalData.Position[2], + ), + true, + ) + if err != nil { + return fmt.Errorf("WriteData: %v", err) + } + // 清除当前告示牌处的方块。 + // 如果不这么做且原本该处的方块是告示牌的话, + // 那么 NBT 数据将会注入失败 + err = gameInterface.SendSettingsCommand( + "replaceitem entity @s slot.hotbar 0 oak_sign", + true, + ) + if err != nil { + return fmt.Errorf("WriteData: %v", err) + } + // 获取一个告示牌到快捷栏 0 + err = gameInterface.ChangeSelectedHotbarSlot(0) + if err != nil { + return fmt.Errorf("WriteData: %v", err) + } + // 切换手持物品栏到快捷栏 0 + uniqueID_1, err = gameInterface.BackupStructure( + GameInterface.MCStructure{ + BeginX: s.BlockEntity.AdditionalData.Position[0] + 1, + BeginY: s.BlockEntity.AdditionalData.Position[1], + BeginZ: s.BlockEntity.AdditionalData.Position[2], + SizeX: 1, + SizeY: 1, + SizeZ: 1, + }, + ) + if err != nil { + return fmt.Errorf("WriteData: %v", err) + } + /* + 我们会在告示牌的 (~1, ~, ~) 处生成一个玻璃, + 然后点击这个玻璃并指定点击的面是 4 以将手中的告示牌放上去。 + + 这样,我们就可以取得反作弊的认同, + 然后我们就可以向告示牌注入 NBT 数据了。 + + 但在生成玻璃前,我们需要备份这个玻璃原本的方块以方便之后恢复它 + */ + _, err = gameInterface.SendWSCommandWithResponse( + fmt.Sprintf( + "setblock %d %d %d glass", + s.BlockEntity.AdditionalData.Position[0]+1, + s.BlockEntity.AdditionalData.Position[1], + s.BlockEntity.AdditionalData.Position[2], + ), + ) + if err != nil { + return fmt.Errorf("WriteData: %v", err) + } + // 生成上文提到的玻璃 + err = gameInterface.PlaceBlock( + GameInterface.UseItemOnBlocks{ + HotbarSlotID: 0, + BlockPos: [3]int32{ + s.BlockEntity.AdditionalData.Position[0] + 1, + s.BlockEntity.AdditionalData.Position[1], + s.BlockEntity.AdditionalData.Position[2], + }, + BlockName: "minecraft:glass", + BlockStates: map[string]interface{}{}, + }, + 4, + ) + if err != nil { + return fmt.Errorf("WriteData: %v", err) + } + // 在玻璃上放置手中的告示牌 + err = gameInterface.SetBlockAsync(s.BlockEntity.AdditionalData.Position, s.BlockEntity.Block.Name, s.BlockEntity.AdditionalData.BlockStates) + if err != nil { + return fmt.Errorf("WriteData: %v", err) + } + // 现在玻璃上有了一个告示牌,这是我们刚刚放上去的, + // 但这个告示牌的种类是 oak_sign ,且朝向固定, + // 因此现在我们需要覆写这个告示牌的种类及朝向为正确的形式。 + // 经过测试,覆写操作不会导致 NBT 数据无法注入 + } + // 放置告示牌 + err := gameInterface.WritePacket(&packet.BlockActorData{ + Position: s.BlockEntity.AdditionalData.Position, + NBTData: s.BlockEntity.Block.NBT, + }) + if err != nil { + return fmt.Errorf("WriteData: %v", err) + } + // 写入告示牌数据 + uniqueID_2, err = gameInterface.BackupStructure(GameInterface.MCStructure{ + BeginX: s.BlockEntity.AdditionalData.Position[0], + BeginY: s.BlockEntity.AdditionalData.Position[1], + BeginZ: s.BlockEntity.AdditionalData.Position[2], + SizeX: 1, + SizeY: 1, + SizeZ: 1, + }) + if err != nil { + return fmt.Errorf("WriteData: %v", err) + } + /* + 备份告示牌处的方块。 + + 稍后我们会恢复上文提到的玻璃处的方块为原本方块, + 而此方块被恢复后,游戏会按照特性刷新它附近的方块, + 也就是告示牌方块。 + + 但我们无法保证刷新后,我们导入的告示牌仍然可以稳定存在, + 因为它可能会因为缺少依附方块而掉落。 + + 因此,我们现在备份一次告示牌,然后再恢复玻璃处的方块, + 然后再强行生成一次告示牌本身。 + + 注:这个解法并不优雅,而且会浪费时间, + 但它可以显著提高告示牌的存活概率, + 而且用户不希望为了告示牌而再导入一次 BDX 文件。 + + TODO: 在某天推迟部分方块的导入顺序, + 使得告示牌这类依附型方块在最后再被导入 + */ + err = gameInterface.RevertStructure( + uniqueID_1, + GameInterface.BlockPos{ + s.BlockEntity.AdditionalData.Position[0] + 1, + s.BlockEntity.AdditionalData.Position[1], + s.BlockEntity.AdditionalData.Position[2], + }, + ) + if err != nil { + return fmt.Errorf("WriteData: %v", err) + } + // 将上文提到的玻璃处的方块恢复为原本的方块 + go func() { + gameInterface.RevertStructure( + uniqueID_2, + GameInterface.BlockPos{ + s.BlockEntity.AdditionalData.Position[0], + s.BlockEntity.AdditionalData.Position[1], + s.BlockEntity.AdditionalData.Position[2], + }, + ) + }() + // 再强行生成一次告示牌本身以抑制其可能发生的掉落 + return nil + // 返回值 +} diff --git a/fastbuilder/bdump/blockNBT/utils.go b/fastbuilder/bdump/block_nbt/utils.go similarity index 69% rename from fastbuilder/bdump/blockNBT/utils.go rename to fastbuilder/bdump/block_nbt/utils.go index 99a5a65b3..3dfe0c311 100644 --- a/fastbuilder/bdump/blockNBT/utils.go +++ b/fastbuilder/bdump/block_nbt/utils.go @@ -10,7 +10,7 @@ import ( // 从 SupportBlocksPool 检查这个方块实体是否已被支持。 // 如果尚未被支持,则返回空字符串,否则返回这种方块的类型。 // 以告示牌为例,所有的告示牌都可以写作为 Sign -func checkIfIsEffectiveNBTBlock(blockName string) string { +func isNBTBlockSupported(blockName string) string { value, ok := SupportBlocksPool[blockName] if ok { return value @@ -35,24 +35,4 @@ func parseBlockModule(singleBlock *types.Module) (GeneralBlock, error) { States: blockStates, NBT: singleBlock.NBTMap, }, nil - // return -} - -// 取得用于放置目标方块实体的 接口/方法 -func getMethod(pack Package) GeneralBlockNBT { - switch pack.Datas.Type { - case "CommandBlock": - return &CommandBlock{Package: &pack, NeedToPlaceBlock: true} - // 命令方块 - case "Container": - return &Container{Package: &pack} - // 容器 - case "Sign": - return &Sign{Package: &pack} - // 告示牌 - default: - return &Default{Package: &pack} - // 其他尚且未被支持的方块实体 - } - // 返回值 } diff --git a/fastbuilder/builder/acme.go b/fastbuilder/builder/acme.go index 6078c1810..08e7438d5 100644 --- a/fastbuilder/builder/acme.go +++ b/fastbuilder/builder/acme.go @@ -1,5 +1,15 @@ package builder +import ( + "errors" + I18n "phoenixbuilder/fastbuilder/i18n" + "phoenixbuilder/fastbuilder/types" +) + +func Acme(config *types.MainConfig, blc chan *types.Module) error { + return errors.New(I18n.T(I18n.Warning_ACME_Deprecated)) +} +/* import ( "bufio" "compress/gzip" @@ -138,3 +148,4 @@ func Acme(config *types.MainConfig, blc chan *types.Module) error { } return nil } +*/ diff --git a/fastbuilder/builder/builder.go b/fastbuilder/builder/builder.go index 8f3f6509c..ddb978324 100644 --- a/fastbuilder/builder/builder.go +++ b/fastbuilder/builder/builder.go @@ -12,8 +12,8 @@ var Builder = map[string]func(config *types.MainConfig, blc chan *types.Module) "sphere": Sphere, "ellipse": Ellipse, "ellipsoid": Ellipsoid, - "plot": Paint, - "schem": Schematic, + "paint": Paint, + "schematic": Schematic, "acme": Acme, "bdump": BDump, "mapart": MapArt, @@ -26,7 +26,3 @@ func Generate(config *types.MainConfig, blc chan *types.Module) error { return Builder[config.Execute](config, blc) } } - -func PipeGenerate(configs []*types.Config) []*types.Module { - return nil -} diff --git a/fastbuilder/builder/geometry.go b/fastbuilder/builder/geometric.go similarity index 80% rename from fastbuilder/builder/geometry.go rename to fastbuilder/builder/geometric.go index 3ff81ff25..f16f58406 100644 --- a/fastbuilder/builder/geometry.go +++ b/fastbuilder/builder/geometric.go @@ -1,43 +1,49 @@ package builder -import "phoenixbuilder/fastbuilder/types" +import ( + "phoenixbuilder/fastbuilder/types" + "math" +) func Circle(config *types.MainConfig, blc chan *types.Module)error { Radius := config.Radius Facing := config.Facing point := config.Position + radius_squared:=math.Pow(float64(Radius), 2) + var push_to_channel func(int, int) switch Facing { case "x": - for i := -Radius; i <= Radius; i++ { - for j := -Radius; j <= Radius; j++ { - if i*i+j*j < Radius*Radius && i*i+j*j >= (Radius-1)*(Radius-1) { - var b types.Module - b.Point = types.Position{point.X, point.Y + i, point.Z + j} - blc <- &b - } + push_to_channel=func (x int, y int) { + blc<-&types.Module { + Point: types.Position {point.X, point.Y + y, point.Z + x}, } } case "y": - for i := -Radius; i <= Radius; i++ { - for j := -Radius; j <= Radius; j++ { - if i*i+j*j < Radius*Radius && i*i+j*j >= (Radius-1)*(Radius-1) { - var b types.Module - b.Point = types.Position{point.X + i, point.Y, point.Z + j} - blc <- &b - } + push_to_channel=func (x int, y int) { + blc<-&types.Module { + Point: types.Position {point.X+x, point.Y, point.Z + y}, } } case "z": - for i := -Radius; i <= Radius; i++ { - for j := -Radius; j <= Radius; j++ { - if i*i+j*j < Radius*Radius && i*i+j*j >= (Radius-1)*(Radius-1) { - var b types.Module - b.Point = types.Position{point.X + i, point.Y + j, point.Z} - blc <- &b - } + push_to_channel=func (x int, y int) { + blc<-&types.Module { + Point: types.Position {point.X+x, point.Y+y, point.Z}, } } } + for i:=0;i<=Radius;i++ { + first_quadrant_val:=int(math.Sqrt(radius_squared-math.Pow(float64(i), 2))) + push_to_channel(i, first_quadrant_val) + if(first_quadrant_val!=0) { + push_to_channel(i, -first_quadrant_val) + } + if(i!=0) { + push_to_channel(-i,first_quadrant_val) + } + if(first_quadrant_val!=0&&i!=0) { + push_to_channel(-i,-first_quadrant_val) + } + } return nil } diff --git a/fastbuilder/builder/paint.go b/fastbuilder/builder/image.go similarity index 100% rename from fastbuilder/builder/paint.go rename to fastbuilder/builder/image.go diff --git a/fastbuilder/builder/schematic.go b/fastbuilder/builder/schematic.go index 12d3d5159..76c833c6c 100644 --- a/fastbuilder/builder/schematic.go +++ b/fastbuilder/builder/schematic.go @@ -1,76 +1,73 @@ package builder import ( - "compress/gzip" - "fmt" - "io/ioutil" - "os" + "errors" I18n "phoenixbuilder/fastbuilder/i18n" "phoenixbuilder/fastbuilder/types" - - "github.com/Tnze/go-mc/nbt" ) func Schematic(config *types.MainConfig, blc chan *types.Module) error { - file, err := os.Open(config.Path) - if err != nil { - return I18n.ProcessSystemFileError(err) - } - defer file.Close() - gzip, err := gzip.NewReader(file) - if err != nil { - return err - } - defer gzip.Close() - buffer, err := ioutil.ReadAll(gzip) - - var SchematicModule struct { - Blocks []byte `nbt:"Blocks"` - Data []byte `nbt:"Data"` - Width int `nbt:"Width"` - Length int `nbt:"Length"` - Height int `nbt:"Height"` - WEOffsetX int `nbt:"WEOffsetX"` - WEOffsetY int `nbt:"WEOffsetY"` - WEOffsetZ int `nbt:"WEOffsetZ"` - } - - if err := nbt.Unmarshal(buffer, &SchematicModule); err != nil { - // Won't return the error `err` since it contains a large content that can - // crash the server after being sent. - return fmt.Errorf(I18n.T(I18n.Sch_FailedToResolve)) - } - if len(SchematicModule.Blocks) == 0 { - return fmt.Errorf("Invalid structure.") - } - Size := [3]int{SchematicModule.Width, SchematicModule.Height, SchematicModule.Length} - Offset := [3]int{SchematicModule.WEOffsetX, SchematicModule.WEOffsetY, SchematicModule.WEOffsetZ} - X, Y, Z := 0, 1, 2 - BlockIndex := 0 - - for y := 0; y < Size[Y]; y++ { - for z := 0; z < Size[Z]; z++ { - for x := 0; x < Size[X]; x++ { - p := config.Position - p.X += x + Offset[X] - p.Y += y + Offset[Y] - p.Z += z + Offset[Z] - var b types.Block - b.Name = &BlockStr[SchematicModule.Blocks[BlockIndex]] - b.Data = uint16(SchematicModule.Data[BlockIndex]) - if BlockIndex-188 <= 5 && BlockIndex-188 >= 0 { - b.Name = &FenceName - b.Data = uint16(BlockIndex - 188) - } - if BlockIndex == 3 && b.Data == 2 { - b.Name = &PodzolName - } - if *b.Name != "air" { - blc <- &types.Module{Point: p, Block: &b} - } - BlockIndex++ - } - } - } - return nil + return errors.New(I18n.T(I18n.Warning_Schem_Deprecated)) + // + //file, err := os.Open(config.Path) + //if err != nil { + // return I18n.ProcessSystemFileError(err) + //} + //defer file.Close() + //gzip, err := gzip.NewReader(file) + //if err != nil { + // return err + //} + //defer gzip.Close() + //buffer, err := ioutil.ReadAll(gzip) + // + //var SchematicModule struct { + // Blocks []byte `nbt:"Blocks"` + // Data []byte `nbt:"Data"` + // Width int `nbt:"Width"` + // Length int `nbt:"Length"` + // Height int `nbt:"Height"` + // WEOffsetX int `nbt:"WEOffsetX"` + // WEOffsetY int `nbt:"WEOffsetY"` + // WEOffsetZ int `nbt:"WEOffsetZ"` + //} + // + //if err := nbt.Unmarshal(buffer, &SchematicModule); err != nil { + // // Won't return the error `err` since it contains a large content that can + // // crash the server after being sent. + // return fmt.Errorf(I18n.T(I18n.Sch_FailedToResolve)) + //} + //if len(SchematicModule.Blocks) == 0 { + // return fmt.Errorf("Invalid structure.") + //} + //Size := [3]int{SchematicModule.Width, SchematicModule.Height, SchematicModule.Length} + //Offset := [3]int{SchematicModule.WEOffsetX, SchematicModule.WEOffsetY, SchematicModule.WEOffsetZ} + //X, Y, Z := 0, 1, 2 + //BlockIndex := 0 + // + //for y := 0; y < Size[Y]; y++ { + // for z := 0; z < Size[Z]; z++ { + // for x := 0; x < Size[X]; x++ { + // p := config.Position + // p.X += x + Offset[X] + // p.Y += y + Offset[Y] + // p.Z += z + Offset[Z] + // var b types.Block + // b.Name = &BlockStr[SchematicModule.Blocks[BlockIndex]] + // b.Data = uint16(SchematicModule.Data[BlockIndex]) + // if BlockIndex-188 <= 5 && BlockIndex-188 >= 0 { + // b.Name = &FenceName + // b.Data = uint16(BlockIndex - 188) + // } + // if BlockIndex == 3 && b.Data == 2 { + // b.Name = &PodzolName + // } + // if *b.Name != "air" { + // blc <- &types.Module{Point: p, Block: &b} + // } + // BlockIndex++ + // } + // } + //} + //return nil } diff --git a/fastbuilder/commands_generator/summon.go b/fastbuilder/commands_generator/summon.go index c0c436697..3c8436bee 100644 --- a/fastbuilder/commands_generator/summon.go +++ b/fastbuilder/commands_generator/summon.go @@ -1,5 +1,3 @@ -// +build do_not_add_this_tag__not_implemented - package commands_generator import ( @@ -9,13 +7,8 @@ import ( func SummonRequest(module *types.Module, config *types.MainConfig) string { - Entity := module.Entity - Point := module.Point - Method := config.Method - if Entity != nil { - return fmt.Sprintf("summon %s %v %v %v", *Entity, Point.X, Point.Y, Point.Z) - } else { - return fmt.Sprintf("summon %s %v %v %v", *Entity, Point.X, Point.Y, Point.Z) - } + entity := config.Entity + point := module.Point + return fmt.Sprintf("summon %s %d %d %d", entity, point.X, point.Y, point.Z) } diff --git a/fastbuilder/configuration/configuration.go b/fastbuilder/configuration/configuration.go index 3902e01fd..f5611f0b6 100644 --- a/fastbuilder/configuration/configuration.go +++ b/fastbuilder/configuration/configuration.go @@ -1,7 +1,6 @@ package configuration import ( - "github.com/google/uuid" "phoenixbuilder/fastbuilder/types" "phoenixbuilder/fastbuilder/environment" ) @@ -72,8 +71,7 @@ func CreateFullConfig() *FullConfig { return &fc } -var ZeroId uuid.UUID -var OneId uuid.UUID + var IsOp bool var SessionInitID int diff --git a/fastbuilder/core/mc_client.go b/fastbuilder/core/mc_client.go index 901a11980..8f0ae2faf 100644 --- a/fastbuilder/core/mc_client.go +++ b/fastbuilder/core/mc_client.go @@ -1,14 +1,14 @@ package core import ( - "bytes" "context" "fmt" "phoenixbuilder/minecraft" "phoenixbuilder/minecraft/protocol/packet" + "phoenixbuilder/fastbuilder/py_rpc" ) -func InitMCConnection(ctx context.Context, authentication minecraft.Authenticator, options ...Option) (conn *minecraft.Conn, err error) { +func InitializeMinecraftConnection(ctx context.Context, authentication minecraft.Authenticator, options ...Option) (conn *minecraft.Conn, err error) { if checkOption(options, OptionDebug) { conn = &minecraft.Conn{ DebugMode: true, @@ -27,30 +27,58 @@ func InitMCConnection(ctx context.Context, authentication minecraft.Authenticato }) runtimeid := fmt.Sprintf("%d", conn.GameData().EntityUniqueID) conn.WritePacket(&packet.PyRpc{ - Content: []byte{0x82, 0xc4, 0x8, 0x5f, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x5f, 0xc4, 0x5, 0x74, 0x75, 0x70, 0x6c, 0x65, 0xc4, 0x5, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x93, 0xc4, 0xc, 0x53, 0x79, 0x6e, 0x63, 0x55, 0x73, 0x69, 0x6e, 0x67, 0x4d, 0x6f, 0x64, 0x82, 0xc4, 0x8, 0x5f, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x5f, 0xc4, 0x5, 0x74, 0x75, 0x70, 0x6c, 0x65, 0xc4, 0x5, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x91, 0x90, 0xc0}, + Value: py_rpc.FromGo([]interface{} { + "SyncUsingMod", + []interface{} {}, + nil, + }), }) conn.WritePacket(&packet.PyRpc{ - Content: []byte{0x82, 0xc4, 0x8, 0x5f, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x5f, 0xc4, 0x5, 0x74, 0x75, 0x70, 0x6c, 0x65, 0xc4, 0x5, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x93, 0xc4, 0xf, 0x53, 0x79, 0x6e, 0x63, 0x56, 0x69, 0x70, 0x53, 0x6b, 0x69, 0x6e, 0x55, 0x75, 0x69, 0x64, 0x82, 0xc4, 0x8, 0x5f, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x5f, 0xc4, 0x5, 0x74, 0x75, 0x70, 0x6c, 0x65, 0xc4, 0x5, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x91, 0xc0, 0xc0}, + Value: py_rpc.FromGo([]interface{} { + "SyncVipSkinUuid", + []interface{} {nil}, + nil, + }), }) conn.WritePacket(&packet.PyRpc{ - Content: []byte{0x82, 0xc4, 0x8, 0x5f, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x5f, 0xc4, 0x5, 0x74, 0x75, 0x70, 0x6c, 0x65, 0xc4, 0x5, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x93, 0xc4, 0x1f, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4c, 0x6f, 0x61, 0x64, 0x41, 0x64, 0x64, 0x6f, 0x6e, 0x73, 0x46, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x46, 0x72, 0x6f, 0x6d, 0x47, 0x61, 0x63, 0x82, 0xc4, 0x8, 0x5f, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x5f, 0xc4, 0x5, 0x74, 0x75, 0x70, 0x6c, 0x65, 0xc4, 0x5, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x90, 0xc0}, + Value: py_rpc.FromGo([]interface{} { + "ClientLoadAddonsFinishedFromGac", + []interface{} {}, + nil, + }), }) conn.WritePacket(&packet.PyRpc{ - Content: bytes.Join([][]byte{[]byte{0x82, 0xc4, 0x8, 0x5f, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x5f, 0xc4, 0x5, 0x74, 0x75, 0x70, 0x6c, 0x65, 0xc4, 0x5, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x93, 0xc4, 0xb, 0x4d, 0x6f, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x43, 0x32, 0x53, 0x82, 0xc4, 0x8, 0x5f, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x5f, 0xc4, 0x5, 0x74, 0x75, 0x70, 0x6c, 0x65, 0xc4, 0x5, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x94, 0xc4, 0x9, 0x4d, 0x69, 0x6e, 0x65, 0x63, 0x72, 0x61, 0x66, 0x74, 0xc4, 0x6, 0x70, 0x72, 0x65, 0x73, 0x65, 0x74, 0xc4, 0x12, 0x47, 0x65, 0x74, 0x4c, 0x6f, 0x61, 0x64, 0x65, 0x64, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x81, 0xc4, 0x8, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x49, 0x64, 0xc4}, - []byte{byte(len(runtimeid))}, - []byte(runtimeid), - []byte{0xc0}, - }, []byte{}), + Value: py_rpc.FromGo([]interface{} { + "ModEventC2S", + []interface{} { + "Minecraft", + "preset", + "GetLoadedInstances", + map[string]interface{} { + "playerId": runtimeid, + }, + }, + nil, + }), }) conn.WritePacket(&packet.PyRpc{ - Content: []byte{0x82, 0xc4, 0x8, 0x5f, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x5f, 0xc4, 0x5, 0x74, 0x75, 0x70, 0x6c, 0x65, 0xc4, 0x5, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x93, 0xc4, 0x19, 0x61, 0x72, 0x65, 0x6e, 0x61, 0x47, 0x61, 0x6d, 0x65, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x46, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x4c, 0x6f, 0x61, 0x64, 0x82, 0xc4, 0x8, 0x5f, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x5f, 0xc4, 0x5, 0x74, 0x75, 0x70, 0x6c, 0x65, 0xc4, 0x5, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x90, 0xc0}, + Value: py_rpc.FromGo([]interface{} { + "arenaGamePlayerFinishLoad", + []interface{} {}, + nil, + }), }) conn.WritePacket(&packet.PyRpc{ - Content: bytes.Join([][]byte{[]byte{0x82, 0xc4, 0x8, 0x5f, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x5f, 0xc4, 0x5, 0x74, 0x75, 0x70, 0x6c, 0x65, 0xc4, 0x5, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x93, 0xc4, 0xb, 0x4d, 0x6f, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x43, 0x32, 0x53, 0x82, 0xc4, 0x8, 0x5f, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x5f, 0xc4, 0x5, 0x74, 0x75, 0x70, 0x6c, 0x65, 0xc4, 0x5, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x94, 0xc4, 0x9, 0x4d, 0x69, 0x6e, 0x65, 0x63, 0x72, 0x61, 0x66, 0x74, 0xc4, 0xe, 0x76, 0x69, 0x70, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0xc4, 0xc, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x55, 0x69, 0x49, 0x6e, 0x69, 0x74, 0xc4}, - []byte{byte(len(runtimeid))}, - []byte(runtimeid), - []byte{0xc0}, - }, []byte{}), + Value: py_rpc.FromGo([]interface{} { + "ModEventC2S", + []interface{} { + "Minecraft", + "vipEventSystem", + "PlayerUiInit", + runtimeid, + }, + nil, + }), }) return } diff --git a/fastbuilder/credentials/token.go b/fastbuilder/credentials/token.go index bfe9936bd..8d91c2c69 100644 --- a/fastbuilder/credentials/token.go +++ b/fastbuilder/credentials/token.go @@ -12,7 +12,7 @@ import ( func ProcessTokenDefault(env *environment.PBEnvironment) bool { token := env.LoginInfo.Token - client := fbauth.CreateClient(env) + client := fbauth.CreateClient(env.ClientOptions) env.FBAuthClient = client if token[0] == '{' { token, err_msg := client.GetToken("", token) diff --git a/fastbuilder/credentials/uesr_input.go b/fastbuilder/credentials/user_input.go similarity index 100% rename from fastbuilder/credentials/uesr_input.go rename to fastbuilder/credentials/user_input.go diff --git a/fastbuilder/cv4/auth/client.go b/fastbuilder/cv4/auth/client.go index a85d1ab4a..372e5ec7f 100644 --- a/fastbuilder/cv4/auth/client.go +++ b/fastbuilder/cv4/auth/client.go @@ -14,44 +14,56 @@ import ( "fmt" "io" - "phoenixbuilder/fastbuilder/args" - "phoenixbuilder/fastbuilder/environment" I18n "phoenixbuilder/fastbuilder/i18n" "github.com/gorilla/websocket" "github.com/pterm/pterm" ) -type Client struct { - privateKey *ecdsa.PrivateKey - rsaPublicKey *rsa.PublicKey +type ClientOptions struct { + AuthServer string + FBUCUsername string +} - salt []byte - client *websocket.Conn +func MakeDefaultClientOptions() *ClientOptions { + return &ClientOptions{ + AuthServer: "wss://api.fastbuilder.pro:2053/", + FBUCUsername: "", + } +} +type Client struct { + privateKey *ecdsa.PrivateKey + rsaPublicKey *rsa.PublicKey + salt []byte + client *websocket.Conn peerNoEncryption bool encryptor *encryptionSession serverResponse chan map[string]interface{} + closed bool + options *ClientOptions - closed bool - - env *environment.PBEnvironment + Uid string + CertSigning bool + LocalKey string + LocalCert string + WorldChatChannel chan []string } -func CreateClient(env *environment.PBEnvironment) *Client { +func CreateClient(options *ClientOptions) *Client { privateKey, err := ecdsa.GenerateKey(elliptic.P384(), rand.Reader) if err != nil { panic(err) } - salt := []byte("2345678987654321") + salt := []byte("23456789f7654321") authclient := &Client{ privateKey: privateKey, salt: salt, serverResponse: make(chan map[string]interface{}), closed: false, - env: env, + options: options, } - cl, _, err := websocket.DefaultDialer.Dial(args.AuthServer(), nil) + cl, _, err := websocket.DefaultDialer.Dial(options.AuthServer, nil) if err != nil { panic(err) } @@ -99,7 +111,7 @@ func CreateClient(env *environment.PBEnvironment) *Client { chat_msg, _ := message["msg"].(string) chat_sender, _ := message["username"].(string) select { - case env.WorldChatChannel <- []string{chat_sender, chat_msg}: + case authclient.WorldChatChannel <- []string{chat_sender, chat_msg}: continue default: continue @@ -108,6 +120,8 @@ func CreateClient(env *environment.PBEnvironment) *Client { authclient.peerNoEncryption = true authclient.SendMessage([]byte(`{"action":"accept_no_encryption"}`)) close(encrypted) + } else if msgaction == "server_message" { + pterm.Info.Printf("[Auth Server] %s\n", message["message"].(string)) } select { case authclient.serverResponse <- message: @@ -164,7 +178,7 @@ type AuthRequest struct { ServerPassword string `json:"serverPassword"` Key string `json:"publicKey"` FBToken string - VersionId int64 `json:"version_id"` + VersionId int64 `json:"version_id"` //IgnoreVersionCheck bool `json:"ignore_version_check"` } @@ -175,7 +189,9 @@ func (client *Client) Auth(ctx context.Context, serverCode string, serverPasswor ServerPassword: serverPassword, Key: key, FBToken: fbtoken, - VersionId: 2, + VersionId: 4, + // New format of PyRpc + // ^ // The implemention of version_id is in no way for the purpose // of blocking the access of old versions, but for saving server @@ -189,10 +205,17 @@ func (client *Client) Auth(ctx context.Context, serverCode string, serverPasswor panic("Failed to encode json") } client.SendMessage(msg) +Retry: select { case <-ctx.Done(): return "", 0, fmt.Errorf("fb auth server response time out (%v)", err) - case resp, _ := <-client.serverResponse: + case resp := <-client.serverResponse: + _, exist := resp["code"] + if !exist { + goto Retry + } + // The first message is `{"action":"server_message","message":"欢迎, xxx !"}`, + // so we need to make sure that the message we get is what we want. code, _ := resp["code"].(float64) if code != 0 { err, _ := resp["message"].(string) @@ -204,25 +227,25 @@ func (client *Client) Auth(ctx context.Context, serverCode string, serverPasswor } uc_username, _ := resp["username"].(string) u_uid, _ := resp["uid"].(string) - client.env.FBUCUsername = uc_username - client.env.Uid = u_uid + client.options.FBUCUsername = uc_username + client.Uid = u_uid str, _ := resp["chainInfo"].(string) - client.env.CertSigning = true + client.CertSigning = true if signingKey, success := resp["privateSigningKey"].(string); success { - client.env.LocalKey = signingKey + client.LocalKey = signingKey } else { pterm.Error.Println("Failed to fetch privateSigningKey from server") - client.env.CertSigning = false - client.env.LocalKey = "" + client.CertSigning = false + client.LocalKey = "" } if keyProve, success := resp["prove"].(string); success { - client.env.LocalCert = keyProve + client.LocalCert = keyProve } else { pterm.Error.Println("Failed to fetch keyProve from server") - client.env.CertSigning = false - client.env.LocalCert = "" + client.CertSigning = false + client.LocalCert = "" } - if !client.env.CertSigning { + if !client.CertSigning { pterm.Error.Println("CertSigning is disabled for errors above.") } return str, 0, nil @@ -262,6 +285,16 @@ type FTokenRequest struct { } func (client *Client) GetToken(username string, password string) (string, string) { + if username!=""{ + tokenstruct := &map[string]interface{}{ + "encrypt_token": true, + "username": username, + "password": password, + } + bytes_token, _ := json.Marshal(tokenstruct) + password=string(bytes_token) + username="" + } rspreq := &FTokenRequest{ Action: "phoenix::get-token", Username: username, @@ -309,17 +342,13 @@ func (client *Client) TransferData(content string, uid string) string { type FNumRequest struct { Action string `json:"action"` - First string `json:"1st"` - Second string `json:"2nd"` - Third int64 `json:"3rd"` + Data string `json:"data"` } -func (client *Client) TransferCheckNum(first string, second string, third int64) (string, string, string) { +func (client *Client) TransferCheckNum(data string) string { rspreq := &FNumRequest{ Action: "phoenix::transfer-check-num", - First: first, - Second: second, - Third: third, + Data: data, } msg, err := json.Marshal(rspreq) if err != nil { @@ -329,12 +358,10 @@ func (client *Client) TransferCheckNum(first string, second string, third int64) resp, _ := <-client.serverResponse code, _ := resp["code"].(float64) if code != 0 { - panic(fmt.Errorf("Failed to transfer checknum: %s",resp["message"])) + panic(fmt.Errorf("Failed to transfer checknum: %s", resp["message"])) } - valM, _ := resp["valM"].(string) - valS, _ := resp["valS"].(string) - valT, _ := resp["valT"].(string) - return valM, valS, valT + val, _ := resp["value"].(string) + return val } type WorldChatRequest struct { diff --git a/fastbuilder/environment/environment.go b/fastbuilder/environment/environment.go index 2d979f212..51113f51a 100644 --- a/fastbuilder/environment/environment.go +++ b/fastbuilder/environment/environment.go @@ -2,6 +2,7 @@ package environment // This package imports only external packages to avoid import cycle. import ( + fbauth "phoenixbuilder/fastbuilder/cv4/auth" "phoenixbuilder/fastbuilder/environment/interfaces" ) @@ -17,31 +18,25 @@ type PBEnvironment struct { ScriptBridge interface{} ScriptHolder interface{} FunctionHolder interfaces.FunctionHolder - FBUCUsername string - WorldChatChannel chan []string FBAuthClient interface{} GlobalFullConfig interface{} RespondUser string - CommandSender interfaces.CommandSender Connection interface{} UQHolder interface{} Resources interface{} ResourcesUpdater interface{} - GlobalAPI interface{} + GameInterface interfaces.GameInterface TaskHolder interface{} OmegaHolder interface{} OmegaAdaptorHolder interface{} ActivateTaskStatus chan bool - Uid string ExternalConnectionHandler interface{} Destructors []func() isStopping bool stoppedWaiter chan struct{} - CertSigning bool - LocalKey string - LocalCert string LRUMemoryChunkCacher interface{} ChunkFeeder interface{} + ClientOptions *fbauth.ClientOptions } func (env *PBEnvironment) Stop() { diff --git a/fastbuilder/environment/interfaces/command_sender.go b/fastbuilder/environment/interfaces/command_sender.go deleted file mode 100644 index 562aa8221..000000000 --- a/fastbuilder/environment/interfaces/command_sender.go +++ /dev/null @@ -1,20 +0,0 @@ -//go:build !is_tweak - -package interfaces - -import ( - "sync" -) - -type CommandSender interface { - // GetUUIDMap() *sync.Map - // ClearUUIDMap() - GetBlockUpdateSubscribeMap() *sync.Map - // SendCommand(string,uuid.UUID) error - // SendWSCommand(string,uuid.UUID) error - // SendSizukanaCommand(string) error - SendChat(string) error - Output(string) error - WorldChatOutput(string, string) error - Title(string) error -} diff --git a/fastbuilder/environment/interfaces/command_sender_tweak.go b/fastbuilder/environment/interfaces/command_sender_tweak.go deleted file mode 100644 index 9c6682c2d..000000000 --- a/fastbuilder/environment/interfaces/command_sender_tweak.go +++ /dev/null @@ -1,22 +0,0 @@ -//go:build is_tweak - -package interfaces - -import ( - "sync" - - "github.com/google/uuid" -) - -type CommandSender interface { - GetUUIDMap() *sync.Map - ClearUUIDMap() - GetBlockUpdateSubscribeMap() *sync.Map - SendCommand(string, uuid.UUID) error - SendWSCommand(string, uuid.UUID) error - SendSizukanaCommand(string) error - SendChat(string) error - Output(string) error - WorldChatOutput(string, string) error - Title(string) error -} diff --git a/fastbuilder/environment/interfaces/game_interface.go b/fastbuilder/environment/interfaces/game_interface.go new file mode 100644 index 000000000..29fea4547 --- /dev/null +++ b/fastbuilder/environment/interfaces/game_interface.go @@ -0,0 +1,20 @@ +// +build !is_tweak + +package interfaces + +import "phoenixbuilder/minecraft/protocol/packet" + +type GameInterface interface { + SendSettingsCommand(string, bool) error + SendCommand(string) error + SendWSCommand(string) error + SendCommandWithResponse(string) (packet.CommandOutput, error) + SendWSCommandWithResponse(string) (packet.CommandOutput, error) + + SetBlock([3]int32,string,string) error + SetBlockAsync([3]int32,string,string) error + + SendChat(string) error + Output(string) error + Title(string) error +} \ No newline at end of file diff --git a/fastbuilder/external/external.go b/fastbuilder/external/external.go index d412fd0c0..8bf3da963 100644 --- a/fastbuilder/external/external.go +++ b/fastbuilder/external/external.go @@ -3,7 +3,6 @@ package external import ( "fmt" "io" - "phoenixbuilder/GameControl/GlobalAPI" "phoenixbuilder/fastbuilder/environment" "phoenixbuilder/fastbuilder/external/connection" "phoenixbuilder/fastbuilder/external/packet" @@ -85,12 +84,12 @@ func (handler *ExternalConnectionHandler) acceptConnection(conn connection.Relia handler.env.FunctionHolder.Process(p.Command) case *packet.GameCommandPacket: if p.CommandType == packet.CommandTypeSettings { - env.GlobalAPI.(*GlobalAPI.GlobalAPI).SendSettingsCommand(p.Command, false) + env.GameInterface.SendSettingsCommand(p.Command, false) break } else if p.CommandType == packet.CommandTypeNormal { - env.GlobalAPI.(*GlobalAPI.GlobalAPI).SendWSCommand(p.Command, p.UUID) + env.GameInterface.SendWSCommand(p.Command) } else { - env.GlobalAPI.(*GlobalAPI.GlobalAPI).SendCommand(p.Command, p.UUID) + env.GameInterface.SendCommand(p.Command) } case *packet.GamePacket: (env.Connection).(*minecraft.Conn).Write(p.Content) diff --git a/fastbuilder/external/packet/game_command.go b/fastbuilder/external/packet/game_command.go index dd047c05c..a7271d08a 100644 --- a/fastbuilder/external/packet/game_command.go +++ b/fastbuilder/external/packet/game_command.go @@ -13,7 +13,7 @@ const ( ) type GameCommandPacket struct { - UUID uuid.UUID + UUID uuid.UUID // reserved CommandType uint8 Command string } diff --git a/fastbuilder/function/function.go b/fastbuilder/function/function.go index 94b882a8c..bf1fc3925 100644 --- a/fastbuilder/function/function.go +++ b/fastbuilder/function/function.go @@ -1,34 +1,34 @@ package function import ( - "strings" "fmt" - "strconv" "phoenixbuilder/fastbuilder/environment" - "phoenixbuilder/fastbuilder/i18n" + I18n "phoenixbuilder/fastbuilder/i18n" + "strconv" + "strings" ) type Function struct { - Name string + Name string OwnedKeywords []string - - FunctionType byte - SFMinSliceLen uint16 + + FunctionType byte + SFMinSliceLen uint16 SFArgumentTypes []byte FunctionContent interface{} // Regular/Simple: func(*environment.PBEnvironment,interface{}) - // Continue: map[string]*FunctionChainItem + // Continue: map[string]*FunctionChainItem } type FunctionChainItem struct { - FunctionType byte + FunctionType byte ArgumentTypes []byte - Content interface{} + Content interface{} } const ( - FunctionTypeSimple = 0 // End of simple chain - FunctionTypeContinue = 1 // Simple chain - FunctionTypeRegular = 2 + FunctionTypeSimple = 0 // End of simple chain + FunctionTypeContinue = 1 // Simple chain + FunctionTypeRegular = 2 ) const ( @@ -41,127 +41,126 @@ const ( type EnumInfo struct { WantedValuesDescription string // "discrete, continuous, none" - Parser func(string)byte - InvalidValue byte + Parser func(string) byte + InvalidValue byte } type FunctionHolder struct { - env *environment.PBEnvironment - FunctionMap map[string]*Function + env *environment.PBEnvironment + FunctionMap map[string]*Function SimpleFunctionEnums []*EnumInfo } func NewFunctionHolder(env *environment.PBEnvironment) *FunctionHolder { - return &FunctionHolder { - env: env, - FunctionMap: map[string]*Function {}, - SimpleFunctionEnums: []*EnumInfo {}, + return &FunctionHolder{ + env: env, + FunctionMap: map[string]*Function{}, + SimpleFunctionEnums: []*EnumInfo{}, } } func (function_holder *FunctionHolder) RegisterFunction(function *Function) { for _, nm := range function.OwnedKeywords { if _, ok := function_holder.FunctionMap[nm]; !ok { - function_holder.FunctionMap[nm]=function + function_holder.FunctionMap[nm] = function } } } -func (function_holder *FunctionHolder) RegisterEnum(desc string,parser func(string)byte,inv byte) int { - function_holder.SimpleFunctionEnums=append(function_holder.SimpleFunctionEnums,&EnumInfo{WantedValuesDescription:desc,InvalidValue:inv,Parser:parser}) - return len(function_holder.SimpleFunctionEnums)-1+SimpleFunctionArgumentEnum +func (function_holder *FunctionHolder) RegisterEnum(desc string, parser func(string) byte, inv byte) int { + function_holder.SimpleFunctionEnums = append(function_holder.SimpleFunctionEnums, &EnumInfo{WantedValuesDescription: desc, InvalidValue: inv, Parser: parser}) + return len(function_holder.SimpleFunctionEnums) - 1 + SimpleFunctionArgumentEnum } // return: Found bool func (function_holder *FunctionHolder) Process(msg string) bool { - cmdsender:=function_holder.env.CommandSender - slc:=strings.Split(msg, " ") + slc := strings.Split(msg, " ") fun, ok := function_holder.FunctionMap[slc[0]] if !ok { return false } if fun.FunctionType == FunctionTypeRegular { - cont, _:=fun.FunctionContent.(func(*environment.PBEnvironment,string)) + cont, _ := fun.FunctionContent.(func(*environment.PBEnvironment, string)) cont(function_holder.env, msg) return true } if len(slc) < int(fun.SFMinSliceLen) { - cmdsender.Output(fmt.Sprintf("Parser: Simple function %s required at least %d arguments, but got %d.",fun.Name, fun.SFMinSliceLen, len(slc))) + function_holder.env.GameInterface.Output(fmt.Sprintf("Parser: Simple function %s required at least %d arguments, but got %d.", fun.Name, fun.SFMinSliceLen, len(slc))) return true } var arguments []interface{} - ic:=1 - cc:=&FunctionChainItem { - FunctionType: fun.FunctionType, + ic := 1 + cc := &FunctionChainItem{ + FunctionType: fun.FunctionType, ArgumentTypes: fun.SFArgumentTypes, - Content: fun.FunctionContent, + Content: fun.FunctionContent, } for { if cc.FunctionType == FunctionTypeContinue { - if len(slc)<=ic { - rf, _:=cc.Content.(map[string]*FunctionChainItem) + if len(slc) <= ic { + rf, _ := cc.Content.(map[string]*FunctionChainItem) itm, got := rf[""] if !got { - cmdsender.Output(I18n.T(I18n.SimpleParser_Too_few_args)) + function_holder.env.GameInterface.Output(I18n.T(I18n.SimpleParser_Too_few_args)) return true } - cc=itm + cc = itm continue } - rfc, _:=cc.Content.(map[string]*FunctionChainItem) + rfc, _ := cc.Content.(map[string]*FunctionChainItem) chainitem, got := rfc[slc[ic]] if !got { - cmdsender.Output(I18n.T(I18n.SimpleParser_Invalid_decider)) + function_holder.env.GameInterface.Output(I18n.T(I18n.SimpleParser_Invalid_decider)) return true } - cc=chainitem + cc = chainitem ic++ continue } if len(cc.ArgumentTypes) > len(slc)-ic { - cmdsender.Output(I18n.T(I18n.SimpleParser_Too_few_args)) + function_holder.env.GameInterface.Output(I18n.T(I18n.SimpleParser_Too_few_args)) return true } for _, tp := range cc.ArgumentTypes { - if tp==SimpleFunctionArgumentString { - arguments=append(arguments,slc[ic]) - }else if tp==SimpleFunctionArgumentDecider { - cmdsender.Output("Parser: Internal error - argument type [decider] is preserved.") + if tp == SimpleFunctionArgumentString { + arguments = append(arguments, slc[ic]) + } else if tp == SimpleFunctionArgumentDecider { + function_holder.env.GameInterface.Output("Parser: Internal error - argument type [decider] is preserved.") fmt.Println("Parser: Internal error - DO NOT REGISTER Decider ARGUMENT!") return true - }else if tp==SimpleFunctionArgumentInt { + } else if tp == SimpleFunctionArgumentInt { parsedInt, err := strconv.Atoi(slc[ic]) if err != nil { - cmdsender.Output(fmt.Sprintf("%s: %v", I18n.T(I18n.SimpleParser_Int_ParsingFailed), err)) + function_holder.env.GameInterface.Output(fmt.Sprintf("%s: %v", I18n.T(I18n.SimpleParser_Int_ParsingFailed), err)) return true } - arguments=append(arguments,parsedInt) - }else if tp==SimpleFunctionArgumentMessage { - messageContent:=strings.Join(slc[ic:]," ") - arguments=append(arguments,messageContent) + arguments = append(arguments, parsedInt) + } else if tp == SimpleFunctionArgumentMessage { + messageContent := strings.Join(slc[ic:], " ") + arguments = append(arguments, messageContent) // Arguments after the message argument isn't allowed. break - }else{ - eindex:=int(tp-SimpleFunctionArgumentEnum) - if eindex>=len(function_holder.SimpleFunctionEnums) { - cmdsender.Output("Parser: Internal error, unregistered enum") - fmt.Printf("Internal error, unregistered enum %d\n",int(tp)) + } else { + eindex := int(tp - SimpleFunctionArgumentEnum) + if eindex >= len(function_holder.SimpleFunctionEnums) { + function_holder.env.GameInterface.Output("Parser: Internal error, unregistered enum") + fmt.Printf("Internal error, unregistered enum %d\n", int(tp)) return true } - ei:=function_holder.SimpleFunctionEnums[eindex] - itm:=ei.Parser(slc[ic]) + ei := function_holder.SimpleFunctionEnums[eindex] + itm := ei.Parser(slc[ic]) if itm == ei.InvalidValue { - cmdsender.Output(fmt.Sprintf(I18n.T(I18n.SimpleParser_InvEnum),ei.WantedValuesDescription)) + function_holder.env.GameInterface.Output(fmt.Sprintf(I18n.T(I18n.SimpleParser_InvEnum), ei.WantedValuesDescription)) return true } - arguments=append(arguments,itm) + arguments = append(arguments, itm) } ic++ } - cont, _:=cc.Content.(func(*environment.PBEnvironment,[]interface{})) - if cont==nil { - cont,_:=cc.Content.(func(interface{},[]interface{})) - if(cont==nil) { + cont, _ := cc.Content.(func(*environment.PBEnvironment, []interface{})) + if cont == nil { + cont, _ := cc.Content.(func(interface{}, []interface{})) + if cont == nil { fmt.Printf("Internal error: invalid type for function\n") return true } @@ -172,7 +171,3 @@ func (function_holder *FunctionHolder) Process(msg string) bool { return true } } - - - - diff --git a/fastbuilder/function/internal.go b/fastbuilder/function/presets.go similarity index 71% rename from fastbuilder/function/internal.go rename to fastbuilder/function/presets.go index c2f003efc..d75454f9f 100644 --- a/fastbuilder/function/internal.go +++ b/fastbuilder/function/presets.go @@ -5,18 +5,18 @@ import ( "os" "path/filepath" - "phoenixbuilder/GameControl/GlobalAPI" "phoenixbuilder/fastbuilder/builder" "phoenixbuilder/fastbuilder/configuration" "phoenixbuilder/fastbuilder/environment" I18n "phoenixbuilder/fastbuilder/i18n" fbtask "phoenixbuilder/fastbuilder/task" "phoenixbuilder/fastbuilder/types" + "phoenixbuilder/fastbuilder/utils" "phoenixbuilder/io/special_tasks" "phoenixbuilder/minecraft" ) -func InitInternalFunctions(fh *FunctionHolder) { +func InitPresetFunctions(fh *FunctionHolder) { delayEnumId := fh.RegisterEnum("continuous, discrete, none", types.ParseDelayMode, types.DelayModeInvalid) fh.RegisterFunction(&Function{ Name: "exit", @@ -24,7 +24,7 @@ func InitInternalFunctions(fh *FunctionHolder) { FunctionType: FunctionTypeSimple, SFMinSliceLen: 1, FunctionContent: func(env *environment.PBEnvironment, _ []interface{}) { - env.CommandSender.Output(I18n.T(I18n.QuitCorrectly)) + env.GameInterface.Output(I18n.T(I18n.QuitCorrectly)) fmt.Printf("%s\n", I18n.T(I18n.QuitCorrectly)) env.Connection.(*minecraft.Conn).Close() os.Exit(0) @@ -37,7 +37,6 @@ func InitInternalFunctions(fh *FunctionHolder) { SFMinSliceLen: 1, FunctionContent: func(env *environment.PBEnvironment, _ []interface{}) { conn := env.Connection.(*minecraft.Conn) - commandSender := env.CommandSender homedir, err := os.UserHomeDir() if err != nil { fmt.Println(I18n.T(I18n.Warning_UserHomeDir)) @@ -48,11 +47,11 @@ func InitInternalFunctions(fh *FunctionHolder) { token := filepath.Join(fbconfigdir, "fbtoken") err = os.Remove(token) if err != nil { - commandSender.Output(fmt.Sprintf(I18n.T(I18n.FBUC_Token_ErrOnRemove), err)) + env.GameInterface.Output(fmt.Sprintf(I18n.T(I18n.FBUC_Token_ErrOnRemove), err)) return } - commandSender.Output(I18n.T(I18n.Logout_Done)) - commandSender.Output(I18n.T(I18n.QuitCorrectly)) + env.GameInterface.Output(I18n.T(I18n.Logout_Done)) + env.GameInterface.Output(I18n.T(I18n.QuitCorrectly)) fmt.Printf("%s\n", I18n.T(I18n.QuitCorrectly)) conn.Close() os.Exit(0) @@ -64,7 +63,7 @@ func InitInternalFunctions(fh *FunctionHolder) { FunctionType: FunctionTypeSimple, SFMinSliceLen: 1, FunctionContent: func(env *environment.PBEnvironment, _ []interface{}) { - env.CommandSender.Output(I18n.T(I18n.SelectLanguageOnConsole)) + env.GameInterface.Output(I18n.T(I18n.SelectLanguageOnConsole)) I18n.SelectLanguage() I18n.UpdateLanguage() }, @@ -84,7 +83,7 @@ func InitInternalFunctions(fh *FunctionHolder) { Y: Y, Z: Z, } - env.CommandSender.Output(fmt.Sprintf("%s: %d, %d, %d.", I18n.T(I18n.PositionSet), X, Y, Z)) + env.GameInterface.Output(fmt.Sprintf("%s: %d, %d, %d.", I18n.T(I18n.PositionSet), X, Y, Z)) }, }) fh.RegisterFunction(&Function{ @@ -102,7 +101,7 @@ func InitInternalFunctions(fh *FunctionHolder) { Y: Y, Z: Z, } - env.CommandSender.Output(fmt.Sprintf("%s: %d, %d, %d.", I18n.T(I18n.PositionSet_End), X, Y, Z)) + env.GameInterface.Output(fmt.Sprintf("%s: %d, %d, %d.", I18n.T(I18n.PositionSet_End), X, Y, Z)) }, }) fh.RegisterFunction(&Function{ @@ -116,12 +115,12 @@ func InitInternalFunctions(fh *FunctionHolder) { ArgumentTypes: []byte{SimpleFunctionArgumentInt}, Content: func(env *environment.PBEnvironment, args []interface{}) { if configuration.GlobalFullConfig(env).Delay().DelayMode == types.DelayModeNone { - env.CommandSender.Output(I18n.T(I18n.DelaySetUnavailableUnderNoneMode)) + env.GameInterface.Output(I18n.T(I18n.DelaySetUnavailableUnderNoneMode)) return } ms, _ := args[0].(int) configuration.GlobalFullConfig(env).Delay().Delay = int64(ms) - env.CommandSender.Output(fmt.Sprintf("%s: %d", I18n.T(I18n.DelaySet), ms)) + env.GameInterface.Output(fmt.Sprintf("%s: %d", I18n.T(I18n.DelaySet), ms)) }, }, "mode": &FunctionChainItem{ @@ -130,7 +129,7 @@ func InitInternalFunctions(fh *FunctionHolder) { "get": &FunctionChainItem{ FunctionType: FunctionTypeSimple, Content: func(env *environment.PBEnvironment, _ []interface{}) { - env.CommandSender.Output(fmt.Sprintf("%s: %s.", I18n.T(I18n.CurrentDefaultDelayMode), types.StrDelayMode(configuration.GlobalFullConfig(env).Delay().DelayMode))) + env.GameInterface.Output(fmt.Sprintf("%s: %s.", I18n.T(I18n.CurrentDefaultDelayMode), types.StrDelayMode(configuration.GlobalFullConfig(env).Delay().DelayMode))) }, }, "set": &FunctionChainItem{ @@ -139,15 +138,15 @@ func InitInternalFunctions(fh *FunctionHolder) { Content: func(env *environment.PBEnvironment, args []interface{}) { delaymode, _ := args[0].(byte) configuration.GlobalFullConfig(env).Delay().DelayMode = delaymode - env.CommandSender.Output(fmt.Sprintf("%s: %s", I18n.T(I18n.DelayModeSet), types.StrDelayMode(delaymode))) + env.GameInterface.Output(fmt.Sprintf("%s: %s", I18n.T(I18n.DelayModeSet), types.StrDelayMode(delaymode))) if delaymode != types.DelayModeNone { dl := decideDelay(delaymode) configuration.GlobalFullConfig(env).Delay().Delay = dl - env.CommandSender.Output(fmt.Sprintf(I18n.T(I18n.DelayModeSet_DelayAuto), dl)) + env.GameInterface.Output(fmt.Sprintf(I18n.T(I18n.DelayModeSet_DelayAuto), dl)) } if delaymode == types.DelayModeDiscrete { configuration.GlobalFullConfig(env).Delay().DelayThreshold = decideDelayThreshold() - env.CommandSender.Output(fmt.Sprintf(I18n.T(I18n.DelayModeSet_ThresholdAuto), configuration.GlobalFullConfig(env).Delay().DelayThreshold)) + env.GameInterface.Output(fmt.Sprintf(I18n.T(I18n.DelayModeSet_ThresholdAuto), configuration.GlobalFullConfig(env).Delay().DelayThreshold)) } }, }, @@ -158,12 +157,12 @@ func InitInternalFunctions(fh *FunctionHolder) { ArgumentTypes: []byte{SimpleFunctionArgumentInt}, Content: func(env *environment.PBEnvironment, args []interface{}) { if configuration.GlobalFullConfig(env).Delay().DelayMode != types.DelayModeDiscrete { - env.CommandSender.Output(I18n.T(I18n.DelayThreshold_OnlyDiscrete)) + env.GameInterface.Output(I18n.T(I18n.DelayThreshold_OnlyDiscrete)) return } thr, _ := args[0].(int) configuration.GlobalFullConfig(env).Delay().DelayThreshold = thr - env.CommandSender.Output(fmt.Sprintf(I18n.T(I18n.DelayThreshold_Set), thr)) + env.GameInterface.Output(fmt.Sprintf(I18n.T(I18n.DelayThreshold_Set), thr)) }, }, }, @@ -178,22 +177,65 @@ func InitInternalFunctions(fh *FunctionHolder) { FunctionType: FunctionTypeSimple, ArgumentTypes: []byte{}, Content: func(env *environment.PBEnvironment, _ []interface{}) { - env.GlobalAPI.(*GlobalAPI.GlobalAPI).SendSettingsCommand("gamerule sendcommandfeedback true", false) - env.GlobalAPI.(*GlobalAPI.GlobalAPI).SendCommand(fmt.Sprintf("execute @a[name=\"%s\"] ~ ~ ~ testforblock ~ ~ ~ air", env.RespondUser), configuration.ZeroId) + env.GameInterface.SendSettingsCommand("gamerule sendcommandfeedback true", false) + p, _ := env.GameInterface.SendCommandWithResponse(fmt.Sprintf("execute @a[name=\"%s\"] ~ ~ ~ testforblock ~ ~ ~ air", env.RespondUser)) + pos, _ := utils.SliceAtoi(p.OutputMessages[0].Parameters) + if !(p.OutputMessages[0].Message == "commands.generic.unknown") { + configuration.IsOp = true + } + if len(pos) == 0 { + env.GameInterface.Output(I18n.T(I18n.InvalidPosition)) + return + } + configuration.GlobalFullConfig(env).Main().Position = types.Position{ + X: pos[0], + Y: pos[1], + Z: pos[2], + } + env.GameInterface.Output(fmt.Sprintf("%s: %v", I18n.T(I18n.PositionGot), pos)) + //env.GameInterface.Output(fmt.Sprintf("%s: %v", I18n.T(I18n.PositionGot), pos)) + //env.GameInterface.SendCommand(fmt.Sprintf("execute @a[name=\"%s\"] ~ ~ ~ testforblock ~ ~ ~ air", env.RespondUser), configuration.ZeroId) }, }, "begin": &FunctionChainItem{ FunctionType: FunctionTypeSimple, Content: func(env *environment.PBEnvironment, _ []interface{}) { - env.GlobalAPI.(*GlobalAPI.GlobalAPI).SendSettingsCommand("gamerule sendcommandfeedback true", false) - env.GlobalAPI.(*GlobalAPI.GlobalAPI).SendCommand(fmt.Sprintf("execute @a[name=\"%s\"] ~ ~ ~ testforblock ~ ~ ~ air", env.RespondUser), configuration.ZeroId) + env.GameInterface.SendSettingsCommand("gamerule sendcommandfeedback true", false) + p, _ := env.GameInterface.SendCommandWithResponse(fmt.Sprintf("execute @a[name=\"%s\"] ~ ~ ~ testforblock ~ ~ ~ air", env.RespondUser)) + pos, _ := utils.SliceAtoi(p.OutputMessages[0].Parameters) + if !(p.OutputMessages[0].Message == "commands.generic.unknown") { + configuration.IsOp = true + } + if len(pos) == 0 { + env.GameInterface.Output(I18n.T(I18n.InvalidPosition)) + return + } + configuration.GlobalFullConfig(env).Main().Position = types.Position{ + X: pos[0], + Y: pos[1], + Z: pos[2], + } + env.GameInterface.Output(fmt.Sprintf("%s: %v", I18n.T(I18n.PositionGot), pos)) + //env.GameInterface.SendCommand(fmt.Sprintf("execute @a[name=\"%s\"] ~ ~ ~ testforblock ~ ~ ~ air", env.RespondUser), configuration.ZeroId) }, }, "end": &FunctionChainItem{ FunctionType: FunctionTypeSimple, Content: func(env *environment.PBEnvironment, _ []interface{}) { - env.GlobalAPI.(*GlobalAPI.GlobalAPI).SendSettingsCommand("gamerule sendcommandfeedback true", false) - env.GlobalAPI.(*GlobalAPI.GlobalAPI).SendCommand(fmt.Sprintf("execute @a[name=\"%s\"] ~ ~ ~ testforblock ~ ~ ~ air", env.RespondUser), configuration.OneId) + env.GameInterface.SendSettingsCommand("gamerule sendcommandfeedback true", false) + p, _ := env.GameInterface.SendCommandWithResponse(fmt.Sprintf("execute @a[name=\"%s\"] ~ ~ ~ testforblock ~ ~ ~ air", env.RespondUser)) + pos, _ := utils.SliceAtoi(p.OutputMessages[0].Parameters) + if len(pos) == 0 { + env.GameInterface.Output(I18n.T(I18n.InvalidPosition)) + return + } + configuration.GlobalFullConfig(env).Main().End = types.Position{ + X: pos[0], + Y: pos[1], + Z: pos[2], + } + env.GameInterface.Output(fmt.Sprintf("%s: %v", I18n.T(I18n.PositionGot), pos)) + //env.GameInterface.SendCommand(fmt.Sprintf("execute @a[name=\"%s\"] ~ ~ ~ testforblock ~ ~ ~ air", env.RespondUser), configuration.ZeroId) }, }, }, @@ -208,7 +250,7 @@ func InitInternalFunctions(fh *FunctionHolder) { FunctionType: FunctionTypeSimple, Content: func(env *environment.PBEnvironment, _ []interface{}) { total := 0 - env.CommandSender.Output(I18n.T(I18n.CurrentTasks)) + env.GameInterface.Output(I18n.T(I18n.CurrentTasks)) taskholder := env.TaskHolder.(*fbtask.TaskHolder) taskholder.TaskMap.Range(func(_tid interface{}, _v interface{}) bool { tid, _ := _tid.(int64) @@ -221,11 +263,11 @@ func InitInternalFunctions(fh *FunctionHolder) { if v.Config.Delay().DelayMode != types.DelayModeNone { dv = v.Config.Delay().Delay } - env.CommandSender.Output(fmt.Sprintf(I18n.T(I18n.TaskStateLine), tid, v.CommandLine, fbtask.GetStateDesc(v.State), dv, types.StrDelayMode(v.Config.Delay().DelayMode), dt)) + env.GameInterface.Output(fmt.Sprintf(I18n.T(I18n.TaskStateLine), tid, v.CommandLine, fbtask.GetStateDesc(v.State), dv, types.StrDelayMode(v.Config.Delay().DelayMode), dt)) total++ return true }) - env.CommandSender.Output(fmt.Sprintf(I18n.T(I18n.TaskTotalCount), total)) + env.GameInterface.Output(fmt.Sprintf(I18n.T(I18n.TaskTotalCount), total)) }, }, "pause": &FunctionChainItem{ @@ -236,11 +278,11 @@ func InitInternalFunctions(fh *FunctionHolder) { taskholder := env.TaskHolder.(*fbtask.TaskHolder) task := taskholder.FindTask(int64(tid)) if task == nil { - env.CommandSender.Output(I18n.T(I18n.TaskNotFoundMessage)) + env.GameInterface.Output(I18n.T(I18n.TaskNotFoundMessage)) return } task.Pause() - env.CommandSender.Output(fmt.Sprintf(I18n.T(I18n.TaskPausedNotice), task.TaskId)) + env.GameInterface.Output(fmt.Sprintf(I18n.T(I18n.TaskPausedNotice), task.TaskId)) }, }, "resume": &FunctionChainItem{ @@ -251,11 +293,11 @@ func InitInternalFunctions(fh *FunctionHolder) { taskholder := env.TaskHolder.(*fbtask.TaskHolder) task := taskholder.FindTask(int64(tid)) if task == nil { - env.CommandSender.Output(I18n.T(I18n.TaskNotFoundMessage)) + env.GameInterface.Output(I18n.T(I18n.TaskNotFoundMessage)) return } task.Resume() - env.CommandSender.Output(fmt.Sprintf(I18n.T(I18n.TaskResumedNotice), task.TaskId)) + env.GameInterface.Output(fmt.Sprintf(I18n.T(I18n.TaskResumedNotice), task.TaskId)) }, }, "break": &FunctionChainItem{ @@ -266,11 +308,11 @@ func InitInternalFunctions(fh *FunctionHolder) { taskholder := env.TaskHolder.(*fbtask.TaskHolder) task := taskholder.FindTask(int64(tid)) if task == nil { - env.CommandSender.Output(I18n.T(I18n.TaskNotFoundMessage)) + env.GameInterface.Output(I18n.T(I18n.TaskNotFoundMessage)) return } task.Break() - env.CommandSender.Output(fmt.Sprintf(I18n.T(I18n.TaskStoppedNotice), task.TaskId)) + env.GameInterface.Output(fmt.Sprintf(I18n.T(I18n.TaskStoppedNotice), task.TaskId)) }, }, "setdelay": &FunctionChainItem{ @@ -282,14 +324,14 @@ func InitInternalFunctions(fh *FunctionHolder) { taskholder := env.TaskHolder.(*fbtask.TaskHolder) task := taskholder.FindTask(int64(tid)) if task == nil { - env.CommandSender.Output(I18n.T(I18n.TaskNotFoundMessage)) + env.GameInterface.Output(I18n.T(I18n.TaskNotFoundMessage)) return } if task.Config.Delay().DelayMode == types.DelayModeNone { - env.CommandSender.Output(I18n.T(I18n.Task_SetDelay_Unavailable)) + env.GameInterface.Output(I18n.T(I18n.Task_SetDelay_Unavailable)) return } - env.CommandSender.Output(fmt.Sprintf(I18n.T(I18n.Task_DelaySet), task.TaskId, del)) + env.GameInterface.Output(fmt.Sprintf(I18n.T(I18n.Task_DelaySet), task.TaskId, del)) task.Config.Delay().Delay = int64(del) }, }, @@ -302,19 +344,19 @@ func InitInternalFunctions(fh *FunctionHolder) { taskholder := env.TaskHolder.(*fbtask.TaskHolder) task := taskholder.FindTask(int64(tid)) if task == nil { - env.CommandSender.Output(I18n.T(I18n.TaskNotFoundMessage)) + env.GameInterface.Output(I18n.T(I18n.TaskNotFoundMessage)) return } task.Pause() task.Config.Delay().DelayMode = delaymode - env.CommandSender.Output(fmt.Sprintf("[%s %d] - %s: %s", I18n.T(I18n.TaskTTeIuKoto), tid, I18n.T(I18n.DelayModeSet), types.StrDelayMode(delaymode))) + env.GameInterface.Output(fmt.Sprintf("[%s %d] - %s: %s", I18n.T(I18n.TaskTTeIuKoto), tid, I18n.T(I18n.DelayModeSet), types.StrDelayMode(delaymode))) if delaymode != types.DelayModeNone { task.Config.Delay().Delay = decideDelay(delaymode) - env.CommandSender.Output(fmt.Sprintf("[%s %d] "+I18n.T(I18n.DelayModeSet_DelayAuto), I18n.T(I18n.TaskTTeIuKoto), task.TaskId, task.Config.Delay().Delay)) + env.GameInterface.Output(fmt.Sprintf("[%s %d] "+I18n.T(I18n.DelayModeSet_DelayAuto), I18n.T(I18n.TaskTTeIuKoto), task.TaskId, task.Config.Delay().Delay)) } if delaymode == types.DelayModeDiscrete { task.Config.Delay().DelayThreshold = decideDelayThreshold() - env.CommandSender.Output(fmt.Sprintf("[%s %d] "+I18n.T(I18n.DelayModeSet_ThresholdAuto), I18n.T(I18n.TaskTTeIuKoto), task.TaskId, task.Config.Delay().DelayThreshold)) + env.GameInterface.Output(fmt.Sprintf("[%s %d] "+I18n.T(I18n.DelayModeSet_ThresholdAuto), I18n.T(I18n.TaskTTeIuKoto), task.TaskId, task.Config.Delay().DelayThreshold)) } task.Resume() }, @@ -328,14 +370,14 @@ func InitInternalFunctions(fh *FunctionHolder) { taskholder := env.TaskHolder.(*fbtask.TaskHolder) task := taskholder.FindTask(int64(tid)) if task == nil { - env.CommandSender.Output(I18n.T(I18n.TaskNotFoundMessage)) + env.GameInterface.Output(I18n.T(I18n.TaskNotFoundMessage)) return } if task.Config.Delay().DelayMode != types.DelayModeDiscrete { - env.CommandSender.Output(I18n.T(I18n.DelayThreshold_OnlyDiscrete)) + env.GameInterface.Output(I18n.T(I18n.DelayThreshold_OnlyDiscrete)) return } - env.CommandSender.Output(fmt.Sprintf("[%s %d] - "+I18n.T(I18n.DelayThreshold_Set), I18n.T(I18n.TaskTTeIuKoto), tid, delayt)) + env.GameInterface.Output(fmt.Sprintf("[%s %d] - "+I18n.T(I18n.DelayThreshold_Set), I18n.T(I18n.TaskTTeIuKoto), tid, delayt)) task.Config.Delay().DelayThreshold = delayt }, }, @@ -351,7 +393,7 @@ func InitInternalFunctions(fh *FunctionHolder) { FunctionContent: func(env *environment.PBEnvironment, args []interface{}) { ev, _ := args[0].(byte) configuration.GlobalFullConfig(env).Global().TaskCreationType = ev - env.CommandSender.Output(fmt.Sprintf(I18n.T(I18n.TaskTypeSwitchedTo), types.MakeTaskType(ev))) + env.GameInterface.Output(fmt.Sprintf(I18n.T(I18n.TaskTypeSwitchedTo), types.MakeTaskType(ev))) }, }) taskDMEnumId := fh.RegisterEnum("true, false", types.ParseTaskDisplayMode, types.TaskDisplayInvalid) @@ -364,7 +406,7 @@ func InitInternalFunctions(fh *FunctionHolder) { FunctionContent: func(env *environment.PBEnvironment, args []interface{}) { ev, _ := args[0].(byte) configuration.GlobalFullConfig(env).Global().TaskDisplayMode = ev - env.CommandSender.Output(fmt.Sprintf(I18n.T(I18n.TaskDisplayModeSet), types.MakeTaskDisplayMode(ev))) + env.GameInterface.Output(fmt.Sprintf(I18n.T(I18n.TaskDisplayModeSet), types.MakeTaskDisplayMode(ev))) }, }) var builderMethods []string @@ -380,7 +422,7 @@ func InitInternalFunctions(fh *FunctionHolder) { if task == nil { return } - env.CommandSender.Output(fmt.Sprintf("%s, ID=%d.", I18n.T(I18n.TaskCreated), task.TaskId)) + env.GameInterface.Output(fmt.Sprintf("%s, ID=%d.", I18n.T(I18n.TaskCreated), task.TaskId)) }, }) fh.RegisterFunction(&Function{ @@ -392,7 +434,7 @@ func InitInternalFunctions(fh *FunctionHolder) { if task == nil { return } - env.CommandSender.Output(fmt.Sprintf("%s, ID=%d.", I18n.T(I18n.TaskCreated), task.TaskId)) + env.GameInterface.Output(fmt.Sprintf("%s, ID=%d.", I18n.T(I18n.TaskCreated), task.TaskId)) }, }) fh.RegisterFunction(&Function{ @@ -404,7 +446,7 @@ func InitInternalFunctions(fh *FunctionHolder) { if task == nil { return } - env.CommandSender.Output(fmt.Sprintf("%s, ID=%d.", I18n.T(I18n.TaskCreated), task.TaskId)) + env.GameInterface.Output(fmt.Sprintf("%s, ID=%d.", I18n.T(I18n.TaskCreated), task.TaskId)) }, }) fh.RegisterFunction(&Function{ @@ -415,13 +457,13 @@ func InitInternalFunctions(fh *FunctionHolder) { SFMinSliceLen: 1, FunctionContent: func(env *environment.PBEnvironment, args []interface{}) { str := args[0].(string) - env.CommandSender.Output(str) + env.GameInterface.Output(str) }, }) } func decideDelay(delaytype byte) int64 { - // Will add system check later,so don't merge into other functions. + // TODO: Being system-based if delaytype == types.DelayModeContinuous { return 1000 } else if delaytype == types.DelayModeDiscrete { @@ -432,6 +474,6 @@ func decideDelay(delaytype byte) int64 { } func decideDelayThreshold() int { - // Will add system check later,so don't merge into other functions. + // TODO: Being system-based return 20000 } diff --git a/fastbuilder/i18n/en_UK.go b/fastbuilder/i18n/en_UK.go index 9599359bb..22b42f234 100644 --- a/fastbuilder/i18n/en_UK.go +++ b/fastbuilder/i18n/en_UK.go @@ -134,6 +134,7 @@ var I18nDict_en_UK map[uint16]string = map[uint16]string{ Task_Summary_2: "[Task %d] Time used: %v second(s)", Task_Summary_3: "[Task %d] Average speed: %v blocks/second", UnsupportedACMEVersion: "Unsupported ACME structure version. Only acme file version 1.2 is supported.", - Warning_ACME_Deprecated: "WARNING - `acme' is deprecated and will be removed in future, please migrate to other format instead.\n", + Warning_ACME_Deprecated: "WARNING - `acme' is deprecated and has been removed, please migrate to BDX format instead.\nSee https://github.com/LNSSPsd/PhoenixBuilder/issues/313 for more informations.", + Warning_Schem_Deprecated: "WARNING - `schem' is deprecated and has been removed, please migrate to BDX format instead. \nSee https://github.com/LNSSPsd/PhoenixBuilder/issues/313 for more informations.", Warning_UserHomeDir: "WARNING - Failed to obtain the user's home directory. made homedir=\".\";\n", } diff --git a/fastbuilder/i18n/en_US.go b/fastbuilder/i18n/en_US.go index cbe07eb6c..999d3b601 100644 --- a/fastbuilder/i18n/en_US.go +++ b/fastbuilder/i18n/en_US.go @@ -136,6 +136,7 @@ var I18nDict_en_US map[uint16]string = map[uint16]string{ Task_Summary_2: "[Task %d] Time used: %v second(s)", Task_Summary_3: "[Task %d] Average speed: %v blocks/second", UnsupportedACMEVersion: "Unsupported ACME structure version. Only acme file version 1.2 is supported.", - Warning_ACME_Deprecated: "WARNING - `acme' is deprecated and will be removed in future, please migrate to other format instead.\n", + Warning_ACME_Deprecated: "WARNING - `acme' is deprecated and has been removed, please migrate to BDX format instead.\nSee https://github.com/LNSSPsd/PhoenixBuilder/issues/313 for more informations.", + Warning_Schem_Deprecated: "WARNING - `schem' is deprecated and has been removed, please migrate to BDX format instead. \nSee https://github.com/LNSSPsd/PhoenixBuilder/issues/313 for more informations.", Warning_UserHomeDir: "WARNING - Failed to obtain the user's home directory. made homedir=\".\";\n", } diff --git a/fastbuilder/i18n/i18n.go b/fastbuilder/i18n/i18n.go index be224c434..536747d90 100644 --- a/fastbuilder/i18n/i18n.go +++ b/fastbuilder/i18n/i18n.go @@ -168,6 +168,7 @@ const ( Task_Summary_3 UnsupportedACMEVersion Warning_ACME_Deprecated + Warning_Schem_Deprecated Warning_UserHomeDir ) diff --git a/fastbuilder/i18n/ja_JP.go b/fastbuilder/i18n/ja_JP.go index 9fb63465e..5e0a1ef04 100644 --- a/fastbuilder/i18n/ja_JP.go +++ b/fastbuilder/i18n/ja_JP.go @@ -136,5 +136,7 @@ var I18nDict_ja_JP map[uint16]string = map[uint16]string{ Task_Summary_2: "[タスク %d] %v 秒をかけた", Task_Summary_3: "[タスク %d] 平均速度: %v ブロック/秒", UnsupportedACMEVersion: "このバーションの ACME ストラクチャーファイルは支援されていません。バーション 1.2 だけが支援されています。", + Warning_ACME_Deprecated: "WARNING - `acme' は非推奨となり、削除されました。代わりにBDX形式に移行してください。\n詳細については、https://github.com/LNSSPsd/PhoenixBuilder/issues/313 を参照してください。", + Warning_Schem_Deprecated: "警告 - `schem' は非推奨となり、削除されました。代わりにBDX形式に移行してください。\n詳細については、https://github.com/LNSSPsd/PhoenixBuilder/issues/313 を参照してください。", Warning_UserHomeDir: "警告 - ユーザーのホームフォルダーの取得に失敗しました。homedir=\".\";をさせていだだきます。\n", } diff --git a/fastbuilder/i18n/ru_RU.go b/fastbuilder/i18n/ru_RU.go index fc73f9c96..d928c19c1 100644 --- a/fastbuilder/i18n/ru_RU.go +++ b/fastbuilder/i18n/ru_RU.go @@ -148,6 +148,7 @@ var I18nDict_ru_RU map[uint16]string = map[uint16]string{ Task_Summary_2: "[миссия %d] Время: %v секунд", Task_Summary_3: "[миссия %d] Средняя скорость: %v квадрат/сек", UnsupportedACMEVersion: "Эта версия структуры ACME не поддерживается (поддерживается только версия файла acme 1.2)", - Warning_ACME_Deprecated: "Предупреждение - Функция 'acme' устарела и будет удалена в будущем.Пожалуйста, перейдите в другой формат файла.\n", + Warning_ACME_Deprecated: "Предупреждение - `acme' является устаревшим и был удален, пожалуйста, перейдите на формат BDX вместо него. \nСм. https://github.com/LNSSPsd/PhoenixBuilder/issues/313 для получения дополнительной информации.", + Warning_Schem_Deprecated: "Предупреждение - `schem' является устаревшим и был удален, пожалуйста, перейдите на формат BDX вместо него. \nСм. https://github.com/LNSSPsd/PhoenixBuilder/issues/313 для получения дополнительной информации.", Warning_UserHomeDir: "Предупреждение - Домашний каталог текущего пользователя не может быть получен, он будет установленhomedir=\".\";\n", -} \ No newline at end of file +} diff --git a/fastbuilder/i18n/tg_JP.go b/fastbuilder/i18n/tg_JP.go index 0575ade07..1a89b7583 100644 --- a/fastbuilder/i18n/tg_JP.go +++ b/fastbuilder/i18n/tg_JP.go @@ -136,5 +136,7 @@ var I18nDict_tg_JP map[uint16]string = map[uint16]string{ Task_Summary_2: "[タスク %d] %v 秒をかけた", Task_Summary_3: "[タスク %d] 平均速度: %v ブロック/秒", UnsupportedACMEVersion: "このバーションの ACME ストラクチャーファイルは支援されていない。バーション 1.2 だけが支援されてる。", + Warning_ACME_Deprecated: "警告 - `acme' は非推奨となり、削除されましたので、代わりにBDX形式に移行していただくようお願いいたします。詳細については、https://github.com/LNSSPsd/PhoenixBuilder/issues/313 をご参照くださいませ。", + Warning_Schem_Deprecated: "警告 - `schem' は非推奨となり、削除されましたので、代わりにBDX形式に移行していただくようお願いいたします。詳細については、https://github.com/LNSSPsd/PhoenixBuilder/issues/313 をご参照くださいませ。", Warning_UserHomeDir: "警告 - ユーザーのホームフォルダーが見つかれん。homedir=\".\";にした。\n", } diff --git a/fastbuilder/i18n/zh_CN.go b/fastbuilder/i18n/zh_CN.go index 4a88c99cf..6dc84c74e 100644 --- a/fastbuilder/i18n/zh_CN.go +++ b/fastbuilder/i18n/zh_CN.go @@ -144,6 +144,7 @@ var I18nDict_zh_CN map[uint16]string = map[uint16]string{ Task_Summary_2: "[任务 %d] 用时: %v 秒", Task_Summary_3: "[任务 %d] 平均速度: %v 方块/秒", UnsupportedACMEVersion: "不支持该版本ACME结构(仅支持acme 1.2文件版本)", - Warning_ACME_Deprecated: "警告 - `acme' 功能已弃用,将在未来被移除。请迁移到其他文件格式。\n", + Warning_ACME_Deprecated: "警告 - `acme' 功能已弃用且已移除,请迁移到BDX格式。详见 https://github.com/LNSSPsd/PhoenixBuilder/issues/313", + Warning_Schem_Deprecated: "警告 - `schem' 功能已弃用且已移除,请迁移到BDX格式。详见 https://github.com/LNSSPsd/PhoenixBuilder/issues/313", Warning_UserHomeDir: "警告 - 无法获取当前用户主目录,将设定homedir=\".\";\n", } diff --git a/fastbuilder/i18n/zh_HK.go b/fastbuilder/i18n/zh_HK.go index ae56a386d..4b6978f5f 100644 --- a/fastbuilder/i18n/zh_HK.go +++ b/fastbuilder/i18n/zh_HK.go @@ -141,6 +141,7 @@ var I18nDict_zh_HK map[uint16]string = map[uint16]string{ Task_Summary_2: "[任務 %d] 用時: %v 秒", Task_Summary_3: "[任務 %d] 平均速度: %v 方塊/秒", UnsupportedACMEVersion: "不支援該版本ACME結構(仅支援acme 1.2文檔版本)", - Warning_ACME_Deprecated: "警告 - `acme' 功能已棄用,將於未來被移除。請轉移至其他檔案格式。\n", + Warning_ACME_Deprecated: "警告 - `acme' 功能已廢棄且已移除,請遷移到BDX格式。詳情請參閱 https://github.com/LNSSPsd/PhoenixBuilder/issues/313", + Warning_Schem_Deprecated: "警告 - `schem' 功能已廢棄且已移除,請遷移到BDX格式。詳情請參閱 https://github.com/LNSSPsd/PhoenixBuilder/issues/313", Warning_UserHomeDir: "警告 - 無法獲取當前user主目錄,將設定homedir=\".\";\n", } diff --git a/fastbuilder/i18n/zh_TW.go b/fastbuilder/i18n/zh_TW.go index ccb828511..2d3f29b33 100644 --- a/fastbuilder/i18n/zh_TW.go +++ b/fastbuilder/i18n/zh_TW.go @@ -141,6 +141,7 @@ var I18nDict_zh_TW map[uint16]string = map[uint16]string{ Task_Summary_2: "[任務 %d] 用時: %v 秒", Task_Summary_3: "[任務 %d] 平均速度: %v 方塊/秒", UnsupportedACMEVersion: "不支援該版本ACME結構(仅支援acme 1.2文檔版本)", - Warning_ACME_Deprecated: "警告 - `acme' 功能已棄用,將於未來被移除。請轉移至其他檔案格式。\n", + Warning_ACME_Deprecated: "警告 - `acme' 功能已棄用且已移除,請轉移到BDX格式。詳見 https://github.com/LNSSPsd/PhoenixBuilder/issues/313", + Warning_Schem_Deprecated: "警告 - `schem' 功能已棄用且已移除,請轉移到BDX格式。詳見 https://github.com/LNSSPsd/PhoenixBuilder/issues/313", Warning_UserHomeDir: "警告 - 無法獲取當前user主目錄,將設定homedir=\".\";\n", } diff --git a/fastbuilder/lib/encoding/big_endian/err.go b/fastbuilder/lib/encoding/big_endian/err.go new file mode 100644 index 000000000..cb30e2a56 --- /dev/null +++ b/fastbuilder/lib/encoding/big_endian/err.go @@ -0,0 +1,5 @@ +package big_endian + +import "errors" + +var ErrStringLengthExceeds = errors.New("string length exceeds maximum length prefix") diff --git a/fastbuilder/lib/encoding/big_endian/read.go b/fastbuilder/lib/encoding/big_endian/read.go new file mode 100644 index 000000000..192181ed0 --- /dev/null +++ b/fastbuilder/lib/encoding/big_endian/read.go @@ -0,0 +1,68 @@ +package big_endian + +import "math" + +type CanReadOutBytes interface { + ReadOut(len int) (b []byte, err error) +} + +// Int16 ... +func Int16(r CanReadOutBytes) (int16, error) { + b, err := r.ReadOut(2) + if err != nil { + return 0, err + } + return int16(uint16(b[0])<<8 | uint16(b[1])), nil +} + +// Int32 ... +func Int32(r CanReadOutBytes) (int32, error) { + b, err := r.ReadOut(4) + if err != nil { + return 0, err + } + return int32(uint32(b[0])<<24 | uint32(b[1])<<16 | uint32(b[2])<<8 | uint32(b[3])), nil +} + +// Int64 ... +func Int64(r CanReadOutBytes) (int64, error) { + b, err := r.ReadOut(8) + if err != nil { + return 0, err + } + return int64(uint64(b[0])<<56 | uint64(b[1])<<48 | uint64(b[2])<<40 | uint64(b[3])<<32 | + uint64(b[4])<<24 | uint64(b[5])<<16 | uint64(b[6])<<8 | uint64(b[7])), nil +} + +// Float32 ... +func Float32(r CanReadOutBytes) (float32, error) { + b, err := r.ReadOut(4) + if err != nil { + return 0, err + } + return math.Float32frombits(uint32(b[0])<<24 | uint32(b[1])<<16 | uint32(b[2])<<8 | uint32(b[3])), nil +} + +// Float64 ... +func Float64(r CanReadOutBytes) (float64, error) { + b, err := r.ReadOut(8) + if err != nil { + return 0, err + } + return math.Float64frombits(uint64(b[0])<<56 | uint64(b[1])<<48 | uint64(b[2])<<40 | uint64(b[3])<<32 | + uint64(b[4])<<24 | uint64(b[5])<<16 | uint64(b[6])<<8 | uint64(b[7])), nil +} + +// String ... +func String(r CanReadOutBytes) (string, error) { + b, err := r.ReadOut(2) + if err != nil { + return "", err + } + stringLength := int(uint16(b[0])<<8 | uint16(b[1])) + data, err := r.ReadOut(stringLength) + if err != nil { + return "", err + } + return string(data), nil +} diff --git a/fastbuilder/lib/encoding/big_endian/write.go b/fastbuilder/lib/encoding/big_endian/write.go new file mode 100644 index 000000000..6870ce7b3 --- /dev/null +++ b/fastbuilder/lib/encoding/big_endian/write.go @@ -0,0 +1,55 @@ +package big_endian + +import ( + "math" + "unsafe" +) + +type CanWriteBytes interface { + Write([]byte) error +} + +// WriteInt16 ... +func WriteInt16(w CanWriteBytes, x int16) error { + return w.Write([]byte{byte(x >> 8), byte(x)}) +} + +// WriteInt32 ... +func WriteInt32(w CanWriteBytes, x int32) error { + return w.Write([]byte{byte(x >> 24), byte(x >> 16), byte(x >> 8), byte(x)}) +} + +// WriteInt64 ... +func WriteInt64(w CanWriteBytes, x int64) error { + return w.Write([]byte{byte(x >> 56), byte(x >> 48), byte(x >> 40), byte(x >> 32), + byte(x >> 24), byte(x >> 16), byte(x >> 8), byte(x)}) +} + +// WriteFloat32 ... +func WriteFloat32(w CanWriteBytes, x float32) error { + bits := math.Float32bits(x) + return w.Write([]byte{byte(bits >> 24), byte(bits >> 16), byte(bits >> 8), byte(bits)}) +} + +// WriteFloat64 ... +func WriteFloat64(w CanWriteBytes, x float64) error { + bits := math.Float64bits(x) + return w.Write([]byte{byte(bits >> 56), byte(bits >> 48), byte(bits >> 40), byte(bits >> 32), + byte(bits >> 24), byte(bits >> 16), byte(bits >> 8), byte(bits)}) +} + +// WriteString ... +func WriteString(w CanWriteBytes, x string) error { + if len(x) > math.MaxInt16 { + return ErrStringLengthExceeds + } + length := int16(len(x)) + if err := w.Write([]byte{byte(length >> 8), byte(length)}); err != nil { + return err + } + // Use unsafe conversion from a string to a byte slice to prevent copying. + if err := w.Write(*(*[]byte)(unsafe.Pointer(&x))); err != nil { + return err + } + return nil +} diff --git a/fastbuilder/lib/encoding/binary_read_write/binary_read_write.go b/fastbuilder/lib/encoding/binary_read_write/binary_read_write.go new file mode 100644 index 000000000..bd1a892b3 --- /dev/null +++ b/fastbuilder/lib/encoding/binary_read_write/binary_read_write.go @@ -0,0 +1,12 @@ +package binary_read_write + +type BinaryWriter interface { + Write(b []byte) (err error) + WriteByte(byte) error +} + +type BinaryReader interface { + Read(b []byte) (err error) + ReadOut(len int) (b []byte, err error) + ReadByte() (b byte, err error) +} diff --git a/fastbuilder/lib/encoding/binary_read_write/err.go b/fastbuilder/lib/encoding/binary_read_write/err.go new file mode 100644 index 000000000..41f799a72 --- /dev/null +++ b/fastbuilder/lib/encoding/binary_read_write/err.go @@ -0,0 +1,6 @@ +package binary_read_write + +import "errors" + +var ErrFailToFullyWrite = errors.New("fail to fully write") +var ErrFailToFullyRead = errors.New("fail to fully read") diff --git a/fastbuilder/lib/encoding/binary_read_write/wrap_reader.go b/fastbuilder/lib/encoding/binary_read_write/wrap_reader.go new file mode 100644 index 000000000..6810522bd --- /dev/null +++ b/fastbuilder/lib/encoding/binary_read_write/wrap_reader.go @@ -0,0 +1,53 @@ +package binary_read_write + +import "io" + +type wrappedReader struct { + underlayReader io.Reader + readByte func() (b byte, err error) +} + +func (w *wrappedReader) Read(b []byte) (err error) { + var n int + n, err = io.ReadAtLeast(w.underlayReader, b, len(b)) + if err != nil { + return err + } + if n != len(b) { + return ErrFailToFullyRead + } + return nil +} + +func (w *wrappedReader) ReadOut(len int) (b []byte, err error) { + holder := make([]byte, len) + err = w.Read(holder) + if err != nil { + return nil, err + } + return holder, err +} + +// it's ok to do so, since compiler will optimize this +func (w *wrappedReader) ReadByte() (b byte, err error) { + return w.readByte() +} + +func WrapBinaryReader(underlayReader io.Reader) BinaryReader { + r := &wrappedReader{ + underlayReader: underlayReader, + readByte: nil, + } + if canReadByte, ok := underlayReader.(interface { + ReadByte() (b byte, err error) + }); ok { + r.readByte = canReadByte.ReadByte + } else { + r.readByte = func() (b byte, err error) { + data := make([]byte, 1) + err = r.Read(data) + return data[0], err + } + } + return r +} diff --git a/fastbuilder/lib/encoding/binary_read_write/wrap_writer.go b/fastbuilder/lib/encoding/binary_read_write/wrap_writer.go new file mode 100644 index 000000000..d20f7e1c2 --- /dev/null +++ b/fastbuilder/lib/encoding/binary_read_write/wrap_writer.go @@ -0,0 +1,42 @@ +package binary_read_write + +import "io" + +type wrappedWriter struct { + underlayWriter io.Writer + writeByte func(b byte) error +} + +func (w *wrappedWriter) Write(b []byte) (err error) { + var n int + n, err = w.underlayWriter.Write(b) + if err != nil { + return err + } + if n != len(b) { + return ErrFailToFullyWrite + } + return nil +} + +// it's ok to do so, since compiler will optimize this +func (w *wrappedWriter) WriteByte(b byte) error { + return w.writeByte(b) +} + +func WrapBinaryWriter(underlayWriter io.Writer) BinaryWriter { + w := &wrappedWriter{ + underlayWriter: underlayWriter, + writeByte: nil, + } + if canWriteByte, ok := underlayWriter.(interface { + WriteByte(b byte) error + }); ok { + w.writeByte = canWriteByte.WriteByte + } else { + w.writeByte = func(b byte) error { + return w.Write([]byte{b}) + } + } + return w +} diff --git a/fastbuilder/lib/encoding/little_endian/err.go b/fastbuilder/lib/encoding/little_endian/err.go new file mode 100644 index 000000000..b01520fb1 --- /dev/null +++ b/fastbuilder/lib/encoding/little_endian/err.go @@ -0,0 +1,5 @@ +package little_endian + +import "errors" + +var ErrStringLengthExceeds = errors.New("string length exceeds maximum length prefix") diff --git a/fastbuilder/lib/encoding/little_endian/read.go b/fastbuilder/lib/encoding/little_endian/read.go new file mode 100644 index 000000000..68d528321 --- /dev/null +++ b/fastbuilder/lib/encoding/little_endian/read.go @@ -0,0 +1,68 @@ +package little_endian + +import "math" + +type CanReadOutBytes interface { + ReadOut(len int) (b []byte, err error) +} + +// Int16 ... +func Int16(r CanReadOutBytes) (int16, error) { + b, err := r.ReadOut(2) + if err != nil { + return 0, err + } + return int16(uint16(b[0]) | uint16(b[1])<<8), nil +} + +// Int32 ... +func Int32(r CanReadOutBytes) (int32, error) { + b, err := r.ReadOut(4) + if err != nil { + return 0, err + } + return int32(uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24), nil +} + +// Int64 ... +func Int64(r CanReadOutBytes) (int64, error) { + b, err := r.ReadOut(8) + if err != nil { + return 0, err + } + return int64(uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | + uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56), nil +} + +// Float32 ... +func Float32(r CanReadOutBytes) (float32, error) { + b, err := r.ReadOut(4) + if err != nil { + return 0, err + } + return math.Float32frombits(uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24), nil +} + +// Float64 ... +func Float64(r CanReadOutBytes) (float64, error) { + b, err := r.ReadOut(8) + if err != nil { + return 0, err + } + return math.Float64frombits(uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | + uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56), nil +} + +// String ... +func String(r CanReadOutBytes) (string, error) { + b, err := r.ReadOut(2) + if err != nil { + return "", err + } + stringLength := int(uint16(b[0]) | uint16(b[1])<<8) + data, err := r.ReadOut(stringLength) + if err != nil { + return "", err + } + return string(data), nil +} diff --git a/fastbuilder/lib/encoding/little_endian/write.go b/fastbuilder/lib/encoding/little_endian/write.go new file mode 100644 index 000000000..c5f13fdb0 --- /dev/null +++ b/fastbuilder/lib/encoding/little_endian/write.go @@ -0,0 +1,55 @@ +package little_endian + +import ( + "math" + "unsafe" +) + +type CanWriteBytes interface { + Write([]byte) error +} + +// WriteInt16 ... +func WriteInt16(w CanWriteBytes, x int16) error { + return w.Write([]byte{byte(x), byte(x >> 8)}) +} + +// WriteInt32 ... +func WriteInt32(w CanWriteBytes, x int32) error { + return w.Write([]byte{byte(x), byte(x >> 8), byte(x >> 16), byte(x >> 24)}) +} + +// WriteInt64 ... +func WriteInt64(w CanWriteBytes, x int64) error { + return w.Write([]byte{byte(x), byte(x >> 8), byte(x >> 16), byte(x >> 24), + byte(x >> 32), byte(x >> 40), byte(x >> 48), byte(x >> 56)}) +} + +// WriteFloat32 ... +func WriteFloat32(w CanWriteBytes, x float32) error { + bits := math.Float32bits(x) + return w.Write([]byte{byte(bits), byte(bits >> 8), byte(bits >> 16), byte(bits >> 24)}) +} + +// WriteFloat64 ... +func WriteFloat64(w CanWriteBytes, x float64) error { + bits := math.Float64bits(x) + return w.Write([]byte{byte(bits), byte(bits >> 8), byte(bits >> 16), byte(bits >> 24), + byte(bits >> 32), byte(bits >> 40), byte(bits >> 48), byte(bits >> 56)}) +} + +// WriteString ... +func WriteString(w CanWriteBytes, x string) error { + if len(x) > math.MaxInt16 { + return ErrStringLengthExceeds + } + length := int16(len(x)) + if err := w.Write([]byte{byte(length), byte(length >> 8)}); err != nil { + return err + } + // Use unsafe conversion from a string to a byte slice to prevent copying. + if err := w.Write(*(*[]byte)(unsafe.Pointer(&x))); err != nil { + return err + } + return nil +} diff --git a/fastbuilder/lib/encoding/little_endian_with_varint/err.go b/fastbuilder/lib/encoding/little_endian_with_varint/err.go new file mode 100644 index 000000000..6f0d33948 --- /dev/null +++ b/fastbuilder/lib/encoding/little_endian_with_varint/err.go @@ -0,0 +1,5 @@ +package little_endian_with_varint + +import "errors" + +var ErrStringLengthExceeds = errors.New("string length exceeds maximum length prefix") diff --git a/fastbuilder/lib/encoding/little_endian_with_varint/read.go b/fastbuilder/lib/encoding/little_endian_with_varint/read.go new file mode 100644 index 000000000..3a9ca0619 --- /dev/null +++ b/fastbuilder/lib/encoding/little_endian_with_varint/read.go @@ -0,0 +1,107 @@ +package little_endian_with_varint + +import "math" + +type CanReadOutBytes interface { + ReadOut(len int) (b []byte, err error) +} + +type CanReadByte interface { + ReadByte() (b byte, err error) +} + +type CanReadBoth interface { + CanReadByte + CanReadOutBytes +} + +// Int16 ... +func Int16(r CanReadOutBytes) (int16, error) { + b, err := r.ReadOut(2) + if err != nil { + return 0, err + } + return int16(uint16(b[0]) | uint16(b[1])<<8), nil +} + +// Int32 ... +func Int32(r CanReadBoth) (int32, error) { + var ux uint32 + for i := uint(0); i < 35; i += 7 { + b, err := r.ReadByte() + if err != nil { + return 0, err + } + ux |= uint32(b&0x7f) << i + if b&0x80 == 0 { + break + } + } + x := int32(ux >> 1) + if ux&1 != 0 { + x = ^x + } + return x, nil +} + +// Int64 ... +func Int64(r CanReadBoth) (int64, error) { + var ux uint64 + for i := uint(0); i < 70; i += 7 { + b, err := r.ReadByte() + if err != nil { + return 0, err + } + ux |= uint64(b&0x7f) << i + if b&0x80 == 0 { + break + } + } + x := int64(ux >> 1) + if ux&1 != 0 { + x = ^x + } + return x, nil +} + +// Float32 ... +func Float32(r CanReadOutBytes) (float32, error) { + b, err := r.ReadOut(4) + if err != nil { + return 0, err + } + return math.Float32frombits(uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24), nil +} + +// Float64 ... +func Float64(r CanReadOutBytes) (float64, error) { + b, err := r.ReadOut(8) + if err != nil { + return 0, err + } + return math.Float64frombits(uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | + uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56), nil +} + +// String ... +func String(r CanReadBoth) (string, error) { + var length uint32 + for i := uint(0); i < 35; i += 7 { + b, err := r.ReadByte() + if err != nil { + return "", err + } + length |= uint32(b&0x7f) << i + if b&0x80 == 0 { + break + } + } + if length > math.MaxInt16 { + return "", ErrStringLengthExceeds + } + data, err := r.ReadOut(int(length)) + if err != nil { + return "", err + } + return string(data), nil +} diff --git a/fastbuilder/lib/encoding/little_endian_with_varint/write.go b/fastbuilder/lib/encoding/little_endian_with_varint/write.go new file mode 100644 index 000000000..66b8e3fa4 --- /dev/null +++ b/fastbuilder/lib/encoding/little_endian_with_varint/write.go @@ -0,0 +1,94 @@ +package little_endian_with_varint + +import ( + "math" + "unsafe" +) + +type CanWriteBytes interface { + Write([]byte) error +} +type CanWriteByte interface { + WriteByte(byte) error +} + +type CanWriteBoth interface { + CanWriteByte + CanWriteBytes +} + +// WriteInt16 ... +func WriteInt16(w CanWriteBytes, x int16) error { + return w.Write([]byte{byte(x), byte(x >> 8)}) +} + +// WriteInt32 ... +func WriteInt32(w CanWriteBoth, x int32) error { + ux := uint32(x) << 1 + if x < 0 { + ux = ^ux + } + for ux >= 0x80 { + if err := w.WriteByte(byte(ux) | 0x80); err != nil { + return err + } + ux >>= 7 + } + if err := w.WriteByte(byte(ux)); err != nil { + return err + } + return nil +} + +// WriteInt64 ... +func WriteInt64(w CanWriteBoth, x int64) error { + ux := uint64(x) << 1 + if x < 0 { + ux = ^ux + } + for ux >= 0x80 { + if err := w.WriteByte(byte(ux) | 0x80); err != nil { + return err + } + ux >>= 7 + } + if err := w.WriteByte(byte(ux)); err != nil { + return err + } + return nil +} + +// WriteFloat32 ... +func WriteFloat32(w CanWriteBytes, x float32) error { + bits := math.Float32bits(x) + return w.Write([]byte{byte(bits), byte(bits >> 8), byte(bits >> 16), byte(bits >> 24)}) +} + +// WriteFloat64 ... +func WriteFloat64(w CanWriteBytes, x float64) error { + bits := math.Float64bits(x) + return w.Write([]byte{byte(bits), byte(bits >> 8), byte(bits >> 16), byte(bits >> 24), + byte(bits >> 32), byte(bits >> 40), byte(bits >> 48), byte(bits >> 56)}) +} + +// WriteString ... +func WriteString(w CanWriteBoth, x string) error { + if len(x) > math.MaxInt16 { + return ErrStringLengthExceeds + } + ux := uint32(len(x)) + for ux >= 0x80 { + if err := w.WriteByte(byte(ux) | 0x80); err != nil { + return err + } + ux >>= 7 + } + if err := w.WriteByte(byte(ux)); err != nil { + return err + } + // Use unsafe conversion from a string to a byte slice to prevent copying. + if err := w.Write(*(*[]byte)(unsafe.Pointer(&x))); err != nil { + return err + } + return nil +} diff --git a/fastbuilder/lib/encoding/note b/fastbuilder/lib/encoding/note new file mode 100644 index 000000000..c3016a106 --- /dev/null +++ b/fastbuilder/lib/encoding/note @@ -0,0 +1 @@ +basically same as minecraft/nbt, but "n" is removed diff --git a/lib/minecraft/algorithms/hop_planner/define.go b/fastbuilder/lib/minecraft/algorithms/hop_planner/define.go similarity index 85% rename from lib/minecraft/algorithms/hop_planner/define.go rename to fastbuilder/lib/minecraft/algorithms/hop_planner/define.go index 6e241cd61..ee8dc5c7e 100644 --- a/lib/minecraft/algorithms/hop_planner/define.go +++ b/fastbuilder/lib/minecraft/algorithms/hop_planner/define.go @@ -1,7 +1,7 @@ package hop_planner import ( - "phoenixbuilder/lib/minecraft/mirror/define" + "phoenixbuilder/fastbuilder/lib/minecraft/mirror/define" ) type HopToChunksPos struct { diff --git a/lib/minecraft/algorithms/hop_planner/planner.go b/fastbuilder/lib/minecraft/algorithms/hop_planner/planner.go similarity index 98% rename from lib/minecraft/algorithms/hop_planner/planner.go rename to fastbuilder/lib/minecraft/algorithms/hop_planner/planner.go index 08d4c188b..5d2cb8f99 100644 --- a/lib/minecraft/algorithms/hop_planner/planner.go +++ b/fastbuilder/lib/minecraft/algorithms/hop_planner/planner.go @@ -2,7 +2,7 @@ package hop_planner import ( "math" - "phoenixbuilder/lib/minecraft/mirror/define" + "phoenixbuilder/fastbuilder/lib/minecraft/mirror/define" ) func PlanHopSwapPath(sx, sz, ex, ez, receptiveRangeByChunk int) (hopPath []*HopToChunksPos, allRequiredChunks ExportedChunksMap) { diff --git a/lib/minecraft/alter/nbt/decode.go b/fastbuilder/lib/minecraft/alter/nbt/decode.go similarity index 100% rename from lib/minecraft/alter/nbt/decode.go rename to fastbuilder/lib/minecraft/alter/nbt/decode.go diff --git a/lib/minecraft/alter/nbt/encode.go b/fastbuilder/lib/minecraft/alter/nbt/encode.go similarity index 100% rename from lib/minecraft/alter/nbt/encode.go rename to fastbuilder/lib/minecraft/alter/nbt/encode.go diff --git a/lib/minecraft/alter/nbt/interface.go b/fastbuilder/lib/minecraft/alter/nbt/interface.go similarity index 100% rename from lib/minecraft/alter/nbt/interface.go rename to fastbuilder/lib/minecraft/alter/nbt/interface.go diff --git a/lib/minecraft/alter/nbt/nbt.go b/fastbuilder/lib/minecraft/alter/nbt/nbt.go similarity index 100% rename from lib/minecraft/alter/nbt/nbt.go rename to fastbuilder/lib/minecraft/alter/nbt/nbt.go diff --git a/lib/minecraft/alter/nbt/rawmsg.go b/fastbuilder/lib/minecraft/alter/nbt/rawmsg.go similarity index 100% rename from lib/minecraft/alter/nbt/rawmsg.go rename to fastbuilder/lib/minecraft/alter/nbt/rawmsg.go diff --git a/lib/minecraft/alter/nbt/snbt.go b/fastbuilder/lib/minecraft/alter/nbt/snbt.go similarity index 100% rename from lib/minecraft/alter/nbt/snbt.go rename to fastbuilder/lib/minecraft/alter/nbt/snbt.go diff --git a/lib/minecraft/alter/nbt/snbt_decode.go b/fastbuilder/lib/minecraft/alter/nbt/snbt_decode.go similarity index 100% rename from lib/minecraft/alter/nbt/snbt_decode.go rename to fastbuilder/lib/minecraft/alter/nbt/snbt_decode.go diff --git a/lib/minecraft/alter/nbt/snbt_scanner.go b/fastbuilder/lib/minecraft/alter/nbt/snbt_scanner.go similarity index 100% rename from lib/minecraft/alter/nbt/snbt_scanner.go rename to fastbuilder/lib/minecraft/alter/nbt/snbt_scanner.go diff --git a/lib/minecraft/alter/nbt/typeinfo.go b/fastbuilder/lib/minecraft/alter/nbt/typeinfo.go similarity index 100% rename from lib/minecraft/alter/nbt/typeinfo.go rename to fastbuilder/lib/minecraft/alter/nbt/typeinfo.go diff --git a/lib/minecraft/mirror/NOTE b/fastbuilder/lib/minecraft/mirror/NOTE similarity index 100% rename from lib/minecraft/mirror/NOTE rename to fastbuilder/lib/minecraft/mirror/NOTE diff --git a/lib/minecraft/mirror/chunk/block_aliases.nbt b/fastbuilder/lib/minecraft/mirror/chunk/block_aliases.nbt similarity index 100% rename from lib/minecraft/mirror/chunk/block_aliases.nbt rename to fastbuilder/lib/minecraft/mirror/chunk/block_aliases.nbt diff --git a/lib/minecraft/mirror/chunk/blockmapping_nemc_2_5_15_mc_1_19.gob.brotli b/fastbuilder/lib/minecraft/mirror/chunk/blockmapping_nemc_2_5_15_mc_1_19.gob.brotli old mode 100755 new mode 100644 similarity index 100% rename from lib/minecraft/mirror/chunk/blockmapping_nemc_2_5_15_mc_1_19.gob.brotli rename to fastbuilder/lib/minecraft/mirror/chunk/blockmapping_nemc_2_5_15_mc_1_19.gob.brotli diff --git a/lib/minecraft/mirror/chunk/chunk.go b/fastbuilder/lib/minecraft/mirror/chunk/chunk.go similarity index 98% rename from lib/minecraft/mirror/chunk/chunk.go rename to fastbuilder/lib/minecraft/mirror/chunk/chunk.go index bee7df36a..19d547e61 100644 --- a/lib/minecraft/mirror/chunk/chunk.go +++ b/fastbuilder/lib/minecraft/mirror/chunk/chunk.go @@ -1,7 +1,7 @@ package chunk import ( - "phoenixbuilder/lib/minecraft/mirror/define" + "phoenixbuilder/fastbuilder/lib/minecraft/mirror/define" "sync" ) diff --git a/lib/minecraft/mirror/chunk/conversion.go b/fastbuilder/lib/minecraft/mirror/chunk/conversion.go similarity index 100% rename from lib/minecraft/mirror/chunk/conversion.go rename to fastbuilder/lib/minecraft/mirror/chunk/conversion.go diff --git a/lib/minecraft/mirror/chunk/decode.go b/fastbuilder/lib/minecraft/mirror/chunk/decode.go similarity index 99% rename from lib/minecraft/mirror/chunk/decode.go rename to fastbuilder/lib/minecraft/mirror/chunk/decode.go index 5d92c4f8a..12996578f 100644 --- a/lib/minecraft/mirror/chunk/decode.go +++ b/fastbuilder/lib/minecraft/mirror/chunk/decode.go @@ -3,7 +3,7 @@ package chunk import ( "bytes" "fmt" - "phoenixbuilder/lib/minecraft/mirror/define" + "phoenixbuilder/fastbuilder/lib/minecraft/mirror/define" "phoenixbuilder/minecraft/nbt" "github.com/pterm/pterm" diff --git a/lib/minecraft/mirror/chunk/encode.go b/fastbuilder/lib/minecraft/mirror/chunk/encode.go similarity index 100% rename from lib/minecraft/mirror/chunk/encode.go rename to fastbuilder/lib/minecraft/mirror/chunk/encode.go diff --git a/lib/minecraft/mirror/chunk/encoding.go b/fastbuilder/lib/minecraft/mirror/chunk/encoding.go similarity index 100% rename from lib/minecraft/mirror/chunk/encoding.go rename to fastbuilder/lib/minecraft/mirror/chunk/encoding.go diff --git a/lib/minecraft/mirror/chunk/mapping.go b/fastbuilder/lib/minecraft/mirror/chunk/mapping.go similarity index 90% rename from lib/minecraft/mirror/chunk/mapping.go rename to fastbuilder/lib/minecraft/mirror/chunk/mapping.go index 2a06c5407..c4e80e811 100644 --- a/lib/minecraft/mirror/chunk/mapping.go +++ b/fastbuilder/lib/minecraft/mirror/chunk/mapping.go @@ -5,9 +5,7 @@ import ( _ "embed" "encoding/gob" "fmt" - "regexp" "sort" - "strconv" "strings" "unsafe" @@ -537,6 +535,57 @@ func InitMapping(mappingInData []byte) { if err := gob.NewDecoder(uncompressor).Decode(&mappingIn); err != nil { panic(err) } + blockNameRegrades := map[string]string{} + for i, blk := range mappingIn.RIDToMCBlock { + if strings.HasPrefix(blk.Name, "minecraft:double_stone_block_slab") { + upperGradeName := blk.Name + blk.Name = strings.ReplaceAll(blk.Name, "minecraft:double_stone_block_slab", "minecraft:double_stone_slab") + lowerGradeName := blk.Name + mappingIn.RIDToMCBlock[i] = blk + blockNameRegrades[upperGradeName] = lowerGradeName + } + if strings.HasPrefix(blk.Name, "minecraft:stone_block_slab") { + upperGradeName := blk.Name + blk.Name = strings.ReplaceAll(blk.Name, "minecraft:stone_block_slab", "minecraft:stone_slab") + lowerGradeName := blk.Name + mappingIn.RIDToMCBlock[i] = blk + blockNameRegrades[upperGradeName] = lowerGradeName + } + if strings.HasSuffix(blk.Name, "_glazed_terracotta") { + upperGradeName := blk.Name + lowerGradeName := strings.ReplaceAll(upperGradeName, "_glazed_terracotta", "") + lowerGradeName = "minecraft:glazedTerracotta." + lowerGradeName[len("minecraft:"):] + blockNameRegrades[lowerGradeName] = upperGradeName + } + if strings.HasSuffix(blk.Name, "sea_lantern") { + upperGradeName := blk.Name + lowerGradeName := strings.ReplaceAll(upperGradeName, "sea_lantern", "seaLantern") + blockNameRegrades[lowerGradeName] = upperGradeName + } + if strings.HasSuffix(blk.Name, "trip_wire") { + upperGradeName := blk.Name + lowerGradeName := strings.ReplaceAll(upperGradeName, "trip_wire", "tripWire") + blockNameRegrades[lowerGradeName] = upperGradeName + } + if strings.HasSuffix(blk.Name, "concrete_powder") { + upperGradeName := blk.Name + lowerGradeName := strings.ReplaceAll(upperGradeName, "concrete_powder", "concretePowder") + blockNameRegrades[lowerGradeName] = upperGradeName + } + } + + blockNameRedirect := func(origBlockName string) (stdMCBlockName string) { + origBlockName = strings.TrimSpace(origBlockName) + if !strings.HasPrefix(origBlockName, "minecraft:") { + origBlockName = "minecraft:" + origBlockName + } + if regradeName, found := blockNameRegrades[origBlockName]; found { + return regradeName + } else { + return origBlockName + } + } + StatePropsToRuntimeIDMapping = make(map[string]map[string]uint32) RuntimeIDToSateStrMapping = make(map[uint32]string) @@ -671,9 +720,6 @@ func InitMapping(mappingInData []byte) { return blk, true } } - numberRegex := regexp.MustCompile(`\d+`) - legacyBlockNameRegex := regexp.MustCompile(`name=.+,`) - legacyBlockValRegex := regexp.MustCompile(`val=.+]`) JavaStrToRuntimeIDMapping = mappingIn.JavaToRid JavaStrPropsToRuntimeIDMapping = make(map[string]map[string]uint32) splitJavaNameAndProps := func(javaName string) (name, prop string) { @@ -699,9 +745,7 @@ func InitMapping(mappingInData []byte) { } BlockPropsToRuntimeID = func(blockName string, blockProps map[string]interface{}) (uint32, bool) { - if !strings.HasPrefix(blockName, "minecraft:") { - blockName = "minecraft:" + blockName - } + blockName = blockNameRedirect(blockName) if oprops, found := StatePropsToRuntimeIDMapping[blockName]; found { bscore := -1 brtid := AirRID @@ -728,10 +772,7 @@ func InitMapping(mappingInData []byte) { return AirRID, false } BlockStateStrToRuntimeID = func(blockName, blockState string) (uint32, bool) { - blockName = strings.TrimSpace(blockName) - if !strings.HasPrefix(blockName, "minecraft:") { - blockName = "minecraft:" + blockName - } + blockName = blockNameRedirect(blockName) sprops := trimStateProps(blockState) if oprops, found := StatePropsToRuntimeIDMapping[blockName]; found { bscore := -1 @@ -760,18 +801,6 @@ func InitMapping(mappingInData []byte) { return AirRID, false } JavaToRuntimeID = func(javaBlockStr string) (runtimeID uint32, found bool) { - if rtid, hasK := JavaStrToRuntimeIDMapping[javaBlockStr]; hasK { - return rtid, true - } else if strings.HasPrefix(javaBlockStr, "omega:as_runtime_id[") { - matchs := numberRegex.FindAllString(javaBlockStr, 1) - if len(matchs) > 0 { - if rtid, err := strconv.Atoi(string(matchs[0])); err == nil { - mappingIn.JavaToRid[javaBlockStr] = uint32(rtid) - return uint32(rtid), true - } - } - mappingIn.JavaToRid[javaBlockStr] = AirRID - } jname, jprop := splitJavaNameAndProps(javaBlockStr) if oprops, found := JavaStrPropsToRuntimeIDMapping[jname]; found { bscore := -1 @@ -795,26 +824,6 @@ func InitMapping(mappingInData []byte) { } return brtid, true } - if strings.HasPrefix(javaBlockStr, "omega:as_legacy_block[") { - name := "air" - matchs := legacyBlockNameRegex.FindAllString(javaBlockStr, 1) - if len(matchs) > 0 { - name = matchs[0] - name = name[5 : len(name)-1] - } - matchs = legacyBlockValRegex.FindAllString(javaBlockStr, 1) - if len(matchs) > 0 { - if val, err := strconv.Atoi(string(matchs[0][4 : len(matchs[0])-1])); err == nil { - rtid, found := LegacyBlockToRuntimeID(name, uint16(val)) - if found { - mappingIn.JavaToRid[javaBlockStr] = uint32(rtid) - return uint32(rtid), true - } - - } - } - mappingIn.JavaToRid[javaBlockStr] = AirRID - } return AirRID, false } RuntimeIDToJavaStrMapping = make(map[uint32]string) diff --git a/lib/minecraft/mirror/chunk/palette.go b/fastbuilder/lib/minecraft/mirror/chunk/palette.go similarity index 100% rename from lib/minecraft/mirror/chunk/palette.go rename to fastbuilder/lib/minecraft/mirror/chunk/palette.go diff --git a/lib/minecraft/mirror/chunk/paletted_storage.go b/fastbuilder/lib/minecraft/mirror/chunk/paletted_storage.go similarity index 100% rename from lib/minecraft/mirror/chunk/paletted_storage.go rename to fastbuilder/lib/minecraft/mirror/chunk/paletted_storage.go diff --git a/lib/minecraft/mirror/chunk/sub_chunk.go b/fastbuilder/lib/minecraft/mirror/chunk/sub_chunk.go similarity index 100% rename from lib/minecraft/mirror/chunk/sub_chunk.go rename to fastbuilder/lib/minecraft/mirror/chunk/sub_chunk.go diff --git a/lib/minecraft/mirror/define/pos.go b/fastbuilder/lib/minecraft/mirror/define/pos.go similarity index 100% rename from lib/minecraft/mirror/define/pos.go rename to fastbuilder/lib/minecraft/mirror/define/pos.go diff --git a/lib/minecraft/mirror/define/range.go b/fastbuilder/lib/minecraft/mirror/define/range.go similarity index 100% rename from lib/minecraft/mirror/define/range.go rename to fastbuilder/lib/minecraft/mirror/define/range.go diff --git a/lib/minecraft/mirror/interface.go b/fastbuilder/lib/minecraft/mirror/interface.go similarity index 95% rename from lib/minecraft/mirror/interface.go rename to fastbuilder/lib/minecraft/mirror/interface.go index aee4fd5a2..a85d83352 100644 --- a/lib/minecraft/mirror/interface.go +++ b/fastbuilder/lib/minecraft/mirror/interface.go @@ -1,8 +1,8 @@ package mirror import ( - "phoenixbuilder/lib/minecraft/mirror/chunk" - "phoenixbuilder/lib/minecraft/mirror/define" + "phoenixbuilder/fastbuilder/lib/minecraft/mirror/chunk" + "phoenixbuilder/fastbuilder/lib/minecraft/mirror/define" "time" ) diff --git a/lib/minecraft/mirror/io/assembler/assembler.go b/fastbuilder/lib/minecraft/mirror/io/assembler/assembler.go similarity index 97% rename from lib/minecraft/mirror/io/assembler/assembler.go rename to fastbuilder/lib/minecraft/mirror/io/assembler/assembler.go index 97f3fba6f..0541c4039 100644 --- a/lib/minecraft/mirror/io/assembler/assembler.go +++ b/fastbuilder/lib/minecraft/mirror/io/assembler/assembler.go @@ -2,9 +2,9 @@ package assembler import ( "fmt" - "phoenixbuilder/lib/minecraft/mirror" - "phoenixbuilder/lib/minecraft/mirror/chunk" - "phoenixbuilder/lib/minecraft/mirror/define" + "phoenixbuilder/fastbuilder/lib/minecraft/mirror" + "phoenixbuilder/fastbuilder/lib/minecraft/mirror/chunk" + "phoenixbuilder/fastbuilder/lib/minecraft/mirror/define" "phoenixbuilder/minecraft/protocol" "phoenixbuilder/minecraft/protocol/packet" "sync" diff --git a/lib/minecraft/mirror/io/global/feeder.go b/fastbuilder/lib/minecraft/mirror/io/global/feeder.go similarity index 94% rename from lib/minecraft/mirror/io/global/feeder.go rename to fastbuilder/lib/minecraft/mirror/io/global/feeder.go index bcbeddadb..7684d1425 100644 --- a/lib/minecraft/mirror/io/global/feeder.go +++ b/fastbuilder/lib/minecraft/mirror/io/global/feeder.go @@ -1,7 +1,7 @@ package global import ( - "phoenixbuilder/lib/minecraft/mirror" + "phoenixbuilder/fastbuilder/lib/minecraft/mirror" "sync" "github.com/google/uuid" diff --git a/lib/minecraft/mirror/io/global/vars.go b/fastbuilder/lib/minecraft/mirror/io/global/vars.go similarity index 59% rename from lib/minecraft/mirror/io/global/vars.go rename to fastbuilder/lib/minecraft/mirror/io/global/vars.go index de174f134..cb39f8472 100644 --- a/lib/minecraft/mirror/io/global/vars.go +++ b/fastbuilder/lib/minecraft/mirror/io/global/vars.go @@ -1,7 +1,7 @@ package global import ( - "phoenixbuilder/lib/minecraft/mirror" + "phoenixbuilder/fastbuilder/lib/minecraft/mirror" ) type ChunkWriteFn func(chunk *mirror.ChunkData) diff --git a/lib/minecraft/mirror/io/lru/lru.go b/fastbuilder/lib/minecraft/mirror/io/lru/lru.go similarity index 96% rename from lib/minecraft/mirror/io/lru/lru.go rename to fastbuilder/lib/minecraft/mirror/io/lru/lru.go index 63d578d16..a6d01b427 100644 --- a/lib/minecraft/mirror/io/lru/lru.go +++ b/fastbuilder/lib/minecraft/mirror/io/lru/lru.go @@ -1,8 +1,8 @@ package lru import ( - "phoenixbuilder/lib/minecraft/mirror" - "phoenixbuilder/lib/minecraft/mirror/define" + "phoenixbuilder/fastbuilder/lib/minecraft/mirror" + "phoenixbuilder/fastbuilder/lib/minecraft/mirror/define" "sort" "sync" "time" diff --git a/lib/minecraft/mirror/io/mcdb/consts.go b/fastbuilder/lib/minecraft/mirror/io/mcdb/consts.go similarity index 100% rename from lib/minecraft/mirror/io/mcdb/consts.go rename to fastbuilder/lib/minecraft/mirror/io/mcdb/consts.go diff --git a/lib/minecraft/mirror/io/mcdb/keys.go b/fastbuilder/lib/minecraft/mirror/io/mcdb/keys.go similarity index 100% rename from lib/minecraft/mirror/io/mcdb/keys.go rename to fastbuilder/lib/minecraft/mirror/io/mcdb/keys.go diff --git a/lib/minecraft/mirror/io/mcdb/level_dat.go b/fastbuilder/lib/minecraft/mirror/io/mcdb/level_dat.go similarity index 100% rename from lib/minecraft/mirror/io/mcdb/level_dat.go rename to fastbuilder/lib/minecraft/mirror/io/mcdb/level_dat.go diff --git a/lib/minecraft/mirror/io/mcdb/provider.go b/fastbuilder/lib/minecraft/mirror/io/mcdb/provider.go similarity index 98% rename from lib/minecraft/mirror/io/mcdb/provider.go rename to fastbuilder/lib/minecraft/mirror/io/mcdb/provider.go index 4a79073cd..a292e2c47 100644 --- a/lib/minecraft/mirror/io/mcdb/provider.go +++ b/fastbuilder/lib/minecraft/mirror/io/mcdb/provider.go @@ -8,13 +8,13 @@ import ( "io/ioutil" "os" "path/filepath" - "phoenixbuilder/lib/minecraft/mirror/define" + "phoenixbuilder/fastbuilder/lib/minecraft/mirror/define" "time" - "phoenixbuilder/lib/minecraft/mirror" + "phoenixbuilder/fastbuilder/lib/minecraft/mirror" "phoenixbuilder/minecraft/nbt" - "phoenixbuilder/lib/minecraft/mirror/chunk" + "phoenixbuilder/fastbuilder/lib/minecraft/mirror/chunk" "github.com/df-mc/goleveldb/leveldb" "github.com/df-mc/goleveldb/leveldb/opt" diff --git a/lib/minecraft/mirror/io/mcdb/version.go b/fastbuilder/lib/minecraft/mirror/io/mcdb/version.go similarity index 100% rename from lib/minecraft/mirror/io/mcdb/version.go rename to fastbuilder/lib/minecraft/mirror/io/mcdb/version.go diff --git a/lib/minecraft/mirror/io/memory/memory.go b/fastbuilder/lib/minecraft/mirror/io/memory/memory.go similarity index 91% rename from lib/minecraft/mirror/io/memory/memory.go rename to fastbuilder/lib/minecraft/mirror/io/memory/memory.go index 70eef977d..bc3d6224e 100644 --- a/lib/minecraft/mirror/io/memory/memory.go +++ b/fastbuilder/lib/minecraft/mirror/io/memory/memory.go @@ -1,8 +1,8 @@ package memory import ( - "phoenixbuilder/lib/minecraft/mirror" - "phoenixbuilder/lib/minecraft/mirror/define" + "phoenixbuilder/fastbuilder/lib/minecraft/mirror" + "phoenixbuilder/fastbuilder/lib/minecraft/mirror/define" "sync" ) diff --git a/lib/minecraft/mirror/io/world/world.go b/fastbuilder/lib/minecraft/mirror/io/world/world.go similarity index 96% rename from lib/minecraft/mirror/io/world/world.go rename to fastbuilder/lib/minecraft/mirror/io/world/world.go index fd85000c5..428e3de43 100644 --- a/lib/minecraft/mirror/io/world/world.go +++ b/fastbuilder/lib/minecraft/mirror/io/world/world.go @@ -1,9 +1,9 @@ package world import ( - "phoenixbuilder/lib/minecraft/mirror" - "phoenixbuilder/lib/minecraft/mirror/chunk" - "phoenixbuilder/lib/minecraft/mirror/define" + "phoenixbuilder/fastbuilder/lib/minecraft/mirror" + "phoenixbuilder/fastbuilder/lib/minecraft/mirror/chunk" + "phoenixbuilder/fastbuilder/lib/minecraft/mirror/define" ) type World struct { diff --git a/lib/minecraft/mirror/items/itemRuntimeID2NameMapping_nemc_2_2_15.gob.brotli b/fastbuilder/lib/minecraft/mirror/items/itemRuntimeID2NameMapping_nemc_2_2_15.gob.brotli old mode 100755 new mode 100644 similarity index 100% rename from lib/minecraft/mirror/items/itemRuntimeID2NameMapping_nemc_2_2_15.gob.brotli rename to fastbuilder/lib/minecraft/mirror/items/itemRuntimeID2NameMapping_nemc_2_2_15.gob.brotli diff --git a/lib/minecraft/mirror/items/mapping.go b/fastbuilder/lib/minecraft/mirror/items/mapping.go similarity index 100% rename from lib/minecraft/mirror/items/mapping.go rename to fastbuilder/lib/minecraft/mirror/items/mapping.go diff --git a/lib/minecraft/mirror/mapping_generator/block/block_1_18_java_to_bedrock.json b/fastbuilder/lib/minecraft/mirror/mapping_generator/block/block_1_18_java_to_bedrock.json similarity index 100% rename from lib/minecraft/mirror/mapping_generator/block/block_1_18_java_to_bedrock.json rename to fastbuilder/lib/minecraft/mirror/mapping_generator/block/block_1_18_java_to_bedrock.json diff --git a/lib/minecraft/mirror/mapping_generator/block/block_states_1_19.nbt b/fastbuilder/lib/minecraft/mirror/mapping_generator/block/block_states_1_19.nbt similarity index 100% rename from lib/minecraft/mirror/mapping_generator/block/block_states_1_19.nbt rename to fastbuilder/lib/minecraft/mirror/mapping_generator/block/block_states_1_19.nbt diff --git a/lib/minecraft/mirror/mapping_generator/block/main.go b/fastbuilder/lib/minecraft/mirror/mapping_generator/block/main.go similarity index 100% rename from lib/minecraft/mirror/mapping_generator/block/main.go rename to fastbuilder/lib/minecraft/mirror/mapping_generator/block/main.go diff --git a/lib/minecraft/mirror/mapping_generator/block/schematic.js b/fastbuilder/lib/minecraft/mirror/mapping_generator/block/schematic.js similarity index 100% rename from lib/minecraft/mirror/mapping_generator/block/schematic.js rename to fastbuilder/lib/minecraft/mirror/mapping_generator/block/schematic.js diff --git a/lib/minecraft/mirror/mapping_generator/item/main.go b/fastbuilder/lib/minecraft/mirror/mapping_generator/item/main.go similarity index 100% rename from lib/minecraft/mirror/mapping_generator/item/main.go rename to fastbuilder/lib/minecraft/mirror/mapping_generator/item/main.go diff --git a/fastbuilder/lib/minecraft/neomega/bundle/micro.go b/fastbuilder/lib/minecraft/neomega/bundle/micro.go new file mode 100644 index 000000000..551812c2a --- /dev/null +++ b/fastbuilder/lib/minecraft/neomega/bundle/micro.go @@ -0,0 +1,70 @@ +package bundle + +import ( + "phoenixbuilder/fastbuilder/lib/minecraft/neomega/decouple/block/placer" + "phoenixbuilder/fastbuilder/lib/minecraft/neomega/decouple/cmdsender" + "phoenixbuilder/fastbuilder/lib/minecraft/neomega/decouple/core" + "phoenixbuilder/fastbuilder/lib/minecraft/neomega/decouple/infosender" + "phoenixbuilder/fastbuilder/lib/minecraft/neomega/omega" +) + +func init() { + if false { + func(omega omega.MicroOmega) {}(&MicroOmega{}) + } +} + +type MicroOmega struct { + omega.ReactCore + omega.InteractCore + omega.InfoSender + omega.CmdSender + omega.MicroUQHolder + omega.BlockPlacer +} + +func (o *MicroOmega) GetMicroUQHolder() omega.MicroUQHolder { + return o.MicroUQHolder +} + +type MicroOmegaOption struct { + CmdSenderOptions *cmdsender.Options +} + +func MakeDefaultMicroOmegaOption() *MicroOmegaOption { + return &MicroOmegaOption{CmdSenderOptions: cmdsender.MakeDefaultCmdSenderOption()} +} + +func NewMicroOmega(interactCore omega.InteractCore, getMicroUQHolder func() omega.MicroUQHolder, options *MicroOmegaOption) *MicroOmega { + if options == nil { + options = MakeDefaultMicroOmegaOption() + } + reactable := core.NewReactCore() + //interactCore := core.NewInteractCore(conn) + //conn.ReadPacketAndBytes() + cmdSender := cmdsender.NewCmdSender(reactable, interactCore, options.CmdSenderOptions) + microUQHolder := getMicroUQHolder() + infoSender := infosender.NewInfoSender(interactCore, cmdSender, microUQHolder.GetBotBasicInfo()) + blockPlacer := placer.NewBlockPlacer(reactable, cmdSender, interactCore) + return &MicroOmega{ + reactable, + interactCore, + infoSender, + cmdSender, + microUQHolder, + blockPlacer, + } +} + +func (o *MicroOmega) GetGameControl() interface { + omega.InteractCore + omega.CmdSender + omega.InfoSender + omega.BlockPlacer +} { + return o +} + +func (o *MicroOmega) GetGameListener() omega.PacketDispatcher { + return o +} diff --git a/lib/minecraft/neomega/decouple/block/placer/placer.go b/fastbuilder/lib/minecraft/neomega/decouple/block/placer/placer.go similarity index 97% rename from lib/minecraft/neomega/decouple/block/placer/placer.go rename to fastbuilder/lib/minecraft/neomega/decouple/block/placer/placer.go index 1cde49ef7..df49e0564 100644 --- a/lib/minecraft/neomega/decouple/block/placer/placer.go +++ b/fastbuilder/lib/minecraft/neomega/decouple/block/placer/placer.go @@ -2,8 +2,8 @@ package placer import ( "fmt" - "phoenixbuilder/lib/minecraft/mirror/define" - "phoenixbuilder/lib/minecraft/neomega/omega" + "phoenixbuilder/fastbuilder/lib/minecraft/mirror/define" + "phoenixbuilder/fastbuilder/lib/minecraft/neomega/omega" "phoenixbuilder/minecraft/protocol/packet" "strings" "sync" diff --git a/lib/minecraft/neomega/decouple/cmdsender/cmdsender.go b/fastbuilder/lib/minecraft/neomega/decouple/cmdsender/cmdsender.go similarity index 93% rename from lib/minecraft/neomega/decouple/cmdsender/cmdsender.go rename to fastbuilder/lib/minecraft/neomega/decouple/cmdsender/cmdsender.go index f5a852ea7..72b818143 100644 --- a/lib/minecraft/neomega/decouple/cmdsender/cmdsender.go +++ b/fastbuilder/lib/minecraft/neomega/decouple/cmdsender/cmdsender.go @@ -1,7 +1,7 @@ package cmdsender import ( - "phoenixbuilder/lib/minecraft/neomega/omega" + "phoenixbuilder/fastbuilder/lib/minecraft/neomega/omega" "phoenixbuilder/minecraft/protocol" "phoenixbuilder/minecraft/protocol/packet" "sync" @@ -28,7 +28,14 @@ type Options struct { ExpectedCmdFeedBack bool } -func NewCmdSender(reactable omega.ReactCore, interactable omega.InteractCore, option Options) omega.CmdSender { +func MakeDefaultCmdSenderOption() *Options { + return &Options{ExpectedCmdFeedBack: false} +} + +func NewCmdSender(reactable omega.ReactCore, interactable omega.InteractCore, option *Options) omega.CmdSender { + if option == nil { + option = MakeDefaultCmdSenderOption() + } c := &CmdSender{ InteractCore: interactable, cbByUUID: sync.Map{}, diff --git a/fastbuilder/lib/minecraft/neomega/decouple/core/interact.go b/fastbuilder/lib/minecraft/neomega/decouple/core/interact.go new file mode 100644 index 000000000..b6d89d82a --- /dev/null +++ b/fastbuilder/lib/minecraft/neomega/decouple/core/interact.go @@ -0,0 +1,66 @@ +package core + +import ( + "bytes" + "phoenixbuilder/fastbuilder/lib/minecraft/neomega/omega" + "phoenixbuilder/minecraft" + "phoenixbuilder/minecraft/protocol" + "phoenixbuilder/minecraft/protocol/packet" +) + +type InteractCore struct { + *minecraft.Conn +} + +func (i *InteractCore) SendPacket(packet packet.Packet) { + i.WritePacket(packet) +} + +func (i *InteractCore) SendPacketBytes(packetID uint32, packet []byte) { + i.WritePacketByte(packetID, packet) +} + +func NewInteractCore(conn *minecraft.Conn) omega.InteractCore { + return &InteractCore{Conn: conn} +} + +type RemoteInteractCoreSlow struct { + sendPacket func(pk packet.Packet) +} + +func (i *RemoteInteractCoreSlow) SendPacket(pk packet.Packet) { + i.sendPacket(pk) +} + +func (i *RemoteInteractCoreSlow) SendPacketBytes(packetID uint32, packet []byte) { + panic("not implemented") +} + +func NewRemoteInteractCore(sendPacket func(pk packet.Packet)) *RemoteInteractCoreSlow { + return &RemoteInteractCoreSlow{sendPacket: sendPacket} +} + +type RemoteInteractCoreDirect struct { + sendPacketBytes func(packetID uint32, packet []byte) + shieldID int32 + //sendPacket func(pk packet.Packet) +} + +func (i *RemoteInteractCoreDirect) SendPacket(pk packet.Packet) { + writer := bytes.NewBuffer(nil) + w := protocol.NewWriter(writer, i.shieldID) + pk.Marshal(w) + i.sendPacketBytes(pk.ID(), writer.Bytes()) +} + +func (i *RemoteInteractCoreDirect) SendPacketBytes(packetID uint32, packet []byte) { + i.sendPacketBytes(packetID, packet) +} + +func (i *RemoteInteractCoreDirect) UpdateShieldID(id int32) { + i.shieldID = id +} + +func NewRemoteInteractCoreDirect(sendPacketBytes func(packetID uint32, packet []byte)) *RemoteInteractCoreDirect { + return &RemoteInteractCoreDirect{sendPacketBytes: sendPacketBytes} +} diff --git a/lib/minecraft/neomega/decouple/core/react.go b/fastbuilder/lib/minecraft/neomega/decouple/core/react.go similarity index 95% rename from lib/minecraft/neomega/decouple/core/react.go rename to fastbuilder/lib/minecraft/neomega/decouple/core/react.go index f202598b6..06f857e3e 100644 --- a/lib/minecraft/neomega/decouple/core/react.go +++ b/fastbuilder/lib/minecraft/neomega/decouple/core/react.go @@ -1,7 +1,7 @@ package core import ( - "phoenixbuilder/lib/minecraft/neomega/omega" + "phoenixbuilder/fastbuilder/lib/minecraft/neomega/omega" "phoenixbuilder/minecraft/protocol/packet" ) diff --git a/lib/minecraft/neomega/decouple/infosender/infosender.go b/fastbuilder/lib/minecraft/neomega/decouple/infosender/infosender.go similarity index 97% rename from lib/minecraft/neomega/decouple/infosender/infosender.go rename to fastbuilder/lib/minecraft/neomega/decouple/infosender/infosender.go index 0e608abd6..4041d1de0 100644 --- a/lib/minecraft/neomega/decouple/infosender/infosender.go +++ b/fastbuilder/lib/minecraft/neomega/decouple/infosender/infosender.go @@ -3,7 +3,7 @@ package infosender import ( "encoding/json" "fmt" - "phoenixbuilder/lib/minecraft/neomega/omega" + "phoenixbuilder/fastbuilder/lib/minecraft/neomega/omega" "phoenixbuilder/minecraft/protocol/packet" "strings" ) diff --git a/lib/minecraft/neomega/decouple/playerKit/playerKit.go b/fastbuilder/lib/minecraft/neomega/decouple/playerKit/playerKit.go similarity index 95% rename from lib/minecraft/neomega/decouple/playerKit/playerKit.go rename to fastbuilder/lib/minecraft/neomega/decouple/playerKit/playerKit.go index 7e009176f..17331f867 100644 --- a/lib/minecraft/neomega/decouple/playerKit/playerKit.go +++ b/fastbuilder/lib/minecraft/neomega/decouple/playerKit/playerKit.go @@ -2,8 +2,8 @@ package playerKit import ( "encoding/json" - "phoenixbuilder/lib/minecraft/mirror/define" - "phoenixbuilder/lib/minecraft/neomega/omega" + "phoenixbuilder/fastbuilder/lib/minecraft/mirror/define" + "phoenixbuilder/fastbuilder/lib/minecraft/neomega/omega" "phoenixbuilder/minecraft/protocol/packet" "phoenixbuilder/omega/utils" "time" diff --git a/fastbuilder/lib/minecraft/neomega/omega/basic.go b/fastbuilder/lib/minecraft/neomega/omega/basic.go new file mode 100644 index 000000000..b3ff45865 --- /dev/null +++ b/fastbuilder/lib/minecraft/neomega/omega/basic.go @@ -0,0 +1,21 @@ +package omega + +// import "phoenixbuilder/fastbuilder/lib/minecraft/mirror/define" + +// type GameChat interface { +// } + +// type PlayerMsgReceivable interface { +// SetOnParamMsg(func(chat GameChat) (catch bool)) error +// GetOnParamMsg() func(chat GameChat) (catch bool) +// } + +// type PlayerKit interface { +// Say(msg string) +// RawSay(msg string) +// ActionBar(msg string) +// Title(msg string) +// SubTitle(msg string) +// GetRelatedUQ() PlayerUQReader +// GetPos(selector string) chan *define.CubePos +// } diff --git a/lib/minecraft/neomega/omega/omega.go b/fastbuilder/lib/minecraft/neomega/omega/omega.go similarity index 87% rename from lib/minecraft/neomega/omega/omega.go rename to fastbuilder/lib/minecraft/neomega/omega/omega.go index a261fd236..c1c1a6fb8 100644 --- a/lib/minecraft/neomega/omega/omega.go +++ b/fastbuilder/lib/minecraft/neomega/omega/omega.go @@ -1,7 +1,7 @@ package omega import ( - "phoenixbuilder/lib/minecraft/mirror/define" + "phoenixbuilder/fastbuilder/lib/minecraft/mirror/define" "phoenixbuilder/minecraft/protocol/packet" "time" @@ -11,6 +11,7 @@ import ( // 可以向游戏发送数据包 type GameIntractable interface { SendPacket(packet.Packet) + SendPacketBytes(pktID uint32, data []byte) } type GameReactable interface { @@ -67,14 +68,14 @@ type MicroOmega interface { } GetGameListener() PacketDispatcher GameReactable - GetBotInfo() BotBasicInfoHolder + GetMicroUQHolder() MicroUQHolder } //type PlayerMsgListener interface { // SetOnParamMsg(playerName string, cb func(chat GameChat) (catch bool)) error //} -type PlayerInteract interface { - GetPlayerKit(name string) PlayerKit - GetPlayerKitByUUID(ud uuid.UUID) PlayerKit -} +// type PlayerInteract interface { +// GetPlayerKit(name string) PlayerKit +// GetPlayerKitByUUID(ud uuid.UUID) PlayerKit +// } diff --git a/fastbuilder/lib/minecraft/neomega/omega/uqholder.go b/fastbuilder/lib/minecraft/neomega/omega/uqholder.go new file mode 100644 index 000000000..994e6198d --- /dev/null +++ b/fastbuilder/lib/minecraft/neomega/omega/uqholder.go @@ -0,0 +1,37 @@ +package omega + +import "phoenixbuilder/minecraft/protocol/packet" + +type UQInfoHolderEntry interface { + Marshal() ([]byte, error) + Unmarshal([]byte) error + UpdateFromPacket(packet packet.Packet) +} + +type BotBasicInfoHolder interface { + GetBotName() string + GetBotRuntimeID() uint64 + GetBotUniqueID() int64 + GetBotIdentity() string + UQInfoHolderEntry +} + +type MicroUQHolder interface { + GetBotBasicInfo() BotBasicInfoHolder + UQInfoHolderEntry +} + +// type PlayerUQsHolder interface { +// GetPlayerUQByName(name string) (uq PlayerUQReader, found bool) +// GetPlayerUQByUUID(ud uuid.UUID) (uq PlayerUQReader, found bool) +// GetBot() (botUQ PlayerUQReader) +// } + +// type PlayerUQReader interface { +// IsBot() bool +// GetPlayerName() string +// } + +// type PlayerUQ interface { +// PlayerUQReader +// } diff --git a/fastbuilder/lib/minecraft/neomega/uqholder/bot_basic_info.go b/fastbuilder/lib/minecraft/neomega/uqholder/bot_basic_info.go new file mode 100644 index 000000000..5939c1b29 --- /dev/null +++ b/fastbuilder/lib/minecraft/neomega/uqholder/bot_basic_info.go @@ -0,0 +1,99 @@ +package uqholder + +import ( + "bytes" + "phoenixbuilder/fastbuilder/lib/encoding/binary_read_write" + LE "phoenixbuilder/fastbuilder/lib/encoding/little_endian" + "phoenixbuilder/fastbuilder/lib/minecraft/neomega/omega" + "phoenixbuilder/minecraft" + "phoenixbuilder/minecraft/protocol/packet" +) + +func init() { + if false { + func(omega.BotBasicInfoHolder) {}(&BotBasicInfoHolder{}) + } +} + +type BotBasicInfoHolder struct { + BotName string + BotRuntimeID uint64 + BotUniqueID int64 + BotIdentity string +} + +func (b *BotBasicInfoHolder) Marshal() (data []byte, err error) { + basicWriter := bytes.NewBuffer(nil) + writer := binary_read_write.WrapBinaryWriter(basicWriter) + err = LE.WriteString(writer, b.BotName) + if err != nil { + return nil, err + } + err = LE.WriteInt64(writer, int64(b.BotRuntimeID)) + if err != nil { + return nil, err + } + err = LE.WriteInt64(writer, int64(b.BotUniqueID)) + if err != nil { + return nil, err + } + err = LE.WriteString(writer, b.BotIdentity) + if err != nil { + return nil, err + } + return basicWriter.Bytes(), err +} + +func (b *BotBasicInfoHolder) Unmarshal(data []byte) (err error) { + basicReader := bytes.NewReader(data) + reader := binary_read_write.WrapBinaryReader(basicReader) + b.BotName, err = LE.String(reader) + if err != nil { + return err + } + var i64 int64 + i64, err = LE.Int64(reader) + if err != nil { + return err + } + b.BotRuntimeID = uint64(i64) + i64, err = LE.Int64(reader) + if err != nil { + return err + } + b.BotUniqueID = i64 + b.BotIdentity, err = LE.String(reader) + if err != nil { + return err + } + return nil +} + +func (b *BotBasicInfoHolder) UpdateFromPacket(packet packet.Packet) { +} + +func (b *BotBasicInfoHolder) GetBotName() string { + return b.BotName +} + +func (b *BotBasicInfoHolder) GetBotRuntimeID() uint64 { + return b.BotRuntimeID +} + +func (b *BotBasicInfoHolder) GetBotUniqueID() int64 { + return b.BotUniqueID +} + +func (b *BotBasicInfoHolder) GetBotIdentity() string { + return b.BotIdentity +} + +func NewBotInfoHolder(conn *minecraft.Conn) omega.BotBasicInfoHolder { + h := &BotBasicInfoHolder{} + gd := conn.GameData() + h.BotRuntimeID = gd.EntityRuntimeID + h.BotUniqueID = gd.EntityUniqueID + h.BotName = conn.IdentityData().DisplayName + h.BotIdentity = conn.IdentityData().Identity + return h +} diff --git a/fastbuilder/lib/minecraft/neomega/uqholder/micro.go b/fastbuilder/lib/minecraft/neomega/uqholder/micro.go new file mode 100644 index 000000000..3a40251d1 --- /dev/null +++ b/fastbuilder/lib/minecraft/neomega/uqholder/micro.go @@ -0,0 +1,97 @@ +package uqholder + +import ( + "bytes" + "errors" + "phoenixbuilder/fastbuilder/lib/encoding/binary_read_write" + LE "phoenixbuilder/fastbuilder/lib/encoding/little_endian" + "phoenixbuilder/fastbuilder/lib/minecraft/neomega/omega" + "phoenixbuilder/minecraft" + "phoenixbuilder/minecraft/protocol/packet" +) + +func init() { + if false { + func(holder omega.MicroUQHolder) {}(&MicroUQHolder{}) + } +} + +type MicroUQHolder struct { + omega.BotBasicInfoHolder +} + +func NewMicroUQHolder(conn *minecraft.Conn) *MicroUQHolder { + uq := &MicroUQHolder{ + NewBotInfoHolder(conn), + } + return uq +} + +func NewMicroUQHolderFromData(data []byte) (uq *MicroUQHolder, err error) { + uq = &MicroUQHolder{} + err = uq.Unmarshal(data) + if err != nil { + return nil, err + } + return uq, nil +} + +func (u *MicroUQHolder) GetBotBasicInfo() omega.BotBasicInfoHolder { + return u.BotBasicInfoHolder +} + +func (u *MicroUQHolder) Marshal() (data []byte, err error) { + basicWriter := bytes.NewBuffer(nil) + writer := binary_read_write.WrapBinaryWriter(basicWriter) + err = LE.WriteString(writer, "BotBasicInfoHolder") + if err != nil { + return nil, err + } + var subData []byte + subData, err = u.BotBasicInfoHolder.Marshal() + if err != nil { + return nil, err + } + err = LE.WriteInt64(writer, int64(len(subData))) + if err != nil { + return nil, err + } + err = writer.Write(subData) + if err != nil { + return nil, err + } + return basicWriter.Bytes(), err +} + +var ErrInvalidUQHolderEntry = errors.New("invalid uqholder entry") + +func (u *MicroUQHolder) Unmarshal(data []byte) error { + if u.BotBasicInfoHolder == nil { + u.BotBasicInfoHolder = &BotBasicInfoHolder{} + } + basicReader := bytes.NewBuffer(data) + reader := binary_read_write.WrapBinaryReader(basicReader) + var name string + name, err := LE.String(reader) + if err != nil { + return err + } + if name != "BotBasicInfoHolder" { + return ErrInvalidUQHolderEntry + } + var subData []byte + var subDataLen int64 + subDataLen, err = LE.Int64(reader) + if err != nil { + return err + } + subData, err = reader.ReadOut(int(subDataLen)) + if err != nil { + return err + } + return u.BotBasicInfoHolder.Unmarshal(subData) +} + +func (u *MicroUQHolder) UpdateFromPacket(packet packet.Packet) { + u.BotBasicInfoHolder.UpdateFromPacket(packet) +} diff --git a/fastbuilder/lib/rental_server_impact/access_helper/errors.go b/fastbuilder/lib/rental_server_impact/access_helper/errors.go new file mode 100644 index 000000000..1c6d08551 --- /dev/null +++ b/fastbuilder/lib/rental_server_impact/access_helper/errors.go @@ -0,0 +1,20 @@ +package access_helper + +import ( + "errors" + "phoenixbuilder/fastbuilder/i18n" +) + +var ErrFBUserCenterLoginFail = errors.New(I18n.T(I18n.Auth_InvalidUser)) +var ErrRentalServerDisconnected = errors.New("connection unexpectedly closed") +var ErrFBServerConnectionTimeOut = errors.New("connection timed out") +var ErrGetTokenTimeOut = errors.New("login timed out") +var ErrFailToConnectFBServer = errors.New("connection to authentication server timed out") +var ErrRentalServerConnectionTimeOut = errors.New("connection to server timed out") +var ErrFailToConnectRentalServer = errors.New("failed to connect to server.") +var ErrFBChallengeSolvingTimeout = errors.New("challenge solving timed out") +var ErrFBTransferDataTimeout = errors.New("netease authentication data calculation timed out") +var ErrFBTransferDataFail = errors.New("netease authentication data calculation failed") +var ErrFBTransferCheckNumTimeOut = errors.New("netease authentication data calculation timed out") +var ErrFBTransferCheckNumFail = errors.New("netease authentication data calculation failed") +var ErrBotOpPrivilegeRemoved = errors.New("privilege lost") diff --git a/fastbuilder/lib/rental_server_impact/access_helper/impact.go b/fastbuilder/lib/rental_server_impact/access_helper/impact.go new file mode 100644 index 000000000..8ed80dbd9 --- /dev/null +++ b/fastbuilder/lib/rental_server_impact/access_helper/impact.go @@ -0,0 +1,136 @@ +package access_helper + +import ( + "context" + "fmt" + "phoenixbuilder/fastbuilder/core" + fbauth "phoenixbuilder/fastbuilder/cv4/auth" + "phoenixbuilder/fastbuilder/lib/minecraft/neomega/bundle" + neomega_core "phoenixbuilder/fastbuilder/lib/minecraft/neomega/decouple/core" + "phoenixbuilder/fastbuilder/lib/minecraft/neomega/omega" + "phoenixbuilder/fastbuilder/lib/minecraft/neomega/uqholder" + "phoenixbuilder/fastbuilder/lib/rental_server_impact/challenges" + "phoenixbuilder/fastbuilder/lib/rental_server_impact/info_collect_utils" + "phoenixbuilder/minecraft" + "phoenixbuilder/minecraft/protocol/packet" +) + +func ImpactServer(ctx context.Context, options *Options) (conn *minecraft.Conn, omegaCore *bundle.MicroOmega, deadReason chan error, err error) { + if ctx == nil { + ctx = context.Background() + } + if options.MaximumWaitTime > 0 { + ctx, _ = context.WithTimeout(ctx, options.MaximumWaitTime) + } + clientOptions := fbauth.MakeDefaultClientOptions() + clientOptions.AuthServer = options.AuthServer + fmt.Println("connecting to fb server...") + fbClient := fbauth.CreateClient(clientOptions) + fmt.Println("done connecting to fb server") + if options.FBUserToken == "" { + var err_val string + fmt.Println("obtaining fb token from fb server...") + options.FBUserToken, err_val = fbClient.GetToken(options.FBUsername, options.FBUserPassword) + if err != nil { + return nil, nil, nil, fmt.Errorf("%v: %s", ErrFBUserCenterLoginFail, err_val) + } + fmt.Println("done obtaining fb token from fb server") + } + if options.WriteBackToken { + info_collect_utils.WriteFBToken(options.FBUserToken, info_collect_utils.LoadTokenPath()) + } + authenticator := fbauth.NewAccessWrapper(fbClient, options.ServerCode, options.ServerPassword, options.FBUserToken) + { + connectMCServer := func() (conn *minecraft.Conn, err error) { + connectCtx := ctx + if options.ServerConnectionTimeout != 0 { + connectCtx, _ = context.WithTimeout(ctx, options.ServerConnectionTimeout) + } + conn, err = core.InitializeMinecraftConnection(connectCtx, authenticator) + if err != nil { + if connectCtx.Err() != nil { + return nil, ErrRentalServerConnectionTimeOut + } + return nil, fmt.Errorf("%v :%v", ErrFailToConnectRentalServer, err) + } + return conn, nil + } + fmt.Println("connecting to mc server...") + retryTimes := 0 + for { + conn, err = connectMCServer() + if err == nil { + break + } else { + fmt.Println(err) + } + if options.ServerConnectRetryTimes <= 0 { + break + } + retryTimes++ + fmt.Printf("fail connecting to mc server, retrying: %v\n", retryTimes) + options.ServerConnectRetryTimes-- + } + if err != nil { + return nil, nil, nil, err + } + fmt.Println("done connecting to mc server") + } + omegaCore = bundle.NewMicroOmega(neomega_core.NewInteractCore(conn), func() omega.MicroUQHolder { + return uqholder.NewMicroUQHolder(conn) + }, options.MicroOmegaOption) + deadReason = make(chan error) + challengeSolver := challenges.NewPyRPCResponder(omegaCore, fbClient.Uid, + fbClient.TransferData, + fbClient.TransferCheckNum, + ) + go func() { + options.ReadLoopFunction(conn, deadReason, omegaCore) + }() + { + fmt.Println("coping with rental server challenges ...") + challengeSolvingCtx := ctx + if options.ChallengeSolvingTimeout != 0 { + challengeSolvingCtx, _ = context.WithTimeout(ctx, options.ChallengeSolvingTimeout) + } + success := challengeSolver.ChallengeCompete(challengeSolvingCtx) + if !success { + return nil, nil, nil, ErrFBChallengeSolvingTimeout + } + fmt.Println("done coping with rental server challenges") + } + if options.ReasonWithPrivilegeStuff { + fmt.Printf("checking bot op permission and game cheat mode...\n") + helper := challenges.NewOperatorChallenge(omegaCore, func() { + if options.OpPrivilegeRemovedCallBack != nil { + options.OpPrivilegeRemovedCallBack() + } + if options.DieOnLosingOpPrivilege { + deadReason <- ErrBotOpPrivilegeRemoved + } + }) + waitErr := make(chan error) + go func() { + waitErr <- helper.WaitForPrivilege(ctx) + }() + select { + case err = <-waitErr: + case err = <-deadReason: + } + if err != nil { + return nil, nil, nil, err + } + fmt.Printf("done checking bot op permission and game cheat mode\n") + } + if options.MakeBotCreative { + omegaCore.GetGameControl().SendPlayerCmdAndInvokeOnResponseWithFeedback("gamemode c @s", func(output *packet.CommandOutput) { + fmt.Printf("done setting bot to creative mode\n") + }) + } + if options.DisableCommandBlock { + omegaCore.GetGameControl().SendPlayerCmdAndInvokeOnResponseWithFeedback("gamerule commandblocksenabled false", func(output *packet.CommandOutput) { + fmt.Printf("done setting commandblocksenabled false\n") + }) + } + return conn, omegaCore, deadReason, nil +} diff --git a/fastbuilder/lib/rental_server_impact/access_helper/options.go b/fastbuilder/lib/rental_server_impact/access_helper/options.go new file mode 100644 index 000000000..e701fcaa1 --- /dev/null +++ b/fastbuilder/lib/rental_server_impact/access_helper/options.go @@ -0,0 +1,70 @@ +package access_helper + +import ( + "fmt" + "phoenixbuilder/fastbuilder/lib/minecraft/neomega/bundle" + "phoenixbuilder/fastbuilder/lib/minecraft/neomega/omega" + "phoenixbuilder/minecraft" + "phoenixbuilder/minecraft/protocol/packet" + "time" +) + +type ReadLoopFunction func(conn *minecraft.Conn, deadReason chan<- error, omega omega.ReactCore) + +var DefaultReadLoopFunction = func(conn *minecraft.Conn, deadReason chan<- error, omega omega.ReactCore) { + var pkt packet.Packet + var err error + for { + pkt, err = conn.ReadPacket() + if err != nil { + deadReason <- fmt.Errorf("%v: %v", ErrRentalServerDisconnected, err) + } + omega.HandlePacket(pkt) + } +} + +type Options struct { + AuthServer string + ServerConnectionTimeout time.Duration + ChallengeSolvingTimeout time.Duration + ServerConnectRetryTimes int + FBUsername string + FBUserPassword string + FBUserToken string + ServerCode string + ServerPassword string + WriteBackToken bool + MicroOmegaOption *bundle.MicroOmegaOption + PrintUQHolderDebugInfo bool + MakeBotCreative bool + DisableCommandBlock bool + MaximumWaitTime time.Duration + DieOnLosingOpPrivilege bool + OpPrivilegeRemovedCallBack func() + ReadLoopFunction ReadLoopFunction + ReasonWithPrivilegeStuff bool +} + +func DefaultOptions() *Options { + return &Options{ + AuthServer: "", + ServerConnectionTimeout: time.Minute, + ChallengeSolvingTimeout: time.Minute, + ServerConnectRetryTimes: 0, + FBUsername: "", + FBUserPassword: "", + FBUserToken: "", + ServerCode: "", + ServerPassword: "", + WriteBackToken: true, + MicroOmegaOption: bundle.MakeDefaultMicroOmegaOption(), + PrintUQHolderDebugInfo: false, + MakeBotCreative: true, + DisableCommandBlock: true, + MaximumWaitTime: time.Minute * 3, + DieOnLosingOpPrivilege: true, + OpPrivilegeRemovedCallBack: nil, + ReadLoopFunction: DefaultReadLoopFunction, + ReasonWithPrivilegeStuff: true, + } +} diff --git a/fastbuilder/lib/rental_server_impact/challenges/privilege_challenge.go b/fastbuilder/lib/rental_server_impact/challenges/privilege_challenge.go new file mode 100644 index 000000000..7abcdc33c --- /dev/null +++ b/fastbuilder/lib/rental_server_impact/challenges/privilege_challenge.go @@ -0,0 +1,97 @@ +package challenges + +import ( + "context" + "fmt" + "phoenixbuilder/fastbuilder/lib/minecraft/neomega/omega" + "phoenixbuilder/minecraft/protocol/packet" + "strings" + "time" +) + +type OperatorChallenge struct { + omega.MicroOmega + hasOpPrivilege bool + cheatOn bool + lostPrivilegeCB func() +} + +func NewOperatorChallenge(omega omega.MicroOmega, lostPrivilegeCallBack func()) *OperatorChallenge { + if lostPrivilegeCallBack == nil { + lostPrivilegeCallBack = func() { + panic(fmt.Errorf("Operator privilege lost")) + } + } + helper := &OperatorChallenge{ + MicroOmega: omega, + lostPrivilegeCB: lostPrivilegeCallBack, + } + omega.GetGameListener().SetOnTypedPacketCallBack(packet.IDAdventureSettings, helper.onAdventurePacket) + return helper +} + +func (o *OperatorChallenge) onAdventurePacket(pk packet.Packet) { + p := pk.(*packet.AdventureSettings) + if o.GetMicroUQHolder().GetBotBasicInfo().GetBotUniqueID() == p.PlayerUniqueID { + if p.PermissionLevel >= packet.PermissionLevelOperator { + o.hasOpPrivilege = true + fmt.Println("Operator privilege granted") + } else { + if o.hasOpPrivilege { + o.lostPrivilegeCB() + } + fmt.Println("Please grant operator privilege") + o.hasOpPrivilege = false + } + } +} + +func (o *OperatorChallenge) WaitForPrivilege(ctx context.Context) (err error) { + for !o.hasOpPrivilege { + o.GetGameControl().SendWSCmdAndInvokeOnResponse("tp @s ~~~", func(output *packet.CommandOutput) { + if output.SuccessCount > 0 { + o.hasOpPrivilege = true + } + }) + o.GetGameControl().BotSay("Please grant operator privilege") + fmt.Println("Please grant operator privilege") + time.Sleep(1 * time.Second) + if ctx.Err() != nil { + return fmt.Errorf("Operator privilege granting timed out") + } + } + fmt.Println("Privilege granted") + first := true + for !o.cheatOn { + o.GetGameControl().SendWSCmdAndInvokeOnResponse("testforblock ~~~ air 0", func(output *packet.CommandOutput) { + if output.SuccessCount > 0 { + o.cheatOn = true + } + if len(output.OutputMessages) > 0 { + if strings.Contains(output.OutputMessages[0].Message, "commands.generic.disabled") { + o.cheatOn = false + if first { + fmt.Println("Please enable cheating.") + first = false + } + } else { + o.cheatOn = true + } + } + }) + o.GetGameControl().SendWSCmdAndInvokeOnResponse("tp @s ~~~", func(output *packet.CommandOutput) { + if output.SuccessCount > 0 { + o.cheatOn = true + } + }) + time.Sleep(1 * time.Second) + if ctx.Err() != nil { + return fmt.Errorf("Ceased waiting") + } + if !o.cheatOn { + o.GetGameControl().BotSay("Please enable cheating.") + fmt.Println("Please enable cheating.") + } + } + return nil +} diff --git a/fastbuilder/lib/rental_server_impact/challenges/py_rpc_responder.go b/fastbuilder/lib/rental_server_impact/challenges/py_rpc_responder.go new file mode 100644 index 000000000..a01227288 --- /dev/null +++ b/fastbuilder/lib/rental_server_impact/challenges/py_rpc_responder.go @@ -0,0 +1,103 @@ +package challenges + +import ( + "context" + "encoding/json" + "phoenixbuilder/fastbuilder/lib/minecraft/neomega/omega" + "phoenixbuilder/fastbuilder/py_rpc" + "phoenixbuilder/minecraft/protocol/packet" +) + +type PyRPCResponder struct { + omega.MicroOmega + isCheckNumResponded bool + chanCheckNumResponded chan struct{} + isGetStartTypeResponded bool + chanGetStartTypeResponded chan struct{} + TransferData func(content string, uid string) string + TransferCheckNum func(arg string) (ret string) + Uid string +} + +func NewPyRPCResponder(omega omega.MicroOmega, Uid string, TransferData func(content string, uid string) string, TransferCheckNum func(arg string) (ret string)) *PyRPCResponder { + responser := &PyRPCResponder{ + MicroOmega: omega, + Uid: Uid, + TransferData: TransferData, + TransferCheckNum: TransferCheckNum, + chanCheckNumResponded: make(chan struct{}), + chanGetStartTypeResponded: make(chan struct{}), + } + omega.GetGameListener().SetOnTypedPacketCallBack(packet.IDPyRpc, responser.onPyRPC) + return responser +} + +func (o *PyRPCResponder) ChallengeCompete(ctx context.Context) bool { + select { + case <-ctx.Done(): + return false + case <-o.chanGetStartTypeResponded: + if o.isCheckNumResponded { + return true + } else { + return o.ChallengeCompete(ctx) + } + case <-o.chanCheckNumResponded: + if o.isGetStartTypeResponded { + return true + } else { + return o.ChallengeCompete(ctx) + } + } +} + +func (o *PyRPCResponder) onPyRPC(pk packet.Packet) { + pkt, ok := pk.(*packet.PyRpc) + if !ok { + return + } + goContentData := pkt.Value.MakeGo() + content := goContentData.([]interface{}) + command := content[0].(string) + data := content[1].([]interface{}) + if command == "S2CHeartBeat" { + o.GetGameControl().SendPacket(&packet.PyRpc{ + Value: py_rpc.FromGo([]interface{}{ + "C2SHeartBeat", + data, + nil, + }), + }) + } else if command == "GetStartType" { + response := o.TransferData(data[0].(string), o.Uid) + o.GetGameControl().SendPacket(&packet.PyRpc{ + Value: py_rpc.FromGo([]interface{}{ + "SetStartType", + []interface{}{response}, + nil, + }), + }) + if !o.isGetStartTypeResponded { + o.isGetStartTypeResponded = true + close(o.chanGetStartTypeResponded) + } + } else if (command == "GetMCPCheckNum") && !o.isCheckNumResponded { + firstArg := data[0].(string) + secondArg := (data[1].([]interface{}))[0].(string) + arg, _ := json.Marshal([]interface{}{firstArg, secondArg, o.GetMicroUQHolder().GetBotBasicInfo().GetBotUniqueID()}) + ret := o.TransferCheckNum(string(arg)) + ret_p := []interface{}{} + json.Unmarshal([]byte(ret), &ret_p) + o.GetGameControl().SendPacket(&packet.PyRpc{ + Value: py_rpc.FromGo([]interface{}{ + "SetMCPCheckNum", + []interface{}{ + ret_p, + }, + nil, + }), + }) + o.isCheckNumResponded = true + close(o.chanCheckNumResponded) + } +} diff --git a/lib/helpers/fbuser/credentials.go b/fastbuilder/lib/rental_server_impact/info_collect_utils/utils.go similarity index 91% rename from lib/helpers/fbuser/credentials.go rename to fastbuilder/lib/rental_server_impact/info_collect_utils/utils.go index bae19bfbc..5cad6e2a8 100644 --- a/lib/helpers/fbuser/credentials.go +++ b/fastbuilder/lib/rental_server_impact/info_collect_utils/utils.go @@ -1,16 +1,15 @@ -package fbuser +package info_collect_utils import ( "bufio" "fmt" + "golang.org/x/term" "io/ioutil" "os" "path/filepath" - I18n "phoenixbuilder/fastbuilder/i18n" + "phoenixbuilder/fastbuilder/i18n" "strings" "syscall" - - "golang.org/x/term" ) func LoadTokenPath() string { @@ -60,7 +59,7 @@ func GetRentalServerCode() (string, string, error) { return strings.TrimRight(code, "\r\n"), strings.TrimSpace(string(bytePassword)), err } -func WriteToken(token string, tokenPath string) { +func WriteFBToken(token string, tokenPath string) { if fp, err := os.Create(tokenPath); err != nil { fmt.Println(I18n.T(I18n.FBUC_Token_ErrOnCreate), err) fmt.Println(I18n.T(I18n.ErrorIgnored)) @@ -74,7 +73,7 @@ func WriteToken(token string, tokenPath string) { } } -func ReadInfo(userName, userPassword, userToken, serverCode, serverPassword string) (string, string, string, string, string, error) { +func ReadUserInfo(userName, userPassword, userToken, serverCode, serverPassword string) (string, string, string, string, string, error) { var err error // read token or get user input I18n.Init() @@ -86,6 +85,7 @@ func ReadInfo(userName, userPassword, userToken, serverCode, serverPassword stri if strings.HasPrefix(userName, "w9/") { userToken = userName userName = "" + break } if err != nil { return userName, userPassword, userToken, serverCode, serverPassword, err diff --git a/lib/utils/cache_wrapper/cache.go b/fastbuilder/lib/utils/cache_wrapper/cache.go similarity index 94% rename from lib/utils/cache_wrapper/cache.go rename to fastbuilder/lib/utils/cache_wrapper/cache.go index ad04dba0a..fb7b3d64d 100644 --- a/lib/utils/cache_wrapper/cache.go +++ b/fastbuilder/lib/utils/cache_wrapper/cache.go @@ -3,10 +3,10 @@ package cache_wrapper import ( "os" "path" - "phoenixbuilder/lib/utils/crypto_wrapper" - "phoenixbuilder/lib/utils/file_wrapper" - "phoenixbuilder/lib/utils/lang" - "phoenixbuilder/lib/utils/triple_wrapper" + "phoenixbuilder/fastbuilder/lib/utils/crypto_wrapper" + "phoenixbuilder/fastbuilder/lib/utils/file_wrapper" + "phoenixbuilder/fastbuilder/lib/utils/lang" + "phoenixbuilder/fastbuilder/lib/utils/triple_wrapper" "strings" ) diff --git a/lib/utils/compress_wrapper/brotli.go b/fastbuilder/lib/utils/compress_wrapper/brotli.go similarity index 100% rename from lib/utils/compress_wrapper/brotli.go rename to fastbuilder/lib/utils/compress_wrapper/brotli.go diff --git a/lib/utils/compress_wrapper/zip.go b/fastbuilder/lib/utils/compress_wrapper/zip.go similarity index 100% rename from lib/utils/compress_wrapper/zip.go rename to fastbuilder/lib/utils/compress_wrapper/zip.go diff --git a/lib/utils/convert_wrapper/convert.go b/fastbuilder/lib/utils/convert_wrapper/convert.go similarity index 100% rename from lib/utils/convert_wrapper/convert.go rename to fastbuilder/lib/utils/convert_wrapper/convert.go diff --git a/lib/utils/crypto_wrapper/crypto.go b/fastbuilder/lib/utils/crypto_wrapper/crypto.go similarity index 100% rename from lib/utils/crypto_wrapper/crypto.go rename to fastbuilder/lib/utils/crypto_wrapper/crypto.go diff --git a/lib/utils/crypto_wrapper/errs.go b/fastbuilder/lib/utils/crypto_wrapper/errs.go similarity index 100% rename from lib/utils/crypto_wrapper/errs.go rename to fastbuilder/lib/utils/crypto_wrapper/errs.go diff --git a/lib/utils/download_wrapper/download.go b/fastbuilder/lib/utils/download_wrapper/download.go similarity index 96% rename from lib/utils/download_wrapper/download.go rename to fastbuilder/lib/utils/download_wrapper/download.go index 37a59e363..3061474ec 100644 --- a/lib/utils/download_wrapper/download.go +++ b/fastbuilder/lib/utils/download_wrapper/download.go @@ -5,9 +5,9 @@ import ( "fmt" "io" "net/http" - "phoenixbuilder/lib/utils/compress_wrapper" - "phoenixbuilder/lib/utils/lang" - "phoenixbuilder/lib/utils/string_wrapper" + "phoenixbuilder/fastbuilder/lib/utils/compress_wrapper" + "phoenixbuilder/fastbuilder/lib/utils/lang" + "phoenixbuilder/fastbuilder/lib/utils/string_wrapper" "strconv" "strings" "time" diff --git a/lib/utils/env_wrapper/docker.go b/fastbuilder/lib/utils/env_wrapper/docker.go similarity index 100% rename from lib/utils/env_wrapper/docker.go rename to fastbuilder/lib/utils/env_wrapper/docker.go diff --git a/lib/utils/error_wrapper/error.go b/fastbuilder/lib/utils/error_wrapper/error.go similarity index 100% rename from lib/utils/error_wrapper/error.go rename to fastbuilder/lib/utils/error_wrapper/error.go diff --git a/lib/utils/file_wrapper/file.go b/fastbuilder/lib/utils/file_wrapper/file.go similarity index 100% rename from lib/utils/file_wrapper/file.go rename to fastbuilder/lib/utils/file_wrapper/file.go diff --git a/lib/utils/generate_wrapper/generate.go b/fastbuilder/lib/utils/generate_wrapper/generate.go similarity index 100% rename from lib/utils/generate_wrapper/generate.go rename to fastbuilder/lib/utils/generate_wrapper/generate.go diff --git a/lib/utils/lang/lang.go b/fastbuilder/lib/utils/lang/lang.go similarity index 100% rename from lib/utils/lang/lang.go rename to fastbuilder/lib/utils/lang/lang.go diff --git a/lib/utils/lang/lang.json b/fastbuilder/lib/utils/lang/lang.json similarity index 100% rename from lib/utils/lang/lang.json rename to fastbuilder/lib/utils/lang/lang.json diff --git a/lib/utils/net_wrapper/main.go b/fastbuilder/lib/utils/net_wrapper/main.go similarity index 100% rename from lib/utils/net_wrapper/main.go rename to fastbuilder/lib/utils/net_wrapper/main.go diff --git a/lib/utils/serialize_wrapper/reader.go b/fastbuilder/lib/utils/serialize_wrapper/reader.go similarity index 100% rename from lib/utils/serialize_wrapper/reader.go rename to fastbuilder/lib/utils/serialize_wrapper/reader.go diff --git a/lib/utils/serialize_wrapper/reader_be.go b/fastbuilder/lib/utils/serialize_wrapper/reader_be.go similarity index 100% rename from lib/utils/serialize_wrapper/reader_be.go rename to fastbuilder/lib/utils/serialize_wrapper/reader_be.go diff --git a/lib/utils/serialize_wrapper/reader_le.go b/fastbuilder/lib/utils/serialize_wrapper/reader_le.go similarity index 100% rename from lib/utils/serialize_wrapper/reader_le.go rename to fastbuilder/lib/utils/serialize_wrapper/reader_le.go diff --git a/lib/utils/serialize_wrapper/writer.go b/fastbuilder/lib/utils/serialize_wrapper/writer.go similarity index 100% rename from lib/utils/serialize_wrapper/writer.go rename to fastbuilder/lib/utils/serialize_wrapper/writer.go diff --git a/lib/utils/serialize_wrapper/writer_be.go b/fastbuilder/lib/utils/serialize_wrapper/writer_be.go similarity index 100% rename from lib/utils/serialize_wrapper/writer_be.go rename to fastbuilder/lib/utils/serialize_wrapper/writer_be.go diff --git a/lib/utils/serialize_wrapper/writer_le.go b/fastbuilder/lib/utils/serialize_wrapper/writer_le.go similarity index 100% rename from lib/utils/serialize_wrapper/writer_le.go rename to fastbuilder/lib/utils/serialize_wrapper/writer_le.go diff --git a/lib/utils/string_wrapper/utils.go b/fastbuilder/lib/utils/string_wrapper/utils.go similarity index 100% rename from lib/utils/string_wrapper/utils.go rename to fastbuilder/lib/utils/string_wrapper/utils.go diff --git a/lib/utils/sync_wrapper/map.go b/fastbuilder/lib/utils/sync_wrapper/map.go similarity index 100% rename from lib/utils/sync_wrapper/map.go rename to fastbuilder/lib/utils/sync_wrapper/map.go diff --git a/lib/utils/triple_wrapper/amd64.go b/fastbuilder/lib/utils/triple_wrapper/amd64.go similarity index 100% rename from lib/utils/triple_wrapper/amd64.go rename to fastbuilder/lib/utils/triple_wrapper/amd64.go diff --git a/lib/utils/triple_wrapper/android.go b/fastbuilder/lib/utils/triple_wrapper/android.go similarity index 100% rename from lib/utils/triple_wrapper/android.go rename to fastbuilder/lib/utils/triple_wrapper/android.go diff --git a/lib/utils/triple_wrapper/arm64.go b/fastbuilder/lib/utils/triple_wrapper/arm64.go similarity index 100% rename from lib/utils/triple_wrapper/arm64.go rename to fastbuilder/lib/utils/triple_wrapper/arm64.go diff --git a/lib/utils/triple_wrapper/linux.go b/fastbuilder/lib/utils/triple_wrapper/linux.go similarity index 100% rename from lib/utils/triple_wrapper/linux.go rename to fastbuilder/lib/utils/triple_wrapper/linux.go diff --git a/lib/utils/triple_wrapper/macos.go b/fastbuilder/lib/utils/triple_wrapper/macos.go similarity index 100% rename from lib/utils/triple_wrapper/macos.go rename to fastbuilder/lib/utils/triple_wrapper/macos.go diff --git a/lib/utils/triple_wrapper/triple.go b/fastbuilder/lib/utils/triple_wrapper/triple.go similarity index 100% rename from lib/utils/triple_wrapper/triple.go rename to fastbuilder/lib/utils/triple_wrapper/triple.go diff --git a/lib/utils/triple_wrapper/windows.go b/fastbuilder/lib/utils/triple_wrapper/windows.go similarity index 100% rename from lib/utils/triple_wrapper/windows.go rename to fastbuilder/lib/utils/triple_wrapper/windows.go diff --git a/lib/utils/triple_wrapper/x86.go b/fastbuilder/lib/utils/triple_wrapper/x86.go similarity index 100% rename from lib/utils/triple_wrapper/x86.go rename to fastbuilder/lib/utils/triple_wrapper/x86.go diff --git a/fastbuilder/mcstructure/main.go b/fastbuilder/mcstructure/main.go index a87db048a..c7278b801 100644 --- a/fastbuilder/mcstructure/main.go +++ b/fastbuilder/mcstructure/main.go @@ -386,6 +386,10 @@ func DumpBlocks( background_blockName = strings.Replace(targetArea.blockPalette[bgId], "minecraft:", "", 1) // 背景层方块的名称 background_blockStates = targetArea.blockPalette_blockStates[bgId] // 背景层方块的方块状态 } + if fgId == -1 && bgId == -1 { + foreground_blockName = "structure_void" + foreground_blockStates = "[]" + } // 获得基本信息 var hasNBT bool = false var blockNBT []byte @@ -442,7 +446,7 @@ func DumpBlocks( } } // 取得方块实体数据 - if foreground_blockName != "" && foreground_blockName != "undefined" && (background_blockName == "water" || background_blockName == "flowing_water") { + if foreground_blockName != "undefined" && (background_blockName == "water" || background_blockName == "flowing_water") { ans = append(ans, &types.Module{ Block: &types.Block{ Name: &background_blockName, @@ -457,7 +461,7 @@ func DumpBlocks( } // 含水类方块的处理。 // 我们将含水类方块处理为 setblock water + targetBlock 的形式 - if foreground_blockName != "" && foreground_blockName != "air" && foreground_blockName != "undefined" { + if foreground_blockName != "air" && foreground_blockName != "undefined" { single := &types.Module{ Block: &types.Block{ Name: &foreground_blockName, diff --git a/fastbuilder/parsing/parsing.go b/fastbuilder/parsing/parsing.go index b82eb8cee..690bf745d 100644 --- a/fastbuilder/parsing/parsing.go +++ b/fastbuilder/parsing/parsing.go @@ -95,11 +95,13 @@ func Parse(Message string, defaultConfig *types.MainConfig) (*types.MainConfig, FlagSet.StringVar(&Config.Facing, "f", defaultConfig.Facing, "Building's facing") FlagSet.StringVar(&Config.Path, "path", defaultConfig.Path, "The path of file") FlagSet.StringVar(&Config.Path, "p", defaultConfig.Path, "The path of file") - FlagSet.StringVar(&Config.Shape, "shape", defaultConfig.Shape, "The path of file") - FlagSet.StringVar(&Config.Shape, "s", defaultConfig.Shape, "The path of file") + FlagSet.StringVar(&Config.Shape, "shape", defaultConfig.Shape, "The shape of geometric structure") + FlagSet.StringVar(&Config.Shape, "s", defaultConfig.Shape, "The shape of geometric structure") //Block - FlagSet.StringVar(&Config.Block.Name, "block", defaultConfig.Block.Name, "Blocks that make up the building") - FlagSet.StringVar(&Config.Block.Name, "b", defaultConfig.Block.Name, "Blocks that make up the building") + FlagSet.StringVar(&Config.Block.Name, "block", defaultConfig.Block.Name, "Blocks making up the structure") + FlagSet.StringVar(&Config.Block.Name, "b", defaultConfig.Block.Name, "Blocks making up the structure") + FlagSet.StringVar(&Config.Entity, "entity", "", "") + FlagSet.StringVar(&Config.Entity, "e", "", "") FlagSet.IntVar(&tempBlockData, "data", int(defaultConfig.Block.Data), "The data of Block") FlagSet.IntVar(&tempBlockData, "d", int(defaultConfig.Block.Data), "The data of Block") //OldBlock diff --git a/fastbuilder/py_rpc/bool_type.go b/fastbuilder/py_rpc/bool_type.go new file mode 100644 index 000000000..e9d1b20c9 --- /dev/null +++ b/fastbuilder/py_rpc/bool_type.go @@ -0,0 +1,34 @@ +package py_rpc + +type PyRpcBoolObject struct { + Value bool +} + +func (o *PyRpcBoolObject) Marshal() []byte { + if o.Value { + return []byte{0xc3} + } + return []byte{0xc2} +} + +func (o *PyRpcBoolObject) Parse(v []byte) uint { + if v[0]==0xc2 { + o.Value=false + }else{ + o.Value=true + } + return 1 +} + +func (_ *PyRpcBoolObject) Type() uint { + return BoolType +} + +func (o *PyRpcBoolObject) MakeGo() interface{} { + return o.Value +} + +func (o *PyRpcBoolObject) FromGo(v interface{}) { + pv:=v.(bool) + o.Value=pv +} \ No newline at end of file diff --git a/fastbuilder/py_rpc/bytes_type.go b/fastbuilder/py_rpc/bytes_type.go new file mode 100644 index 000000000..1b691cf57 --- /dev/null +++ b/fastbuilder/py_rpc/bytes_type.go @@ -0,0 +1,63 @@ +package py_rpc + +import "encoding/binary" + +type PyRpcBytesObject struct { + Value []byte +} + +func (o *PyRpcBytesObject) Marshal() []byte { + var header []byte + if len(o.Value)<=0xff { + header=[]byte{0xc4, byte(len(o.Value))} + }else if(len(o.Value)<=0xffff) { + header=[]byte{0xc5,0x00,0x00} + binary.BigEndian.PutUint16(header[1:], uint16(len(o.Value))) + }else if(uint(len(o.Value))<=uint(0xffffffff)) { + header=make([]byte, 1+4) + header[0]=0xc6 + binary.BigEndian.PutUint32(header[1:], uint32(len(o.Value))) + }else{ + panic("PyRpcBytesObject: Maximum allowed size exceeded") + } + return append(header, o.Value...) +} + +func (o *PyRpcBytesObject) Parse(v []byte) uint { + var size uint32 + var header_consumed uint8 + var nokori []byte + if v[0]==0xc4 { + size=uint32(v[1]) + nokori=v[2:] + header_consumed=2 + }else if v[0]==0xc5 { + size=uint32(binary.BigEndian.Uint16(v[1:])) + nokori=v[3:] + header_consumed=3 + }else if v[0]==0xc6 { + size=uint32(binary.BigEndian.Uint32(v[1:])) + nokori=v[5:] + header_consumed=1+4 + }else{ + panic("PyRpcBytesObject/Parse: Not even a bytes object") + } + if len(nokori) - -int compareVersion(char *latestVersion,char *currentVersion) { - char *latestVersionParts[3]; - int vpi=1; - latestVersionParts[0]=latestVersion; - for(char *p=latestVersion;*p!=0;p++) { - if(*p<'0'||*p>'9') { - if(vpi>=3)break; - *p=0; - latestVersionParts[vpi]=p+1; - vpi++; - } - } - int lvMajor=atoi(latestVersionParts[0]); - int lvMinor=atoi(latestVersionParts[1]); - int lvPatch=atoi(latestVersionParts[2]); - char *currentVersionParts[3]; - vpi=1; - currentVersionParts[0]=currentVersion; - for(char *p=currentVersion;*p!=0;p++) { - if(*p<'0'||*p>'9') { - if(vpi>=3)break; - *p=0; - currentVersionParts[vpi]=p+1; - vpi++; - } - } - int cMajor=atoi(currentVersionParts[0]); - int cMinor=atoi(currentVersionParts[1]); - int cPatch=atoi(currentVersionParts[2]); - free(latestVersion); - free(currentVersion); - if(cMajor 8 { hotbarSlotID = 0 } @@ -30,22 +30,22 @@ func (g *GlobalAPI) ChangeSelectedHotbarSlot(hotbarSlotID uint8) error { 返回值的第一项代表执行结果,为真时背包被成功打开,否则反之。 如需要关闭已打开的背包,请直接使用函数 CloseContainer . -请确保打开前占用了容器资源,否则会造成程序惊慌。 +请确保打开前占用了容器资源,否则会造成程序 panic 。 */ -func (g *GlobalAPI) OpenInventory() (bool, error) { - g.Resources.Container.AwaitChangesBeforeSendPacket() +func (g *GameInterface) OpenInventory() (bool, error) { + g.Resources.Container.AwaitChangesBeforeSendingPacket() // await responce before send packet err := g.WritePacket(&packet.Interact{ ActionType: packet.InteractActionOpenInventory, - TargetEntityRuntimeID: g.BotInfo.BotRunTimeID, + TargetEntityRuntimeID: g.ClientInfo.EntityRuntimeID, }) if err != nil { return false, fmt.Errorf("OpenInventory: %v", err) } // open inventory - g.Resources.Container.AwaitChangesAfterSendPacket() + g.Resources.Container.AwaitChangesAfterSendingPacket() // wait changes - if g.Resources.Container.GetContainerOpenDatas() == nil { + if g.Resources.Container.GetContainerOpeningData() == nil { return false, nil } // if unsuccess diff --git a/GameControl/GlobalAPI/itemOperation.go b/game_control/game_interface/item_operation.go similarity index 86% rename from GameControl/GlobalAPI/itemOperation.go rename to game_control/game_interface/item_operation.go index 3374305cd..6d8fc20bc 100644 --- a/GameControl/GlobalAPI/itemOperation.go +++ b/game_control/game_interface/item_operation.go @@ -1,8 +1,8 @@ -package GlobalAPI +package GameInterface import ( "fmt" - "phoenixbuilder/GameControl/ResourcesControlCenter" + "phoenixbuilder/game_control/resources_control" "phoenixbuilder/minecraft/protocol" "phoenixbuilder/minecraft/protocol/packet" ) @@ -18,10 +18,10 @@ type ItemLocation struct { // 且只移动 moveCount 个物品。 // details 指代相应槽位的预期变动结果,它将作为更新本地库存数据的依据。 // 当且仅当物品操作得到租赁服的响应后,此函数才会返回物品操作结果。 -func (g *GlobalAPI) MoveItem( +func (g *GameInterface) MoveItem( source ItemLocation, destination ItemLocation, - details ItemChangeDetails, + details ItemChangingDetails, moveCount uint8, ) ([]protocol.ItemStackResponse, error) { placeStackRequestAction := protocol.PlaceStackRequestAction{} @@ -49,7 +49,7 @@ func (g *GlobalAPI) MoveItem( StackNetworkID: itemOnDestination.StackNetworkID, } // 构造 placeStackRequestAction 结构体 - ans, err := g.SendItemStackRequestWithResponce( + ans, err := g.SendItemStackRequestWithResponse( &packet.ItemStackRequest{ Requests: []protocol.ItemStackRequest{ { @@ -59,7 +59,7 @@ func (g *GlobalAPI) MoveItem( }, }, }, - []ItemChangeDetails{details}, + []ItemChangingDetails{details}, ) if err != nil { return []protocol.ItemStackResponse{}, fmt.Errorf("MoveItem: %v", err) @@ -73,11 +73,11 @@ func (g *GlobalAPI) MoveItem( // windowID 指代被丢出物品所在库存的窗口 ID 。 // 返回值第一项代表丢出结果, // 为真时代表成功丢出,否则反之 -func (g *GlobalAPI) DropItemAll( +func (g *GameInterface) DropItemAll( source protocol.StackRequestSlotInfo, windowID uint32, ) (bool, error) { - ans, err := g.SendItemStackRequestWithResponce( + ans, err := g.SendItemStackRequestWithResponse( &packet.ItemStackRequest{ Requests: []protocol.ItemStackRequest{ { @@ -91,10 +91,10 @@ func (g *GlobalAPI) DropItemAll( }, }, }, - []ItemChangeDetails{ + []ItemChangingDetails{ { - map[ResourcesControlCenter.ContainerID]ResourcesControlCenter.StackRequestContainerInfo{ - ResourcesControlCenter.ContainerID(source.ContainerID): { + map[ResourcesControl.ContainerID]ResourcesControl.StackRequestContainerInfo{ + ResourcesControl.ContainerID(source.ContainerID): { WindowID: windowID, ChangeResult: map[uint8]protocol.ItemInstance{ source.Slot: AirItem, diff --git a/GameControl/GlobalAPI/changeItemName.go b/game_control/game_interface/item_renaming.go similarity index 82% rename from GameControl/GlobalAPI/changeItemName.go rename to game_control/game_interface/item_renaming.go index 8b1130a83..166227550 100644 --- a/GameControl/GlobalAPI/changeItemName.go +++ b/game_control/game_interface/item_renaming.go @@ -1,9 +1,9 @@ -package GlobalAPI +package GameInterface import ( "encoding/gob" "fmt" - "phoenixbuilder/GameControl/ResourcesControlCenter" + ResourcesControl "phoenixbuilder/game_control/resources_control" "phoenixbuilder/minecraft/protocol" "phoenixbuilder/minecraft/protocol/packet" ) @@ -20,25 +20,25 @@ import ( // 如果背包中所有物品栏都已被占用,则物品会被留在铁砧内。 // // 部分情况下此函数可能会遇见无法处理的错误,届时程序将抛出严重错误(panic) -func (g *GlobalAPI) ChangeItemName( +func (g *GameInterface) RenameItem( name string, slot uint8, -) (*AnvilOperationResponce, error) { - containerOpenDatas := g.Resources.Container.GetContainerOpenDatas() +) (*AnvilOperationResponse, error) { + containerOpeningData := g.Resources.Container.GetContainerOpeningData() // 取得已打开的容器的数据 - if containerOpenDatas == nil { - return nil, fmt.Errorf("ChangeItemName: Anvil has not opened") + if containerOpeningData == nil { + return nil, fmt.Errorf("RenameItem: Anvil has not opened") } // 如果铁砧未被打开 var itemDatas protocol.ItemInstance get, err := g.Resources.Inventory.GetItemStackInfo( - uint32(containerOpenDatas.WindowID), + uint32(containerOpeningData.WindowID), 1, ) if err != nil { - return nil, fmt.Errorf("ChangeItemName: %v", err) + return nil, fmt.Errorf("RenameItem: %v", err) } - ResourcesControlCenter.DeepCopy( + ResourcesControl.DeepCopy( &get, &itemDatas, func() { @@ -47,7 +47,7 @@ func (g *GlobalAPI) ChangeItemName( ) // 取得已放入铁砧的物品的物品数据并保存在 itemDatas 处 var backup protocol.ItemInstance - ResourcesControlCenter.DeepCopy( + ResourcesControl.DeepCopy( &get, &backup, func() { @@ -58,7 +58,7 @@ func (g *GlobalAPI) ChangeItemName( getOptionalSlot := func() []uint8 { filterAns, err := g.Resources.Inventory.ListSlot(0, &[]int32{0}) if err != nil { - panic(fmt.Sprintf("ChangeItemName: %v", err)) + panic(fmt.Sprintf("RenameItem: %v", err)) } // 筛选出背包中还未被占用实际物品的物品栏 optionalSlot := []uint8{slot} @@ -71,7 +71,7 @@ func (g *GlobalAPI) ChangeItemName( // return } // 构造一个函数以用于取得背包中的空气物品栏 - revertFunc := func() (*AnvilOperationResponce, error) { + revertFunc := func() (*AnvilOperationResponse, error) { for _, value := range getOptionalSlot() { placeStackRequestAction := protocol.PlaceStackRequestAction{} placeStackRequestAction.Source = protocol.StackRequestSlotInfo{ @@ -86,7 +86,7 @@ func (g *GlobalAPI) ChangeItemName( } placeStackRequestAction.Count = byte(backup.Stack.Count) // 构造一个新的 placeStackRequestAction 结构体 - resp, err := g.SendItemStackRequestWithResponce( + resp, err := g.SendItemStackRequestWithResponse( &packet.ItemStackRequest{ Requests: []protocol.ItemStackRequest{ { @@ -97,11 +97,11 @@ func (g *GlobalAPI) ChangeItemName( }, }, }, - []ItemChangeDetails{ + []ItemChangingDetails{ { - details: map[ResourcesControlCenter.ContainerID]ResourcesControlCenter.StackRequestContainerInfo{ + details: map[ResourcesControl.ContainerID]ResourcesControl.StackRequestContainerInfo{ 0x0: { - WindowID: uint32(containerOpenDatas.WindowID), + WindowID: uint32(containerOpeningData.WindowID), ChangeResult: map[uint8]protocol.ItemInstance{ 1: AirItem, }, @@ -121,8 +121,8 @@ func (g *GlobalAPI) ChangeItemName( return nil, err } if resp[0].Status == protocol.ItemStackResponseStatusOK { - return &AnvilOperationResponce{ - SuccessStates: false, + return &AnvilOperationResponse{ + Successful: false, Destination: &ItemLocation{ WindowID: 0, ContainerID: 0xc, @@ -133,10 +133,10 @@ func (g *GlobalAPI) ChangeItemName( // 如果成功还原的话,那么返回值 } // 尝试把被操作物品从铁砧放回背包中 - return &AnvilOperationResponce{ - SuccessStates: false, + return &AnvilOperationResponse{ + Successful: false, Destination: &ItemLocation{ - WindowID: int16(containerOpenDatas.WindowID), + WindowID: int16(containerOpeningData.WindowID), ContainerID: 0, Slot: 1, }, @@ -201,7 +201,7 @@ func (g *GlobalAPI) ChangeItemName( // 更新物品数据中的 RepairCost 字段用于更新本地库存数据 err = g.Resources.ItemStackOperation.WriteRequest( newRequestID, - map[ResourcesControlCenter.ContainerID]ResourcesControlCenter.StackRequestContainerInfo{ + map[ResourcesControl.ContainerID]ResourcesControl.StackRequestContainerInfo{ 0xc: { WindowID: 0, ChangeResult: map[uint8]protocol.ItemInstance{ @@ -209,19 +209,19 @@ func (g *GlobalAPI) ChangeItemName( }, }, 0x0: { - WindowID: uint32(containerOpenDatas.WindowID), + WindowID: uint32(containerOpeningData.WindowID), ChangeResult: map[uint8]protocol.ItemInstance{ 1: AirItem, }, }, 0x1: { - WindowID: uint32(containerOpenDatas.WindowID), + WindowID: uint32(containerOpeningData.WindowID), ChangeResult: map[uint8]protocol.ItemInstance{ 2: AirItem, }, }, 0x3c: { - WindowID: uint32(containerOpenDatas.WindowID), + WindowID: uint32(containerOpeningData.WindowID), ChangeResult: map[uint8]protocol.ItemInstance{ 0x32: AirItem, }, @@ -234,10 +234,10 @@ func (g *GlobalAPI) ChangeItemName( // 写入请求到等待队列 err = g.WritePacket(&newItemStackRequest) if err != nil { - panic(fmt.Sprintf("ChangeItemName: %v", err)) + panic(fmt.Sprintf("RenameItem: %v", err)) } // 发送物品操作请求 - ans, err := g.Resources.ItemStackOperation.LoadResponceAndDelete(newRequestID) + ans, err := g.Resources.ItemStackOperation.LoadResponseAndDelete(newRequestID) if err != nil { return revertFunc() } @@ -247,8 +247,8 @@ func (g *GlobalAPI) ChangeItemName( } // 此时改名失败,原因是物品的新名称与原始名称重名 if ans.Status == protocol.ItemStackResponseStatusOK { - return &AnvilOperationResponce{ - SuccessStates: true, + return &AnvilOperationResponse{ + Successful: true, Destination: &ItemLocation{ WindowID: 0, ContainerID: 0xc, diff --git a/GameControl/GlobalAPI/senditemstackrequest.go b/game_control/game_interface/item_stack_request.go similarity index 75% rename from GameControl/GlobalAPI/senditemstackrequest.go rename to game_control/game_interface/item_stack_request.go index 7d91f77da..e13d32158 100644 --- a/GameControl/GlobalAPI/senditemstackrequest.go +++ b/game_control/game_interface/item_stack_request.go @@ -1,19 +1,19 @@ -package GlobalAPI +package GameInterface import ( "fmt" - "phoenixbuilder/GameControl/ResourcesControlCenter" + "phoenixbuilder/game_control/resources_control" "phoenixbuilder/minecraft/protocol" "phoenixbuilder/minecraft/protocol/packet" ) // 每个物品操作请求都会使用这样一个结构体, // 它用于描述单个的物品操作请求中各容器中各槽位的变动情况 -type ItemChangeDetails struct { +type ItemChangingDetails struct { // 描述多个库存(容器)中物品的变动结果。 // 租赁服不会在返回 ItemStackResponce 时返回完整的物品数据,因此需要您提供对应 // 槽位的更改结果以便于我们依此更新本地存储的库存数据 - details map[ResourcesControlCenter.ContainerID]ResourcesControlCenter.StackRequestContainerInfo + details map[ResourcesControl.ContainerID]ResourcesControl.StackRequestContainerInfo } /* @@ -25,12 +25,12 @@ details 指代物品操作请求后物品的变动结果,这将用于更新本 1. 无论 request 中填写的 RequestID 是什么,它们最终会被覆写为正确的值; 2. request.Requests[key] 与 details[key] 一一对应 */ -func (g *GlobalAPI) SendItemStackRequestWithResponce( +func (g *GameInterface) SendItemStackRequestWithResponse( request *packet.ItemStackRequest, - details []ItemChangeDetails, + details []ItemChangingDetails, ) ([]protocol.ItemStackResponse, error) { requestIDList := []int32{} - ans := []protocol.ItemStackResponse{} + res := []protocol.ItemStackResponse{} // 初始化 for range request.Requests { requestIDList = append( @@ -49,17 +49,17 @@ func (g *GlobalAPI) SendItemStackRequestWithResponce( // 重新设定每个请求的请求 ID 并写入请求到等待队列 err := g.WritePacket(request) if err != nil { - return nil, fmt.Errorf("SendItemStackRequestWithResponce: %v", err) + return nil, fmt.Errorf("SendItemStackRequestWithResponse: %v", err) } // 发送物品操作请求 for _, value := range requestIDList { - got, err := g.Resources.ItemStackOperation.LoadResponceAndDelete(value) + got, err := g.Resources.ItemStackOperation.LoadResponseAndDelete(value) if err != nil { - return nil, fmt.Errorf("SendItemStackRequestWithResponce: %v", err) + return nil, fmt.Errorf("SendItemStackRequestWithResponse: %v", err) } - ans = append(ans, got) + res = append(res, got) } // 等待租赁服回应所有物品操作请求。同时,每当一个请求被响应,就把对应的结果保存下来 - return ans, nil + return res, nil // 返回值 } diff --git a/game_control/game_interface/querytarget.go b/game_control/game_interface/querytarget.go new file mode 100644 index 000000000..328c55f95 --- /dev/null +++ b/game_control/game_interface/querytarget.go @@ -0,0 +1,116 @@ +package GameInterface + +import ( + "encoding/json" + "fmt" + "phoenixbuilder/minecraft/protocol/packet" +) + +// 用于描述单个 querytarget 结果的结构体 +type TargetQueryingInfo struct { + Dimension byte + Position [3]float32 + UniqueId string + YRot float32 +} + +// 解析 querytarget 命令的返回值为列表,因为同一时刻可以查询多个实体的相关数据。 +// 列表内单个数据的数据类型为 QuerytargetInfo 结构体 +func (g *GameInterface) ParseTargetQueryingInfo(pk packet.CommandOutput) ([]TargetQueryingInfo, error) { + res := []TargetQueryingInfo{} + // 初始化 + if pk.SuccessCount <= 0 || len(pk.OutputMessages[0].Parameters) <= 0 { + return []TargetQueryingInfo{}, nil + } + // 如果命令失败或者未能找到任何可以解析的信息 + datas := pk.OutputMessages[0].Parameters[0] + var datasDecodeAns []interface{} + err := json.Unmarshal([]byte(datas), &datasDecodeAns) + if err != nil { + return []TargetQueryingInfo{}, fmt.Errorf("ParseTargetQueryingInfo: %v", err) + } + // 解析 JSON 数据 + for _, value := range datasDecodeAns { + newStruct := TargetQueryingInfo{} + // 初始化 + val, normal := value.(map[string]interface{}) + if !normal { + return []TargetQueryingInfo{}, fmt.Errorf("ParseTargetQueryingInfo: Could not convert value into map[string]interface{}; value = %#v", value) + } + // 将列表中的被遍历元素解析为 map[string]interface{} + _, ok := val["dimension"] + if !ok { + return []TargetQueryingInfo{}, fmt.Errorf("ParseTargetQueryingInfo: Crashed in val[\"dimension\"]; val = %#v", val) + } + dimension, normal := val["dimension"].(float64) + if !normal { + return []TargetQueryingInfo{}, fmt.Errorf("ParseTargetQueryingInfo: Crashed in val[\"dimension\"]; val = %#v", val) + } + newStruct.Dimension = byte(dimension) + // dimension + _, ok = val["position"] + if !ok { + return []TargetQueryingInfo{}, fmt.Errorf("ParseTargetQueryingInfo: Crashed in val[\"position\"]; val = %#v", val) + } + position, normal := val["position"].(map[string]interface{}) + if normal { + _, ok := position["x"] + if !ok { + return []TargetQueryingInfo{}, fmt.Errorf("ParseTargetQueryingInfo: Crashed in val[\"position\"][\"x\"]; val[\"position\"] = %#v", position) + } + x, normal := position["x"].(float64) + if !normal { + return []TargetQueryingInfo{}, fmt.Errorf("ParseTargetQueryingInfo: Crashed in val[\"position\"][\"x\"]; val[\"position\"] = %#v", position) + } + newStruct.Position = [3]float32{float32(x), 0, 0} + // posx + _, ok = position["y"] + if !ok { + return []TargetQueryingInfo{}, fmt.Errorf("ParseTargetQueryingInfo: Crashed in val[\"position\"][\"y\"]; val[\"position\"] = %#v", position) + } + y, normal := position["y"].(float64) + if !normal { + return []TargetQueryingInfo{}, fmt.Errorf("ParseTargetQueryingInfo: Crashed in val[\"position\"][\"y\"]; val[\"position\"] = %#v", position) + } + newStruct.Position[1] = float32(y) + // posy + _, ok = position["z"] + if !ok { + return []TargetQueryingInfo{}, fmt.Errorf("ParseTargetQueryingInfo: Crashed in val[\"position\"][\"z\"]; val[\"position\"] = %#v", position) + } + z, normal := position["z"].(float64) + if !normal { + return []TargetQueryingInfo{}, fmt.Errorf("ParseTargetQueryingInfo: Crashed in val[\"position\"][\"z\"]; val[\"position\"] = %#v", position) + } + newStruct.Position[2] = float32(z) + // posz + } else { + return []TargetQueryingInfo{}, fmt.Errorf("ParseTargetQueryingInfo: Crashed in val[\"position\"]; val = %#v", val) + } + // position + _, ok = val["uniqueId"] + if !ok { + return []TargetQueryingInfo{}, fmt.Errorf("ParseTargetQueryingInfo: Crashed in val[\"uniqueId\"]; val = %#v", val) + } + uniqueId, normal := val["uniqueId"].(string) + if !normal { + return []TargetQueryingInfo{}, fmt.Errorf("ParseTargetQueryingInfo: Crashed in val[\"uniqueId\"]; val = %#v", val) + } + newStruct.UniqueId = uniqueId + // uniqueId + _, ok = val["yRot"] + if !ok { + return []TargetQueryingInfo{}, fmt.Errorf("ParseTargetQueryingInfo: Crashed in val[\"yRot\"]; val = %#v", val) + } + yRot, normal := val["yRot"].(float64) + if !normal { + return []TargetQueryingInfo{}, fmt.Errorf("ParseTargetQueryingInfo: Crashed in val[\"yRot\"]; val = %#v", val) + } + newStruct.YRot = float32(yRot) + // yRot + res = append(res, newStruct) + // append struct + } + return res, nil + // 返回值 +} diff --git a/GameControl/GlobalAPI/setblock.go b/game_control/game_interface/setblock.go similarity index 78% rename from GameControl/GlobalAPI/setblock.go rename to game_control/game_interface/setblock.go index 449242fd6..242a1f8be 100644 --- a/GameControl/GlobalAPI/setblock.go +++ b/game_control/game_interface/setblock.go @@ -1,4 +1,4 @@ -package GlobalAPI +package GameInterface import ( "fmt" @@ -7,7 +7,7 @@ import ( ) // 在 pos 处以 setblock 命令放置名为 name 且方块状态为 states 的方块。只有请求被返回时此函数再返回值 -func (g *GlobalAPI) SetBlock(pos [3]int32, name string, states string) error { +func (g *GameInterface) SetBlock(pos [3]int32, name string, states string) error { request := commands_generator.SetBlockRequest(&types.Module{ Block: &types.Block{ Name: &name, @@ -19,7 +19,7 @@ func (g *GlobalAPI) SetBlock(pos [3]int32, name string, states string) error { Z: int(pos[2]), }, }, &types.MainConfig{}) - _, err := g.SendWSCommandWithResponce(request) + _, err := g.SendWSCommandWithResponse(request) if err != nil { return fmt.Errorf("SetBlock: %v", err) } @@ -28,7 +28,7 @@ func (g *GlobalAPI) SetBlock(pos [3]int32, name string, states string) error { // 在 pos 处以 setblock 命令放置名为 name 且方块状态为 states 的方块。 // 特别地,此方法使用 settings command 来发送命令,因此该函数在被调用后不会等待返回值 -func (g *GlobalAPI) SetBlockFastly(pos [3]int32, name string, states string) error { +func (g *GameInterface) SetBlockAsync(pos [3]int32, name string, states string) error { request := commands_generator.SetBlockRequest(&types.Module{ Block: &types.Block{ Name: &name, @@ -42,7 +42,7 @@ func (g *GlobalAPI) SetBlockFastly(pos [3]int32, name string, states string) err }, &types.MainConfig{}) err := g.SendSettingsCommand(request, true) if err != nil { - return fmt.Errorf("SetBlockFastly: %v", err) + return fmt.Errorf("SetBlockForgetfully: %v", err) } return nil } diff --git a/GameControl/GlobalAPI/backupStructure.go b/game_control/game_interface/structure_backup.go similarity index 78% rename from GameControl/GlobalAPI/backupStructure.go rename to game_control/game_interface/structure_backup.go index 172218d7f..e191baa22 100644 --- a/GameControl/GlobalAPI/backupStructure.go +++ b/game_control/game_interface/structure_backup.go @@ -1,4 +1,6 @@ -package GlobalAPI +package GameInterface + +// TODO: 在某天支持 结构空位 的备份和恢复 import ( "fmt" @@ -15,13 +17,13 @@ type BlockPos mcstructure.BlockPos // 备份 structure 所指代的区域为结构。 // 返回一个 uuid.UUID 对象,其字符串形式代表被备份结构的名称 -func (g *GlobalAPI) BackupStructure(structure MCStructure) (uuid.UUID, error) { +func (g *GameInterface) BackupStructure(structure MCStructure) (uuid.UUID, error) { uniqueId := generateUUID() // get new uuid - resp, err := g.SendWSCommandWithResponce( + resp, err := g.SendWSCommandWithResponse( fmt.Sprintf( - `structure save "%v" %d %d %d %d %d %d`, - uuid_to_safety_string(uniqueId), + `structure save "%s" %d %d %d %d %d %d`, + uuid_to_safe_string(uniqueId), structure.BeginX, structure.BeginY, structure.BeginZ, @@ -43,11 +45,11 @@ func (g *GlobalAPI) BackupStructure(structure MCStructure) (uuid.UUID, error) { } // 在 pos 处恢复名称为 unique.String() 的备份用结构并删除此结构 -func (g *GlobalAPI) RevertStructure(uniqueID uuid.UUID, pos BlockPos) error { - resp, err := g.SendWSCommandWithResponce( +func (g *GameInterface) RevertStructure(uniqueID uuid.UUID, pos BlockPos) error { + resp, err := g.SendWSCommandWithResponse( fmt.Sprintf( `structure load "%v" %d %d %d`, - uuid_to_safety_string(uniqueID), + uuid_to_safe_string(uniqueID), pos[0], pos[1], pos[2], @@ -63,7 +65,7 @@ func (g *GlobalAPI) RevertStructure(uniqueID uuid.UUID, pos BlockPos) error { err = g.SendSettingsCommand( fmt.Sprintf( `structure delete "%v"`, - uuid_to_safety_string(uniqueID), + uuid_to_safe_string(uniqueID), ), false, ) diff --git a/GameControl/GlobalAPI/requestStructure.go b/game_control/game_interface/structure_requesting.go similarity index 71% rename from GameControl/GlobalAPI/requestStructure.go rename to game_control/game_interface/structure_requesting.go index 1454316c8..3a45013e8 100644 --- a/GameControl/GlobalAPI/requestStructure.go +++ b/game_control/game_interface/structure_requesting.go @@ -1,4 +1,4 @@ -package GlobalAPI +package GameInterface import ( "fmt" @@ -8,17 +8,17 @@ import ( // 请求 request 代表的结构请求并获取与之对应的响应体。 // 当且仅当租赁服响应结构请求时本函数才会返回值。 // -// 请确保在使用此函数前占用了结构资源,否则这将导致程序惊慌 -func (g *GlobalAPI) SendStructureRequestWithResponce( +// 请确保在使用此函数前占用了结构资源,否则这将导致程序 panic +func (g *GameInterface) SendStructureRequestWithResponse( request *packet.StructureTemplateDataRequest, ) (packet.StructureTemplateDataResponse, error) { g.Resources.Structure.WriteRequest() // prepare err := g.WritePacket(request) if err != nil { - return packet.StructureTemplateDataResponse{}, fmt.Errorf("SendStructureRequestWithResponce: %v", err) + return packet.StructureTemplateDataResponse{}, fmt.Errorf("SendStructureRequestWithResponse: %v", err) } // send packet - return g.Resources.Structure.LoadResponce(), nil - // load responce and return + return g.Resources.Structure.LoadResponse(), nil + // load response and return } diff --git a/game_control/game_interface/tick_sync_requesting.go b/game_control/game_interface/tick_sync_requesting.go new file mode 100644 index 000000000..521d23d26 --- /dev/null +++ b/game_control/game_interface/tick_sync_requesting.go @@ -0,0 +1,33 @@ +package GameInterface + +import ( + "fmt" + "phoenixbuilder/minecraft/protocol/packet" +) + +// 用于获取当前的游戏刻。 +// 此操作不会被立即完成, +// 因为它需要请求一个数据包 +func (g *GameInterface) GetCurrentTick() (int64, error) { + uniqueId := generateUUID() + // get a new uuid + err := g.Resources.Others.WriteCurrentTickRequest(uniqueId) + if err != nil { + return 0, fmt.Errorf("GetCurrentTick: %v", err) + } + // write request + err = g.WritePacket(&packet.TickSync{ + ClientRequestTimestamp: 0, + ServerReceptionTimestamp: 0, + }) + if err != nil { + return 0, fmt.Errorf("GetCurrentTick: %v", err) + } + // send packet + ans, err := g.Resources.Others.Load_TickSync_Packet_Responce_and_Delete_Request(uniqueId) + if err != nil { + return 0, fmt.Errorf("GetCurrentTick: %v", err) + } + return ans, nil + // load responce and return +} diff --git a/GameControl/GlobalAPI/useItemOnBlocks.go b/game_control/game_interface/use_item_on_blocks.go similarity index 93% rename from GameControl/GlobalAPI/useItemOnBlocks.go rename to game_control/game_interface/use_item_on_blocks.go index 59d47b9f3..531b1cb20 100644 --- a/GameControl/GlobalAPI/useItemOnBlocks.go +++ b/game_control/game_interface/use_item_on_blocks.go @@ -1,4 +1,4 @@ -package GlobalAPI +package GameInterface import ( "fmt" @@ -22,7 +22,7 @@ type UseItemOnBlocks struct { 你亦可以对物品展示框使用这样的操作, 这会使得物品被放入或令展示框内的物品旋转 */ -func (g *GlobalAPI) ClickBlock(request UseItemOnBlocks) error { +func (g *GameInterface) ClickBlock(request UseItemOnBlocks) error { blockRuntimeID, err := blockStatesToNEMCRuntimeID( request.BlockName, request.BlockStates, @@ -55,7 +55,7 @@ func (g *GlobalAPI) ClickBlock(request UseItemOnBlocks) error { return fmt.Errorf("ClickBlock: %v", err) } err = g.WritePacket(&packet.PlayerAction{ - EntityRuntimeID: g.BotInfo.BotRunTimeID, + EntityRuntimeID: g.ClientInfo.EntityRuntimeID, ActionType: protocol.PlayerActionStartBuildingBlock, BlockPosition: request.BlockPos, }) @@ -74,7 +74,7 @@ request 指代实际被点击的方块,但这并不代表新方块被创建的 我们通过点击 request 处的方块,并指定点击的面为 blockFace , 然后租赁服根据这些信息,在另外相应的位置创建这些新的方块 */ -func (g *GlobalAPI) PlaceBlock( +func (g *GameInterface) PlaceBlock( request UseItemOnBlocks, blockFace int32, ) error { @@ -92,7 +92,7 @@ func (g *GlobalAPI) PlaceBlock( } // get datas of the target item stack err = g.WritePacket(&packet.PlayerAction{ - EntityRuntimeID: g.BotInfo.BotRunTimeID, + EntityRuntimeID: g.ClientInfo.EntityRuntimeID, ActionType: protocol.PlayerActionStartItemUseOn, BlockPosition: request.BlockPos, }) @@ -119,7 +119,7 @@ func (g *GlobalAPI) PlaceBlock( return fmt.Errorf("PlaceBlock: %v", err) } err = g.WritePacket(&packet.PlayerAction{ - EntityRuntimeID: g.BotInfo.BotRunTimeID, + EntityRuntimeID: g.ClientInfo.EntityRuntimeID, ActionType: protocol.PlayerActionStopItemUseOn, BlockPosition: request.BlockPos, }) diff --git a/GameControl/GlobalAPI/utils.go b/game_control/game_interface/utils.go similarity index 94% rename from GameControl/GlobalAPI/utils.go rename to game_control/game_interface/utils.go index 9879fd915..2f2007f4c 100644 --- a/GameControl/GlobalAPI/utils.go +++ b/game_control/game_interface/utils.go @@ -1,4 +1,4 @@ -package GlobalAPI +package GameInterface import ( "fmt" @@ -21,7 +21,7 @@ func generateUUID() uuid.UUID { // 返回 uniqueID 在字符串化之后的安全形式, // 因为我们得考虑 NEMC 的屏蔽词机制 -func uuid_to_safety_string(uniqueID uuid.UUID) string { +func uuid_to_safe_string(uniqueID uuid.UUID) string { str := uniqueID.String() for key, value := range StringUUIDReplaceMap { str = strings.ReplaceAll(str, key, value) diff --git a/GameControl/ResourcesControlCenter/ItemStackOperation.go b/game_control/resources_control/Item_stack_operation.go similarity index 78% rename from GameControl/ResourcesControlCenter/ItemStackOperation.go rename to game_control/resources_control/Item_stack_operation.go index aeefbadfe..57aba4dde 100644 --- a/GameControl/ResourcesControlCenter/ItemStackOperation.go +++ b/game_control/resources_control/Item_stack_operation.go @@ -1,4 +1,4 @@ -package ResourcesControlCenter +package ResourcesControl import ( "fmt" @@ -8,18 +8,18 @@ import ( // 提交物品请求 ID 为 key 的物品操作。 // howToChange 指代相应槽位的变动结果,这用于更新本地库存数据 -func (i *itemStackReuqestWithResponce) WriteRequest( +func (i *itemStackRequestWithResponse) WriteRequest( key int32, howToChange map[ContainerID]StackRequestContainerInfo, ) error { - _, exist := i.requestWithResponce.Load(key) + _, exist := i.requestWithResponse.Load(key) if exist { return fmt.Errorf("WriteRequest: %v has already existed", key) } // if key has already exist - i.requestWithResponce.Store( + i.requestWithResponse.Store( key, - singleItemStackRequestWithResponce{ + singleItemStackRequestWithResponse{ resp: make(chan protocol.ItemStackResponse, 1), howToChange: howToChange, }, @@ -30,59 +30,59 @@ func (i *itemStackReuqestWithResponce) WriteRequest( } // 向请求 ID 为 key 的物品操作写入返回值 resp 。 -// 当 key 不存在时,将会抛出程序惊慌。 +// 当 key 不存在时,将会抛出程序 panic 。 // 属于私有实现。 -func (i *itemStackReuqestWithResponce) writeResponce( +func (i *itemStackRequestWithResponse) writeResponse( key int32, resp protocol.ItemStackResponse, ) { - value, exist := i.requestWithResponce.Load(key) + value, exist := i.requestWithResponse.Load(key) if !exist { - panic("writeResponce: Attempt to send packet.ItemStackRequest without using ResourcesControlCenter") + panic("writeResponse: Attempt to send packet.ItemStackRequest without using ResourcesControlCenter") } // if key is not exist - get, normal := value.(singleItemStackRequestWithResponce) + get, normal := value.(singleItemStackRequestWithResponse) if !normal { - panic(fmt.Sprintf("writeResponce: Failed to convert value into singleItemStackRequestWithResponce; value = %#v", value)) + panic(fmt.Sprintf("writeResponse: Failed to convert value into singleItemStackRequestWithResponse; value = %#v", value)) } // convert data get.resp <- resp - // send responce + // send response } // 读取请求 ID 为 key 的物品操作请求的返回值, // 同时移除此物品操作请求 -func (i *itemStackReuqestWithResponce) LoadResponceAndDelete(key int32) (protocol.ItemStackResponse, error) { - value, exist := i.requestWithResponce.Load(key) +func (i *itemStackRequestWithResponse) LoadResponseAndDelete(key int32) (protocol.ItemStackResponse, error) { + value, exist := i.requestWithResponse.Load(key) if !exist { - return protocol.ItemStackResponse{}, fmt.Errorf("LoadResponceAndDelete: %v is not recorded", key) + return protocol.ItemStackResponse{}, fmt.Errorf("LoadResponseAndDelete: %v is not recorded", key) } // if key is not exist - get, normal := value.(singleItemStackRequestWithResponce) + get, normal := value.(singleItemStackRequestWithResponse) if !normal { - return protocol.ItemStackResponse{}, fmt.Errorf("tryToWriteResponce: Failed to convert value into singleItemStackRequestWithResponce; value = %#v", value) + return protocol.ItemStackResponse{}, fmt.Errorf("tryToWriteResponse: Failed to convert value into singleItemStackRequestWithResponse; value = %#v", value) } // convert data - ans := <-get.resp - i.requestWithResponce.Delete(key) - return ans, nil + ret := <-get.resp + i.requestWithResponse.Delete(key) + return ret, nil // return } // 以原子操作获取上一次的请求 ID ,即 RequestID 。 // 如果从未进行过物品操作,则将会返回 1 -func (i *itemStackReuqestWithResponce) GetCurrentRequestID() int32 { +func (i *itemStackRequestWithResponse) GetCurrentRequestID() int32 { return atomic.LoadInt32(&i.currentRequestID) } // 以原子操作获取一个新的请求 ID ,即 RequestID -func (i *itemStackReuqestWithResponce) GetNewRequestID() int32 { +func (i *itemStackRequestWithResponse) GetNewRequestID() int32 { return atomic.AddInt32(&i.currentRequestID, -2) } // 利用 newItemName 更新 item 中存储的物品名称信息。 // 如果传入的 newItemName 为空字符串,则将会从 item 中移除物品名称信息 -func (i *itemStackReuqestWithResponce) SetItemName( +func (i *itemStackRequestWithResponse) SetItemName( item *protocol.ItemInstance, newItemName string, ) error { @@ -149,7 +149,7 @@ func (i *itemStackReuqestWithResponce) SetItemName( // 根据 newItem 中预期的新数据和租赁服返回的 resp , // 返回完整的新物品数据。 -func (i *itemStackReuqestWithResponce) GetNewItemData( +func (i *itemStackRequestWithResponse) GetNewItemData( newItem protocol.ItemInstance, resp protocol.StackResponseSlotInfo, ) (protocol.ItemInstance, error) { @@ -175,18 +175,18 @@ inventory 必须是一个指针,它指向了客户端库存数据在内存中 来加载原有的请求数据,并访问其中描述的物品变动的预期结果, 然后依此字段和 resp 字段更新本地库存数据。 */ -func (i *itemStackReuqestWithResponce) updateItemData( +func (i *itemStackRequestWithResponse) updateItemData( resp protocol.ItemStackResponse, inventory *inventoryContents, ) error { - value, exist := i.requestWithResponce.Load(resp.RequestID) + value, exist := i.requestWithResponse.Load(resp.RequestID) if !exist { panic("updateItemData: Attempt to send packet.ItemStackRequest without using ResourcesControlCenter") } // if key is not exist - get, normal := value.(singleItemStackRequestWithResponce) + get, normal := value.(singleItemStackRequestWithResponse) if !normal { - panic(fmt.Sprintf("updateItemData: Failed to convert value into singleItemStackRequestWithResponce; value = %#v", value)) + panic(fmt.Sprintf("updateItemData: Failed to convert value into singleItemStackRequestWithResponse; value = %#v", value)) } // convert data for _, val := range resp.ContainerInfo { diff --git a/GameControl/ResourcesControlCenter/Command.go b/game_control/resources_control/command.go similarity index 62% rename from GameControl/ResourcesControlCenter/Command.go rename to game_control/resources_control/command.go index 05ec4bcf4..d2537bb24 100644 --- a/GameControl/ResourcesControlCenter/Command.go +++ b/game_control/resources_control/command.go @@ -1,4 +1,4 @@ -package ResourcesControlCenter +package ResourcesControl import ( "fmt" @@ -8,13 +8,13 @@ import ( ) // 提交请求 ID 为 key 的命令请求 -func (c *commandRequestWithResponce) WriteRequest(key uuid.UUID) error { - _, exist := c.requestWithResponce.Load(key) +func (c *commandRequestWithResponse) WriteRequest(key uuid.UUID) error { + _, exist := c.requestWithResponse.Load(key) if exist { return fmt.Errorf("WriteRequest: %v has already existed", key.String()) } // if key has already exist - c.requestWithResponce.Store(key, make(chan packet.CommandOutput, 1)) + c.requestWithResponse.Store(key, make(chan packet.CommandOutput, 1)) return nil // return } @@ -22,18 +22,18 @@ func (c *commandRequestWithResponce) WriteRequest(key uuid.UUID) error { // 尝试向请求 ID 为 key 的命令请求写入返回值 resp 。 // 属于私有实现。 // 如果 key 不存在,亦不会返回错误。 -func (c *commandRequestWithResponce) tryToWriteResponce( +func (c *commandRequestWithResponse) tryToWriteResponse( key uuid.UUID, resp packet.CommandOutput, ) error { - value, exist := c.requestWithResponce.Load(key) + value, exist := c.requestWithResponse.Load(key) if !exist { return nil } // if key is not exist chanGet, normal := value.(chan packet.CommandOutput) if !normal { - return fmt.Errorf("tryToWriteResponce: Failed to convert value into (chan packet.CommandOutput); value = %#v", value) + return fmt.Errorf("tryToWriteResponse: Failed to convert value into (chan packet.CommandOutput); value = %#v", value) } // convert data chanGet <- resp @@ -44,19 +44,19 @@ func (c *commandRequestWithResponce) tryToWriteResponce( // 读取请求 ID 为 key 的命令请求的返回值, // 同时移除此命令请求 -func (c *commandRequestWithResponce) LoadResponceAndDelete(key uuid.UUID) (packet.CommandOutput, error) { - value, exist := c.requestWithResponce.Load(key) +func (c *commandRequestWithResponse) LoadResponseAndDelete(key uuid.UUID) (packet.CommandOutput, error) { + value, exist := c.requestWithResponse.Load(key) if !exist { - return packet.CommandOutput{}, fmt.Errorf("LoadResponceAndDelete: %v is not recorded", key.String()) + return packet.CommandOutput{}, fmt.Errorf("LoadResponseAndDelete: %v is not recorded", key.String()) } // if key is not exist chanGet, normal := value.(chan packet.CommandOutput) if !normal { - return packet.CommandOutput{}, fmt.Errorf("LoadResponceAndDelete: Failed to convert value into (chan packet.CommandOutput); value = %#v", value) + return packet.CommandOutput{}, fmt.Errorf("LoadResponseAndDelete: Failed to convert value into (chan packet.CommandOutput); value = %#v", value) } // convert data - ans := <-chanGet - c.requestWithResponce.Delete(key) - return ans, nil + res := <-chanGet + c.requestWithResponse.Delete(key) + return res, nil // return } diff --git a/GameControl/ResourcesControlCenter/Container.go b/game_control/resources_control/container.go similarity index 73% rename from GameControl/ResourcesControlCenter/Container.go rename to game_control/resources_control/container.go index 791e39507..409184f15 100644 --- a/GameControl/ResourcesControlCenter/Container.go +++ b/game_control/resources_control/container.go @@ -1,4 +1,4 @@ -package ResourcesControlCenter +package ResourcesControl import ( "phoenixbuilder/minecraft/protocol/packet" @@ -9,7 +9,7 @@ import ( // 达到等待租赁服响应容器操作的目的。 // // 无论如何,即便不需要得到响应,也仍然需要使用此函数。 -func (c *container) AwaitChangesBeforeSendPacket() { +func (c *container) AwaitChangesBeforeSendingPacket() { c.responded = make(chan struct{}, 1) } @@ -18,7 +18,7 @@ func (c *container) AwaitChangesBeforeSendPacket() { // 在调用此函数后,会持续阻塞直到相关的管道受到数据。 // // 无论如何,即便不需要得到响应,也仍然需要使用此函数。 -func (c *container) AwaitChangesAfterSendPacket() { +func (c *container) AwaitChangesAfterSendingPacket() { <-c.responded } @@ -26,7 +26,7 @@ func (c *container) AwaitChangesAfterSendPacket() { // 如果容器资源未被占用,则通知不会被发送。 // 当且仅当租赁服确认客户端的容器操作时,此函数才会被调用。 // 属于私有实现 -func (c *container) responceContainerOperation() { +func (c *container) respondToContainerOperation() { if c.GetOccupyStates() { c.responded <- struct{}{} close(c.responded) @@ -34,46 +34,46 @@ func (c *container) responceContainerOperation() { } // 向 c.containerOpenData 写入容器开启数据 data ,属于私有实现 -func (c *container) writeContainerOpenDatas(data *packet.ContainerOpen) { +func (c *container) writeContainerOpeningData(data *packet.ContainerOpen) { c.lockDown.Lock() defer c.lockDown.Unlock() - c.containerOpenData = data + c.containerOpeningData = data } // 取得当前已打开容器的数据。 // 如果容器未被打开或已被关闭,则会返回 nil 。 // 返回值虽然是一个地址,但它所指向的实际是一个副本 -func (c *container) GetContainerOpenDatas() *packet.ContainerOpen { +func (c *container) GetContainerOpeningData() *packet.ContainerOpen { c.lockDown.RLock() defer c.lockDown.RUnlock() // lock down - if c.containerOpenData == nil { + if c.containerOpeningData == nil { return nil } else { - new := *c.containerOpenData + new := *c.containerOpeningData return &new } // return } // 向 c.containerCloseData 写入容器关闭数据 data ,属于私有实现 -func (c *container) writeContainerCloseDatas(data *packet.ContainerClose) { +func (c *container) writeContainerClosingData(data *packet.ContainerClose) { c.lockDown.Lock() defer c.lockDown.Unlock() - c.containerCloseData = data + c.containerClosingData = data } // 取得上次关闭容器时租赁服的响应数据。 // 如果现在有容器已被打开或容器从未被关闭,则会返回 nil 。 // 返回值虽然是一个地址,但它所指向的实际是一个副本 -func (c *container) GetContainerCloseDatas() *packet.ContainerClose { +func (c *container) GetContainerClosingData() *packet.ContainerClose { c.lockDown.RLock() defer c.lockDown.RUnlock() // lock down - if c.containerCloseData == nil { + if c.containerClosingData == nil { return nil } else { - new := *c.containerCloseData + new := *c.containerClosingData return &new } // return diff --git a/GameControl/ResourcesControlCenter/Inventory.go b/game_control/resources_control/inventory.go similarity index 95% rename from GameControl/ResourcesControlCenter/Inventory.go rename to game_control/resources_control/inventory.go index 69575ac16..75e31944a 100644 --- a/GameControl/ResourcesControlCenter/Inventory.go +++ b/game_control/resources_control/inventory.go @@ -1,4 +1,4 @@ -package ResourcesControlCenter +package ResourcesControl import ( "fmt" @@ -59,11 +59,11 @@ func (i *inventoryContents) ListSlot( // get slots list sort.Stable(sort.IntSlice(tmp)) // sort - ans := []byte{} + res := []byte{} for _, value := range tmp { - ans = append(ans, byte(value)) + res = append(res, byte(value)) } - return ans, nil + return res, nil // return } @@ -72,12 +72,12 @@ func (i *inventoryContents) GetInventoryInfo(windowID uint32) (map[uint8]protoco i.lockDown.RLock() defer i.lockDown.RUnlock() // init - ans, ok := i.datas[windowID] + res, ok := i.datas[windowID] if !ok { return map[uint8]protocol.ItemInstance{}, fmt.Errorf("GetInventoryInfo: %v is not recorded in i.datas; i.datas = %#v", windowID, i.datas) } // if windowsID is not exist - return ans, nil + return res, nil // return } @@ -91,12 +91,12 @@ func (i *inventoryContents) GetItemStackInfo(windowID uint32, slotLocation uint8 return protocol.ItemInstance{}, fmt.Errorf("GetItemStackInfo: %v is not recorded in i.datas; i.datas = %#v", windowID, i.datas) } // if windowsID is not exist - ans, ok := got[slotLocation] + ret, ok := got[slotLocation] if !ok { return protocol.ItemInstance{}, fmt.Errorf("GetItemStackInfo: %v is not recorded in i.datas[%v]; i.datas[%v] = %#v", slotLocation, windowID, windowID, i.datas[windowID]) } // if slot is not exist - return ans, nil + return ret, nil // return } diff --git a/game_control/resources_control/others.go b/game_control/resources_control/others.go new file mode 100644 index 000000000..7f600013c --- /dev/null +++ b/game_control/resources_control/others.go @@ -0,0 +1,67 @@ +package ResourcesControl + +import ( + "fmt" + "phoenixbuilder/minecraft/protocol/packet" + + "github.com/google/uuid" +) + +// ------------------------- currentTick ------------------------- + +// 提交请求 ID 为 key 的请求用于获取当前的游戏刻 +func (o *others) WriteCurrentTickRequest(key uuid.UUID) error { + _, exist := o.currentTickRequestWithResp.Load(key) + if exist { + return fmt.Errorf("WriteCurrentTickRequest: %v has already existed", key.String()) + } + // if key has already exist + o.currentTickRequestWithResp.Store(key, make(chan int64, 1)) + return nil + // return +} + +// 根据租赁服返回的 packet.TickSync(resp) 包, +// 向所有请求过 获取当前游戏刻 的请求写入此响应体的 +// ServerReceptionTimestamp 字段 +func (o *others) writeTickSyncPacketResponse(resp packet.TickSync) error { + var err error = nil + o.currentTickRequestWithResp.Range(func(key, value any) bool { + chanGet, normal := value.(chan int64) + if !normal { + err = fmt.Errorf("writeTickSyncPacketResponse: Failed to convert value into (chan int64); key(RequestID) = %#v, value = %#v", key, value) + return false + } + // convert data + chanGet <- resp.ServerReceptionTimestamp + close(chanGet) + return true + // return + }) + // write responce for all the request + return err + // return +} + +// 读取请求 ID 为 key 的 获取当前游戏刻 的请求所对应返回值, +// 同时移除该请求 +func (o *others) Load_TickSync_Packet_Responce_and_Delete_Request( + key uuid.UUID, +) (int64, error) { + value, exist := o.currentTickRequestWithResp.Load(key) + if !exist { + return 0, fmt.Errorf("Load_TickSync_Packet_Responce_and_Delete_Request: %v is not recorded", key.String()) + } + // if key is not exist + chanGet, normal := value.(chan int64) + if !normal { + return 0, fmt.Errorf("Load_TickSync_Packet_Responce_and_Delete_Request: Failed to convert value into (chan int64); value = %#v", value) + } + // convert data + res := <-chanGet + o.currentTickRequestWithResp.Delete(key) + return res, nil + // return +} + +// ------------------------- END ------------------------- diff --git a/GameControl/ResourcesControlCenter/packetHandler.go b/game_control/resources_control/packet_handler.go similarity index 73% rename from GameControl/ResourcesControlCenter/packetHandler.go rename to game_control/resources_control/packet_handler.go index cd6dcccf0..bfd9648e1 100644 --- a/GameControl/ResourcesControlCenter/packetHandler.go +++ b/game_control/resources_control/packet_handler.go @@ -1,4 +1,4 @@ -package ResourcesControlCenter +package ResourcesControl import ( "fmt" @@ -11,19 +11,22 @@ import ( // 根据收到的数据包更新客户端的资源数据 func (r *Resources) handlePacket(pk *packet.Packet) { switch p := (*pk).(type) { + case *packet.TickSync: + r.Others.writeTickSyncPacketResponse(*p) + // sync game tick case *packet.CommandOutput: - err := r.Command.tryToWriteResponce(p.CommandOrigin.UUID, *p) + err := r.Command.tryToWriteResponse(p.CommandOrigin.UUID, *p) if err != nil { pterm.Error.Printf("handlePacket: %v\n", err) } - // send ws command with responce + // send ws command with response case *packet.InventoryContent: for key, value := range p.Content { if value.Stack.ItemType.NetworkID != -1 { r.Inventory.writeItemStackInfo(p.WindowID, uint8(key), value) } } - // inventory contents(global) + // inventory contents(basic) case *packet.InventoryTransaction: for _, value := range p.Actions { if value.SourceType == protocol.InventoryActionSourceCreative { @@ -40,20 +43,20 @@ func (r *Resources) handlePacket(pk *packet.Packet) { if value.Status == protocol.ItemStackResponseStatusOK { r.ItemStackOperation.updateItemData(value, &r.Inventory) } - // update local inventory datas - r.ItemStackOperation.writeResponce(value.RequestID, value) - // write responce + // update local inventory data + r.ItemStackOperation.writeResponse(value.RequestID, value) + // write response } // item stack request case *packet.ContainerOpen: if !r.Container.GetOccupyStates() { panic("handlePacket: Attempt to send packet.ContainerOpen without using ResourcesControlCenter") } - r.Container.writeContainerCloseDatas(nil) - r.Container.writeContainerOpenDatas(p) + r.Container.writeContainerClosingData(nil) + r.Container.writeContainerOpeningData(p) r.Inventory.createNewInventory(uint32(p.WindowID)) - r.Container.responceContainerOperation() - // while open a container + r.Container.respondToContainerOperation() + // when a container is opened case *packet.ContainerClose: if p.WindowID != 0 && p.WindowID != 119 && p.WindowID != 120 && p.WindowID != 124 { err := r.Inventory.deleteInventory(uint32(p.WindowID)) @@ -64,15 +67,15 @@ func (r *Resources) handlePacket(pk *packet.Packet) { if !p.ServerSide && !r.Container.GetOccupyStates() { panic("handlePacket: Attempt to send packet.ContainerClose without using ResourcesControlCenter") } - r.Container.writeContainerOpenDatas(nil) - r.Container.writeContainerCloseDatas(p) - r.Container.responceContainerOperation() - // while a container is closed + r.Container.writeContainerOpeningData(nil) + r.Container.writeContainerClosingData(p) + r.Container.respondToContainerOperation() + // when a container has been closed case *packet.StructureTemplateDataResponse: if !r.Structure.GetOccupyStates() { panic("handlePacket: Attempt to send packet.StructureTemplateDataRequest without using ResourcesControlCenter") } - r.Structure.writeResponce(*p) - // packet.StructureTemplateDataRequest + r.Structure.writeResponse(*p) + // used to request mcstructure data } } diff --git a/GameControl/ResourcesControlCenter/define.go b/game_control/resources_control/resouces_control.go similarity index 82% rename from GameControl/ResourcesControlCenter/define.go rename to game_control/resources_control/resouces_control.go index 4221ef63a..d393402b5 100644 --- a/GameControl/ResourcesControlCenter/define.go +++ b/game_control/resources_control/resouces_control.go @@ -1,4 +1,4 @@ -package ResourcesControlCenter +package ResourcesControl import ( "phoenixbuilder/minecraft/protocol" @@ -11,24 +11,27 @@ import ( // 管理和保存 PhoenixBuilder 的各类公用资源 type Resources struct { // 管理命令请求队列及命令返回值 - Command commandRequestWithResponce + Command commandRequestWithResponse // 管理本地库存数据,如背包物品 Inventory inventoryContents // 管理物品操作请求及结果 - ItemStackOperation itemStackReuqestWithResponce + ItemStackOperation itemStackRequestWithResponse // 管理容器资源的占用状态,同时存储容器操作的结果 Container container // 管理结构资源并保存结构请求的回应 Structure mcstructure + // 管理和保存其他小型的资源, + // 例如例如游戏刻相关 + Others others } // ------------------------- commandRequestWithResponce ------------------------- // 存放命令请求及结果 -type commandRequestWithResponce struct { +type commandRequestWithResponse struct { // 存放命令请求及返回值队列。 // 数据类型为 map[uuid.UUID](chan packet.CommandOutput) - requestWithResponce sync.Map + requestWithResponse sync.Map } // ------------------------- inventoryContents ------------------------- @@ -43,19 +46,19 @@ type inventoryContents struct { datas map[uint32]map[uint8]protocol.ItemInstance } -// ------------------------- itemStackReuqestWithResponce ------------------------- +// ------------------------- itemStackReuqestWithResponse ------------------------- /* 存放物品操作请求及结果。 !!! 重要 !!! 任何物品操作都应该通过此结构体下的有关实现来完成,否则可能会造成严重后果。 -因此,为了绝对的安全,如果尝试绕过相关实现而直接发送物品操作数据包,则会造成程序惊慌。 +因此,为了绝对的安全,如果尝试绕过相关实现而直接发送物品操作数据包,则会造成程序 panic */ -type itemStackReuqestWithResponce struct { +type itemStackRequestWithResponse struct { // 存放物品操作的请求队列。 - // 数据类型为 map[int32]singleItemStackRequestWithResponce - requestWithResponce sync.Map + // 数据类型为 map[int32]singleItemStackRequestWithResponse + requestWithResponse sync.Map /* 记录已累计的 RequestID 。 @@ -69,13 +72,13 @@ type itemStackReuqestWithResponce struct { 尽管始终为 ItemStackRequest 的 RequestID 字段填写 -1 并不会造成造成断开连接的发生, 但这样并不能保证物品操作的唯一性。 - 因此,绝对地,请使用已提供的 API 发送物品操作请求,否则将导致程序惊慌 + 因此,绝对地,请使用已提供的 API 发送物品操作请求,否则将导致程序 panic */ currentRequestID int32 } // 每个物品操作请求都会使用这样一个结构体,它用于描述单个的物品操作请求 -type singleItemStackRequestWithResponce struct { +type singleItemStackRequestWithResponse struct { // 描述物品操作请求的返回值 resp chan protocol.ItemStackResponse // 描述多个库存(容器)中物品的变动结果。 @@ -106,7 +109,7 @@ type ContainerID uint8 容器由于是 PhoenixBuilder 的其中一个公用资源,因此为了公平性, 现在由我们(资源管理中心)负责完成对该公用资源的占用和释放之实现。 -因此,为了绝对的安全,如果尝试绕过相关实现而直接 打开/关闭 容器,则会造成程序惊慌。 +因此,为了绝对的安全,如果尝试绕过相关实现而直接 打开/关闭 容器,则会造成程序 panic 。 任何时刻,如果你需要打开或关闭容器,或者在某一段时间内使用某容器,则请提前占用此资源, 然后再发送相应数据包,完成后再释放此公用资源 @@ -117,7 +120,7 @@ type container struct { // 存放容器被打开时的数据。 // 当客户端打开容器后,租赁服会以此数据包回应,届时此变量将被赋值。 // 当容器被关闭或从未被打开,则此变量将会为 nil - containerOpenData *packet.ContainerOpen + containerOpeningData *packet.ContainerOpen /* 存放容器被关闭时的数据。 @@ -127,7 +130,7 @@ type container struct { 当侦测到来自租赁服的响应,此变量将被赋值。 当容器被打开或从未被关闭,则此变量将会为 nil */ - containerCloseData *packet.ContainerClose + containerClosingData *packet.ContainerClose // 其他实现在打开或关闭容器后可能需要等待回应,此管道便是为了完成这一实现 responded chan struct{} // 描述容器资源的占用状态及占用者 @@ -144,4 +147,14 @@ type mcstructure struct { resp chan packet.StructureTemplateDataResponse } +// ------------------------- others ------------------------- + +// 记录其他小型的资源,例如游戏刻相关 +type others struct { + // 存放 TickSync 请求并保存其对应的返回值, + // 它用于获取当前的游戏刻。 + // 数据类型为 map[uuid.UUID]chan int64 + currentTickRequestWithResp sync.Map +} + // ------------------------- END ------------------------- diff --git a/GameControl/ResourcesControlCenter/resourcesOccupy.go b/game_control/resources_control/resources_occupy.go similarity index 97% rename from GameControl/ResourcesControlCenter/resourcesOccupy.go rename to game_control/resources_control/resources_occupy.go index 6ad32d74c..a934a8925 100644 --- a/GameControl/ResourcesControlCenter/resourcesOccupy.go +++ b/game_control/resources_control/resources_occupy.go @@ -1,4 +1,4 @@ -package ResourcesControlCenter +package ResourcesControl import ( "sync" diff --git a/GameControl/ResourcesControlCenter/initStruct.go b/game_control/resources_control/struct_initialization.go similarity index 69% rename from GameControl/ResourcesControlCenter/initStruct.go rename to game_control/resources_control/struct_initialization.go index 33e3c048f..50e8dfde3 100644 --- a/GameControl/ResourcesControlCenter/initStruct.go +++ b/game_control/resources_control/struct_initialization.go @@ -1,4 +1,4 @@ -package ResourcesControlCenter +package ResourcesControl import ( "phoenixbuilder/minecraft/protocol" @@ -15,22 +15,22 @@ import ( */ func (r *Resources) Init() func(pk *packet.Packet) { *r = Resources{ - Command: commandRequestWithResponce{ - requestWithResponce: sync.Map{}, + Command: commandRequestWithResponse{ + requestWithResponse: sync.Map{}, }, Inventory: inventoryContents{ lockDown: sync.RWMutex{}, datas: make(map[uint32]map[uint8]protocol.ItemInstance), }, - ItemStackOperation: itemStackReuqestWithResponce{ - requestWithResponce: sync.Map{}, + ItemStackOperation: itemStackRequestWithResponse{ + requestWithResponse: sync.Map{}, currentRequestID: 1, }, Container: container{ - lockDown: sync.RWMutex{}, - containerOpenData: nil, - containerCloseData: nil, - responded: make(chan struct{}, 1), + lockDown: sync.RWMutex{}, + containerOpeningData: nil, + containerClosingData: nil, + responded: make(chan struct{}, 1), resourcesOccupy: resourcesOccupy{ lockDown: sync.Mutex{}, holder: "", @@ -43,6 +43,9 @@ func (r *Resources) Init() func(pk *packet.Packet) { }, resp: make(chan packet.StructureTemplateDataResponse, 1), }, + Others: others{ + currentTickRequestWithResp: sync.Map{}, + }, } // init struct return r.handlePacket diff --git a/GameControl/ResourcesControlCenter/Structure.go b/game_control/resources_control/structure.go similarity index 69% rename from GameControl/ResourcesControlCenter/Structure.go rename to game_control/resources_control/structure.go index c8e2c2ec2..d4097e3ad 100644 --- a/GameControl/ResourcesControlCenter/Structure.go +++ b/game_control/resources_control/structure.go @@ -1,4 +1,4 @@ -package ResourcesControlCenter +package ResourcesControl import "phoenixbuilder/minecraft/protocol/packet" @@ -9,12 +9,12 @@ func (m *mcstructure) WriteRequest() { // 向结构请求写入返回值 resp 。 // 属于私有实现。 -func (m *mcstructure) writeResponce(data packet.StructureTemplateDataResponse) { +func (m *mcstructure) writeResponse(data packet.StructureTemplateDataResponse) { m.resp <- data close(m.resp) } // 从管道读取结构请求的返回值 -func (m *mcstructure) LoadResponce() packet.StructureTemplateDataResponse { +func (m *mcstructure) LoadResponse() packet.StructureTemplateDataResponse { return <-m.resp } diff --git a/GameControl/ResourcesControlCenter/utils.go b/game_control/resources_control/utils.go similarity index 95% rename from GameControl/ResourcesControlCenter/utils.go rename to game_control/resources_control/utils.go index 4183d55f1..e7e40d02b 100644 --- a/GameControl/ResourcesControlCenter/utils.go +++ b/game_control/resources_control/utils.go @@ -1,4 +1,4 @@ -package ResourcesControlCenter +package ResourcesControl import ( "bytes" diff --git a/go.mod b/go.mod index 892ce662d..08cb8dc76 100644 --- a/go.mod +++ b/go.mod @@ -3,68 +3,63 @@ module phoenixbuilder go 1.18 require ( - github.com/df-mc/atomic v1.10.0 - golang.org/x/exp v0.0.0-20220713135740-79cabaa25d75 - gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b + github.com/cheggaaa/pb v1.0.29 + github.com/df-mc/goleveldb v1.1.9 + github.com/go-zeromq/zmq4 v0.15.0 + github.com/hashicorp/go-version v1.6.0 + github.com/mitchellh/mapstructure v1.5.0 + github.com/pebbe/zmq4 v1.2.10 + github.com/pierrec/lz4 v2.6.1+incompatible rogchap.com/v8go v0.7.0 ) require ( github.com/atomicgo/cursor v0.0.1 // indirect - github.com/cheggaaa/pb v1.0.29 // indirect - github.com/df-mc/goleveldb v1.1.9 // indirect + github.com/frankban/quicktest v1.14.5 // indirect + github.com/go-zeromq/goczmq/v4 v4.2.2 // indirect github.com/golang/snappy v0.0.1 // indirect github.com/gookit/color v1.4.2 // indirect - github.com/hashicorp/go-version v1.6.0 // indirect github.com/klauspost/cpuid v1.3.1 // indirect github.com/klauspost/reedsolomon v1.9.9 // indirect github.com/mattn/go-runewidth v0.0.13 // indirect - github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mmcloughlin/avo v0.0.0-20200803215136-443f81d77104 // indirect - github.com/pierrec/lz4 v2.6.1+incompatible // indirect github.com/pkg/errors v0.9.1 // indirect github.com/rivo/uniseg v0.2.0 // indirect - github.com/syndtr/goleveldb v1.0.0 // indirect github.com/templexxx/cpu v0.0.7 // indirect github.com/templexxx/xorsimd v0.4.1 // indirect github.com/tjfoc/gmsm v1.3.2 // indirect github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect - golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8 // indirect - golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect - golang.org/x/sys v0.0.0-20211019181941-9d821ace8654 // indirect - golang.org/x/tools v0.1.10 // indirect - golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect + golang.org/x/image v0.5.0 // indirect + golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect + golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect + golang.org/x/sys v0.5.0 // indirect + golang.org/x/tools v0.1.12 // indirect ) replace rogchap.com/v8go v0.7.0 => ./depends/v8go@v0.7.0 require ( - github.com/Shopify/go-lua v0.0.0-20221004153744-91867de107cf github.com/Tnze/go-mc v1.17.0 github.com/andybalholm/brotli v1.0.3 github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb - github.com/brentp/intintmap v0.0.0-20190211203843-30dc0ade9af9 - github.com/cespare/xxhash v1.1.0 github.com/disintegration/imaging v1.6.2 github.com/go-gl/mathgl v1.0.0 - github.com/google/go-cmp v0.5.8 // indirect + github.com/google/go-cmp v0.5.9 // indirect github.com/google/uuid v1.1.2 github.com/gorilla/websocket v1.4.2 github.com/klauspost/compress v1.13.6 github.com/lucasb-eyer/go-colorful v1.2.0 github.com/muhammadmuzzammil1998/jsonc v0.0.0-20211230184646-baf1f7156737 - github.com/pelletier/go-toml v1.9.4 github.com/pterm/pterm v0.12.29 github.com/sandertv/go-raknet v1.9.1 - github.com/sirupsen/logrus v1.8.1 github.com/xtaci/kcp-go/v5 v5.6.1 github.com/yuin/gopher-lua v1.1.0 go.kuoruan.net/v8go-polyfills v0.5.0 go.uber.org/atomic v1.9.0 - golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 // indirect - golang.org/x/net v0.0.0-20220107192237-5cfca573fb4d - golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b - golang.org/x/text v0.3.7 + golang.org/x/crypto v0.1.0 // indirect + golang.org/x/net v0.7.0 + golang.org/x/term v0.5.0 + golang.org/x/text v0.7.0 gopkg.in/square/go-jose.v2 v2.6.0 ) diff --git a/go.sum b/go.sum index 7696702be..eaae63038 100644 --- a/go.sum +++ b/go.sum @@ -1,45 +1,37 @@ github.com/MarvinJWendt/testza v0.1.0 h1:4m+JkB/4e0nUlXdIa10Mg0poUz9CanQKjB3L+xecjAo= github.com/MarvinJWendt/testza v0.1.0/go.mod h1:7AxNvlfeHP7Z/hDQ5JtE3OKYT3XFUeLCDE2DQninSqs= -github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/Shopify/go-lua v0.0.0-20221004153744-91867de107cf h1:VSUCKpFV0AfYGslgQSRdBI9HCVp1TCXJmScWD0VXL5g= -github.com/Shopify/go-lua v0.0.0-20221004153744-91867de107cf/go.mod h1:UCCi6u6YA8oXfJ15vEMiMGIaWWfLiOacinBPHxLXtEU= -github.com/Tnze/go-mc v1.17.0 h1:eux33waaSNAUJmnRjYjUmR3NgoHgQStFxHSBYg9I1WM= -github.com/Tnze/go-mc v1.17.0/go.mod h1:t0AI38F1BEmmy8/uLhr9RCOUeDbBj3oUNQH9akjzMc0= github.com/andybalholm/brotli v1.0.3 h1:fpcw+r1N1h0Poc1F/pHbW40cUm/lMEQslZtCkBQ0UnM= github.com/andybalholm/brotli v1.0.3/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/atomicgo/cursor v0.0.1 h1:xdogsqa6YYlLfM+GyClC/Lchf7aiMerFiZQn7soTOoU= github.com/atomicgo/cursor v0.0.1/go.mod h1:cBON2QmmrysudxNBFthvMtN32r3jxVRIvzkUiF/RuIk= github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb h1:m935MPodAbYS46DG4pJSv7WO+VECIWUQ7OJYSoTrMh4= github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb/go.mod h1:PkYb9DJNAwrSvRx5DYA+gUcOIgTGVMNkfSCbZM8cWpI= -github.com/brentp/intintmap v0.0.0-20190211203843-30dc0ade9af9 h1:/G0ghZwrhou0Wq21qc1vXXMm/t/aKWkALWwITptKbE0= -github.com/brentp/intintmap v0.0.0-20190211203843-30dc0ade9af9/go.mod h1:TOk10ahXejq9wkEaym3KPRNeuR/h5Jx+s8QRWIa2oTM= -github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cheggaaa/pb v1.0.29 h1:FckUN5ngEk2LpvuG0fw1GEFx6LtyY2pWI/Z2QgCnEYo= github.com/cheggaaa/pb v1.0.29/go.mod h1:W40334L7FMC5JKWldsTWbdGjLo0RxUKK73K+TuPxX30= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/df-mc/atomic v1.10.0 h1:0ZuxBKwR/hxcFGorKiHIp+hY7hgY+XBTzhCYD2NqSEg= -github.com/df-mc/atomic v1.10.0/go.mod h1:Gw9rf+rPIbydMjA329Jn4yjd/O2c/qusw3iNp4tFGSc= github.com/df-mc/goleveldb v1.1.9 h1:ihdosZyy5jkQKrxucTQmN90jq/2lUwQnJZjIYIC/9YU= github.com/df-mc/goleveldb v1.1.9/go.mod h1:+NHCup03Sci5q84APIA21z3iPZCuk6m6ABtg4nANCSk= github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c= github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4= +github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= +github.com/frankban/quicktest v1.14.5 h1:dfYrrRyLtiqT9GyKXgdh+k4inNeTvmGbuSgZ3lx3GhA= +github.com/frankban/quicktest v1.14.5/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/go-gl/mathgl v1.0.0 h1:t9DznWJlXxxjeeKLIdovCOVJQk/GzDEL7h/h+Ro2B68= github.com/go-gl/mathgl v1.0.0/go.mod h1:yhpkQzEiH9yPyxDUGzkmgScbaBVlhC06qodikEM0ZwQ= +github.com/go-zeromq/goczmq/v4 v4.2.2 h1:HAJN+i+3NW55ijMJJhk7oWxHKXgAuSBkoFfvr8bYj4U= +github.com/go-zeromq/goczmq/v4 v4.2.2/go.mod h1:Sm/lxrfxP/Oxqs0tnHD6WAhwkWrx+S+1MRrKzcxoaYE= +github.com/go-zeromq/zmq4 v0.15.0 h1:SLqukpmLTx0JsLaOaCCjwy5eBdfJ+ouJX/677HoFbJM= +github.com/go-zeromq/zmq4 v0.15.0/go.mod h1:sD47DcXifeUFsVTB2ps8ijqTpEuTAlYgfuLoiWEXdCE= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w= -github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= -github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -49,10 +41,9 @@ github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0U github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/iancoleman/strcase v0.1.3/go.mod h1:SK73tn/9oHe+/Y0h39VT4UCxmurVJkR5NA7kMEAOgSE= -github.com/klauspost/compress v1.11.1 h1:bPb7nMRdOZYDrpPMTA3EInUQrdgoBinqUuSwlGdKDdE= -github.com/klauspost/compress v1.11.1/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/cpuid v1.2.4/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= @@ -60,12 +51,18 @@ github.com/klauspost/cpuid v1.3.1 h1:5JNjFYYQrZeKRJ0734q51WCEEn2huer72Dc7K+R/b6s github.com/klauspost/cpuid v1.3.1/go.mod h1:bYW4mA6ZgKPob1/Dlai2LviZJO7KGI3uoWLd42rAQw4= github.com/klauspost/reedsolomon v1.9.9 h1:qCL7LZlv17xMixl55nq2/Oa1Y86nfO8EqDfv2GHND54= github.com/klauspost/reedsolomon v1.9.9/go.mod h1:O7yFFHiQwDR6b2t63KPUpccPtNdp5ADgh1gg4fd12wo= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= +github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= @@ -77,12 +74,15 @@ github.com/mmcloughlin/avo v0.0.0-20200803215136-443f81d77104/go.mod h1:wqKykBG2 github.com/muhammadmuzzammil1998/jsonc v0.0.0-20211230184646-baf1f7156737 h1:JFxhe475THdL2ggIfmZYxzRCTQw8lPz3T09mi6c2z6A= github.com/muhammadmuzzammil1998/jsonc v0.0.0-20211230184646-baf1f7156737/go.mod h1:saF2fIVw4banK0H4+/EuqfFLpRnoy5S+ECwTOCcRcSU= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhECwM= -github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/pebbe/zmq4 v1.2.10 h1:wQkqRZ3CZeABIeidr3e8uQZMMH5YAykA/WN0L5zkd1c= +github.com/pebbe/zmq4 v1.2.10/go.mod h1:nqnPueOapVhE2wItZ0uOErngczsJdLOGkebMxaO8r48= github.com/pierrec/lz4 v2.6.1+incompatible h1:9UY3+iC23yxF0UfGaYrGplQ+79Rg+h/q9FV9ix19jjM= github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -92,20 +92,15 @@ github.com/pterm/pterm v0.12.29 h1:wWRNFkC3+fk/agzHIO4aaXtQuRYdXJKngP3ed+LZlMU= github.com/pterm/pterm v0.12.29/go.mod h1:WI3qxgvoQFFGKGjGnJR849gU0TsEOvKn5Q8LlY1U7lg= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/sandertv/go-raknet v1.9.1 h1:nAtrjdTq4OZT9Mimv2A+RDN4ncZDdn/LhBh1QRrEXN8= github.com/sandertv/go-raknet v1.9.1/go.mod h1:s1lD7LTts74R9csTeI4WlGcp6PmXAGX+DeJlQF3KMlg= -github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= -github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 h1:qLC7fQah7D6K1B0ujays3HV9gkFtllcxhzImRR7ArPQ= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE= -github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= github.com/templexxx/cpu v0.0.1/go.mod h1:w7Tb+7qgcAlIyX4NhLuDKt78AHA5SzPmq0Wj6HiEnnk= github.com/templexxx/cpu v0.0.7 h1:pUEZn8JBy/w5yzdYWgx+0m0xL9uk6j4K91C5kOViAzo= github.com/templexxx/cpu v0.0.7/go.mod h1:w7Tb+7qgcAlIyX4NhLuDKt78AHA5SzPmq0Wj6HiEnnk= @@ -121,12 +116,11 @@ github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae h1:J0GxkO96kL4WF+A github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae/go.mod h1:gXtu8J62kEgmN++bm9BVICuT/e8yiLI2KFobd/TRFsE= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/gopher-lua v1.1.0 h1:BojcDhfyDWgU2f2TOzYK/g5p2gxMrku8oupLDqlnSqE= github.com/yuin/gopher-lua v1.1.0/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw= go.kuoruan.net/v8go-polyfills v0.5.0 h1:wd2WxsFIXWK/FcrpITw6BOo8Rn24xMmd4qoHofgg8hc= go.kuoruan.net/v8go-polyfills v0.5.0/go.mod h1:egHzK8RIHR7dPOYzhnRsomClFTVmYCtvhTWqec4JXaY= -go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= -go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= golang.org/x/arch v0.0.0-20190909030613-46d78d1859ac/go.mod h1:flIaEI6LNU6xOCD5PaJvn9wGP0agmIOqjrtsKGRguv4= @@ -135,30 +129,33 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20191219195013-becbf705a915/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 h1:0es+/5331RGQPcXlMfP+WrnIIS6dNnNRe0WB02W0F4M= -golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/exp v0.0.0-20220713135740-79cabaa25d75 h1:x03zeu7B2B11ySp+daztnwM5oBJ/8wGUSqrwcw9L0RA= -golang.org/x/exp v0.0.0-20220713135740-79cabaa25d75/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU= +golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= golang.org/x/image v0.0.0-20190321063152-3fc05d484e9f/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8 h1:hVwzHzIUGRjiF7EcUjqNxk3NCfkPxbDKRdnNE1Rpg0U= golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.5.0 h1:5JMiNunQeQw++mMOz48/ISeNu3Iweh/JaZU8ZLqHRrI= +golang.org/x/image v0.5.0/go.mod h1:FVC7BI/5Ym8R25iw5OLsgshdUBbT1h5jZTpA+mvAdZ4= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 h1:kQgndtyPBW/JIYERgdxfwMYh3AVStj88WQTlNDi2a+o= -golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20220107192237-5cfca573fb4d h1:62NvYBuaanGXR2ZOfwDFkhhl6X1DUgf8qg3GuQvxZsE= -golang.org/x/net v0.0.0-20220107192237-5cfca573fb4d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -170,32 +167,38 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200808120158-1030fc2bf1d9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211019181941-9d821ace8654 h1:id054HUawV2/6IGm2IV8KZQjqtwAOo2CYlOToYqa0d0= -golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b h1:9zKuko04nR4gjZ4+DNjHqRlAJqbJETHwiNKDqTfOjfE= golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200425043458-8463f397d07c/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200808161706-5bf02b21f123 h1:4JSJPND/+4555t1HfXYF4UEqDqiSKCgeV0+hbA8hMs4= golang.org/x/tools v0.0.0-20200808161706-5bf02b21f123/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.1.10 h1:QjFRCZxdOhBJ/UNgnBZLbNV13DlbnK0quyivTnXJM20= -golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= +golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI= gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/io/bridge.go b/io/bridge.go deleted file mode 100644 index ccbaacabb..000000000 --- a/io/bridge.go +++ /dev/null @@ -1,3 +0,0 @@ -// +build !is_tweak - -package io diff --git a/io/bridge_tweak.go b/io/bridge_tweak.go deleted file mode 100644 index 58a20f6ac..000000000 --- a/io/bridge_tweak.go +++ /dev/null @@ -1,80 +0,0 @@ -// +build is_tweak - -package io - -import ( - "phoenixbuilder/fastbuilder/environment" - "phoenixbuilder/fastbuilder/task" - "phoenixbuilder/io/commands" - "phoenixbuilder/fastbuilder/function" - "phoenixbuilder/minecraft/protocol" - "phoenixbuilder/minecraft/protocol/packet" -) - -import "C" - -var refid uint64=1 -var refs map[uint64]interface{}=map[uint64]interface{} {} - -//export phoenixbuilder_create -func phoenixbuilder_create() uint64 { - env:=&environment.PBEnvironment {} - env.ActivateTaskStatus=make(chan bool) - env.TaskHolder=task.NewTaskHolder() - env.LoginInfo=environment.LoginInfo { - Token: "", - ServerCode: "LOCAL", - ServerPasscode: "", - } - commands.InitCommandSender(env) - functionHolder := function.NewFunctionHolder(env) - env.FunctionHolder=functionHolder - function.InitInternalFunctions(functionHolder) - retval:=refid - refid++ - refs[retval]=env - return retval -} - -// Caller free ! -//export phoenixbuilder_execute -func phoenixbuilder_execute(ref uint64, command *C.char) bool { - env:=refs[ref].(*environment.PBEnvironment) - found:=env.FunctionHolder.Process(C.GoString(command)) - return found -} - -//export phoenixbuilder_destroy -func phoenixbuilder_destroy(ref uint64) { - env:=refs[ref].(*environment.PBEnvironment) - env.Stop() - env.WaitStopped() - delete(refs, ref) - return -} - -// caller free -//export phoenixbuilder_command_output -func phoenixbuilder_command_output(ref uint64,uuid *C.char, succ bool, message *C.char, param *C.char) { - env:=refs[ref].(*environment.PBEnvironment) - item, found:=env.CommandSender.GetUUIDMap().LoadAndDelete(C.GoString(uuid)) - if(!found) { - return - } - succCount:=0 - if(succ) { - succCount++ - } - rit:=item.(chan *packet.CommandOutput) - rit<-&packet.CommandOutput { - SuccessCount: uint32(succCount), - OutputMessages: []protocol.CommandOutputMessage { - protocol.CommandOutputMessage { - Success: succ, - Message: C.GoString(message), - Parameters: []string{C.GoString(param)}, - }, - }, - } -} - diff --git a/io/commands/command_block_tweak.go b/io/commands/command_block_tweak.go deleted file mode 100644 index 6fe219abd..000000000 --- a/io/commands/command_block_tweak.go +++ /dev/null @@ -1,29 +0,0 @@ -//go:build is_tweak - -package commands - -import ( - "phoenixbuilder/fastbuilder/types" -) - -/* -// All strings are callee free -void phoenixbuilder_update_command_block(int x,int y,int z,unsigned int mode,char *command,char *customName,char *lastOutput,int tickDelay,char executeOnFirstTick,char trackOutput,char conditional,char needsRedstone); -*/ -import "C" - -func booltochar(gobool bool) C.char { - if gobool { - return C.char(1) - } - return C.char(0) -} - -func (sender *CommandSender) UpdateCommandBlock(x int32, y int32, z int32, d *types.CommandBlockData) { - C.phoenixbuilder_update_command_block(C.int(x), C.int(y), C.int(z), - C.uint(d.Mode), C.CString(d.Command), C.CString(d.CustomName), - C.CString(d.LastOutput), C.int(d.TickDelay), - booltochar(d.ExecuteOnFirstTick), - booltochar(d.TrackOutput), booltochar(d.Conditional), - booltochar(d.NeedsRedstone)) -} diff --git a/io/commands/commands.go b/io/commands/commands.go deleted file mode 100644 index c9383c4c7..000000000 --- a/io/commands/commands.go +++ /dev/null @@ -1,20 +0,0 @@ -//go:build !is_tweak - -package commands - -import ( - "phoenixbuilder/fastbuilder/environment" - "sync" -) - -type CommandSender struct { - env *environment.PBEnvironment - BlockUpdateSubscribeMap sync.Map -} - -func InitCommandSender(env *environment.PBEnvironment) *CommandSender { - env.CommandSender = &CommandSender{ - env: env, - } - return env.CommandSender.(*CommandSender) -} diff --git a/io/commands/commands_tweak.go b/io/commands/commands_tweak.go deleted file mode 100644 index 11d92f263..000000000 --- a/io/commands/commands_tweak.go +++ /dev/null @@ -1,21 +0,0 @@ -//go:build is_tweak - -package commands - -import ( - "phoenixbuilder/fastbuilder/environment" - "sync" -) - -type CommandSender struct { - env *environment.PBEnvironment - UUIDMap sync.Map - BlockUpdateSubscribeMap sync.Map -} - -func InitCommandSender(env *environment.PBEnvironment) *CommandSender { - env.CommandSender = &CommandSender{ - env: env, - } - return env.CommandSender.(*CommandSender) -} diff --git a/io/commands/output.go b/io/commands/output.go deleted file mode 100644 index 15ab8f241..000000000 --- a/io/commands/output.go +++ /dev/null @@ -1,71 +0,0 @@ -//go:build !is_tweak - -package commands - -import ( - "fmt" - - "encoding/json" - "phoenixbuilder/GameControl/GlobalAPI" - "phoenixbuilder/fastbuilder/args" - "phoenixbuilder/fastbuilder/types" - "strings" - "time" -) - -type TellrawItem struct { - Text string `json:"text"` -} - -type TellrawStruct struct { - RawText []TellrawItem `json:"rawtext"` -} - -func TellRawRequest(target types.Target, lines ...string) string { - now := time.Now().Format("§6{15:04:05}§b") - var items []TellrawItem - for _, text := range lines { - msg := fmt.Sprintf("%v %v", now, strings.Replace(text, "schematic", "sc***atic", -1)) - items = append(items, TellrawItem{Text: msg}) - } - final := &TellrawStruct{ - RawText: items, - } - content, _ := json.Marshal(final) - cmd := fmt.Sprintf("tellraw %v %s", target, content) - return cmd -} - -func (sender *CommandSender) Output(content string) error { - //uuid1, _ := uuid.NewUUID() - fmt.Printf("%s\n", content) - if !args.InGameResponse() { - return nil - } - msg := strings.Replace(content, "schematic", "sc***atic", -1) - msg = strings.Replace(msg, ".", ".", -1) - return sender.SendChat(fmt.Sprintf("§b%s", msg)) - // Netease set .bdx, .schematic, .mcacblock, etc as blocked words - // So we should replace half-width points w/ full-width points to avoid being - // blocked - //return SendChat(fmt.Sprintf("§b%s",msg), conn) - //return sender.SendSizukanaCommand(TellRawRequest(types.AllPlayers, msg)) -} - -func RawTellRawRequest(target types.Target, line string) string { - var items []TellrawItem - msg := strings.Replace(line, "schematic", "sc***atic", -1) - items = append(items, TellrawItem{Text: msg}) - final := &TellrawStruct{ - RawText: items, - } - content, _ := json.Marshal(final) - cmd := fmt.Sprintf("tellraw %v %s", target, content) - return cmd -} - -func (cmd_sender *CommandSender) WorldChatOutput(sender string, content string) error { - fmt.Printf("W <%s> %s\n", sender, content) - str := fmt.Sprintf("§eW §r<%s> %s", sender, content) - return cmd_sender.env.GlobalAPI.(*GlobalAPI.GlobalAPI).SendSettingsCommand(RawTellRawRequest(types.AllPlayers, str), false) -} diff --git a/io/commands/output_tweak.go b/io/commands/output_tweak.go deleted file mode 100644 index bf3c3674b..000000000 --- a/io/commands/output_tweak.go +++ /dev/null @@ -1,28 +0,0 @@ -//go:build is_tweak - -package commands - -import "fmt" - -/* -void phoenixbuilder_output(char *content); -void phoenixbuilder_worldchat_output(char *formatted_string, char *sender, char *content); - -*/ -import "C" - -func (sender *CommandSender) Output(content string) error { - //fmt.Printf("%s\n", content) - //if(!args.InGameResponse()) { - // return nil - //} - C.phoenixbuilder_output(C.CString(content)) - return nil -} - -func (cmd_sender *CommandSender) WorldChatOutput(sender string, content string) error { - //fmt.Printf("W <%s> %s\n", sender, content) - str := fmt.Sprintf("§eW §r<%s> %s", sender, content) - C.phoenixbuilder_worldchat_output(C.CString(str), C.CString(sender), C.CString(content)) - return nil -} diff --git a/io/commands/sender.go b/io/commands/sender.go deleted file mode 100644 index a9a85c874..000000000 --- a/io/commands/sender.go +++ /dev/null @@ -1,32 +0,0 @@ -//go:build !is_tweak - -package commands - -import ( - "fmt" - "phoenixbuilder/minecraft" - "phoenixbuilder/minecraft/protocol/packet" - "sync" -) - -func (sender *CommandSender) GetBlockUpdateSubscribeMap() *sync.Map { - return &sender.BlockUpdateSubscribeMap -} - -func (sender *CommandSender) getConn() *minecraft.Conn { - conn := sender.env.Connection.(*minecraft.Conn) - return conn -} - -func (sender *CommandSender) SendChat(content string) error { - conn := sender.getConn() - idd := conn.IdentityData() - return conn.WritePacket(&packet.Text{ - TextType: packet.TextTypeChat, - NeedsTranslation: false, - SourceName: idd.DisplayName, - Message: content, - XUID: idd.XUID, - PlayerRuntimeID: fmt.Sprintf("%d", conn.GameData().EntityUniqueID), - }) -} diff --git a/io/commands/sender_tweak.go b/io/commands/sender_tweak.go deleted file mode 100644 index 1a38f8959..000000000 --- a/io/commands/sender_tweak.go +++ /dev/null @@ -1,54 +0,0 @@ -//go:build is_tweak - -package commands - -import ( - "sync" - - "github.com/google/uuid" -) - -/* -// Callee free -void phoenixbuilder_send_silent_command(char *command); -void phoenixbuilder_send_ws_command(char *command, char *uuid); -void phoenixbuilder_send_command(char *command, char *uuid); -void phoenixbuilder_send_chat(char *content); -*/ -import "C" - -func (sender *CommandSender) GetBlockUpdateSubscribeMap() *sync.Map { - return &sender.BlockUpdateSubscribeMap -} - -func (sender *CommandSender) GetUUIDMap() *sync.Map { - return &sender.UUIDMap -} - -func (sender *CommandSender) ClearUUIDMap() { - sender.UUIDMap = sync.Map{} -} - -func (sender *CommandSender) SendCommand(command string, UUID uuid.UUID) error { - C.phoenixbuilder_send_command(C.CString(command), C.CString(UUID.String())) - return nil -} - -func (sender *CommandSender) SendWSCommand(command string, UUID uuid.UUID) error { - C.phoenixbuilder_send_ws_command(C.CString(command), C.CString(UUID.String())) - return nil -} - -func (sender *CommandSender) SendSizukanaCommand(command string) error { - C.phoenixbuilder_send_silent_command(C.CString(command)) - return nil -} - -func (sender *CommandSender) SendDimensionalCommand(command string) error { - return sender.SendSizukanaCommand(command) -} - -func (sender *CommandSender) SendChat(content string) error { - C.phoenixbuilder_send_chat(C.CString(content)) - return nil -} diff --git a/io/commands/title.go b/io/commands/title.go deleted file mode 100644 index 76d73876c..000000000 --- a/io/commands/title.go +++ /dev/null @@ -1,28 +0,0 @@ -//go:build !is_tweak - -package commands - -import ( - "encoding/json" - "fmt" - "phoenixbuilder/GameControl/GlobalAPI" - "phoenixbuilder/fastbuilder/types" - "strings" -) - -func TitleRequest(target types.Target, lines ...string) string { - var items []TellrawItem - for _, text := range lines { - items = append(items, TellrawItem{Text: strings.Replace(text, "schematic", "sc***atic", -1)}) - } - final := &TellrawStruct{ - RawText: items, - } - content, _ := json.Marshal(final) - cmd := fmt.Sprintf("titleraw %v actionbar %s", target, content) - return cmd -} - -func (sender *CommandSender) Title(message string) error { - return sender.env.GlobalAPI.(*GlobalAPI.GlobalAPI).SendSettingsCommand(TitleRequest(types.AllPlayers, message), false) -} diff --git a/io/commands/title_tweak.go b/io/commands/title_tweak.go deleted file mode 100644 index e3cb0e189..000000000 --- a/io/commands/title_tweak.go +++ /dev/null @@ -1,12 +0,0 @@ -// +build is_tweak - -package commands -// callee free plz - -// void phoenixbuilder_show_title(char *message); -import "C" - -func (sender *CommandSender) Title(message string) error { - C.phoenixbuilder_show_title(C.CString(message)) - return nil -} \ No newline at end of file diff --git a/io/special_tasks/export.go b/io/special_tasks/export.go index 8689c57c1..0e6196b49 100644 --- a/io/special_tasks/export.go +++ b/io/special_tasks/export.go @@ -6,9 +6,9 @@ package special_tasks import ( "bytes" "fmt" - "phoenixbuilder/GameControl/GlobalAPI" "phoenixbuilder/fastbuilder/bdump" "phoenixbuilder/fastbuilder/configuration" + fbauth "phoenixbuilder/fastbuilder/cv4/auth" "phoenixbuilder/fastbuilder/environment" "phoenixbuilder/fastbuilder/parsing" "phoenixbuilder/fastbuilder/task" @@ -26,18 +26,16 @@ import ( "strings" "time" - "github.com/google/uuid" "github.com/pterm/pterm" ) func CreateExportTask(commandLine string, env *environment.PBEnvironment) *task.Task { - cmdsender := env.CommandSender cfg, err := parsing.Parse(commandLine, configuration.GlobalFullConfig(env).Main()) if err != nil { - cmdsender.Output(fmt.Sprintf("Failed to parse command: %v", err)) + env.GameInterface.Output(fmt.Sprintf("Failed to parse command: %v", err)) return nil } - //cmdsender.Output("Sorry, but compatibility works haven't been done yet, please use lexport.") + //env.GameInterface.Output("Sorry, but compatibility works haven't been done yet, please use lexport.") //return nil beginPos := cfg.Position endPos := cfg.End @@ -70,11 +68,9 @@ func CreateExportTask(commandLine string, env *environment.PBEnvironment) *task. fmt.Println("Hop Left: ", len(hopPath)) teleportFn := func(x, z int) { cmd := fmt.Sprintf("tp @s %v 128 %v", x, z) - uid, _ := uuid.NewUUID() - env.GlobalAPI.(*GlobalAPI.GlobalAPI).SendCommand(cmd, uid) + env.GameInterface.SendCommand(cmd) cmd = fmt.Sprintf("execute @s ~~~ spreadplayers ~ ~ 3 4 @s") - uid, _ = uuid.NewUUID() - env.GlobalAPI.(*GlobalAPI.GlobalAPI).SendCommand(cmd, uid) + env.GameInterface.SendCommand(cmd) } feedChan := make(chan *fetcher.ChunkDefineWithPos, 1024) deRegFn := env.ChunkFeeder.(*global.ChunkFeeder).RegNewReader(func(chunk *mirror.ChunkData) { @@ -88,13 +84,12 @@ func CreateExportTask(commandLine string, env *environment.PBEnvironment) *task. if !inHopping { break } - uuidval, _ := uuid.NewUUID() yv := (yc-4)*16 + 8 yc-- if yc < 0 { yc = 23 } - env.GlobalAPI.(*GlobalAPI.GlobalAPI).SendCommand(fmt.Sprintf("tp @s ~ %d ~", yv), uuidval) + env.GameInterface.SendCommand(fmt.Sprintf("tp @s ~ %d ~", yv)) time.Sleep(time.Millisecond * 50) } }() @@ -133,7 +128,7 @@ func CreateExportTask(commandLine string, env *environment.PBEnvironment) *task. fmt.Println("go routine @ fastbuilder.task export crashed ", r) } }() - cmdsender.Output("EXPORT >> Exporting...") + env.GameInterface.Output("EXPORT >> Exporting...") V := (endPos.X - beginPos.X + 1) * (endPos.Y - beginPos.Y + 1) * (endPos.Z - beginPos.Z + 1) blocks := make([]*types.Module, V) counter := 0 @@ -370,17 +365,17 @@ func CreateExportTask(commandLine string, env *environment.PBEnvironment) *task. if strings.LastIndex(cfg.Path, ".bdx") != len(cfg.Path)-4 || len(cfg.Path) < 4 { cfg.Path += ".bdx" } - cmdsender.Output("EXPORT >> Writing output file") - err, signerr := out.WriteToFile(cfg.Path, env.LocalCert, env.LocalKey) + env.GameInterface.Output("EXPORT >> Writing output file") + err, signerr := out.WriteToFile(cfg.Path, env.FBAuthClient.(*fbauth.Client).LocalCert, env.FBAuthClient.(*fbauth.Client).LocalKey) if err != nil { - cmdsender.Output(fmt.Sprintf("EXPORT >> ERROR: Failed to export: %v", err)) + env.GameInterface.Output(fmt.Sprintf("EXPORT >> ERROR: Failed to export: %v", err)) return } else if signerr != nil { - cmdsender.Output(fmt.Sprintf("EXPORT >> Note: The file is unsigned since the following error was trapped: %v", signerr)) + env.GameInterface.Output(fmt.Sprintf("EXPORT >> Note: The file is unsigned since the following error was trapped: %v", signerr)) } else { - cmdsender.Output(fmt.Sprintf("EXPORT >> File signed successfully")) + env.GameInterface.Output(fmt.Sprintf("EXPORT >> File signed successfully")) } - cmdsender.Output(fmt.Sprintf("EXPORT >> Successfully exported your structure to %v", cfg.Path)) + env.GameInterface.Output(fmt.Sprintf("EXPORT >> Successfully exported your structure to %v", cfg.Path)) runtime.GC() }() return nil diff --git a/io/special_tasks/lexport.go b/io/special_tasks/lexport.go index 244fe340b..007930008 100644 --- a/io/special_tasks/lexport.go +++ b/io/special_tasks/lexport.go @@ -5,27 +5,27 @@ package special_tasks import ( "fmt" - "phoenixbuilder/GameControl/GlobalAPI" "phoenixbuilder/fastbuilder/bdump" "phoenixbuilder/fastbuilder/configuration" + fbauth "phoenixbuilder/fastbuilder/cv4/auth" "phoenixbuilder/fastbuilder/environment" "phoenixbuilder/fastbuilder/mcstructure" "phoenixbuilder/fastbuilder/parsing" "phoenixbuilder/fastbuilder/task" + GameInterface "phoenixbuilder/game_control/game_interface" "phoenixbuilder/minecraft" "phoenixbuilder/minecraft/protocol" "phoenixbuilder/minecraft/protocol/packet" "runtime/debug" "strings" - "github.com/google/uuid" "github.com/pterm/pterm" ) func CreateLegacyExportTask(commandLine string, env *environment.PBEnvironment) *task.Task { cfg, err := parsing.Parse(commandLine, configuration.GlobalFullConfig(env).Main()) if err != nil { - env.CommandSender.Output(pterm.Error.Sprintf("Failed to parse command: %v", err)) + env.GameInterface.Output(pterm.Error.Sprintf("Failed to parse command: %v", err)) return nil } // 解析控制台输入 @@ -53,21 +53,21 @@ func CreateLegacyExportTask(commandLine string, env *environment.PBEnvironment) if endPos.Y > 320 { endPos.Y = 320 } + gameInterface := env.GameInterface.(*GameInterface.GameInterface) go func() { defer func() { err := recover() if err != nil { debug.PrintStack() - env.CommandSender.Output(pterm.Error.Sprintf("go routine @ fastbuilder.task lexport crashed")) - env.CommandSender.Output(pterm.Error.Sprintf("%v", err)) + env.GameInterface.Output(pterm.Error.Sprintf("go routine @ fastbuilder.task lexport crashed")) + env.GameInterface.Output(pterm.Error.Sprintf("%v", err)) } }() - u_d0, _ := uuid.NewUUID() - env.GlobalAPI.(*GlobalAPI.GlobalAPI).SendWSCommand("gamemode c", u_d0) + gameInterface.SendWSCommand("gamemode c") - resp, _ := env.GlobalAPI.(*GlobalAPI.GlobalAPI).SendWSCommandWithResponce("querytarget @s") - parseResult, _ := env.GlobalAPI.(*GlobalAPI.GlobalAPI).ParseQuerytargetInfo(resp) + resp, _ := gameInterface.SendWSCommandWithResponse("querytarget @s") + parseResult, _ := gameInterface.ParseTargetQueryingInfo(resp) var testAreaIsLoaded string = "testforblocks ~-31 -64 ~-31 ~31 319 ~31 ~-31 -64 ~-31" if parseResult[0].Dimension == 1 { testAreaIsLoaded = "testforblocks ~-31 0 ~-31 ~31 127 ~31 ~-31 0 ~-31" @@ -89,20 +89,20 @@ func CreateLegacyExportTask(commandLine string, env *environment.PBEnvironment) allAreas := make([]mcstructure.Mcstructure, 0) for key, value := range splittedAreas { currentProgress := indicativeMap[key] - env.CommandSender.Output(pterm.Info.Sprintf("Fetching data from area [%d, %d]", currentProgress[0], currentProgress[1])) - env.GlobalAPI.(*GlobalAPI.GlobalAPI).SendWSCommandWithResponce(fmt.Sprintf("tp %d %d %d", value.BeginX+value.SizeX/2, value.BeginY+value.SizeY/2, value.BeginZ+value.SizeZ/2)) + env.GameInterface.Output(pterm.Info.Sprintf("Fetching data from area [%d, %d]", currentProgress[0], currentProgress[1])) + gameInterface.SendWSCommandWithResponse(fmt.Sprintf("tp %d %d %d", value.BeginX+value.SizeX/2, value.BeginY+value.SizeY/2, value.BeginZ+value.SizeZ/2)) for { - resp, _ := env.GlobalAPI.(*GlobalAPI.GlobalAPI).SendWSCommandWithResponce(testAreaIsLoaded) + resp, _ := gameInterface.SendWSCommandWithResponse(testAreaIsLoaded) if resp.OutputMessages[0].Message != "commands.generic.outOfWorld" { break } } // 等待当前被访问的区块加载完成 - holder := env.GlobalAPI.(*GlobalAPI.GlobalAPI).Resources.Structure.Occupy() - exportData, _ := env.GlobalAPI.(*GlobalAPI.GlobalAPI).SendStructureRequestWithResponce( + holder := gameInterface.Resources.Structure.Occupy() + exportData, _ := gameInterface.SendStructureRequestWithResponse( &packet.StructureTemplateDataRequest{ - StructureName: "mystructure:aaaaa", + StructureName: "mystructure:bbbbb", Position: protocol.BlockPos{int32(value.BeginX), int32(value.BeginY), int32(value.BeginZ)}, Settings: protocol.StructureSettings{ PaletteName: "default", @@ -120,7 +120,7 @@ func CreateLegacyExportTask(commandLine string, env *environment.PBEnvironment) RequestType: packet.StructureTemplateRequestExportFromSave, }, ) - env.GlobalAPI.(*GlobalAPI.GlobalAPI).Resources.Structure.Release(holder) + gameInterface.Resources.Structure.Release(holder) // 获取 mcstructure got, err := mcstructure.GetMCStructureData(value, exportData.StructureTemplate) if err != nil { @@ -129,8 +129,8 @@ func CreateLegacyExportTask(commandLine string, env *environment.PBEnvironment) allAreas = append(allAreas, got) } } - env.CommandSender.Output(pterm.Info.Sprint("Data received, processing......")) - env.CommandSender.Output(pterm.Info.Sprint("Extracting blocks......")) + env.GameInterface.Output(pterm.Info.Sprint("Data received, processing......")) + env.GameInterface.Output(pterm.Info.Sprint("Extracting blocks......")) processedData, err := mcstructure.DumpBlocks(allAreas, reversedMap, mcstructure.Area{ BeginX: int32(beginPos.X), @@ -151,17 +151,17 @@ func CreateLegacyExportTask(commandLine string, env *environment.PBEnvironment) cfg.Path += ".bdx" } - env.CommandSender.Output(pterm.Info.Sprint("Writing output file......")) - err, signerr := outputResult.WriteToFile(cfg.Path, env.LocalCert, env.LocalKey) + env.GameInterface.Output(pterm.Info.Sprint("Writing output file......")) + err, signerr := outputResult.WriteToFile(cfg.Path, env.FBAuthClient.(*fbauth.Client).LocalCert, env.FBAuthClient.(*fbauth.Client).LocalKey) if err != nil { - env.CommandSender.Output(pterm.Error.Sprintf("Failed to export: %v", err)) + env.GameInterface.Output(pterm.Error.Sprintf("Failed to export: %v", err)) return } else if signerr != nil { - env.CommandSender.Output(pterm.Info.Sprintf("Note: The file is unsigned since the following error was trapped: %v", signerr)) + env.GameInterface.Output(pterm.Info.Sprintf("Note: The file is unsigned since the following error was trapped: %v", signerr)) } else { - env.CommandSender.Output(pterm.Success.Sprint("File signed successfully")) + env.GameInterface.Output(pterm.Success.Sprint("File signed successfully")) } - env.CommandSender.Output(pterm.Success.Sprintf("Successfully exported your structure to %v", cfg.Path)) + env.GameInterface.Output(pterm.Success.Sprintf("Successfully exported your structure to %v", cfg.Path)) }() return nil } diff --git a/io/special_tasks/define.go b/io/special_tasks/special_tasks.go similarity index 100% rename from io/special_tasks/define.go rename to io/special_tasks/special_tasks.go diff --git a/lib/encoding/basic.go b/lib/encoding/basic.go deleted file mode 100644 index c56fcea67..000000000 --- a/lib/encoding/basic.go +++ /dev/null @@ -1,34 +0,0 @@ -package encoding - -import ( - "bytes" - "fmt" -) - -// 创建一个新的阅读器 -func NewReader(reader *bytes.Buffer) IO { - return &Reader{r: reader} -} - -// 创建一个新的写入者 -func NewWriter(writer *bytes.Buffer) IO { - return &Writer{w: writer} -} - -// 取得阅读器的底层切片 -func (r *Reader) GetBuffer() (*bytes.Buffer, error) { - ans, success := r.r.(*bytes.Buffer) - if !success { - return nil, fmt.Errorf("(r *Reader) GetBuffer: Failed to convert r.r into *bytes.Buffer; r.r = %#v", r.r) - } - return ans, nil -} - -// 取得写入者的底层切片 -func (w *Writer) GetBuffer() (*bytes.Buffer, error) { - ans, success := w.w.(*bytes.Buffer) - if !success { - return nil, fmt.Errorf("(w *Writer) GetBuffer: Failed to convert w.w into *bytes.Buffer; w.w = %#v", w.w) - } - return ans, nil -} diff --git a/lib/encoding/define.go b/lib/encoding/define.go deleted file mode 100644 index bc1e62920..000000000 --- a/lib/encoding/define.go +++ /dev/null @@ -1,21 +0,0 @@ -package encoding - -import ( - "io" -) - -const StringLengthMaxLimited = 65535 // 单个字符串的最大长度上限 -const SliceLengthMaxLimited = 4294967295 // 单个切片的最大长度上限 -const MapLengthMaxLimited = 65535 // 单个 Map 的最大长度上限 - -const UUIDConstantLength = 16 // 单个 uuid.UUID 的固定长度 - -// 用于读取二进制切片的阅读器 -type Reader struct { - r interface{ io.Reader } -} - -// 用于写入二进制切片的写入者 -type Writer struct { - w interface{ io.Writer } -} diff --git a/lib/encoding/doc.md b/lib/encoding/doc.md deleted file mode 100644 index 5dc3d6722..000000000 --- a/lib/encoding/doc.md +++ /dev/null @@ -1,30 +0,0 @@ -# phoenixbuilder/lib/encoding -`encoding(phoenixbuilder/lib/encoding)` 包提供了一个二进制流编码和解码实现,它允许您简单地在网络上编码和解码二进制数据。 - -如果没有特殊说明,所有数字类型的数据都将以 `大端字节序(Big Endian)` 记录。 - -下表列出了已有的对于基本数据类型的全部支持及对应编码方法。 - -| 数据类型 | 编码方法 | 样例(二进制形式) | 样例(可读形式) | 备注 | -| ------------------------------------- | ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------- | ------------------------------------- | ---------------------------------------------------------------------- | -| `slice([]byte)` | `uint32 length; buffer[length]` | `\x00\x00\x00\x05`
`\x01\x02\x03\x04\x05` | `[1, 2, 3, 4, 5]` | 单个 `slice` 的最大长度上限为 `4294967295` | -| `string` | `uint16 length; buffer[length]` | `\x00\x05`
`Happy` | `Happy` | 单个 `字符串` 的最大长度上限为 `65535` | -| `string slice([]string)` | `uint32 length; string[length]` | `\x00\x00\x00\x03`
`\x00\x01A\x00\x02AB\x00\x03ABC` | `["A", "AB", "ABC"]` | 单个 `string slice` 的最大长度上限为 `4294967295` | -| `map[string]slice(map[string][]byte)` | `uint16 length; {string, slice}[length]` | `\x00\x02`
`\x00\x02AB`
`\x00\x00\x00\x01\x02`
`\x00\x03ABC`
`\x00\x00\x00\x05\x01\x02\x03\x04\x05` | `{"AB": [2], "ABC": [1, 2, 3, 4, 5]}` | 单个 `map[string]slice` 的最大长度上限为 `65535` | -| `bool` | `uint8(0 or 1)` | `\x01` | `true` | 接受值仅限于 `0(false)` 或 `1(true)` | -| `uint8` | `uint8` | `\x03` | `3` | 单个 `uint8` 的取值范围为 `0 - 255` | -| `int8` | `int8` | `\xe9` | `-23` | 单个 `int8` 的取值范围为 `-128 - 127` | -| `uint16` | `uint16` | `\xab\xcd` | `43981` | 单个 `uint16` 的取值范围为 `0 - 65535` | -| `int16` | `int16` | `\x20\x18` | `8216` | 单个 `int16` 的取值范围为 `-32768 - 32767` | -| `uint32` | `uint32` | `\x20\x18\x20\x18` | `538451992` | 单个 `uint32` 的取值范围为 `0 - 4294967295` | -| `int32` | `int32` | `\x24\x01pt` | `604074100` | 单个 `int32` 的取值范围为 `-2147483648 - 2147483647` | -| `uint64` | `uint64` | `\x00\x00\x00\x00\x00\x00\x00\x08` | `8` | 单个 `uint64` 的取值范围为 `0 - 18446744073709551615` | -| `int64` | `int64` | `\x24\x01pt\x20\x18\x20\x16` | `2594478504399085590` | 单个 `int64` 的取值范围为 `-9223372036854775808 - 9223372036854775807` | - -下表列出了已有的对于自定义数据类型的全部支持及对应编码方法。 - -| 数据类型 | 编码方法 | 样例(二进制形式) | 样例(可读形式) | 备注 | -| --------------------------------- | ------------ | ------------------------------------------------------------------ | -------------------------------------- | ---------------------------------- | -| `uuid.UUID` | `buffer[16]` | `\x78\xca\x9b\xf3\x07\x4c\x11\xee\x93\x1b\x00\xff\xad\x4d\xc5\x4d` | `78ca9bf3-074c-11ee-931b-00ffad4dc54d` | 单个 `uuid.UUID` 的长度为常数 `16` | -| `protocol.CommandOutputMessage` | 请参阅代码 | _None_ | _None_ | _None_ | -| `[]protocol.CommandOutputMessage` | 请参阅代码 | _None_ | _None_ | _None_ | \ No newline at end of file diff --git a/lib/encoding/interface.go b/lib/encoding/interface.go deleted file mode 100644 index c09b4e183..000000000 --- a/lib/encoding/interface.go +++ /dev/null @@ -1,46 +0,0 @@ -package encoding - -import ( - "bytes" - "phoenixbuilder/minecraft/protocol" - - "github.com/google/uuid" -) - -// 为二进制数据实现的 IO 操作流 -type IO interface { - AutoMarshal - GetBuffer -} - -// 取得阅读器或写入者的底层切片 -type GetBuffer interface { - GetBuffer() (*bytes.Buffer, error) -} - -// 为二进制数据实现的自动化 解码/编码 实现。 -// -// 以下列出的每个函数都提供了两个实现, -// 以允许编码或解码二进制数据。 -// -// 当传入 encoding.Reader 时,数据将从 encoding.Reader 解码至 x ; -// 当传入 encoding.Writer 时,x 将被编码至 encoding.Writer -type AutoMarshal interface { - Slice(x *[]byte) error - String(x *string) error - StringSlice(x *[]string) error - Map(x *map[string][]byte) error - Bool(x *bool) error - Uint8(x *uint8) error - Int8(x *int8) error - Uint16(x *uint16) error - Int16(x *int16) error - Uint32(x *uint32) error - Int32(x *int32) error - Uint64(x *uint64) error - Int64(x *int64) error - - UUID(x *uuid.UUID) error - CommandOutputMessage(x *protocol.CommandOutputMessage) error - CommandOutputMessageSlice(x *[]protocol.CommandOutputMessage) error -} diff --git a/lib/encoding/marshal.go b/lib/encoding/marshal.go deleted file mode 100644 index 878574ab6..000000000 --- a/lib/encoding/marshal.go +++ /dev/null @@ -1,264 +0,0 @@ -package encoding - -import ( - "encoding/binary" - "fmt" - "phoenixbuilder/minecraft/protocol" - - "github.com/google/uuid" -) - -// 向写入者写入字节切片 p -func (w *Writer) WriteBytes(p []byte) error { - _, err := w.w.Write(p) - if err != nil { - return fmt.Errorf("WriteBytes: %v", err) - } - return nil -} - -// 向写入者写入二进制切片 x -func (w *Writer) Slice(x *[]byte) error { - if len(*x) > SliceLengthMaxLimited { - return fmt.Errorf("(w *Writer) Slice: The length of the target slice is out of the max limited %v", SliceLengthMaxLimited) - } - // check length - err := binary.Write(w.w, binary.BigEndian, uint32(len(*x))) - if err != nil { - return fmt.Errorf("(w *Writer) Slice: %v", err) - } - // write the length of the target slice - err = w.WriteBytes(*x) - if err != nil { - return fmt.Errorf("(w *Writer) Slice: %v", err) - } - // write slice - return nil - // return -} - -// 向写入者写入字符串 x -func (w *Writer) String(x *string) error { - if len(*x) > StringLengthMaxLimited { - return fmt.Errorf("(w *Writer) String: The length of the target string is out of the max limited %v", StringLengthMaxLimited) - } - // check length - err := binary.Write(w.w, binary.BigEndian, uint16(len(*x))) - if err != nil { - return fmt.Errorf("(w *Writer) String: %v", err) - } - // write the length of the target string - err = w.WriteBytes([]byte(*x)) - if err != nil { - return fmt.Errorf("(w *Writer) String: %v", err) - } - // write string - return nil - // return -} - -// 向写入者写入字符串切片 x -func (w *Writer) StringSlice(x *[]string) error { - if len(*x) > SliceLengthMaxLimited { - return fmt.Errorf("(w *Writer) StringSlice: The length of the target slice is out of the max limited %v", SliceLengthMaxLimited) - } - // check length - err := binary.Write(w.w, binary.BigEndian, uint32(len(*x))) - if err != nil { - return fmt.Errorf("(w *Writer) StringSlice: %v", err) - } - // write the length of the target slice - for _, value := range *x { - err = w.String(&value) - if err != nil { - return fmt.Errorf("(w *Writer) StringSlice: %v", err) - } - } - // write slice - return nil - // return -} - -// 向写入者写入 map[string][]byte -func (w *Writer) Map(x *map[string][]byte) error { - if len(*x) > MapLengthMaxLimited { - return fmt.Errorf("(w *Writer) Map: The length of the target map is out of the max limited %v", MapLengthMaxLimited) - } - // check length - err := binary.Write(w.w, binary.BigEndian, uint16(len(*x))) - if err != nil { - return fmt.Errorf("(w *Writer) Map: %v", err) - } - // write the length of the target map - for key, value := range *x { - err := w.String(&key) - if err != nil { - return fmt.Errorf("(w *Writer) Map: %v", err) - } - err = w.Slice(&value) - if err != nil { - return fmt.Errorf("(w *Writer) Map: %v", err) - } - } - // write map - return nil - // return -} - -// 向写入者写入布尔值 x -func (w *Writer) Bool(x *bool) error { - if *x { - err := w.WriteBytes([]byte{1}) - if err != nil { - return fmt.Errorf("(w *Writer) Bool: %v", err) - } - } else { - err := w.WriteBytes([]byte{0}) - if err != nil { - return fmt.Errorf("(w *Writer) Bool: %v", err) - } - } - return nil -} - -// 向写入者写入 x(uint8) -func (w *Writer) Uint8(x *uint8) error { - err := w.WriteBytes([]byte{*x}) - if err != nil { - return fmt.Errorf("(w *Writer) Uint8: %v", err) - } - return nil -} - -// 向写入者写入 x(int8) -func (w *Writer) Int8(x *int8) error { - err := binary.Write(w.w, binary.BigEndian, *x) - if err != nil { - return fmt.Errorf("(w *Writer) Int8: %v", err) - } - return nil -} - -// 向写入者写入 x(uint16) -func (w *Writer) Uint16(x *uint16) error { - err := binary.Write(w.w, binary.BigEndian, *x) - if err != nil { - return fmt.Errorf("(w *Writer) Uint16: %v", err) - } - return nil -} - -// 向写入者写入 x(int16) -func (w *Writer) Int16(x *int16) error { - err := binary.Write(w.w, binary.BigEndian, *x) - if err != nil { - return fmt.Errorf("(w *Writer) Int16: %v", err) - } - return nil -} - -// 向写入者写入 x(uint32) -func (w *Writer) Uint32(x *uint32) error { - err := binary.Write(w.w, binary.BigEndian, *x) - if err != nil { - return fmt.Errorf("(w *Writer) Uint32: %v", err) - } - return nil -} - -// 向写入者写入 x(int32) -func (w *Writer) Int32(x *int32) error { - err := binary.Write(w.w, binary.BigEndian, *x) - if err != nil { - return fmt.Errorf("(w *Writer) Int32: %v", err) - } - return nil -} - -// 向写入者写入 x(uint64) -func (w *Writer) Uint64(x *uint64) error { - err := binary.Write(w.w, binary.BigEndian, *x) - if err != nil { - return fmt.Errorf("(w *Writer) Uint64: %v", err) - } - return nil -} - -// 向写入者写入 x(int64) -func (w *Writer) Int64(x *int64) error { - err := binary.Write(w.w, binary.BigEndian, *x) - if err != nil { - return fmt.Errorf("(w *Writer) Int64: %v", err) - } - return nil -} - -// 向写入者写入 x(uuid.UUID) -func (w *Writer) UUID(x *uuid.UUID) error { - p, err := x.MarshalBinary() - if err != nil { - return fmt.Errorf("(w *Writer) UUID: %v", err) - } - // get binary of uuid - if len(p) != UUIDConstantLength { - return fmt.Errorf("(w *Writer) UUID: Unexpected length %v was find, but expected to be %v", len(p), UUIDConstantLength) - } - // check length - err = w.WriteBytes(p) - if err != nil { - return fmt.Errorf("(w *Writer) UUID: %v", err) - } - // writer binary of uuid - return nil - // return -} - -// 向写入者写入 x(protocol.CommandOutputMessage) -func (w *Writer) CommandOutputMessage(x *protocol.CommandOutputMessage) error { - err := w.Bool(&x.Success) - if err != nil { - return fmt.Errorf("(w *Writer) CommandOutputMessage: %v", err) - } - // Success - err = w.String(&x.Message) - if err != nil { - return fmt.Errorf("(w *Writer) CommandOutputMessage: %v", err) - } - // Message - if x.Parameters == nil { - err = w.WriteBytes([]byte{0, 0, 0, 0}) - if err != nil { - return fmt.Errorf("(w *Writer) CommandOutputMessage: %v", err) - } - } else { - err = w.StringSlice(&x.Parameters) - if err != nil { - return fmt.Errorf("(w *Writer) CommandOutputMessage: %v", err) - } - } - // Parameters - return nil - // return -} - -// 向写入者写入 x([]protocol.CommandOutputMessage) -func (w *Writer) CommandOutputMessageSlice(x *[]protocol.CommandOutputMessage) error { - if len(*x) > SliceLengthMaxLimited { - return fmt.Errorf("(w *Writer) CommandOutputMessageSlice: The length of x is out of the max limited %v", SliceLengthMaxLimited) - } - // check length - err := binary.Write(w.w, binary.BigEndian, uint32(len(*x))) - if err != nil { - return fmt.Errorf("(w *Writer) CommandOutputMessageSlice: %v", err) - } - // write length - for _, value := range *x { - err = w.CommandOutputMessage(&value) - if err != nil { - return fmt.Errorf("(w *Writer) CommandOutputMessageSlice: %v", err) - } - } - // write data - return nil - // return -} diff --git a/lib/encoding/unmarshal.go b/lib/encoding/unmarshal.go deleted file mode 100644 index bf3f2bde1..000000000 --- a/lib/encoding/unmarshal.go +++ /dev/null @@ -1,253 +0,0 @@ -package encoding - -import ( - "encoding/binary" - "fmt" - "phoenixbuilder/minecraft/protocol" - - "github.com/google/uuid" -) - -// 从阅读器阅读 length 个字节 -func (r *Reader) ReadBytes(length int) ([]byte, error) { - ans := make([]byte, length) - _, err := r.r.Read(ans) - if err != nil { - return nil, fmt.Errorf("ReadBytes: %v", err) - } - return ans, nil -} - -// 从阅读器阅读一个二进制切片并返回到 x 上 -func (r *Reader) Slice(x *[]byte) error { - var length uint32 - err := binary.Read(r.r, binary.BigEndian, &length) - if err != nil { - return fmt.Errorf("(r *Reader) Slice: %v", err) - } - // get the length of the target string - slice, err := r.ReadBytes(int(length)) - if err != nil { - return fmt.Errorf("(r *Reader) Slice: %v", err) - } - *x = slice - // get the target slice - return nil - // return -} - -// 从阅读器阅读一个字符串并返回到 x 上 -func (r *Reader) String(x *string) error { - var length uint16 - err := binary.Read(r.r, binary.BigEndian, &length) - if err != nil { - return fmt.Errorf("(r *Reader) String: %v", err) - } - // get the length of the target string - stringBytes, err := r.ReadBytes(int(length)) - if err != nil { - return fmt.Errorf("(r *Reader) String: %v", err) - } - *x = string(stringBytes) - // get the target string - return nil - // return -} - -// 从阅读器阅读一个字符串切片并返回到 x 上 -func (r *Reader) StringSlice(x *[]string) error { - var length uint32 - err := binary.Read(r.r, binary.BigEndian, &length) - if err != nil { - return fmt.Errorf("(r *Reader) StringSlice: %v", err) - } - // get the length of the target slice - *x = make([]string, length) - // make - for i := 0; i < int(length); i++ { - err = r.String(&(*x)[i]) - if err != nil { - return fmt.Errorf("(r *Reader) StringSlice: %v", err) - } - } - // get the target slice - return nil - // return -} - -// 从阅读器阅读一个 map[string][]byte 并返回到 x 上 -func (r *Reader) Map(x *map[string][]byte) error { - var length uint16 - err := binary.Read(r.r, binary.BigEndian, &length) - if err != nil { - return fmt.Errorf("(r *Reader) Map: %v", err) - } - // get the length of the target map - for i := 0; i < int(length); i++ { - key := "" - value := []byte{} - err = r.String(&key) - if err != nil { - return fmt.Errorf("(r *Reader) Map: %v", err) - } - err = r.Slice(&value) - if err != nil { - return fmt.Errorf("(r *Reader) Map: %v", err) - } - (*x)[key] = value - } - // read map and unmarshal it into x - return nil - // return -} - -// 从阅读器阅读一个布尔值并返回到 x 上 -func (r *Reader) Bool(x *bool) error { - ans, err := r.ReadBytes(1) - if err != nil { - return fmt.Errorf("(r *Reader) Bool: %v", err) - } - switch ans[0] { - case 0: - *x = false - case 1: - *x = true - case 2: - return fmt.Errorf("(r *Reader) Bool: Unexpected value %#v was find", ans) - } - return nil -} - -// 从阅读器阅读一个 uint8 并返回到 x 上 -func (r *Reader) Uint8(x *uint8) error { - ans, err := r.ReadBytes(1) - if err != nil { - return fmt.Errorf("(r *Reader) Uint8: %v", err) - } - *x = ans[0] - return nil -} - -// 从阅读器阅读一个 int8 并返回到 x 上 -func (r *Reader) Int8(x *int8) error { - err := binary.Read(r.r, binary.BigEndian, x) - if err != nil { - return fmt.Errorf("(r *Reader) Int8: %v", err) - } - return nil -} - -// 从阅读器阅读一个 uint16 并返回到 x 上 -func (r *Reader) Uint16(x *uint16) error { - err := binary.Read(r.r, binary.BigEndian, x) - if err != nil { - return fmt.Errorf("(r *Reader) Uint16: %v", err) - } - return nil -} - -// 从阅读器阅读一个 int16 并返回到 x 上 -func (r *Reader) Int16(x *int16) error { - err := binary.Read(r.r, binary.BigEndian, x) - if err != nil { - return fmt.Errorf("(r *Reader) Int16: %v", err) - } - return nil -} - -// 从阅读器阅读一个 uint32 并返回到 x 上 -func (r *Reader) Uint32(x *uint32) error { - err := binary.Read(r.r, binary.BigEndian, x) - if err != nil { - return fmt.Errorf("(r *Reader) Uint32: %v", err) - } - return nil -} - -// 从阅读器阅读一个 int32 并返回到 x 上 -func (r *Reader) Int32(x *int32) error { - err := binary.Read(r.r, binary.BigEndian, x) - if err != nil { - return fmt.Errorf("(r *Reader) Int32: %v", err) - } - return nil -} - -// 从阅读器阅读一个 uint64 并返回到 x 上 -func (r *Reader) Uint64(x *uint64) error { - err := binary.Read(r.r, binary.BigEndian, x) - if err != nil { - return fmt.Errorf("(r *Reader) Uint64: %v", err) - } - return nil -} - -// 从阅读器阅读一个 int64 并返回到 x 上 -func (r *Reader) Int64(x *int64) error { - err := binary.Read(r.r, binary.BigEndian, x) - if err != nil { - return fmt.Errorf("(r *Reader) Int64: %v", err) - } - return nil -} - -// 从阅读器阅读一个 uuid.UUID 并返回到 x 上 -func (r *Reader) UUID(x *uuid.UUID) error { - p, err := r.ReadBytes(UUIDConstantLength) - if err != nil { - return fmt.Errorf("(r *Reader) UUID: %v", err) - } - // get binary of uuid - err = x.UnmarshalBinary(p) - if err != nil { - return fmt.Errorf("(r *Reader) UUID: %v", err) - } - // unmarshal - return nil - // return -} - -// 从阅读器阅读一个 protocol.CommandOutputMessage 并返回到 x 上 -func (r *Reader) CommandOutputMessage(x *protocol.CommandOutputMessage) error { - err := r.Bool(&x.Success) - if err != nil { - return fmt.Errorf("(r *Reader) CommandOutputMessage: %v", err) - } - // Success - err = r.String(&x.Message) - if err != nil { - return fmt.Errorf("(r *Reader) CommandOutputMessage: %v", err) - } - // Message - if x.Parameters == nil { - x.Parameters = make([]string, 0) - } - err = r.StringSlice(&x.Parameters) - if err != nil { - return fmt.Errorf("(r *Reader) CommandOutputMessage: %v", err) - } - // Parameters - return nil - // return -} - -// 从阅读器阅读一个 []protocol.CommandOutputMessage 并返回到 x 上 -func (r *Reader) CommandOutputMessageSlice(x *[]protocol.CommandOutputMessage) error { - var length uint32 - err := binary.Read(r.r, binary.BigEndian, &length) - if err != nil { - return fmt.Errorf("(r *Reader) CommandOutputMessageSlice: %v", err) - } - // get length - *x = make([]protocol.CommandOutputMessage, length) - // make - for i := 0; i < int(length); i++ { - err = r.CommandOutputMessage(&(*x)[i]) - if err != nil { - return fmt.Errorf("(r *Reader) CommandOutputMessageSlice: %v", err) - } - } - // read data - return nil - // return -} diff --git a/lib/fbauth/client.go b/lib/fbauth/client.go deleted file mode 100644 index e7e0f6517..000000000 --- a/lib/fbauth/client.go +++ /dev/null @@ -1,212 +0,0 @@ -package fbauth - -import ( - "bytes" - "compress/gzip" - "context" - "crypto/ecdsa" - "crypto/elliptic" - "crypto/rand" - "crypto/rsa" - "crypto/x509" - "encoding/base64" - "encoding/json" - "fmt" - "io" - - "github.com/gorilla/websocket" -) - -type Client struct { - privateKey *ecdsa.PrivateKey - rsaPublicKey *rsa.PublicKey - - salt []byte - wsClient *websocket.Conn - - peerNoEncryption bool - encryptor *encryptionSession - serverResponse chan map[string]interface{} - - readCtx context.Context - waitEncrypted chan struct{} - noEcrypted bool - lastReadErr error -} - -func NewClient(ctx context.Context) *Client { - return &Client{ - readCtx: ctx, - } -} - -func (c *Client) initReadLoop() { - var err error - defer func() { - c.lastReadErr = err - if c.lastReadErr == nil { - c.lastReadErr = fmt.Errorf("unknown error") - } - }() - var msg []byte - for { - _, msg, err = c.wsClient.ReadMessage() - if err != nil { - break - } - if err = c.readCtx.Err(); err != nil { - break - } - var message map[string]interface{} - var outbuf bytes.Buffer - var inbuf bytes.Buffer - inbuf.Write(msg) - reader, _ := gzip.NewReader(&inbuf) - reader.Close() - io.Copy(&outbuf, reader) - msg = outbuf.Bytes() - if c.encryptor != nil { - c.encryptor.decrypt(msg) - } - if err = json.Unmarshal(msg, &message); err != nil { - break - } - if action, ok := message["action"].(string); !ok { - select { - case c.serverResponse <- message: - default: - } - } else if action == "encryption" { - spub := new(ecdsa.PublicKey) - keyb64, _ := message["publicKey"].(string) - keydata, _ := base64.StdEncoding.DecodeString(keyb64) - spp, _ := x509.ParsePKIXPublicKey(keydata) - ek, _ := spp.(*ecdsa.PublicKey) - *spub = *ek - c.encryptor = &encryptionSession{ - serverPrivateKey: c.privateKey, - clientPublicKey: spub, - salt: c.salt, - } - if err = c.encryptor.init(); err != nil { - break - } - close(c.waitEncrypted) - continue - } else if action == "no_encryption" { - c.noEcrypted = true - if err = c.sendMessage([]byte(`{"action":"accept_no_encryption"}`)); err != nil { - break - } - close(c.waitEncrypted) - } - } -} - -func (c *Client) SendMessage(data []byte) (err error) { - if c.encryptor == nil && c.noEcrypted == false { - return fmt.Errorf("should wait until channel is ecrypted") - } - if !c.noEcrypted && c.encryptor != nil { - c.encryptor.encrypt(data) - } - err = c.sendMessage(data) - if err != nil { - return err - } - return c.lastReadErr -} - -func (c *Client) sendMessage(data []byte) (err error) { - if c.readCtx.Err() != nil { - return fmt.Errorf("connection closed: %v (read loop: %v)", c.readCtx.Err(), c.lastReadErr) - } - var inbuf bytes.Buffer - wr := gzip.NewWriter(&inbuf) - _, err = wr.Write(data) - if err != nil { - return err - } - err = wr.Close() - if err != nil { - return err - } - err = c.wsClient.WriteMessage(websocket.BinaryMessage, inbuf.Bytes()) - if err != nil { - return err - } - return nil -} - -func (c *Client) sendMessageAndGetResponse(data []byte) (resp <-chan map[string]interface{}, err error) { - if err = c.SendMessage(data); err != nil { - return - } - responseC := make(chan map[string]interface{}, 1) - go func() { - r := <-c.serverResponse - responseC <- r - }() - return responseC, nil -} - -func (c *Client) SendMessageAndGetResponseWithDeadline(data []byte, deadline context.Context) (resp map[string]interface{}, err error) { - responseC, err := c.sendMessageAndGetResponse(data) - if err != nil { - return nil, err - } - select { - case <-deadline.Done(): - return nil, fmt.Errorf("auth server no response before deadline") - case resp = <-responseC: - return resp, nil - } -} - -func (c *Client) sendEncryptRequest() error { - publicKeyBytes, err := x509.MarshalPKIXPublicKey(&c.privateKey.PublicKey) - if err != nil { - return err - } - publicKeyStr := base64.StdEncoding.EncodeToString(publicKeyBytes) - if err = c.sendMessage([]byte(`{"action":"enable_encryption_v2","publicKey":"` + string(publicKeyStr) + `"}`)); err != nil { - return err - } - return nil -} - -func (c *Client) EstablishConnectionToAuthServer(connectContext context.Context, authServerAddr string) (err error) { - if c.privateKey, err = ecdsa.GenerateKey(elliptic.P384(), rand.Reader); err != nil { - return - } - c.waitEncrypted = make(chan struct{}) - c.salt = []byte("2345678987654321") - c.serverResponse = make(chan map[string]interface{}) - var cancelFn context.CancelFunc - c.readCtx, cancelFn = context.WithCancel(c.readCtx) - if c.wsClient, _, err = websocket.DefaultDialer.DialContext(connectContext, authServerAddr, nil); err != nil { - cancelFn() - return fmt.Errorf("cannot connect to auth server") - } - go func() { - c.initReadLoop() - err = fmt.Errorf("fbauth server: read loop closed with error: %v", c.lastReadErr) - fmt.Println(err) - cancelFn() - }() - if err = c.sendEncryptRequest(); err != nil { - return err - } - select { - case <-connectContext.Done(): - return connectContext.Err() - case <-c.readCtx.Done(): - return c.readCtx.Err() - case <-c.waitEncrypted: - return nil - } -} - -func (c *Client) Closed() <-chan struct{} { - return c.readCtx.Done() -} diff --git a/lib/fbauth/encryption.go b/lib/fbauth/encryption.go deleted file mode 100644 index 2ad54a712..000000000 --- a/lib/fbauth/encryption.go +++ /dev/null @@ -1,75 +0,0 @@ -package fbauth - -import ( - "crypto/aes" - "crypto/cipher" - "crypto/ecdsa" - "crypto/sha256" - "fmt" -) - -type encryptionSession struct { - serverPrivateKey *ecdsa.PrivateKey - clientPublicKey *ecdsa.PublicKey - salt []byte - - sharedSecret []byte - secretKeyBytes [32]byte - cipherBlock cipher.Block - - encryptIV []byte - decryptIV []byte - - sendCounter int64 -} - -// init initialises the encryption session, computing the shared secret and secret key bytes as required to -// initialise the cipher blocks for encryption and decryption. -func (session *encryptionSession) init() error { - session.computeSharedSecret() - return session.computeIVs() -} - -// computeSharedSecret computes the shared secret required for encryption and decryption. -func (session *encryptionSession) computeSharedSecret() { - // We only care about the 'x' part of this. - x, _ := session.clientPublicKey.Curve.ScalarMult(session.clientPublicKey.X, session.clientPublicKey.Y, session.serverPrivateKey.D.Bytes()) - session.sharedSecret = x.Bytes() -} - -// computeIVs computes the IVs and cipher required to start encrypting and decrypting. -func (session *encryptionSession) computeIVs() error { - var err error - - // First compute the secret key bytes, which is a hash of the salt and the shared secret computed using - // the method above. - first12 := append([]byte(nil), session.sharedSecret[:12]...) - sec := append(first12, 0, 0, 1, 228) - session.secretKeyBytes = sha256.Sum256(append(sec, session.salt...)) - session.cipherBlock, err = aes.NewCipher(session.secretKeyBytes[:]) - if err != nil { - return fmt.Errorf("error creating AES cipher: %v", err) - } - - session.encryptIV = append([]byte{}, session.secretKeyBytes[:aes.BlockSize]...) - session.decryptIV = append([]byte{}, session.secretKeyBytes[:aes.BlockSize]...) - return nil -} - -// encrypt encrypts the data passed in the slice itself. -func (session *encryptionSession) encrypt(data []byte) { - for i := range data { - cipherFeedback := cipher.NewCFBEncrypter(session.cipherBlock, session.encryptIV) - cipherFeedback.XORKeyStream(data[i:i+1], data[i:i+1]) - session.encryptIV = append(session.encryptIV[1:], data[i]) - } -} - -// decrypt decrypts the data passed in the slice itself. -func (session *encryptionSession) decrypt(data []byte) { - for i, b := range data { - cipherFeedback := cipher.NewCFBDecrypter(session.cipherBlock, session.decryptIV) - cipherFeedback.XORKeyStream(data[i:i+1], data[i:i+1]) - session.decryptIV = append(session.decryptIV[1:], b) - } -} diff --git a/lib/fbauth/nemc_access_wrapper.go b/lib/fbauth/nemc_access_wrapper.go deleted file mode 100644 index 615156853..000000000 --- a/lib/fbauth/nemc_access_wrapper.go +++ /dev/null @@ -1,234 +0,0 @@ -package fbauth - -import ( - "context" - "encoding/base64" - "encoding/json" - "fmt" - "strings" -) - -type AccessWrapper struct { - ServerCode string - ServerPassword string - FBToken string - Client *Client - ucUserName string - ucUID string - privateKeyStr, keyProveStr string -} - -func NewAccessWrapper(client *Client, FBToken string) *AccessWrapper { - return &AccessWrapper{ - Client: client, - FBToken: FBToken, - } -} - -type FTokenRequest struct { - Action string `json:"action"` - Username string `json:"username"` - Password string `json:"password"` -} - -func GetTokenByPassword(connectCtx context.Context, client *Client, userName, userPassword string) (writeBackToken string, err error) { - fakePassword := &struct { - EncryptToken bool `json:"encrypt_token"` - Username string `json:"username"` - Password string `json:"password"` - }{ - EncryptToken: true, - Username: userName, - Password: userPassword, - } - - fakePasswdStr, err := json.Marshal(fakePassword) - if err != nil { - panic(fmt.Errorf("Failed to encode json %v", err)) - } - rspreq := &struct { - Action string `json:"action"` - Username string `json:"username"` - Password string `json:"password"` - }{ - Action: "phoenix::get-token", - Username: "", - Password: string(fakePasswdStr), - } - - msg, err := json.Marshal(rspreq) - if err != nil { - panic(fmt.Errorf("Failed to encode json %v", err)) - } - resp, err := client.SendMessageAndGetResponseWithDeadline(msg, connectCtx) - if err != nil { - return "", fmt.Errorf("user auth fail: may be incorrect username or password (%v)", err) - } - code, _ := resp["code"].(float64) - if code != 0 { - return "", fmt.Errorf("user auth fail: %v", resp["message"].(string)) - } - FBToken, ok := resp["token"].(string) - if !ok { - return "", fmt.Errorf("user auth fail: may be incorrect username or password (invalid server token response)") - } - return FBToken, nil -} - -func (aw *AccessWrapper) SetServerInfo(ServerCode, Password string) { - aw.ServerCode = ServerCode - aw.ServerPassword = Password -} - -func (aw *AccessWrapper) GetFBUid() string { - return aw.ucUID -} - -type AuthRequest struct { - Action string `json:"action"` - ServerCode string `json:"serverCode"` - ServerPassword string `json:"serverPassword"` - Key string `json:"publicKey"` - FBToken string - ProtocolVersionId int64 `json:"version_id"` -} - -func (aw *AccessWrapper) auth(ctx context.Context, publicKey []byte) (resp string, err error) { - authreq := &AuthRequest{ - Action: "phoenix::login", - ServerCode: aw.ServerCode, - ServerPassword: aw.ServerPassword, - Key: base64.StdEncoding.EncodeToString(publicKey), - FBToken: aw.FBToken, - ProtocolVersionId: 2, - } - msg, err := json.Marshal(authreq) - if err != nil { - return "", err - } - response, err := aw.Client.SendMessageAndGetResponseWithDeadline(msg, ctx) - if err != nil { - return "", err - } - errServerResponseFmt := fmt.Errorf("cannot understand the format of server response") - code, ok := response["code"].(float64) - if !ok { - return "", errServerResponseFmt - } - if code != 0 { - errS, ok := response["message"].(string) - if !ok { - return "", errServerResponseFmt - } - //trans, hasTranslation := response["translation"].(float64) - return "", fmt.Errorf("%s", errS) - } - aw.ucUserName, ok = response["username"].(string) - if !ok { - return "", errServerResponseFmt - } - aw.ucUID, ok = response["uid"].(string) - if !ok { - return "", errServerResponseFmt - } - chainInfo, ok := response["chainInfo"].(string) - if !ok { - return "", errServerResponseFmt - } - if aw.privateKeyStr, ok = response["privateSigningKey"].(string); !ok { - aw.privateKeyStr = "" - } - if aw.keyProveStr, ok = response["prove"].(string); !ok { - aw.keyProveStr = "" - } - return chainInfo, nil -} - -func (aw *AccessWrapper) GetAccess(ctx context.Context, publicKey []byte) (address string, chainInfo string, err error) { - chainAddr, err := aw.auth(ctx, publicKey) - if err != nil { - return "", "", err - } - chainAndAddr := strings.Split(chainAddr, "|") - if chainAndAddr == nil || len(chainAndAddr) != 2 { - return "", "", fmt.Errorf("fail to request rentail server entry") - } - chainInfo = chainAndAddr[0] - address = chainAndAddr[1] - return address, chainInfo, nil -} - -func (aw *AccessWrapper) BotOwner(ctx context.Context) (name string, err error) { - rspreq := struct { - Action string `json:"action"` - }{ - Action: "phoenix::get-user", - } - msg, _ := json.Marshal(rspreq) - resp, err := aw.Client.SendMessageAndGetResponseWithDeadline(msg, ctx) - if err != nil { - return "", err - } - shouldRespond, _ := resp["username"].(string) - return shouldRespond, nil -} - -type RPCEncRequest struct { - Action string `json:"action"` - Content string `json:"content"` - Uid string `json:"uid"` -} - -func (aw *AccessWrapper) TransferData(ctx context.Context, content string, uid string) (string, error) { - rspreq := &RPCEncRequest{ - Action: "phoenix::transfer-data", - Content: content, - Uid: uid, - } - msg, err := json.Marshal(rspreq) - if err != nil { - panic("Failed to encode json") - } - resp, err := aw.Client.SendMessageAndGetResponseWithDeadline(msg, ctx) - if err != nil { - return "", err - } - code, _ := resp["code"].(float64) - if code != 0 { - panic("Failed to transfer start type") - } - data, _ := resp["data"].(string) - return data, nil -} - -type RPCNumRequest struct { - Action string `json:"action"` - First string `json:"1st"` - Second string `json:"2nd"` - Third int64 `json:"3rd"` -} - -func (aw *AccessWrapper) TransferCheckNum(ctx context.Context, first string, second string, third int64) (string, string, string, error) { - rspreq := &RPCNumRequest{ - Action: "phoenix::transfer-check-num", - First: first, - Second: second, - Third: third, - } - msg, err := json.Marshal(rspreq) - if err != nil { - panic("Failed to encode json") - } - resp, err := aw.Client.SendMessageAndGetResponseWithDeadline(msg, ctx) - if err != nil { - return "", "", "", err - } - code, _ := resp["code"].(float64) - if code != 0 { - return "", "", "", fmt.Errorf("failed to transfer checknum %v", resp["message"]) - } - valM, _ := resp["valM"].(string) - valS, _ := resp["valS"].(string) - valT, _ := resp["valT"].(string) - return valM, valS, valT, nil -} diff --git a/lib/helpers/bot_privilege/pyrpcResponser.go b/lib/helpers/bot_privilege/pyrpcResponser.go deleted file mode 100644 index 182ce6f5a..000000000 --- a/lib/helpers/bot_privilege/pyrpcResponser.go +++ /dev/null @@ -1,121 +0,0 @@ -package bot_privilege - -import ( - "bytes" - "encoding/binary" - "phoenixbuilder/lib/minecraft/neomega/omega" - "phoenixbuilder/minecraft/protocol/packet" - "strings" -) - -type PyRPCResponser struct { - omega.MicroOmega - isCheckNumResponded bool - chanCheckNumResponded chan struct{} - isGetStartTypeResponded bool - chanGetStartTypeResponded chan struct{} - clientClosed <-chan struct{} - TransferData func(content string, uid string) string - TransferCheckNum func(firstArg string, secondArg string, botEntityUniqueID int64) (valM string, valS string, valT string) - Uid string -} - -func NewPyRPCResponser(omega omega.MicroOmega, Uid string, clientClosed <-chan struct{}, TransferData func(content string, uid string) string, TransferCheckNum func(firstArg string, secondArg string, botEntityUniqueID int64) (valM string, valS string, valT string)) *PyRPCResponser { - responser := &PyRPCResponser{ - MicroOmega: omega, - Uid: Uid, - TransferData: TransferData, - TransferCheckNum: TransferCheckNum, - chanCheckNumResponded: make(chan struct{}), - chanGetStartTypeResponded: make(chan struct{}), - clientClosed: clientClosed, - } - omega.GetGameListener().SetOnTypedPacketCallBack(packet.IDPyRpc, responser.onPyRPC) - return responser -} - -func (o *PyRPCResponser) ChallengeCompete() bool { - select { - case <-o.clientClosed: - return false - case <-o.chanGetStartTypeResponded: - if o.isCheckNumResponded { - return true - } else { - return o.ChallengeCompete() - } - case <-o.chanCheckNumResponded: - if o.isGetStartTypeResponded { - return true - } else { - return o.ChallengeCompete() - } - } -} - -func (o *PyRPCResponser) onPyRPC(pk packet.Packet) { - p, ok := pk.(*packet.PyRpc) - if !ok { - return - } - if strings.Contains(string(p.Content), "GetStartType") { - // fmt.Printf("GetStartType: %X", p.Content) - // thank you rup! - encData := p.Content[len(p.Content)-163 : len(p.Content)-1] - response := o.TransferData(string(encData), o.Uid) - //fmt.Printf("%s\n", response) - o.GetGameControl().SendPacket(&packet.PyRpc{ - Content: bytes.Join([][]byte{[]byte{0x82, 0xc4, 0x8, 0x5f, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x5f, 0xc4, 0x5, 0x74, 0x75, 0x70, 0x6c, 0x65, 0xc4, 0x5, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x93, 0xc4, 0xc, 0x53, 0x65, 0x74, 0x53, 0x74, 0x61, 0x72, 0x74, 0x54, 0x79, 0x70, 0x65, 0x82, 0xc4, 0x8, 0x5f, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x5f, 0xc4, 0x5, 0x74, 0x75, 0x70, 0x6c, 0x65, 0xc4, 0x5, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x91, 0xc4}, - []byte{byte(len(response))}, - []byte(response), - []byte{0xc0}, - }, []byte{}), - }) - if !o.isGetStartTypeResponded { - o.isGetStartTypeResponded = true - close(o.chanGetStartTypeResponded) - } - } else if !o.isCheckNumResponded { - if strings.Contains(string(p.Content), "GetMCPCheckNum") { - // This shit sucks, so as netease. - //fmt.Printf("%X", p.Content) - //fmt.Printf("%s\n", p.Content) - firstArgLenB := p.Content[19:21] - firstArgLen := binary.BigEndian.Uint16(firstArgLenB) - firstArg := string(p.Content[21 : 21+firstArgLen]) - secondArgLen := uint16(p.Content[23+firstArgLen]) - secondArg := string(p.Content[24+firstArgLen : 24+firstArgLen+secondArgLen]) - //fmt.Printf("%s\n", secondArg) - //valM,_:=getUserInputMD5() - //valS,_:=getUserInputMD5() - //valM := utils.GetMD5(fmt.Sprintf("qhk+um%ssvdrx,9=>", secondArg)) - //valS := utils.GetMD5(fmt.Sprintf("%s%s", valM[16:], valM[:16])) - //fmt.Printf("%s\n",valM) - valM, valS, valT := o.TransferCheckNum(firstArg, secondArg, o.GetBotInfo().GetBotUniqueID()) - /*conn.WritePacket(&packet.PyRpc{ - Content: bytes.Join([][]byte{[]byte{0x82, 0xc4, 0x8, 0x5f, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x5f, 0xc4, 0x5, 0x74, 0x75, 0x70, 0x6c, 0x65, 0xc4, 0x5, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x93, 0xc4, 0xe, 0x53, 0x65, 0x74, 0x4d, 0x43, 0x50, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x4e, 0x75, 0x6d, 0x82, 0xc4, 0x8, 0x5f, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x5f, 0xc4, 0x5, 0x74, 0x75, 0x70, 0x6c, 0x65, 0xc4, 0x5, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x91, 0xc4, 0x20}, - []byte(valM), - []byte{0xc0}, - }, []byte{}), - })*/ - o.GetGameControl().SendPacket(&packet.PyRpc{ - Content: bytes.Join([][]byte{[]byte{0x93, 0xc4, 0x0e}, []byte("SetMCPCheckNum"), []byte{0x91, 0x98, 0xc4, 0x20}, - []byte(valM), - []byte{0xc4, 0x20}, - []byte(valS), - []byte{0xc2}, - []byte{0x90}, - []byte{0xc4, 0x00}, - []byte{0xc4, 0x00}, - []byte{3}, - []byte{0xc4, 0x20}, - []byte(valT), - []byte{0xC0}, - }, []byte{}), - }) - o.isCheckNumResponded = true - close(o.chanCheckNumResponded) - } - - } -} diff --git a/lib/helpers/bot_privilege/setupHelper.go b/lib/helpers/bot_privilege/setupHelper.go deleted file mode 100644 index 29a668749..000000000 --- a/lib/helpers/bot_privilege/setupHelper.go +++ /dev/null @@ -1,99 +0,0 @@ -package bot_privilege - -import ( - "errors" - "fmt" - "phoenixbuilder/lib/minecraft/neomega/omega" - "phoenixbuilder/minecraft/protocol/packet" - "strings" - "time" -) - -type SetupHelper struct { - omega.MicroOmega - hasOpPrivilege bool - cheatOn bool -} - -func NewSetupHelper(omega omega.MicroOmega) *SetupHelper { - helper := &SetupHelper{ - MicroOmega: omega, - } - omega.GetGameListener().SetOnTypedPacketCallBack(packet.IDAdventureSettings, helper.onAdventurePacket) - return helper -} - -func (o *SetupHelper) onAdventurePacket(pk packet.Packet) { - p := pk.(*packet.AdventureSettings) - if o.GetBotInfo().GetBotUniqueID() == p.PlayerUniqueID { - if p.PermissionLevel >= packet.PermissionLevelOperator { - o.hasOpPrivilege = true - fmt.Println("机器人已获得管理员权限") - } else { - fmt.Println("请给予机器人管理员权限") - if o.hasOpPrivilege { - o.lostPrivilege() - } - o.hasOpPrivilege = false - } - } -} - -func (o *SetupHelper) lostPrivilege() { - panic(fmt.Errorf("机器人OP权限被关闭")) -} - -var ErrMaximumWaitTimeExeceed = errors.New("maximum wait time execeed") - -func (o *SetupHelper) WaitOK(challengeCompleted func() bool) { - time.Sleep(3 * time.Second) - for !o.hasOpPrivilege { - o.GetGameControl().SendWSCmdAndInvokeOnResponse("tp @s ~~~", func(output *packet.CommandOutput) { - if output.SuccessCount > 0 { - o.hasOpPrivilege = true - } - }) - o.GetGameControl().BotSay("请给予机器人管理员权限") - fmt.Println("请给予机器人管理权限") - time.Sleep(1 * time.Second) - } - fmt.Println("机器人已获得管理权限") - first := true - fmt.Println("等待FB服务器答复网易租赁服 challenge ...") - success := challengeCompleted() - if !success { - panic(fmt.Errorf("FB服务器未能在一定时间内完成网易租赁服零知识身份证明")) - } else { - fmt.Println("已完成网易租赁服关于机器人的零知识身份证明") - } - for !o.cheatOn { - o.GetGameControl().SendWSCmdAndInvokeOnResponse("testforblock ~~~ air 0", func(output *packet.CommandOutput) { - if output.SuccessCount > 0 { - o.cheatOn = true - } - if len(output.OutputMessages) > 0 { - if strings.Contains(output.OutputMessages[0].Message, "commands.generic.disabled") { - o.cheatOn = false - if first { - fmt.Println("请打开作弊模式") - first = false - } - } else { - fmt.Println("作弊模式已经打开") - o.cheatOn = true - } - } - }) - o.GetGameControl().SendWSCmdAndInvokeOnResponse("tp @s ~~~", func(output *packet.CommandOutput) { - if output.SuccessCount > 0 { - o.cheatOn = true - } - }) - time.Sleep(3 * time.Second) - if !o.cheatOn { - o.GetGameControl().BotSay("请打开作弊模式") - fmt.Println("请打开作弊模式") - } - } - -} diff --git a/lib/minecraft/neomega/bundle/micro.go b/lib/minecraft/neomega/bundle/micro.go deleted file mode 100644 index 2128484ba..000000000 --- a/lib/minecraft/neomega/bundle/micro.go +++ /dev/null @@ -1,65 +0,0 @@ -package bundle - -import ( - "phoenixbuilder/lib/minecraft/neomega/decouple/block/placer" - "phoenixbuilder/lib/minecraft/neomega/decouple/cmdsender" - "phoenixbuilder/lib/minecraft/neomega/decouple/core" - "phoenixbuilder/lib/minecraft/neomega/decouple/infosender" - "phoenixbuilder/lib/minecraft/neomega/omega" - "phoenixbuilder/lib/minecraft/neomega/uqholder" - "phoenixbuilder/minecraft" -) - -func init() { - if false { - func(omega omega.MicroOmega) {}(&MicroOmega{}) - } -} - -type MicroOmega struct { - omega.ReactCore - omega.InteractCore - omega.InfoSender - omega.CmdSender - omega.BotBasicInfoHolder - omega.BlockPlacer -} - -func (o *MicroOmega) GetBotInfo() omega.BotBasicInfoHolder { - return o.BotBasicInfoHolder -} - -type MicroOmegaOption struct { - CmdSenderOptions cmdsender.Options - PrintUQHolderDebugInfo bool -} - -func NewMicroOmega(conn *minecraft.Conn, options MicroOmegaOption) *MicroOmega { - reactable := core.NewReactCore() - interactCore := core.NewInteractCore(conn) - cmdSender := cmdsender.NewCmdSender(reactable, interactCore, options.CmdSenderOptions) - botBasicInfoHolder := uqholder.NewBotInfoHolder(conn, options.PrintUQHolderDebugInfo) - infoSender := infosender.NewInfoSender(interactCore, cmdSender, botBasicInfoHolder) - blockPlacer := placer.NewBlockPlacer(reactable, cmdSender, interactCore) - return &MicroOmega{ - reactable, - interactCore, - infoSender, - cmdSender, - botBasicInfoHolder, - blockPlacer, - } -} - -func (o *MicroOmega) GetGameControl() interface { - omega.InteractCore - omega.CmdSender - omega.InfoSender - omega.BlockPlacer -} { - return o -} - -func (o *MicroOmega) GetGameListener() omega.PacketDispatcher { - return o -} diff --git a/lib/minecraft/neomega/decouple/core/interact.go b/lib/minecraft/neomega/decouple/core/interact.go deleted file mode 100644 index de3df674a..000000000 --- a/lib/minecraft/neomega/decouple/core/interact.go +++ /dev/null @@ -1,19 +0,0 @@ -package core - -import ( - "phoenixbuilder/lib/minecraft/neomega/omega" - "phoenixbuilder/minecraft" - "phoenixbuilder/minecraft/protocol/packet" -) - -type InteractCore struct { - *minecraft.Conn -} - -func (i *InteractCore) SendPacket(packet packet.Packet) { - i.WritePacket(packet) -} - -func NewInteractCore(conn *minecraft.Conn) omega.InteractCore { - return &InteractCore{Conn: conn} -} diff --git a/lib/minecraft/neomega/omega/basic.go b/lib/minecraft/neomega/omega/basic.go deleted file mode 100644 index 8c2b3343e..000000000 --- a/lib/minecraft/neomega/omega/basic.go +++ /dev/null @@ -1,21 +0,0 @@ -package omega - -import "phoenixbuilder/lib/minecraft/mirror/define" - -type GameChat interface { -} - -type PlayerMsgReceivable interface { - SetOnParamMsg(func(chat GameChat) (catch bool)) error - GetOnParamMsg() func(chat GameChat) (catch bool) -} - -type PlayerKit interface { - Say(msg string) - RawSay(msg string) - ActionBar(msg string) - Title(msg string) - SubTitle(msg string) - GetRelatedUQ() PlayerUQReader - GetPos(selector string) chan *define.CubePos -} diff --git a/lib/minecraft/neomega/omega/uqholder.go b/lib/minecraft/neomega/omega/uqholder.go deleted file mode 100644 index 47cffcb26..000000000 --- a/lib/minecraft/neomega/omega/uqholder.go +++ /dev/null @@ -1,24 +0,0 @@ -package omega - -import "github.com/google/uuid" - -type BotBasicInfoHolder interface { - GetBotName() string - GetBotRuntimeID() uint64 - GetBotUniqueID() int64 -} - -type PlayerUQsHolder interface { - GetPlayerUQByName(name string) (uq PlayerUQReader, found bool) - GetPlayerUQByUUID(ud uuid.UUID) (uq PlayerUQReader, found bool) - GetBot() (botUQ PlayerUQReader) -} - -type PlayerUQReader interface { - IsBot() bool - GetPlayerName() string -} - -type PlayerUQ interface { - PlayerUQReader -} diff --git a/lib/minecraft/neomega/uqholder/botInfo.go b/lib/minecraft/neomega/uqholder/botInfo.go deleted file mode 100644 index 4c858167e..000000000 --- a/lib/minecraft/neomega/uqholder/botInfo.go +++ /dev/null @@ -1,57 +0,0 @@ -package uqholder - -import ( - "fmt" - "phoenixbuilder/lib/minecraft/neomega/omega" - minecraft "phoenixbuilder/minecraft" -) - -func init() { - if false { - func(omega.BotBasicInfoHolder) {}(&BotInfoHolder{}) - func(uq omega.PlayerUQ) {}(&BotInfoHolder{}) - } -} - -type BotInfoHolder struct { - debug bool - BotName string - BotRuntimeID uint64 - BotUniqueID int64 -} - -func (b *BotInfoHolder) IsBot() bool { - return true -} - -func (b *BotInfoHolder) GetPlayerName() string { - return b.GetBotName() -} - -func (b *BotInfoHolder) GetBotName() string { - return b.BotName -} - -func (b *BotInfoHolder) GetBotRuntimeID() uint64 { - return b.BotRuntimeID -} - -func (b *BotInfoHolder) GetBotUniqueID() int64 { - return b.BotUniqueID -} - -func NewBotInfoHolder(conn *minecraft.Conn, debug bool) omega.BotBasicInfoHolder { - h := &BotInfoHolder{ - debug: debug, - } - gd := conn.GameData() - h.BotRuntimeID = gd.EntityRuntimeID - h.BotUniqueID = gd.EntityUniqueID - h.BotName = conn.IdentityData().DisplayName - if h.debug { - fmt.Printf("uqHolder.GetBotName()=%v\n", h.GetBotName()) - fmt.Printf("uqHolder.GetBotRuntimeID()=%v\n", h.GetBotRuntimeID()) - fmt.Printf("uqHolder.GetBotUniqueID()=%v\n", h.GetBotUniqueID()) - } - return h -} diff --git a/lib/minecraft/neomega/uqholder/playerUQ.go b/lib/minecraft/neomega/uqholder/playerUQ.go deleted file mode 100644 index e63380966..000000000 --- a/lib/minecraft/neomega/uqholder/playerUQ.go +++ /dev/null @@ -1,22 +0,0 @@ -package uqholder - -import "phoenixbuilder/lib/minecraft/neomega/omega" - -func init() { - if false { - func(uq omega.PlayerUQ) {}(&PlayerUQ{}) - } -} - -type PlayerUQ struct { -} - -func (p PlayerUQ) IsBot() bool { - //TODO implement me - panic("implement me") -} - -func (p PlayerUQ) GetPlayerName() string { - //TODO implement me - panic("implement me") -} diff --git a/lib/minecraft/neomega/uqholder/uqholder.go b/lib/minecraft/neomega/uqholder/uqholder.go deleted file mode 100644 index 62d1c3731..000000000 --- a/lib/minecraft/neomega/uqholder/uqholder.go +++ /dev/null @@ -1 +0,0 @@ -package uqholder diff --git a/lib/utils/core/processCMDOutput.go b/lib/utils/core/processCMDOutput.go deleted file mode 100644 index 901c7ece3..000000000 --- a/lib/utils/core/processCMDOutput.go +++ /dev/null @@ -1,12 +0,0 @@ -//go:build !is_tweak - -package utils_core - -import ( - "phoenixbuilder/io/commands" - "phoenixbuilder/minecraft/protocol/packet" -) - -// 此实现在非 is_tweak 构建下已被迁移至 -// package GlobalAPI(pheonixbuilder/GameControl/GlobalAPI) -func ProcessCommandOutput(sender *commands.CommandSender, resp *packet.CommandOutput) {} diff --git a/lib/utils/core/processCMDOutput_tweak.go b/lib/utils/core/processCMDOutput_tweak.go deleted file mode 100644 index 2d1321d2e..000000000 --- a/lib/utils/core/processCMDOutput_tweak.go +++ /dev/null @@ -1,16 +0,0 @@ -//go:build is_tweak - -package utils_core - -import ( - "phoenixbuilder/io/commands" - "phoenixbuilder/minecraft/protocol/packet" -) - -func ProcessCommandOutput(sender *commands.CommandSender, resp *packet.CommandOutput) { - pr, ok := sender.UUIDMap.LoadAndDelete(resp.CommandOrigin.UUID.String()) - if ok { - pu := pr.(chan *packet.CommandOutput) - pu <- resp - } -} diff --git a/minecraft/conn.go b/minecraft/conn.go index 49f854ba0..473895ddb 100644 --- a/minecraft/conn.go +++ b/minecraft/conn.go @@ -10,6 +10,12 @@ import ( "fmt" "github.com/google/uuid" "github.com/sandertv/go-raknet" + "go.uber.org/atomic" + "gopkg.in/square/go-jose.v2" + "gopkg.in/square/go-jose.v2/jwt" + "io" + "log" + "net" "phoenixbuilder/minecraft/internal" "phoenixbuilder/minecraft/nbt" "phoenixbuilder/minecraft/protocol" @@ -17,12 +23,6 @@ import ( "phoenixbuilder/minecraft/protocol/packet" "phoenixbuilder/minecraft/resource" "phoenixbuilder/minecraft/text" - "go.uber.org/atomic" - "gopkg.in/square/go-jose.v2" - "gopkg.in/square/go-jose.v2/jwt" - "io" - "log" - "net" "strings" "sync" "time" @@ -125,7 +125,7 @@ type Conn struct { disconnectMessage atomic.String shieldID atomic.Int32 - + DebugMode bool } @@ -164,6 +164,10 @@ func newConn(netConn net.Conn, key *ecdsa.PrivateKey, log *log.Logger) *Conn { return conn } +func (conn *Conn) GetShieldID() int32 { + return conn.shieldID.Load() +} + // IdentityData returns the identity data of the connection. It holds the UUID, XUID and username of the // connected client. func (conn *Conn) IdentityData() login.IdentityData { @@ -320,6 +324,37 @@ func (conn *Conn) WritePacket(pk packet.Packet) error { return nil } +func (conn *Conn) WritePacketByte(pkID uint32, data []byte) error { + if conn.DebugMode { + return nil + } + select { + case <-conn.close: + return conn.closeErr("write packet") + default: + } + conn.sendMu.Lock() + defer conn.sendMu.Unlock() + + buf := internal.BufferPool.Get().(*bytes.Buffer) + defer func() { + // Reset the buffer so we can return it to the buffer pool safely. + buf.Reset() + internal.BufferPool.Put(buf) + }() + + conn.hdr.PacketID = pkID + _ = conn.hdr.Write(buf) + l := buf.Len() + buf.Write(data) + if conn.packetFunc != nil { + conn.packetFunc(*conn.hdr, buf.Bytes()[l:], conn.LocalAddr(), conn.RemoteAddr()) + } + + conn.bufferedSend = append(conn.bufferedSend, append([]byte(nil), buf.Bytes()...)) + return nil +} + // ReadPacket reads a packet from the Conn, depending on the packet ID that is found in front of the packet // data. If a read deadline is set, an error is returned if the deadline is reached before any packet is // received. ReadPacket must not be called on multiple goroutines simultaneously. diff --git a/minecraft/protocol/packet/py_rpc.go b/minecraft/protocol/packet/py_rpc.go index 031673214..f09551cc7 100644 --- a/minecraft/protocol/packet/py_rpc.go +++ b/minecraft/protocol/packet/py_rpc.go @@ -4,11 +4,12 @@ import ( //"bytes" //"fmt" "phoenixbuilder/minecraft/protocol" + "phoenixbuilder/fastbuilder/py_rpc" ) type PyRpc struct { - Content []byte + Value py_rpc.PyRpcObject } // ID ... @@ -18,7 +19,9 @@ func (*PyRpc) ID() uint32 { // Marshal ... func (pk *PyRpc) Marshal(w *protocol.Writer) { - w.ByteSlice(&pk.Content) + //w.ByteSlice(&pk.Content) + content:=pk.Value.Marshal() + w.ByteSlice(&content) w.Bytes(&[]byte{0xae,0x23,0xdb,0x05}) //fmt.Printf("%d\n",len(pk.Content)) //fmt.Printf("%X\n",buf.Bytes()) @@ -34,7 +37,10 @@ func (pk *PyRpc) Marshal(w *protocol.Writer) { // Unmarshal ... func (pk *PyRpc) Unmarshal(r *protocol.Reader) { - r.ByteSlice(&pk.Content) + var content []byte + r.ByteSlice(&content) + pk.Value=py_rpc.Unmarshal(content) + //r.ByteSlice(&pk.Content) /*var bt byte var bt2 byte var bt3 byte diff --git a/newcircle_test/test.js b/newcircle_test/test.js deleted file mode 100644 index 5280126ef..000000000 --- a/newcircle_test/test.js +++ /dev/null @@ -1,13 +0,0 @@ -function circle(radius) { - let arr=[]; - let radius_square=Math.pow(radius,2); - for(let i=0;i<=radius;i++) { // x - let first_quadrant_val=Math.sqrt(radius_square-Math.pow(i,2)); - arr.push([i,first_quadrant_val]); - if(first_quadrant_val)arr.push([i,-first_quadrant_val]); - if(i)arr.push([-i,first_quadrant_val]); - if(first_quadrant_val&&i)arr.push([-i,-first_quadrant_val]); - } - return arr; -} -console.log(circle(10)); \ No newline at end of file diff --git a/omega/cli/embed/embed.go b/omega/cli/embed/embed.go index 783430ded..2f2db36a6 100644 --- a/omega/cli/embed/embed.go +++ b/omega/cli/embed/embed.go @@ -76,7 +76,7 @@ func (ea *EmbeddedAdaptor) QuerySensitiveInfo(key defines.SensitiveInfoType) (re case defines.SENSITIVE_INFO_SERVER_CODE_HASH: rawVal = ea.env.ServerCode case defines.SENSITIVE_INFO_USERNAME_HASH: - _frags := strings.Split(ea.env.FBUCUsername, "|") + _frags := strings.Split(ea.env.ClientOptions.FBUCUsername, "|") if len(_frags) > 0 { rawVal = _frags[0] } diff --git a/omega/components/qqGroupLink/cq-http.go b/omega/components/qqGroupLink/cq-http.go index 903599541..38a15f557 100644 --- a/omega/components/qqGroupLink/cq-http.go +++ b/omega/components/qqGroupLink/cq-http.go @@ -394,6 +394,35 @@ func (cq *QGroupLink) onNewGameMsg(chat *defines.GameChat) bool { if len(chat.RawParameters) > 0 { msg = msg + " (" + strings.Join(chat.RawParameters, ", ") + ")" } + if strings.HasPrefix(msg, "{\"rawtext") { + // handle json + var jsonMsg struct { + Texts []struct { + Text string `json:"text"` + } `json:"rawtext"` + } + if err := json.Unmarshal([]byte(msg), &jsonMsg); err == nil { + cleanedMsg := "" + for _, v := range jsonMsg.Texts { + cleanedMsg += v.Text + } + // remove anything like §a, §l, etc + cleanedMsg = strings.ReplaceAll(cleanedMsg, "%%", "%") + ignoreNext := false + for _, v := range msg { + if ignoreNext { + ignoreNext = false + continue + } + if v == '§' { + ignoreNext = true + continue + } + cleanedMsg += string(v) + } + msg = cleanedMsg + } + } if cq.ShowExchangeDetail { cq.Frame.GetBackendDisplay().Write("MC->QQ: " + msg) } diff --git a/omega/utils/text_coding.go b/omega/utils/text_coding.go index db16822a1..51ff5dbe5 100644 --- a/omega/utils/text_coding.go +++ b/omega/utils/text_coding.go @@ -7,6 +7,8 @@ import ( "golang.org/x/text/encoding/simplifiedchinese" ) +// Better to just drop GBK support + func IsGBK(data []byte) (isGBK bool, failAtPos int) { length := len(data) var i int = 0 diff --git a/plantform_specific/fix_timer/others.go b/plantform_specific/fix_timer/others.go deleted file mode 100644 index 57d9d27b9..000000000 --- a/plantform_specific/fix_timer/others.go +++ /dev/null @@ -1,3 +0,0 @@ -//go:build !windows - -package fixtimer diff --git a/plantform_specific/fix_timer/windows.go b/plantform_specific/fix_timer/windows.go deleted file mode 100644 index 1931a3829..000000000 --- a/plantform_specific/fix_timer/windows.go +++ /dev/null @@ -1,17 +0,0 @@ -//go:build windows - -package fixtimer - -import ( - "fmt" - "syscall" -) - -func init() { - var ( - winmmDLL = syscall.NewLazyDLL("winmm.dll") - procTimeBeginPeriod = winmmDLL.NewProc("timeBeginPeriod") - ) - fmt.Println("DEBUG: Try to use high precision timer") - procTimeBeginPeriod.Call(uintptr(1)) -} diff --git a/solutions/fastbuilder/bootstrap.go b/solutions/fastbuilder/bootstrap.go index 561e96352..8c57f610a 100644 --- a/solutions/fastbuilder/bootstrap.go +++ b/solutions/fastbuilder/bootstrap.go @@ -13,8 +13,6 @@ import ( "github.com/pterm/pterm" "phoenixbuilder/fastbuilder/readline" - _ "phoenixbuilder/io" - _ "phoenixbuilder/plantform_specific/fix_timer" ) func setup() { @@ -35,22 +33,22 @@ func setup() { } } - if !args.NoReadline() { + if !args.NoReadline { readline.InitReadline() } } func display_info() { pterm.DefaultBox.Println(pterm.LightCyan("https://github.com/LNSSPsd/PhoenixBuilder")) - pterm.Println(pterm.Yellow("PhoenixBuilder " + args.GetFBVersion())) + pterm.Println(pterm.Yellow("PhoenixBuilder " + args.FBVersion)) if I18n.ShouldDisplaySpecial() { fmt.Printf("%s", I18n.T(I18n.Special_Startup)) } } -func hash_check() { +func check_update() { fmt.Printf(I18n.T(I18n.Notice_CheckUpdate)) - hasUpdate, latestVersion := utils.CheckUpdate(args.GetFBVersion()) + hasUpdate, latestVersion := utils.CheckUpdate(args.FBPlainVersion) fmt.Printf(I18n.T(I18n.Notice_OK)) if hasUpdate { fmt.Printf(I18n.T(I18n.Notice_UpdateAvailable), latestVersion) @@ -61,22 +59,20 @@ func hash_check() { } func Bootstrap() { - args.ParseArgs() - if len(args.PackScripts()) != 0 { - os.Exit(script_bridge.MakePackage(args.PackScripts(), args.PackScriptsOut())) + //args.ParseArgs() + // ^^ Argument parser would parse arguments before go starts now + if len(args.PackScripts) != 0 { + os.Exit(script_bridge.MakePackage(args.PackScripts, args.PackScriptsOut)) } - // setup pterm - // setup i18n - // setup readline setup() display_info() defer Fatal() - if args.DebugMode() { + if args.DebugMode { init_and_run_debug_client() return } - if !args.ShouldDisableHashCheck() { - hash_check() + if !args.ShouldDisableVersionCheck { + check_update() } token := loadFBTokenOrAskFBCredential() @@ -89,8 +85,8 @@ func runInteractiveClient(token string) { if !args.SpecifiedServer() { code, serverPasswd, err = credentials.GetRentalServerCode() } else { - code = args.ServerCode() - serverPasswd = args.ServerPassword() + code = args.ServerCode + serverPasswd = args.ServerPassword } if err != nil { diff --git a/solutions/fastbuilder/core.go b/solutions/fastbuilder/core.go index 80c01cb65..48ca11cf6 100644 --- a/solutions/fastbuilder/core.go +++ b/solutions/fastbuilder/core.go @@ -2,16 +2,11 @@ package fastbuilder import ( "bufio" - "bytes" "context" - "encoding/binary" "encoding/json" "fmt" "os" - "phoenixbuilder/GameControl/GlobalAPI" - "phoenixbuilder/GameControl/ResourcesControlCenter" "phoenixbuilder/fastbuilder/args" - "phoenixbuilder/fastbuilder/configuration" "phoenixbuilder/fastbuilder/core" fbauth "phoenixbuilder/fastbuilder/cv4/auth" "phoenixbuilder/fastbuilder/environment" @@ -19,15 +14,15 @@ import ( "phoenixbuilder/fastbuilder/function" I18n "phoenixbuilder/fastbuilder/i18n" "phoenixbuilder/fastbuilder/move" + "phoenixbuilder/fastbuilder/py_rpc" "phoenixbuilder/fastbuilder/readline" script_bridge "phoenixbuilder/fastbuilder/script_engine/bridge" "phoenixbuilder/fastbuilder/signalhandler" fbtask "phoenixbuilder/fastbuilder/task" "phoenixbuilder/fastbuilder/types" "phoenixbuilder/fastbuilder/uqHolder" - "phoenixbuilder/fastbuilder/utils" - "phoenixbuilder/io/commands" - utils_core "phoenixbuilder/lib/utils/core" + GameInterface "phoenixbuilder/game_control/game_interface" + ResourcesControl "phoenixbuilder/game_control/resources_control" "phoenixbuilder/minecraft" "phoenixbuilder/minecraft/protocol" "phoenixbuilder/minecraft/protocol/packet" @@ -39,16 +34,15 @@ import ( "strings" "time" - "github.com/google/uuid" "github.com/pterm/pterm" ) func EnterReadlineThread(env *environment.PBEnvironment, breaker chan struct{}) { - if args.NoReadline() { + if args.NoReadline { return } defer Fatal() - commandSender := env.CommandSender.(*commands.CommandSender) + gameInterface := env.GameInterface functionHolder := env.FunctionHolder.(*function.FunctionHolder) for { if breaker != nil { @@ -67,32 +61,12 @@ func EnterReadlineThread(env *environment.PBEnvironment, breaker chan struct{}) continue } if cmd[0] == '.' { - resp, _ := env.GlobalAPI.(*GlobalAPI.GlobalAPI).SendCommandWithResponce(cmd[1:]) + resp, _ := gameInterface.SendCommandWithResponse(cmd[1:]) fmt.Printf("%+v\n", resp) } else if cmd[0] == '!' { - resp, _ := env.GlobalAPI.(*GlobalAPI.GlobalAPI).SendWSCommandWithResponce(cmd[1:]) + resp, _ := gameInterface.SendWSCommandWithResponse(cmd[1:]) fmt.Printf("%+v\n", resp) } - if cmd == "move" { - go func() { - for { - move.Auto() - time.Sleep(time.Second / 20) - } - }() - continue - } - if cmd[0] == '>' && len(cmd) > 1 { - umsg := cmd[1:] - if env.FBAuthClient != nil { - fbcl := env.FBAuthClient.(*fbauth.Client) - if !fbcl.CanSendMessage() { - commandSender.WorldChatOutput("FastBuilder", "Lost connection to the authentication server.") - break - } - fbcl.WorldChat(umsg) - } - } functionHolder.Process(cmd) } } @@ -100,7 +74,6 @@ func EnterReadlineThread(env *environment.PBEnvironment, breaker chan struct{}) func EnterWorkerThread(env *environment.PBEnvironment, breaker chan struct{}) { conn := env.Connection.(*minecraft.Conn) hostBridgeGamma := env.ScriptBridge.(*script_bridge.HostBridgeGamma) - commandSender := env.CommandSender.(*commands.CommandSender) functionHolder := env.FunctionHolder.(*function.FunctionHolder) chunkAssembler := assembler.NewAssembler(assembler.REQUEST_AGGRESSIVE, time.Second*5) @@ -118,6 +91,7 @@ func EnterWorkerThread(env *environment.PBEnvironment, breaker chan struct{}) { default: } } + pk, data, err := conn.ReadPacketAndBytes() if err != nil { panic(err) @@ -126,76 +100,51 @@ func EnterWorkerThread(env *environment.PBEnvironment, breaker chan struct{}) { { p, ok := pk.(*packet.PyRpc) if ok { - if strings.Contains(string(p.Content), "GetStartType") { - // 2021-12-22 10:51~11:55 - // 2023-05-30 - // Thank netease for wasting my time again ;) - //fmt.Printf("%X\n", p.Content) - encData := p.Content[len(p.Content)-163 : len(p.Content)-1] - //fmt.Printf("%s\n", p.Content) - //fmt.Printf("%s\n", encData) - //fmt.Printf("%s\n", env.Uid) + go_p_val := p.Value.MakeGo() + //json_val, _:=json.MarshalIndent(go_p_val, "", "\t") + //fmt.Printf("Received PyRpc: %s\n", json_val) + pyrpc_val := go_p_val.([]interface{}) + command := pyrpc_val[0].(string) + data := pyrpc_val[1].([]interface{}) + if command == "S2CHeartBeat" { + conn.WritePacket(&packet.PyRpc{ + Value: py_rpc.FromGo([]interface{}{ + "C2SHeartBeat", + data, + nil, + }), + }) + } else if command == "GetStartType" { client := env.FBAuthClient.(*fbauth.Client) - response := client.TransferData(string(encData), fmt.Sprintf("%s", env.Uid)) - //fmt.Printf("%s\n", response) + response := client.TransferData(data[0].(string), fmt.Sprintf("%s", env.FBAuthClient.(*fbauth.Client).Uid)) conn.WritePacket(&packet.PyRpc{ - Content: bytes.Join([][]byte{[]byte{0x82, 0xc4, 0x8, 0x5f, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x5f, 0xc4, 0x5, 0x74, 0x75, 0x70, 0x6c, 0x65, 0xc4, 0x5, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x93, 0xc4, 0xc, 0x53, 0x65, 0x74, 0x53, 0x74, 0x61, 0x72, 0x74, 0x54, 0x79, 0x70, 0x65, 0x82, 0xc4, 0x8, 0x5f, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x5f, 0xc4, 0x5, 0x74, 0x75, 0x70, 0x6c, 0x65, 0xc4, 0x5, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x91, 0xc4}, - []byte{byte(len(response))}, - []byte(response), - []byte{0xc0}, - }, []byte{}), + Value: py_rpc.FromGo([]interface{}{ + "SetStartType", + []interface{}{response}, + nil, + }), }) - //fmt.Printf("%s\n", response) - } else if strings.Contains(string(p.Content), "GetMCPCheckNum") { - // This shit sucks, so as netease. + } else if command == "GetMCPCheckNum" { if getchecknum_everPassed { continue } - //fmt.Printf("%X", p.Content) - firstArgLenB := p.Content[19:21] - firstArgLen := binary.BigEndian.Uint16(firstArgLenB) - firstArg := string(p.Content[21 : 21+firstArgLen]) - secondArgLen := uint16(p.Content[23+firstArgLen]) - secondArg := string(p.Content[24+firstArgLen : 24+firstArgLen+secondArgLen]) - //fmt.Printf("%s\n%s\n",firstArg, secondArg) - //fmt.Printf("%v\n", env.Connection.(*minecraft.Conn).GameData().EntityUniqueID) - //fmt.Printf("%X\n", p.Content) - //valM,_:=getUserInputMD5() - //valS,_:=getUserInputMD5() - //valT,_:=getUserInputMD5() - + firstArg := data[0].(string) + secondArg := (data[1].([]interface{}))[0].(string) client := env.FBAuthClient.(*fbauth.Client) - valM, valS, valT := client.TransferCheckNum(firstArg, secondArg, env.Connection.(*minecraft.Conn).GameData().EntityUniqueID) - - /*conn.WritePacket(&packet.PyRpc{ - Content: bytes.Join([][]byte{[]byte{0x82, 0xc4, 0x8, 0x5f, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x5f, 0xc4, 0x5, 0x74, 0x75, 0x70, 0x6c, 0x65, 0xc4, 0x5, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x93, 0xc4, 0xe, 0x53, 0x65, 0x74, 0x4d, 0x43, 0x50, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x4e, 0x75, 0x6d, 0x82, 0xc4, 0x8, 0x5f, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x5f, 0xc4, 0x5, 0x74, 0x75, 0x70, 0x6c, 0x65, 0xc4, 0x5, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x91, 0xc4, 0x20}, - []byte(valM), - []byte{0xc0}, - }, []byte{}), - })*/ + arg, _ := json.Marshal([]interface{}{firstArg, secondArg, env.Connection.(*minecraft.Conn).GameData().EntityUniqueID}) + ret := client.TransferCheckNum(string(arg)) + ret_p := []interface{}{} + json.Unmarshal([]byte(ret), &ret_p) conn.WritePacket(&packet.PyRpc{ - Content: bytes.Join([][]byte{[]byte{0x93, 0xc4, 0x0e}, []byte("SetMCPCheckNum"), []byte{0x91, 0x98, 0xc4, 0x20}, - []byte(valM), - []byte{0xc4, 0x20}, - []byte(valS), - []byte{0xc2}, - []byte{0x90}, - []byte{0xc4, 0x00}, - []byte{0xc4, 0x00}, - []byte{3}, - []byte{0xc4,0x20}, - []byte(valT), - []byte{0xC0}, - }, []byte{}), + Value: py_rpc.FromGo([]interface{}{ + "SetMCPCheckNum", + []interface{}{ + ret_p, + }, + nil, + }), }) getchecknum_everPassed = true - /*go func() { - time.Sleep(3*time.Second) - resp, _ := env.GlobalAPI.(*GlobalAPI.GlobalAPI).SendCommandWithResponce("list") - fmt.Printf("%+v\n", resp) - } ()*/ - } else { - //fmt.Printf("PyRpc! %s\n", p.Content) } } } @@ -238,45 +187,13 @@ func EnterWorkerThread(env *environment.PBEnvironment, breaker chan struct{}) { // pterm.Info.Println("ClientCacheBlobStatus", p) case *packet.Text: if p.TextType == packet.TextTypeChat { - if args.InGameResponse() { + if args.InGameResponse { if p.SourceName == env.RespondUser { functionHolder.Process(p.Message) } } break } - case *packet.CommandOutput: - if p.CommandOrigin.UUID.String() == configuration.ZeroId.String() { - pos, _ := utils.SliceAtoi(p.OutputMessages[0].Parameters) - if !(p.OutputMessages[0].Message == "commands.generic.unknown") { - configuration.IsOp = true - } - if len(pos) == 0 { - commandSender.Output(I18n.T(I18n.InvalidPosition)) - break - } - configuration.GlobalFullConfig(env).Main().Position = types.Position{ - X: pos[0], - Y: pos[1], - Z: pos[2], - } - commandSender.Output(fmt.Sprintf("%s: %v", I18n.T(I18n.PositionGot), pos)) - break - } else if p.CommandOrigin.UUID.String() == configuration.OneId.String() { - pos, _ := utils.SliceAtoi(p.OutputMessages[0].Parameters) - if len(pos) == 0 { - commandSender.Output(I18n.T(I18n.InvalidPosition)) - break - } - configuration.GlobalFullConfig(env).Main().End = types.Position{ - X: pos[0], - Y: pos[1], - Z: pos[2], - } - commandSender.Output(fmt.Sprintf("%s: %v", I18n.T(I18n.PositionGot_End), pos)) - break - } - utils_core.ProcessCommandOutput(commandSender, p) case *packet.ActorEvent: if p.EventType == packet.ActorEventDeath && p.EntityRuntimeID == conn.GameData().EntityRuntimeID { conn.WritePacket(&packet.PlayerAction{ @@ -321,12 +238,6 @@ func EnterWorkerThread(env *environment.PBEnvironment, breaker chan struct{}) { requests := chunkAssembler.GenRequestFromLevelChunk(p) chunkAssembler.ScheduleRequest(requests) } - case *packet.UpdateBlock: - channel, h := commandSender.BlockUpdateSubscribeMap.LoadAndDelete(p.Position) - if h { - ch := channel.(chan bool) - ch <- true - } case *packet.Respawn: if p.EntityRuntimeID == conn.GameData().EntityRuntimeID { move.Position = p.Position @@ -356,7 +267,8 @@ func EnterWorkerThread(env *environment.PBEnvironment, breaker chan struct{}) { func EstablishConnectionAndInitEnv(env *environment.PBEnvironment) { if env.FBAuthClient == nil { - env.FBAuthClient = fbauth.CreateClient(env) + env.ClientOptions.AuthServer = args.AuthServer + env.FBAuthClient = fbauth.CreateClient(env.ClientOptions) } pterm.Println(pterm.Yellow(fmt.Sprintf("%s: %s", I18n.T(I18n.ServerCodeTrans), env.LoginInfo.ServerCode))) @@ -371,7 +283,7 @@ func EstablishConnectionAndInitEnv(env *environment.PBEnvironment) { env.LoginInfo.ServerPasscode, env.LoginInfo.Token, ) - conn, err := core.InitMCConnection(ctx, authenticator, options...) + conn, err := core.InitializeMinecraftConnection(ctx, authenticator, options...) if err != nil { pterm.Error.Println(err) @@ -382,13 +294,13 @@ func EstablishConnectionAndInitEnv(env *environment.PBEnvironment) { panic(err) } if len(env.RespondUser) == 0 { - if args.GetCustomGameName() == "" { + if args.CustomGameName == "" { go func() { user := env.FBAuthClient.(*fbauth.Client).ShouldRespondUser() env.RespondUser = user }() } else { - env.RespondUser = args.GetCustomGameName() + env.RespondUser = args.CustomGameName } } env.Connection = conn @@ -397,28 +309,28 @@ func EstablishConnectionAndInitEnv(env *environment.PBEnvironment) { env.UQHolder.(*uqHolder.UQHolder).UpdateFromConn(conn) env.UQHolder.(*uqHolder.UQHolder).CurrentTick = 0 - env.Resources = &ResourcesControlCenter.Resources{} - env.ResourcesUpdater = env.Resources.(*ResourcesControlCenter.Resources).Init() - env.GlobalAPI = &GlobalAPI.GlobalAPI{ + env.Resources = &ResourcesControl.Resources{} + env.ResourcesUpdater = env.Resources.(*ResourcesControl.Resources).Init() + env.GameInterface = &GameInterface.GameInterface{ WritePacket: env.Connection.(*minecraft.Conn).WritePacket, - BotInfo: GlobalAPI.BotInfo{ - BotName: env.Connection.(*minecraft.Conn).IdentityData().DisplayName, - BotIdentity: env.Connection.(*minecraft.Conn).IdentityData().Identity, - BotRunTimeID: env.Connection.(*minecraft.Conn).GameData().EntityRuntimeID, - BotUniqueID: env.Connection.(*minecraft.Conn).GameData().EntityUniqueID, + ClientInfo: GameInterface.ClientInfo{ + DisplayName: env.Connection.(*minecraft.Conn).IdentityData().DisplayName, + ClientIdentity: env.Connection.(*minecraft.Conn).IdentityData().Identity, + XUID: env.Connection.(*minecraft.Conn).IdentityData().XUID, + EntityRuntimeID: env.Connection.(*minecraft.Conn).GameData().EntityRuntimeID, + EntityUniqueID: env.Connection.(*minecraft.Conn).GameData().EntityUniqueID, }, - Resources: env.Resources.(*ResourcesControlCenter.Resources), + Resources: env.Resources.(*ResourcesControl.Resources), } - if args.ShouldEnableOmegaSystem() { + if args.ShouldEnableOmegaSystem { _, cb := embed.EnableOmegaSystem(env) go cb() //cb() } - commandSender := commands.InitCommandSender(env) functionHolder := env.FunctionHolder.(*function.FunctionHolder) - function.InitInternalFunctions(functionHolder) + function.InitPresetFunctions(functionHolder) fbtask.InitTaskStatusDisplay(env) move.ConnectTime = time.Time{} move.Position = conn.GameData().PlayerPosition @@ -431,37 +343,21 @@ func EstablishConnectionAndInitEnv(env *environment.PBEnvironment) { hostBridgeGamma := env.ScriptBridge.(*script_bridge.HostBridgeGamma) hostBridgeGamma.HostSetSendCmdFunc(func(mcCmd string, waitResponse bool) *packet.CommandOutput { - ud, _ := uuid.NewUUID() if !waitResponse { - env.GlobalAPI.(*GlobalAPI.GlobalAPI).SendCommand(mcCmd, ud) + env.GameInterface.SendCommand(mcCmd) return nil } - resp, _ := env.GlobalAPI.(*GlobalAPI.GlobalAPI).SendCommandWithResponce(mcCmd) + resp, _ := env.GameInterface.SendCommandWithResponse(mcCmd) return &resp }) hostBridgeGamma.HostConnectEstablished() defer hostBridgeGamma.HostConnectTerminate() - go func() { - if args.ShouldMuteWorldChat() { - return - } - for { - csmsg := <-env.WorldChatChannel - commandSender.WorldChatOutput(csmsg[0], csmsg[1]) - } - }() - taskholder := env.TaskHolder.(*fbtask.TaskHolder) types.ForwardedBrokSender = taskholder.BrokSender - zeroId, _ := uuid.NewUUID() - oneId, _ := uuid.NewUUID() - configuration.ZeroId = zeroId - configuration.OneId = oneId - - if args.ExternalListenAddress() != "" { - external.ListenExt(env, args.ExternalListenAddress()) + if args.ExternalListenAddress != "" { + external.ListenExt(env, args.ExternalListenAddress) } env.UQHolder.(*uqHolder.UQHolder).UpdateFromConn(conn) return diff --git a/solutions/fastbuilder/env.go b/solutions/fastbuilder/env.go index 8a3110aee..993914f6e 100644 --- a/solutions/fastbuilder/env.go +++ b/solutions/fastbuilder/env.go @@ -14,7 +14,9 @@ import ( ) func create_environment() *environment.PBEnvironment { - env := &environment.PBEnvironment{} + env := &environment.PBEnvironment{ + ClientOptions: fbauth.MakeDefaultClientOptions(), + } env.UQHolder = nil env.Resources = nil env.ActivateTaskStatus = make(chan bool) @@ -29,10 +31,10 @@ func create_environment() *environment.PBEnvironment { return env.LoginInfo.ServerCode }, "fb_version": func() string { - return args.GetFBVersion() + return args.FBVersion }, "uc_username": func() string { - return env.FBUCUsername + return env.ClientOptions.FBUCUsername }, } for _, key := range args.CustomSEUndefineConsts { @@ -47,8 +49,8 @@ func create_environment() *environment.PBEnvironment { env.ScriptBridge = hostBridgeGamma scriptHolder := script_holder.InitScriptHolder(env) env.ScriptHolder = scriptHolder - if args.StartupScript() != "" { - scriptHolder.LoadScript(args.StartupScript(), env) + if args.StartupScript != "" { + scriptHolder.LoadScript(args.StartupScript, env) } env.Destructors = append(env.Destructors, func() { scriptHolder.Destroy() @@ -67,7 +69,7 @@ func ConfigRealEnvironment(token string, server_code string, server_password str ServerCode: server_code, ServerPasscode: server_password, } - env.FBAuthClient = fbauth.CreateClient(env) + env.FBAuthClient = fbauth.CreateClient(env.ClientOptions) return env } diff --git a/solutions/fastbuilder/fatal_control.go b/solutions/fastbuilder/fatal_control.go index 9cd260bf7..305e23bc1 100644 --- a/solutions/fastbuilder/fatal_control.go +++ b/solutions/fastbuilder/fatal_control.go @@ -13,23 +13,27 @@ import ( I18n "phoenixbuilder/fastbuilder/i18n" "github.com/pterm/pterm" + _ "unsafe" ) var PassFatal bool = false +//go:linkname onFatal args_hook_on_fatal +func onFatal(string) + func Fatal() { if PassFatal { return } if err := recover(); err != nil { - if !args.NoReadline() { + if !args.NoReadline { readline.HardInterrupt() } debug.PrintStack() pterm.Error.Println(I18n.T(I18n.Crashed_Tip)) pterm.Error.Println(I18n.T(I18n.Crashed_StackDump_And_Error)) pterm.Error.Println(err) - if args.ShouldEnableOmegaSystem() { + if args.ShouldEnableOmegaSystem { omegaSuggest := suggest.GetOmegaErrorSuggest(fmt.Sprintf("%v", err)) fmt.Print(omegaSuggest) } diff --git a/solutions/fastbuilder/token.go b/solutions/fastbuilder/token.go index ec1e3656d..adb75f745 100644 --- a/solutions/fastbuilder/token.go +++ b/solutions/fastbuilder/token.go @@ -46,7 +46,7 @@ func loadFBTokenOrAskFBCredential() (token string) { } } } else { - token = args.CustomTokenContent() + token = args.CustomTokenContent } return } diff --git a/solutions/minimal_fastbuilder_client/main.go b/solutions/minimal_fastbuilder_client/main.go index 25459fcf5..24b2aa409 100644 --- a/solutions/minimal_fastbuilder_client/main.go +++ b/solutions/minimal_fastbuilder_client/main.go @@ -1,107 +1,64 @@ package main import ( - "context" + "bufio" "fmt" - "phoenixbuilder/fastbuilder/core" - "phoenixbuilder/lib/fbauth" - "phoenixbuilder/lib/helpers/bot_privilege" - "phoenixbuilder/lib/helpers/fbuser" - "phoenixbuilder/lib/minecraft/neomega/bundle" - "phoenixbuilder/lib/minecraft/neomega/decouple/cmdsender" + "os" + "phoenixbuilder/fastbuilder/lib/minecraft/neomega/omega" + "phoenixbuilder/fastbuilder/lib/rental_server_impact/access_helper" + "phoenixbuilder/fastbuilder/lib/rental_server_impact/info_collect_utils" "phoenixbuilder/minecraft/protocol/packet" "time" ) -var errFBUserCenterLoginFail = "无效的 Fastbuilder 用户名或密码" -var errRentalServerDisconnected = "与租赁服的连接已断开" - -func WrapAuthenticator(connectContext context.Context, client *fbauth.Client, userName, userPassword, userToken, serverCode, serverPassword string) (authenticator *fbauth.AccessWrapper, writeBackToken string, err error) { - if userToken == "" { - userToken, err = fbauth.GetTokenByPassword(connectContext, client, userName, userPassword) - if err != nil { - return nil, "", fmt.Errorf("%v: %v", errFBUserCenterLoginFail, err) - } - } - authenticator = fbauth.NewAccessWrapper(client, userToken) - authenticator.SetServerInfo(serverCode, serverPassword) - return authenticator, writeBackToken, nil -} - func main() { authServer := "wss://api.fastbuilder.pro:2053/" - fmt.Println("Connecting to FB Server...") - ctx := context.Background() - fbClient := fbauth.NewClient(ctx) - { - connectCtx, _ := context.WithTimeout(ctx, 30*time.Second) - err := fbClient.EstablishConnectionToAuthServer(connectCtx, authServer) - if err != nil { - panic(err) - } - } - - fmt.Println("Reading Info...") - userName, userPassword, userToken, serverCode, serverPassword, err := fbuser.ReadInfo("", "", "", "", "") + username, userPassword, userToken, serverCode, serverPassword, err := info_collect_utils.ReadUserInfo("", "", "", "", "") if err != nil { panic(err) } - fmt.Println("Authenticating...") - ctx, _ = context.WithTimeout(ctx, 30*time.Second) - authenticator, writeBackToken, err := WrapAuthenticator(ctx, fbClient, userName, userPassword, userToken, serverCode, serverPassword) - if err != nil { - panic(err) - } - if writeBackToken != "" { - fbuser.WriteToken(writeBackToken, fbuser.LoadTokenPath()) - } + accessOption := access_helper.DefaultOptions() + accessOption.AuthServer = authServer + accessOption.FBUsername = username + accessOption.FBUserPassword = userPassword + accessOption.FBUserToken = userToken + accessOption.ServerCode = serverCode + accessOption.ServerPassword = serverPassword + accessOption.MakeBotCreative = true + accessOption.DisableCommandBlock = false + accessOption.ReasonWithPrivilegeStuff = true - fmt.Printf("Connecting to MC Server: (Code:%v, Password:%v)\n", authenticator.ServerCode, authenticator.ServerPassword) - ctx, _ = context.WithTimeout(ctx, 30*time.Second) - client, err := core.InitMCConnection(ctx, authenticator) + var deadReason chan error + var omegaCore omega.MicroOmega + _, omegaCore, deadReason, err = access_helper.ImpactServer(nil, accessOption) if err != nil { panic(err) } - fmt.Printf("Successfully Connected to MC Server!\n") - var pkt packet.Packet - omega := bundle.NewMicroOmega(client, bundle.MicroOmegaOption{ - CmdSenderOptions: cmdsender.Options{ - ExpectedCmdFeedBack: false, - }, - PrintUQHolderDebugInfo: false, - }) - fmt.Printf("Adding Omega Components...\n") - bot_privilege.NewPyRPCResponser(omega, authenticator.GetFBUid(), - func(content, uid string) string { - ctx, _ = context.WithTimeout(ctx, 30*time.Second) - data, err := authenticator.TransferData(ctx, content, uid) - if err != nil { - panic(err) - } - return data - }, - func(firstArg, secondArg string) (valM string, valS string) { - ctx, _ = context.WithTimeout(ctx, 30*time.Second) - valM, valS, err = authenticator.TransferCheckNum(ctx, firstArg, secondArg) - if err != nil { - panic(err) - } - return - }, - ) - helper := bot_privilege.NewSetupHelper(omega) - fmt.Printf("Running Omega...\n") + go func() { + err = <-deadReason + panic(err) + }() + resultWaitor := make(chan *packet.CommandOutput, 1) + firstTime := true + startTime := time.Now() go func() { for { - pkt, err = client.ReadPacket() - if err != nil { - panic(fmt.Errorf("%v: %v", errRentalServerDisconnected, err)) + omegaCore.GetGameControl().SendWSCmdAndInvokeOnResponse("testforblock ~~~ air", func(output *packet.CommandOutput) { + resultWaitor <- output + }) + select { + case r := <-resultWaitor: + if firstTime { + fmt.Println(r) + firstTime = false + } + fmt.Printf("\ralive %v", time.Since(startTime)) + time.Sleep(time.Second / 10) + case <-time.NewTimer(time.Second * 3).C: + panic(fmt.Errorf("no response after 3 second, bot is down (alive %v)", time.Since(startTime))) } - omega.HandlePacket(pkt) } }() - - helper.WaitOK(time.Minute * 3) - fmt.Println("Minimal Client exited.") + bufio.NewReader(os.Stdin).ReadByte() } diff --git a/solutions/minimal_fastbuilder_client/minimal_fastbuilder_client b/solutions/minimal_fastbuilder_client/minimal_fastbuilder_client new file mode 100755 index 000000000..ec73c3121 Binary files /dev/null and b/solutions/minimal_fastbuilder_client/minimal_fastbuilder_client differ diff --git a/solutions/remote_omega/access_point/access_point b/solutions/remote_omega/access_point/access_point new file mode 100755 index 000000000..62aa7c45c Binary files /dev/null and b/solutions/remote_omega/access_point/access_point differ diff --git a/solutions/remote_omega/access_point/main.go b/solutions/remote_omega/access_point/main.go new file mode 100644 index 000000000..8f96ca86c --- /dev/null +++ b/solutions/remote_omega/access_point/main.go @@ -0,0 +1,75 @@ +package main + +import ( + "context" + "fmt" + "phoenixbuilder/fastbuilder/lib/minecraft/neomega/omega" + "phoenixbuilder/fastbuilder/lib/rental_server_impact/access_helper" + "phoenixbuilder/fastbuilder/lib/rental_server_impact/info_collect_utils" + "phoenixbuilder/minecraft" + "phoenixbuilder/minecraft/protocol/packet" + "phoenixbuilder/solutions/remote_omega/transfer" +) + +func main() { + authServer := "wss://api.fastbuilder.pro:2053/" + fmt.Println("Reading Info...") + username, userPassword, userToken, serverCode, serverPassword, err := info_collect_utils.ReadUserInfo("", "", "", "", "") + if err != nil { + panic(err) + } + + accessOption := access_helper.DefaultOptions() + accessOption.AuthServer = authServer + accessOption.FBUsername = username + accessOption.FBUserPassword = userPassword + accessOption.FBUserToken = userToken + accessOption.ServerCode = serverCode + accessOption.ServerPassword = serverPassword + accessOption.MakeBotCreative = true + accessOption.DisableCommandBlock = false + + transferHandler, err := transfer.NewTransferAccessPoint( + context.Background(), + transfer.DefaultPubSubAccessPoint, + transfer.DefaultCtrlAccessPoint, + nil, + ) + if err != nil { + panic(err) + } + directPubMode := transfer.DefaultDirectPubSubModeEnable + if directPubMode { + accessOption.ReadLoopFunction = func(conn *minecraft.Conn, deadReason chan<- error, omega omega.ReactCore) { + for { + pkt, pktDataShared, err := conn.ReadPacketAndBytes() + pktData := make([]byte, len(pktDataShared)) + copy(pktData, pktDataShared) + if err != nil { + deadReason <- fmt.Errorf("%v: %v", access_helper.ErrRentalServerDisconnected, err) + } + err = transferHandler.PubGamePacketData(pktData) + if err != nil { + deadReason <- fmt.Errorf("fail to remote dispatch packets") + } + omega.HandlePacket(pkt) + } + } + } + + conn, omegaCore, deadReason, err := access_helper.ImpactServer(nil, accessOption) + if err != nil { + panic(err) + } + transferHandler.UpdateGetShieldIDFn(conn.GetShieldID) + if !directPubMode { + omegaCore.GetGameListener().SetOnAnyPacketCallBack(func(p packet.Packet) { + transferHandler.PubGamePacket(p) + }) + } + go transferHandler.EnableCtrlTransfer(omegaCore) + fmt.Println("access point ready") + + err = <-deadReason + panic(err) +} diff --git a/solutions/remote_omega/handler/main.go b/solutions/remote_omega/handler/main.go new file mode 100644 index 000000000..8c3f2193e --- /dev/null +++ b/solutions/remote_omega/handler/main.go @@ -0,0 +1,39 @@ +package main + +import ( + "bufio" + "fmt" + "os" + "phoenixbuilder/minecraft/protocol/packet" + "phoenixbuilder/solutions/remote_omega/transfer" + "time" +) + +func main() { + omegaCore, err := transfer.ConnectToAccessPoint(nil, nil, nil) + if err != nil { + panic(err) + } + resultWaitor := make(chan *packet.CommandOutput, 1) + firstTime := true + startTime := time.Now() + go func() { + for { + omegaCore.GetGameControl().SendWSCmdAndInvokeOnResponse("testforblock ~~~ air", func(output *packet.CommandOutput) { + resultWaitor <- output + }) + select { + case r := <-resultWaitor: + if firstTime { + fmt.Println(r) + firstTime = false + } + fmt.Printf("\ralive %v", time.Since(startTime)) + time.Sleep(time.Second / 10) + case <-time.NewTimer(time.Second * 3).C: + panic(fmt.Errorf("no response after 3 second, bot is down (alive %v)", time.Since(startTime))) + } + } + }() + bufio.NewReader(os.Stdin).ReadByte() +} diff --git a/solutions/remote_omega/transfer/basic.go b/solutions/remote_omega/transfer/basic.go new file mode 100644 index 000000000..89d5b5cd6 --- /dev/null +++ b/solutions/remote_omega/transfer/basic.go @@ -0,0 +1,147 @@ +package transfer + +import ( + "bytes" + "context" + "fmt" + zmq "github.com/go-zeromq/zmq4" + "github.com/google/uuid" + "github.com/pterm/pterm" + "phoenixbuilder/fastbuilder/lib/encoding/binary_read_write" + LE "phoenixbuilder/fastbuilder/lib/encoding/little_endian" + "phoenixbuilder/fastbuilder/lib/utils/sync_wrapper" + "phoenixbuilder/minecraft/protocol" + "phoenixbuilder/minecraft/protocol/packet" +) + +func RevertToRawPacketWithShield(pk packet.Packet) (data []byte) { + writer := bytes.NewBuffer(nil) + packetID := pk.ID() + LE.WriteInt32(binary_read_write.WrapBinaryWriter(writer), int32(packetID)) + w := protocol.NewWriter(writer, 0) + pk.Marshal(w) + return writer.Bytes() +} + +func ConvertFromRawPacketWithShield(pool packet.Pool, data []byte) (pk packet.Packet, err error) { + reader := bytes.NewBuffer(data) + packetID, _ := LE.Int32(binary_read_write.WrapBinaryReader(reader)) + r := protocol.NewReader(reader, 0) + if pkMaker, found := pool[uint32(packetID)]; found { + pk = pkMaker() + } else { + return nil, fmt.Errorf("pktID %v not found", uint32(packetID)) + } + pk.Unmarshal(r) + return pk, nil +} + +type ZMQFunctionSets map[string]func(args [][]byte, onResult func([][]byte)) + +func DefaultZMQFunctionSetsRpcExpose(socket zmq.Socket, sets ZMQFunctionSets) (err error) { + //ErrCallFormat := zmq.NewMsgFrom([]byte("err"), []byte("illegal frames length")) + //ErrCallFnName := zmq.NewMsgFrom([]byte("err"), []byte("function name not found")) + for { + var msg zmq.Msg + msg, err = socket.Recv() + if err != nil { + return fmt.Errorf("receiving: %w", err) + } + frames := msg.Frames + if len(frames) < 3 { + //socket.Send(ErrCallFormat) + continue + } + fnName := string(frames[2]) + if fn, found := sets[fnName]; found { + fn(frames[3:], func(rets [][]byte) { + socket.SendMulti(zmq.NewMsgFrom(append(frames[:2], rets...)...)) + }) + } else { + //socket.Send(ErrCallFnName) + continue + } + } +} + +type ZMQRpcCaller struct { + socket zmq.Socket + cbs *sync_wrapper.SyncMap[func([][]byte)] +} + +func NewZMQRpcCaller(ctx context.Context, endPoint string) (caller *ZMQRpcCaller, err error) { + if ctx == nil { + ctx = context.Background() + } + var cancelFn func() + ctx, cancelFn = context.WithCancel(ctx) + id := zmq.SocketIdentity(fmt.Sprintf("dealer-%d", uuid.New().String())) + socket := zmq.NewDealer(context.Background(), zmq.WithID(id)) + go func() { + <-ctx.Done() + socket.Close() + }() + if err = socket.Dial(endPoint); err != nil { + cancelFn() + return nil, fmt.Errorf("dialing: %w", err) + } + c := &ZMQRpcCaller{socket: socket, cbs: sync_wrapper.NewInstanceMap[func([][]byte)]()} + go func() { + var msg zmq.Msg + for ctx.Err() == nil { + msg, err = socket.Recv() + if err != nil { + pterm.Error.Println(err) + break + } + idx := msg.Frames[0] + rets := msg.Frames[1:] + if cb, ok := c.cbs.Get(string(idx)); ok { + cb(rets) + } + } + cancelFn() + }() + return c, nil +} + +func (c *ZMQRpcCaller) call(fn string, args [][]byte) (idx []byte) { + idx = []byte(uuid.New().String()) + frames := append([][]byte{idx, []byte(fn)}, args...) + err := c.socket.SendMulti(zmq.NewMsgFrom(frames...)) + if err != nil { + return nil + } + return idx +} + +func (c *ZMQRpcCaller) BlockCallAndGet(ctx context.Context, fn string, args [][]byte) (rets [][]byte) { + if ctx == nil { + ctx = context.Background() + } + idx := c.call(fn, args) + if idx == nil { + return nil + } + waitor := make(chan [][]byte) + c.cbs.Set(string(idx), func(i [][]byte) { + waitor <- i + }) + select { + case rets = <-waitor: + return rets + case <-ctx.Done(): + return nil + } +} + +func (c *ZMQRpcCaller) CallAndSetCB(fn string, args [][]byte, cb func(rets [][]byte)) { + idx := c.call(fn, args) + if idx != nil && cb != nil { + c.cbs.Set(string(idx), cb) + } +} + +func (c *ZMQRpcCaller) CallNoResponse(fn string, args [][]byte) { + c.call(fn, args) +} diff --git a/solutions/remote_omega/transfer/end_point.go b/solutions/remote_omega/transfer/end_point.go new file mode 100644 index 000000000..3da83221e --- /dev/null +++ b/solutions/remote_omega/transfer/end_point.go @@ -0,0 +1,141 @@ +package transfer + +import ( + "bytes" + "context" + "encoding/binary" + "fmt" + zmq "github.com/go-zeromq/zmq4" + "phoenixbuilder/fastbuilder/lib/minecraft/neomega/omega" + "phoenixbuilder/fastbuilder/lib/minecraft/neomega/uqholder" + "phoenixbuilder/minecraft/protocol" + "phoenixbuilder/minecraft/protocol/packet" + "time" +) + +type Endpoint struct { + sub zmq.Socket + caller *ZMQRpcCaller + pool packet.Pool +} + +func NewEndPoint(ctx context.Context, pubAccessPoint, ctrlAccessPoint string) (endPoint *Endpoint, err error) { + sub := zmq.NewSub(ctx) + go func() { + <-ctx.Done() + sub.Close() + }() + err = sub.Dial(pubAccessPoint) + if err != nil { + return nil, err + } + err = sub.SetOption(zmq.OptionSubscribe, "packet") + if err != nil { + return nil, err + } + caller, err := NewZMQRpcCaller(nil, ctrlAccessPoint) + if err != nil { + panic(err) + } + return &Endpoint{ + pool: packet.NewPool(), + sub: sub, + caller: caller, + }, nil +} + +func (e *Endpoint) WaitReady() { + for { + if e.CheckAccessPointReady() { + break + } + time.Sleep(time.Second / 10) + } +} + +func (e *Endpoint) CheckAccessPointReady() bool { + ret := e.caller.BlockCallAndGet(nil, "botReady", nil) + if len(ret) > 0 && string(ret[0]) == "botReady" { + return true + } + return false +} + +func (e *Endpoint) GetUQHolder() omega.MicroUQHolder { + uqHolderData := e.caller.BlockCallAndGet(nil, "getUQHolderBytes", nil) + uq, err := uqholder.NewMicroUQHolderFromData(uqHolderData[0]) + if err != nil { + panic(err) + } + return uq +} + +func (e *Endpoint) GetShieldID() int32 { + shieldIDBytes := e.caller.BlockCallAndGet(nil, "getConnShieldID", nil) + return int32(binary.LittleEndian.Uint32(shieldIDBytes[0])) +} + +func (e *Endpoint) SendPacket(pk packet.Packet) { + e.caller.CallNoResponse("sendPacket", [][]byte{RevertToRawPacketWithShield(pk)}) +} + +func (e *Endpoint) SendPacketData(pktID uint32, data []byte) { + packetIDBytes := make([]byte, 4) + binary.LittleEndian.PutUint32(packetIDBytes, pktID) + e.caller.CallNoResponse("sendPacketBytes", [][]byte{packetIDBytes, data}) +} + +func (e *Endpoint) RecvPacket() (pk packet.Packet, shieldID int32, err error) { + var msg zmq.Msg + msg, err = e.sub.Recv() + if err != nil { + return nil, 0, err + } + shieldID = int32(binary.LittleEndian.Uint32(msg.Frames[2])) + pk, err = ConvertFromRawPacketWithShield(e.pool, msg.Frames[1]) + if err != nil { + return nil, 0, err + } + return pk, shieldID, err +} + +func safeDecode(pkt packet.Packet, r *protocol.Reader) (p packet.Packet, err error) { + defer func() { + if recoveredErr := recover(); recoveredErr != nil { + err = fmt.Errorf("%T: %w", pkt, recoveredErr.(error)) + //fmt.Println(err) + } + }() + pkt.Unmarshal(r) + return pkt, nil +} + +func (e *Endpoint) RecvDirectPacket() (pk packet.Packet, shieldID int32, err error) { + var msg zmq.Msg + msg, err = e.sub.Recv() + if err != nil { + return nil, 0, err + } + shieldIDBytes, packetData, dataLenBytes := msg.Frames[1], msg.Frames[2], msg.Frames[3] + shieldID = int32(binary.LittleEndian.Uint32(shieldIDBytes)) + dataLen := binary.LittleEndian.Uint32(dataLenBytes) + if int(dataLen) != len(packetData) { + return nil, 0, fmt.Errorf("len mismatch %v!=%v\n", int(dataLen), len(packetData)) + } + reader := bytes.NewBuffer(packetData) + header := &packet.Header{} + if err := header.Read(reader); err != nil { + return nil, 0, fmt.Errorf("error reading packet header: %v", err) + } + r := protocol.NewReader(reader, shieldID) + if pktMake, found := e.pool[header.PacketID]; found { + pk = pktMake() + } else { + return nil, 0, fmt.Errorf("pktID %v not found", header.PacketID) + } + pk, err = safeDecode(pk, r) + if err != nil { + return nil, 0, err + } + return pk, shieldID, nil +} diff --git a/solutions/remote_omega/transfer/helper.go b/solutions/remote_omega/transfer/helper.go new file mode 100644 index 000000000..ab88de44c --- /dev/null +++ b/solutions/remote_omega/transfer/helper.go @@ -0,0 +1,64 @@ +package transfer + +import ( + "context" + "fmt" + "phoenixbuilder/fastbuilder/lib/minecraft/neomega/bundle" + "phoenixbuilder/fastbuilder/lib/minecraft/neomega/decouple/core" + "phoenixbuilder/fastbuilder/lib/minecraft/neomega/omega" + "phoenixbuilder/minecraft/protocol/packet" +) + +func ConnectToAccessPoint(ctx context.Context, endPointOption *EndPointOption, omegaOption *bundle.MicroOmegaOption) (omegaCore omega.MicroOmega, err error) { + if ctx == nil { + ctx = context.Background() + } + if endPointOption == nil { + endPointOption = MakeDefaultEndPointOption() + } + if omegaOption == nil { + omegaOption = bundle.MakeDefaultMicroOmegaOption() + } + endPoint, err := NewEndPoint( + ctx, + endPointOption.PubAccessPoint, + endPointOption.CtrlAccessPoint, + ) + if err != nil { + return nil, err + } + endPoint.WaitReady() + fmt.Println("connected to access point") + var interactCore omega.InteractCore + if endPointOption.DirectSendMode { + interactCore = core.NewRemoteInteractCoreDirect(endPoint.SendPacketData) + interactCore.(*core.RemoteInteractCoreDirect).UpdateShieldID(endPoint.GetShieldID()) + } else { + interactCore = core.NewRemoteInteractCore(endPoint.SendPacket) + } + omegaCore = bundle.NewMicroOmega(interactCore, endPoint.GetUQHolder, omegaOption) + + go func() { + var err error + var pkt packet.Packet + var shieldID int32 + var recvFn func() (pk packet.Packet, shieldID int32, err error) + if endPointOption.DirectSubMode { + recvFn = endPoint.RecvDirectPacket + } else { + recvFn = endPoint.RecvPacket + } + for { + pkt, shieldID, err = recvFn() + if err != nil { + fmt.Println(err) + continue + } + if endPointOption.DirectSendMode { + interactCore.(*core.RemoteInteractCoreDirect).UpdateShieldID(shieldID) + } + omegaCore.HandlePacket(pkt) + } + }() + return omegaCore, nil +} diff --git a/solutions/remote_omega/transfer/options.go b/solutions/remote_omega/transfer/options.go new file mode 100644 index 000000000..a2586e7fd --- /dev/null +++ b/solutions/remote_omega/transfer/options.go @@ -0,0 +1,24 @@ +package transfer + +const ( + DefaultPubSubAccessPoint = "ipc://neomega_pub_sub.ipc" //"tcp://localhost:24016" + DefaultCtrlAccessPoint = "ipc://neomega_ctrl.ipc" //"tcp://localhost:24015" + DefaultDirectPubSubModeEnable = true + DefaultDirectSendModeEnable = true +) + +type EndPointOption struct { + PubAccessPoint string + CtrlAccessPoint string + DirectSendMode bool + DirectSubMode bool +} + +func MakeDefaultEndPointOption() *EndPointOption { + return &EndPointOption{ + PubAccessPoint: DefaultPubSubAccessPoint, + CtrlAccessPoint: DefaultCtrlAccessPoint, + DirectSendMode: DefaultDirectSendModeEnable, + DirectSubMode: DefaultDirectPubSubModeEnable, + } +} diff --git a/solutions/remote_omega/transfer/transfer.go b/solutions/remote_omega/transfer/transfer.go new file mode 100644 index 000000000..573eb9b25 --- /dev/null +++ b/solutions/remote_omega/transfer/transfer.go @@ -0,0 +1,136 @@ +package transfer + +import ( + "context" + "encoding/binary" + "fmt" + zmq "github.com/go-zeromq/zmq4" + "github.com/pterm/pterm" + "os" + "phoenixbuilder/fastbuilder/lib/minecraft/neomega/omega" + "phoenixbuilder/minecraft/protocol/packet" + "strings" +) + +type TransferAccessPoint struct { + pub zmq.Socket + ctrl zmq.Socket + getShieldID func() int32 +} + +func NewTransferAccessPoint(ctx context.Context, pubEndPoint, ctrlEndPoint string, getShieldID func() int32) (transfer *TransferAccessPoint, err error) { + pub := zmq.NewPub(ctx) + removeIPC := func(ipc string) error { + if strings.HasPrefix(ipc, "ipc://") { + ipcFile := ipc[len("ipc://"):] + if _, err := os.Stat(ipcFile); err == nil { + if err = os.Remove(ipcFile); err != nil { + return err + } + } + } + return nil + } + err = removeIPC(pubEndPoint) + if err != nil { + return nil, err + } + err = pub.Listen(pubEndPoint) + if err != nil { + return nil, err + } + go func() { + <-ctx.Done() + pub.Close() + }() + ctrl := zmq.NewRouter(ctx, zmq.WithID(zmq.SocketIdentity("router"))) + go func() { + <-ctx.Done() + ctrl.Close() + }() + err = removeIPC(ctrlEndPoint) + if err != nil { + return nil, err + } + if err = ctrl.Listen(ctrlEndPoint); err != nil { + return nil, fmt.Errorf("listening: %w", err) + } + if getShieldID == nil { + getShieldID = func() int32 { + return 0 + } + } + t := &TransferAccessPoint{ + pub, + ctrl, + getShieldID, + } + return t, nil +} + +func (t *TransferAccessPoint) UpdateGetShieldIDFn(getShieldID func() int32) { + t.getShieldID = getShieldID +} + +func (t *TransferAccessPoint) PubGamePacket(pk packet.Packet) error { + shieldIDBytes := make([]byte, 4) + binary.LittleEndian.PutUint32(shieldIDBytes, uint32(t.getShieldID())) + return t.pub.SendMulti(zmq.NewMsgFrom( + []byte("packet"), + RevertToRawPacketWithShield(pk), + shieldIDBytes, + )) +} + +func (t *TransferAccessPoint) PubGamePacketData(packetData []byte) error { + shieldIDBytes := make([]byte, 4) + dataLenBytes := make([]byte, 4) + binary.LittleEndian.PutUint32(shieldIDBytes, uint32(t.getShieldID())) + binary.LittleEndian.PutUint32(dataLenBytes, uint32(len(packetData))) + return t.pub.SendMulti(zmq.NewMsgFrom( + []byte("packet"), + shieldIDBytes, + packetData, + dataLenBytes, + )) +} + +func (t *TransferAccessPoint) EnableCtrlTransfer(omega omega.MicroOmega) (err error) { + getUQHolderBytes := func() []byte { + data, err := omega.GetMicroUQHolder().Marshal() + if err != nil { + pterm.Error.Println(err) + } + return data + } + pool := packet.NewPool() + return DefaultZMQFunctionSetsRpcExpose(t.ctrl, ZMQFunctionSets{ + "getUQHolderBytes": func(args [][]byte, onResult func([][]byte)) { + onResult([][]byte{getUQHolderBytes()}) + }, + "sendPacket": func(args [][]byte, onResult func([][]byte)) { + pk, err := ConvertFromRawPacketWithShield(pool, args[0]) + if err == nil { + omega.GetGameControl().SendPacket(pk) + } + }, + "sendPacketBytes": func(args [][]byte, onResult func([][]byte)) { + if len(args) == 2 { + pktIDBytes := args[0] + packetDataBytes := args[1] + if len(pktIDBytes) == 4 { + packetID := binary.LittleEndian.Uint32(pktIDBytes) + omega.GetGameControl().SendPacketBytes(packetID, packetDataBytes) + } + } + }, + "botReady": func(args [][]byte, onResult func([][]byte)) { + onResult([][]byte{[]byte("botReady")}) + }, + "getConnShieldID": func(args [][]byte, onResult func([][]byte)) { + shieldIDBytes := make([]byte, 4) + binary.LittleEndian.PutUint32(shieldIDBytes, uint32(t.getShieldID())) + onResult([][]byte{shieldIDBytes}) + }, + }) +} diff --git a/version b/version index 84197c894..d41f08f1f 100644 --- a/version +++ b/version @@ -1 +1 @@ -5.3.2 +5.5.1 \ No newline at end of file