├── .gitattributes
├── .github
└── workflows
│ ├── build-template.yml
│ └── updateSDK.yml
├── .gitignore
├── .gitmodules
├── .idea
└── cmake.xml
├── CMakeLists.txt
├── GOHelper
├── .idea
│ ├── .gitignore
│ ├── .name
│ ├── GOHelper.iml
│ ├── modules.xml
│ └── vcs.xml
├── go.mod
├── go.sum
├── json.go
└── png.go
├── README.md
├── Template.sln
├── Template
├── GoLang.hpp
├── Plugin.cpp
├── Resource.rc
├── Setting.cpp
├── Setting.h
├── Template.vcxproj
├── Template.vcxproj.filters
├── Version.h
├── dllmain.cpp
├── framework.h
├── godef.h
└── resource.h
├── build.bat
├── fetchSDK.cmd
└── prepareLib.cmd
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/.github/workflows/build-template.yml:
--------------------------------------------------------------------------------
1 | name: Build Plugin(Publish if tag)
2 |
3 | on: [push]
4 |
5 | env:
6 | PLUGIN_NAME: CustomMapX
7 | SOLUTION_FILE_PATH: ./Template.sln
8 | VERSION_FILE_PATH: Template/Version.h
9 | BUILD_CONFIGURATION: Release
10 | Platform: X64
11 | SDK_DIR: ./SDK
12 | BDS_VERSION: 1.19.30.04
13 |
14 | jobs:
15 | build:
16 | runs-on: windows-latest
17 |
18 | steps:
19 | - uses: actions/checkout@v2
20 | with:
21 | submodules: 'true'
22 |
23 | # - name: Get information from Version.h file (TODO)
24 | # working-directory: ${{env.GITHUB_WORKSPACE}}
25 | # id: ver
26 | # run: |
27 | # pwd
28 | # shell: bash
29 |
30 | - name: Download Server
31 | working-directory: ${{env.GITHUB_WORKSPACE}}
32 | run: |
33 | mkdir -p ${{ env.SDK_DIR }}/Tools/Server
34 | # ServerLink=$(cat 'Scripts/LINK.txt')
35 | ServerLink=https://minecraft.azureedge.net/bin-win/bedrock-server-${{ env.BDS_VERSION }}.zip
36 | curl -L -o ${{ env.SDK_DIR }}/Tools/Server/server.zip "$ServerLink"
37 | unzip ${{ env.SDK_DIR }}/Tools/Server/server.zip -d ${{ env.SDK_DIR }}/Tools/Server/ > /dev/null
38 | shell: bash
39 |
40 | - name: Build Library
41 | working-directory: ${{env.GITHUB_WORKSPACE}}
42 | run: |
43 | cd ${{ env.SDK_DIR }}\Tools
44 | LibraryBuilder.exe -o ..\Lib .\Server
45 | shell: cmd
46 |
47 | - name: Add MSBuild to PATH
48 | uses: microsoft/setup-msbuild@v1
49 |
50 | - name: Change PLUGIN_VERSION_STATUS_BETA
51 | working-directory: ${{env.GITHUB_WORKSPACE}}
52 | if: false == startsWith(github.ref, 'refs/tags/')
53 | run: |
54 | sed -r -i 's/#define\s+PLUGIN_VERSION_STATUS\s+PLUGIN_VERSION_\w+/#define PLUGIN_VERSION_STATUS PLUGIN_VERSION_BETA/' ${{env.VERSION_FILE_PATH}}
55 | sed -r -i 's/#define\s+PLUGIN_VERSION_BUILD\s+.*/#define PLUGIN_VERSION_BUILD ${{ github.run_number }}\r/' ${{env.VERSION_FILE_PATH}}
56 | shell: bash
57 |
58 | - name: Change PLUGIN_VERSION_STATUS_RELEASE
59 | working-directory: ${{env.GITHUB_WORKSPACE}}
60 | if: startsWith(github.ref, 'refs/tags/')
61 | run: |
62 | sed -r -i 's/#define\s+PLUGIN_VERSION_STATUS\s+PLUGIN_VERSION_\w+/#define PLUGIN_VERSION_STATUS PLUGIN_VERSION_RELEASE/' ${{env.VERSION_FILE_PATH}}
63 | sed -r -i 's/#define\s+PLUGIN_VERSION_BUILD\s+.*/#define PLUGIN_VERSION_BUILD ${{ github.run_number }}\r/' ${{env.VERSION_FILE_PATH}}
64 | shell: bash
65 |
66 | - name: Build
67 | working-directory: ${{env.GITHUB_WORKSPACE}}
68 | id: build
69 | run: |
70 | MSBuild.exe ${{env.SOLUTION_FILE_PATH}} -property:Configuration=${{env.BUILD_CONFIGURATION}}
71 | ./build.bat
72 | shell: bash
73 |
74 | - name: copy dll and pdb files
75 | working-directory: ${{env.GITHUB_WORKSPACE}}
76 | run: |
77 | mkdir output/
78 | mkdir output/${{env.PLUGIN_NAME}}/
79 | cp -f x64/Release/*.dll output/${{env.PLUGIN_NAME}}/
80 | mkdir output/${{env.PLUGIN_NAME}}/lib/
81 | cp -f GOHelper/*.dll output/${{env.PLUGIN_NAME}}/lib/
82 | mkdir output/PDB/
83 | cp -f x64/Release/*.pdb output/PDB/
84 | # mkdir output/${{env.PLUGIN_NAME}}/${{env.PLUGIN_NAME}}/
85 | # cp -r Data/* output/${{env.PLUGIN_NAME}}/${{env.PLUGIN_NAME}}/
86 | shell: bash
87 |
88 | - name: Pack Release
89 | working-directory: ${{env.GITHUB_WORKSPACE}}
90 | if: startsWith(github.ref, 'refs/tags/')
91 | run: |
92 | Compress-Archive -Path output\${{env.PLUGIN_NAME}}\ ${{env.PLUGIN_NAME}}.zip
93 | Compress-Archive -Path output\PDB\ PDB.zip
94 |
95 | - name: Prepare for creating Release
96 | working-directory: ${{env.GITHUB_WORKSPACE}}
97 | id: rel
98 | if: startsWith(github.ref, 'refs/tags/')
99 | run: |
100 | echo ::set-output name=tag::${GITHUB_REF#refs/tags/*}
101 | mv ${{env.PLUGIN_NAME}}.zip ${{env.PLUGIN_NAME}}-${GITHUB_REF#refs/tags/*}.zip
102 | mv PDB.zip PDB-${GITHUB_REF#refs/tags/*}.zip
103 | shell: bash
104 |
105 | - name: Upload PLUGIN
106 | uses: actions/upload-artifact@v2
107 | with:
108 | name: ${{env.PLUGIN_NAME}}-actions-${{ github.run_number }}
109 | path: ${{ github.workspace }}\output\${{env.PLUGIN_NAME}}
110 |
111 | - name: Upload PDB
112 | uses: actions/upload-artifact@v2
113 | with:
114 | name: PDB-actions-${{ github.run_number }}
115 | path: ${{ github.workspace }}\output\PDB
116 |
117 |
118 | - name: Create New Release
119 | uses: softprops/action-gh-release@v1
120 | if: startsWith(github.ref, 'refs/tags/')
121 | with:
122 | # body_path: ${{ github.workspace }}\CHANGELOG.txt
123 | files: |
124 | ${{ github.workspace }}\${{env.PLUGIN_NAME}}-${{ steps.rel.outputs.tag }}.zip
125 | ${{ github.workspace }}\PDB-${{ steps.rel.outputs.tag }}.zip
126 | env:
127 | GITHUB_REPOSITORY: ${{env.GITHUB_ACTION_REPOSITORY}}
128 |
129 |
--------------------------------------------------------------------------------
/.github/workflows/updateSDK.yml:
--------------------------------------------------------------------------------
1 | name: Update SDK
2 |
3 | on:
4 | schedule:
5 | - cron: "0 0 * * *"
6 | workflow_dispatch:
7 |
8 | jobs:
9 | update:
10 | runs-on: ubuntu-latest
11 |
12 | steps:
13 |
14 | - name: Checkout
15 | uses: actions/checkout@v2.4.0
16 |
17 | - name: Update SDK
18 | run: git submodule update --init --recursive --remote
19 |
20 | - name: Push
21 | run: |
22 | git config --global user.name "github-actions[bot]"
23 | git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
24 | git commit -am "fetch upstream SDK" || exit 0
25 | git push || exit 0
26 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .vs/
2 | **/x64/
3 | **/*.user
4 | **/.vscode/
5 |
6 | **/bedrock_server_api.lib
7 | **/bedrock_server_var.lib
8 |
9 | /.idea/*
10 | !/.idea/cmake.xml
11 | /cmake-build-*
12 | build/*
13 | /out/*
14 | GOHelper/MAP_Golang_Module.dll
15 | GOHelper/MAP_Golang_Module.h
16 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "SDK"]
2 | path = SDK
3 | url = https://github.com/LiteLDev/LiteLoaderSDK
4 | branch = main
5 |
--------------------------------------------------------------------------------
/.idea/cmake.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.21)
2 | project(TemplatePlugin)
3 |
4 | set(CMAKE_CXX_STANDARD 17)
5 | set(CMAKE_BUILD_TYPE Release)
6 |
7 | file(GLOB_RECURSE SRC_FILES_DIR
8 | ${PROJECT_SOURCE_DIR}/SDK/include/*.cpp
9 | ${PROJECT_SOURCE_DIR}/SDK/include/*.hpp
10 | ${PROJECT_SOURCE_DIR}/SDK/include/*.h
11 | ${PROJECT_SOURCE_DIR}/Template/*.cpp
12 | ${PROJECT_SOURCE_DIR}/Template/*.hpp
13 | ${PROJECT_SOURCE_DIR}/Template/*.h
14 | )
15 |
16 | include_directories(SDK/include)
17 | include_directories(SDK/include/third-party)
18 | include_directories(Template)
19 |
20 | link_directories(.)
21 |
22 | add_definitions(-D"NDEBUG" -D"TEMPLATE_EXPORTS" -D"WIN32_LEAN_AND_MEAN" -D"_CRT_SECURE_NO_WARNINGS" -D"_WINDOWS"
23 | -D"_USRDLL" -D"_AMD64_" -D"NOMINMAX" -D"_WINDLL" -D"_UNICODE" -D"UNICODE")
24 |
25 | add_compile_options(
26 | /permissive- /GS /GL /W3 /Gy /Zc:wchar_t /Zi /Gm- /sdl /Zc:inline /fp:precise /errorReport:prompt /WX-
27 | /Zc:forScope /Gd /Oi /MD /std:c++17 /FC /EHsc /nologo /diagnostics:column
28 | )
29 |
30 | add_link_options(
31 | /MANIFEST /LTCG:incremental /NXCOMPAT /DEBUG /DLL /MACHINE:X64 /OPT:REF /INCREMENTAL:NO /SUBSYSTEM:WINDOWS
32 | /MANIFESTUAC:NO /OPT:ICF /ERRORREPORT:PROMPT /NOLOGO /DELAYLOAD:"bedrock_server.dll" /TLBID:1
33 | )
34 |
35 | add_library(TemplatePlugin SHARED ${SRC_FILES_DIR})
36 |
37 | add_custom_command(TARGET TemplatePlugin PRE_BUILD
38 | COMMAND cmd /c ${PROJECT_SOURCE_DIR}/prepareLib.cmd ${PROJECT_SOURCE_DIR}
39 | COMMENT "Preparing Library"
40 | )
41 |
--------------------------------------------------------------------------------
/GOHelper/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # 默认忽略的文件
2 | /shelf/
3 | /workspace.xml
4 | # 基于编辑器的 HTTP 客户端请求
5 | /httpRequests/
6 | # Datasource local storage ignored files
7 | /dataSources/
8 | /dataSources.local.xml
9 |
--------------------------------------------------------------------------------
/GOHelper/.idea/.name:
--------------------------------------------------------------------------------
1 | png.go
--------------------------------------------------------------------------------
/GOHelper/.idea/GOHelper.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/GOHelper/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/GOHelper/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/GOHelper/go.mod:
--------------------------------------------------------------------------------
1 | module GOHelper
2 |
3 | go 1.18
4 |
5 | require (
6 | github.com/df-mc/dragonfly v0.6.0
7 | github.com/shamsher31/goimgtype v1.0.0
8 | )
9 |
10 | require github.com/shamsher31/goimgext v1.0.0 // indirect
11 |
--------------------------------------------------------------------------------
/GOHelper/go.sum:
--------------------------------------------------------------------------------
1 | github.com/df-mc/dragonfly v0.6.0 h1:rqdIKtyK/y6byQwp9qtE6G++FPIEMWHQTWtuQW8e1Zk=
2 | github.com/df-mc/dragonfly v0.6.0/go.mod h1:Z41+mculxbyubTw4pU0spDUuvuLb9pSar2VQWQgp/jI=
3 | github.com/shamsher31/goimgext v1.0.0 h1:wFKf9GeeE0Xr6UQtliaPgYYgTju2izobM7XpCEgUCC8=
4 | github.com/shamsher31/goimgext v1.0.0/go.mod h1:rYLKgXuTGBIaH49z+jUVSWz7gUWIZmqvYUsdvJbNNOc=
5 | github.com/shamsher31/goimgtype v1.0.0 h1:7nmPz5GEb01sjFUojCbZJcBI68A8tmLXoCFbb5I34u4=
6 | github.com/shamsher31/goimgtype v1.0.0/go.mod h1:OZm3NZQDbK0ezlk9IV5oq3cWQwjF1oVSxKNx19bkf64=
7 |
--------------------------------------------------------------------------------
/GOHelper/json.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | type RootEntity struct {
4 | DownloadImg DownloadImgEntity `json:"DownloadImg"`
5 | ImgSize ImgSizeEntity `json:"ImgSize"`
6 | LocalImg LocalImgEntity `json:"LocalImg"`
7 | MemberRateLimit int64 `json:"MemberRateLimit"`
8 | }
9 |
10 | type DownloadImgEntity struct {
11 | AllowMember bool `json:"Allow-Member"`
12 | }
13 |
14 | type ImgSizeEntity struct {
15 | MaxFileSize int64 `json:"maxFileSize"`
16 | MaxHeight int64 `json:"maxHeight"`
17 | MaxWidth int64 `json:"maxWidth"`
18 | }
19 |
20 | type LocalImgEntity struct {
21 | AllowMember bool `json:"Allow-Member"`
22 | }
23 |
--------------------------------------------------------------------------------
/GOHelper/png.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "encoding/binary"
5 | "encoding/json"
6 | "image"
7 | "image/jpeg"
8 | "image/png"
9 | "net/url"
10 | "os"
11 | "strconv"
12 | )
13 |
14 | /*
15 | #include
16 | #include
17 | typedef struct {
18 | void* data;
19 | long long len;
20 | long long cap;
21 | } CgoSlice;
22 | #cgo LDFLAGS: -Wl,--allow-multiple-definition
23 | */
24 | import "C"
25 | import (
26 | "bytes"
27 | imgext "github.com/shamsher31/goimgext"
28 | _ "image/gif"
29 | "io"
30 | "io/ioutil"
31 | "net/http"
32 | "strings"
33 | )
34 |
35 | //export png2PixelArr
36 | func png2PixelArr(paths string) C.CgoSlice {
37 | image.RegisterFormat("png", "png", png.Decode, png.DecodeConfig)
38 | image.RegisterFormat("jpeg", "jpeg", jpeg.Decode, jpeg.DecodeConfig)
39 | rr, err := os.Open(paths)
40 | if err != nil {
41 | var ret C.CgoSlice
42 | ret.data = nil
43 | ret.len = C.longlong(-1)
44 | ret.cap = C.longlong(0)
45 | return ret
46 | }
47 | defer rr.Close()
48 | img, _, err := image.Decode(rr)
49 | if err != nil {
50 | var ret C.CgoSlice
51 | ret.data = nil
52 | ret.len = C.longlong(-2)
53 | ret.cap = C.longlong(0)
54 | return ret
55 | }
56 | w, h := img.Bounds().Dx(), img.Bounds().Dy()
57 | data := make([]byte, 0, w*h*4)
58 | for y := 0; y < h; y++ {
59 | for x := 0; x < w; x++ {
60 | r, g, b, a := img.At(x, y).RGBA()
61 | data = append(data, byte(r>>8), byte(g>>8), byte(b>>8), byte(a>>8))
62 | }
63 | }
64 | out := []byte(strconv.Itoa(w))
65 | out = append(out, []byte{'\n'}...)
66 | out = append(out, strconv.Itoa(h)...)
67 | out = append(out, []byte{'\n'}...)
68 | out = append(out, data...)
69 |
70 | var ret C.CgoSlice
71 | ret.data = C.CBytes(out)
72 | ret.len = C.longlong(len(out))
73 | ret.cap = C.longlong(len(out))
74 |
75 | return ret
76 | }
77 |
78 | func IntToBytes(n int) []byte {
79 | x := int32(n)
80 | bytesBuffer := bytes.NewBuffer([]byte{})
81 | binary.Write(bytesBuffer, binary.BigEndian, x)
82 | return bytesBuffer.Bytes()
83 | }
84 |
85 | func isURL(urls string) bool {
86 | _, err := url.ParseRequestURI(urls)
87 | if err != nil {
88 | return false
89 | }
90 | return true
91 | }
92 |
93 | func ReadConfig() (int64, int64, int64) {
94 | data, err := ioutil.ReadFile("plugins\\CustomMapX\\config.json")
95 | if err != nil {
96 | return 0, 0, 0
97 | }
98 | var root RootEntity
99 | err = json.Unmarshal(data, &root)
100 | if err != nil {
101 | return 0, 0, 0
102 | }
103 | return root.ImgSize.MaxWidth, root.ImgSize.MaxHeight, root.ImgSize.MaxFileSize
104 | }
105 |
106 | //export getUrlPngData
107 | func getUrlPngData(url string) C.CgoSlice {
108 | image.RegisterFormat("png", "png", png.Decode, png.DecodeConfig)
109 | image.RegisterFormat("jpeg", "jpeg", jpeg.Decode, jpeg.DecodeConfig)
110 | if isURL(url) {
111 | header, err := http.Head(url)
112 | if err != nil {
113 | var ret C.CgoSlice
114 | ret.data = nil
115 | ret.len = C.longlong(-4)
116 | ret.cap = C.longlong(0)
117 | return ret
118 | }
119 | maxw, maxh, maxsize := ReadConfig()
120 | length := float64(header.ContentLength) / 1024 / 1024
121 | if length > float64(maxsize) {
122 | var ret C.CgoSlice
123 | ret.data = nil
124 | ret.len = C.longlong(-6)
125 | ret.cap = C.longlong(0)
126 | return ret
127 | }
128 | if length != 0 {
129 | resp, err := http.Get(url)
130 | defer resp.Body.Close()
131 | if err != nil {
132 | var ret C.CgoSlice
133 | ret.data = nil
134 | ret.len = C.longlong(-1)
135 | ret.cap = C.longlong(0)
136 | return ret
137 | }
138 | allbody, err := ioutil.ReadAll(resp.Body)
139 | if err != nil {
140 | var ret C.CgoSlice
141 | ret.data = nil
142 | ret.len = C.longlong(-1)
143 | ret.cap = C.longlong(0)
144 | return ret
145 | }
146 | imgtype := GetImageType(ioutil.NopCloser(bytes.NewReader(allbody)))
147 | if imgtype != "" {
148 | if err != nil {
149 | var ret C.CgoSlice
150 | ret.data = nil
151 | ret.len = C.longlong(-3)
152 | ret.cap = C.longlong(0)
153 | return ret
154 | }
155 | img, _, err := image.Decode(ioutil.NopCloser(bytes.NewReader(allbody)))
156 | if err != nil {
157 | var ret C.CgoSlice
158 | ret.data = nil
159 | ret.len = C.longlong(-5)
160 | ret.cap = C.longlong(0)
161 | return ret
162 | }
163 | w, h := img.Bounds().Dx(), img.Bounds().Dy()
164 | if int64(w) > maxw || int64(h) > maxh {
165 | var ret C.CgoSlice
166 | ret.data = nil
167 | ret.len = C.longlong(-2)
168 | ret.cap = C.longlong(0)
169 | return ret
170 | }
171 | data := make([]byte, 0, w*h*4)
172 | for y := 0; y < h; y++ {
173 | for x := 0; x < w; x++ {
174 | r, g, b, a := img.At(x, y).RGBA()
175 | data = append(data, byte(r>>8), byte(g>>8), byte(b>>8), byte(a>>8))
176 | }
177 | }
178 | out := []byte(strconv.Itoa(w))
179 | out = append(out, []byte{'\n'}...)
180 | out = append(out, strconv.Itoa(h)...)
181 | out = append(out, []byte{'\n'}...)
182 | out = append(out, data...)
183 |
184 | var ret C.CgoSlice
185 | ret.data = C.CBytes(out)
186 | ret.len = C.longlong(len(out))
187 | ret.cap = C.longlong(len(out))
188 |
189 | return ret
190 | }
191 | }
192 | }
193 | var ret C.CgoSlice
194 | ret.data = nil
195 | ret.len = C.longlong(-1)
196 | ret.cap = C.longlong(0)
197 | return ret
198 | }
199 |
200 | func GetImageType(reader io.ReadCloser) string {
201 | buff := make([]byte, 512)
202 | _, err := reader.Read(buff)
203 | if err != nil {
204 | return ""
205 | }
206 | filetype := http.DetectContentType(buff)
207 | ext := imgext.Get()
208 | for i := 0; i < len(ext); i++ {
209 | if strings.Contains(ext[i], filetype[6:len(filetype)]) {
210 | return filetype
211 | }
212 | }
213 | return ""
214 | }
215 |
216 | func main() {
217 |
218 | }
219 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # CustomMapX
2 |
3 | `CustomMapX` A plugin for customizing map images.
4 |
5 | ### How to use?
6 | - You need to put your picture into `plugins\CustomMapX\picture`
7 | - Then type `/map add ` in the server
8 |
9 | - If you add images after the server has been start, you will need `/map reload`, to refresh the image list.
10 |
11 | - You can get help with `/map help`
12 |
13 |
14 |
15 | ### ⚠️ Warning
16 |
17 | Please do not reproduce without permission, integration! This may keep it from ever being updated
18 |
19 | #### Extra Restrictions & Exceptions
20 |
21 | You can't distribute, integrate, etc. without my authorized permission
22 |
--------------------------------------------------------------------------------
/Template.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.0.31903.59
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Template", "Template\Template.vcxproj", "{ABEB5558-C92F-473E-8BDF-90F58BD3811C}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Release|x64 = Release|x64
11 | EndGlobalSection
12 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
13 | {ABEB5558-C92F-473E-8BDF-90F58BD3811C}.Release|x64.ActiveCfg = Release|x64
14 | {ABEB5558-C92F-473E-8BDF-90F58BD3811C}.Release|x64.Build.0 = Release|x64
15 | EndGlobalSection
16 | GlobalSection(SolutionProperties) = preSolution
17 | HideSolutionNode = FALSE
18 | EndGlobalSection
19 | GlobalSection(ExtensibilityGlobals) = postSolution
20 | SolutionGuid = {9F46E45F-CD85-4250-93FD-0DD973FB8ECF}
21 | EndGlobalSection
22 | EndGlobal
23 |
--------------------------------------------------------------------------------
/Template/GoLang.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "godef.h"
3 |
4 | namespace GolangFunc {
5 | namespace FuncDef {
6 | typedef GoSlice (*png2PixelArr)(GoString);
7 | typedef GoSlice(*getUrlPngData)(GoString);
8 | } // namespace FuncDef
9 | FuncDef::png2PixelArr png2PixelArr;
10 | FuncDef::getUrlPngData getUrlPngData;
11 | } // namespace GolangFunc
--------------------------------------------------------------------------------
/Template/Plugin.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include "Version.h"
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include "Setting.h"
24 | std::unordered_map tempList;
25 |
26 | int MapIndex;
27 |
28 | Logger logger(PLUGIN_NAME);
29 |
30 | inline void getAllFiles(std::string strPath, std::vector& vecFiles)
31 | {
32 | char cEnd = *strPath.rbegin();
33 | if (cEnd == '\\' || cEnd == '/')
34 | {
35 | strPath = strPath.substr(0, strPath.length() - 1);
36 | }
37 | if (strPath.empty() || strPath == (".") || strPath == (".."))
38 | return;
39 | std::error_code ec;
40 | std::filesystem::path fsPath(strPath);
41 | if (!std::filesystem::exists(strPath, ec)) {
42 | return;
43 | }
44 | for (auto& itr : std::filesystem::directory_iterator(fsPath))
45 | {
46 | if (std::filesystem::is_directory(itr.status()))
47 | {
48 | getAllFiles(UTF82String(itr.path().u8string()), vecFiles);
49 | }
50 | else
51 | {
52 | vecFiles.push_back(UTF82String(itr.path().filename().u8string()));
53 | }
54 | }
55 | }
56 |
57 | time_t getTimeStamp()
58 | {
59 | std::chrono::time_point tp = std::chrono::time_point_cast(std::chrono::system_clock::now());
60 | auto tmp = std::chrono::duration_cast(tp.time_since_epoch());
61 | std::time_t timestamp = tmp.count();
62 | return timestamp;
63 | }
64 | time_t getTimeStamp2()
65 | {
66 | std::chrono::time_point tp = std::chrono::time_point_cast(std::chrono::system_clock::now());
67 | auto tmp = std::chrono::duration_cast(tp.time_since_epoch());
68 | std::time_t timestamp = tmp.count();
69 | return timestamp;
70 | }
71 |
72 |
73 | std::mutex mtx;
74 | #include
75 | std::tuple, unsigned, unsigned,string> isChange = std::make_tuple(false, std::vector(), 0, 0,"");
76 |
77 |
78 | namespace mce{
79 |
80 | class Blob {
81 | public:
82 | void* unk0;
83 | std::unique_ptr buffer;
84 | size_t length = 0;
85 |
86 |
87 | inline Blob() {}
88 | inline Blob(Blob&& rhs) : buffer(std::move(rhs.buffer)), length(rhs.length) { rhs.length = 0; }
89 | inline Blob(size_t input_length) : buffer(std::make_unique(input_length)), length(input_length) {}
90 | inline Blob(unsigned char const* input, size_t input_length) : Blob(input_length) {
91 | memcpy(buffer.get(), input, input_length);
92 | }
93 |
94 | inline Blob& operator=(Blob&& rhs) {
95 | if (&rhs != this) {
96 | buffer = std::move(rhs.buffer);
97 | length = rhs.length;
98 | rhs.length = 0;
99 | }
100 | return *this;
101 | }
102 |
103 | inline Blob clone() const { return { data(), size() }; }
104 |
105 | inline unsigned char* begin() { return buffer.get(); }
106 | inline unsigned char* end() { return buffer.get() + length; }
107 | inline unsigned char const* cbegin() const { return buffer.get(); }
108 | inline unsigned char const* cend() const { return buffer.get() + length; }
109 |
110 | inline unsigned char* data() { return buffer.get(); }
111 | inline unsigned char const* data() const { return buffer.get(); }
112 |
113 | inline bool empty() const { return length == 0; }
114 | inline size_t size() const { return length; }
115 |
116 | inline auto getSpan() const { return gsl::make_span(data(), size()); }
117 |
118 | };
119 |
120 | static_assert(sizeof(Blob) == 24);
121 |
122 | enum class ImageFormat {
123 | NONE = 0,
124 | RGB = 1,
125 | RGBA = 2
126 | };
127 |
128 | enum class ImageUsage : int8_t {
129 | unknown = 0,
130 | sRGB = 1,
131 | data = 2
132 | };
133 |
134 | inline unsigned numChannels(ImageFormat format) {
135 | switch (format) {
136 | case ImageFormat::RGB: return 3;
137 | case ImageFormat::RGBA: return 4;
138 | default: return 0;
139 | }
140 | }
141 |
142 | class Image {
143 | inline Image(ImageFormat format, unsigned width, unsigned height, ImageUsage usage, Blob&& data)
144 | : format(format), width(width), height(height), usage(usage), data(std::move(data)) {}
145 |
146 | public:
147 | ImageFormat format{}; // 0x0
148 | unsigned width{}, height{}; // 0x4, 0x8
149 | ImageUsage usage{}; // 0xC
150 | Blob data; // 0x10
151 |
152 | inline Image(Blob&& data) : data(std::move(data)) {}
153 | inline Image(unsigned width, unsigned height, ImageFormat format, ImageUsage usage)
154 | : format(format), width(width), height(height), usage(usage) {}
155 | inline Image() {}
156 |
157 | inline Image& operator=(Image&& rhs) {
158 | format = rhs.format;
159 | width = rhs.width;
160 | height = rhs.height;
161 | usage = rhs.usage;
162 | data = std::move(rhs.data);
163 | return *this;
164 | }
165 |
166 | inline Image clone() const { return { format, width, height, usage, data.clone() }; }
167 |
168 | inline void copyRawImage(Blob const& blob) { data = blob.clone(); }
169 |
170 | inline bool isEmpty() const { return data.empty(); }
171 |
172 | inline void resizeImageBytesToFitImageDescription() { data = Blob{ width * height * numChannels(format) }; }
173 |
174 | inline void setImageDescription(unsigned width, unsigned height, ImageFormat format, ImageUsage usage) {
175 | this->width = width;
176 | this->height = height;
177 | this->format = format;
178 | this->usage = usage;
179 | }
180 |
181 | inline void setRawImage(Blob&& buffer) { data = std::move(buffer); }
182 |
183 | Image(const Image& a1) {
184 | format = a1.format;
185 | width = a1.width;
186 | height = a1.height;
187 | usage = a1.usage;
188 | data = a1.data.clone();
189 | }
190 | };
191 |
192 | static_assert(offsetof(Image, data) == 0x10);
193 | static_assert(offsetof(Image, format) == 0x0);
194 | static_assert(offsetof(Image, usage) == 0xC);
195 | static_assert(sizeof(Image) == 40);
196 |
197 |
198 | }; // namespace mce
199 |
200 | class Image2D {
201 | public:
202 | vector rawColor;
203 |
204 | unsigned width = 0, height = 0;
205 |
206 | Image2D(unsigned w, unsigned h, vector c) : width(w), height(h), rawColor(c) {};
207 | };
208 | extern HMODULE DllMainPtr;
209 | //#include"MemoryModule.h"
210 | #include "GoLang.hpp"
211 | void golang() {
212 | //HRSRC DLL = ::FindResource(DllMainPtr, MAKEINTRESOURCE(4), L"DLL");
213 | //DWORD ResSize = ::SizeofResource(DllMainPtr, DLL);
214 | //HGLOBAL ResData = ::LoadResource(DllMainPtr, DLL);
215 | //void* ResDataRef = ::LockResource(ResData);
216 | //HMEMORYMODULE lib = MemoryLoadLibrary(ResDataRef, ResSize);
217 | //if (lib) {
218 | // GolangFunc::png2PixelArr = (GolangFunc::FuncDef::png2PixelArr)MemoryGetProcAddress(lib, "png2PixelArr");
219 | // GolangFunc::getUrlPngData = (GolangFunc::FuncDef::getUrlPngData)MemoryGetProcAddress(lib, "getUrlPngData");
220 | //}
221 | //else {
222 | // Logger("CustomNpcModule").warn("Failed to load MAP_SubModule");
223 | //}
224 |
225 | if (std::filesystem::exists("plugins/lib/MAP_Golang_Module.dll")) {
226 | auto lib = LoadLibrary(L"plugins/lib/MAP_Golang_Module.dll");
227 | if (lib) {
228 | GolangFunc::png2PixelArr = (GolangFunc::FuncDef::png2PixelArr)GetProcAddress(lib, "png2PixelArr");
229 | GolangFunc::getUrlPngData = (GolangFunc::FuncDef::getUrlPngData)GetProcAddress(lib, "getUrlPngData");
230 | }
231 | else {
232 | logger.error("Failed to load MAP_SubModule");
233 | }
234 | }
235 | else {
236 | logger.error("Failed to load MAP_SubModule");
237 | }
238 | }
239 | namespace Helper {
240 | vector split(char* a1) {
241 | vector result;
242 | char* a2 = a1;
243 | int a3 = 0;
244 | while (*a2) {
245 | if (a3 < 2) {
246 | if (*a2 == '\n') {
247 | *a2 = 0;
248 | a3++;
249 | result.push_back(a1);
250 | a1 = a2 + 1;
251 | }
252 | }
253 | a2++;
254 | }
255 | result.push_back(a1);
256 | return result;
257 | }
258 |
259 | const std::tuple, unsigned, unsigned> Png2Pix(string path,ServerPlayer* pl) {
260 | GoString paths{ path.c_str(),(int64_t)path.size() };
261 | auto imagedata = GolangFunc::png2PixelArr(paths);
262 | auto data = imagedata.data();
263 | if (pl) {
264 | switch (imagedata.length())
265 | {
266 | case -1: {
267 | pl->sendText("§l§6[CustomMapX] §cImage does not exist!");
268 | return std::make_tuple(std::vector(), 0, 0);
269 | }
270 | case -2: {
271 | pl->sendText("§l§6[CustomMapX] §cImage decoding failure!");
272 | return std::make_tuple(std::vector(), 0, 0);
273 | }
274 | }
275 | }
276 | if (imagedata.length() != 0 && data != nullptr) {
277 | auto out = split(data);
278 | if (out.size() == 3) {
279 | int w = atoi(out[0]);
280 | int h = atoi(out[1]);
281 | std::vector image;
282 | image.resize(w * h * 4);
283 | memcpy(image.data(), (void*)out[2], w * h * 4);
284 | if (!pl->isOP())
285 | tempList[pl->getRealName()] = getTimeStamp();
286 | return std::make_tuple(image, w, h);
287 | }
288 | }
289 | return std::make_tuple(std::vector(), 0, 0);
290 | }
291 |
292 | void Url2Pix(string url,string plname) {
293 | try {
294 | GoString urls{ url.c_str(),(int64_t)url.size() };
295 | auto imagedata = GolangFunc::getUrlPngData(urls);
296 | auto data = imagedata.data();
297 | auto pl = Global->getPlayer(plname);
298 | if (pl) {
299 | switch (imagedata.length())
300 | {
301 | case -1: {
302 | pl->sendText("§l§6[CustomMapX] §cURL is not legal!");
303 | return;
304 | }
305 | case -2: {
306 | pl->sendText("§l§6[CustomMapX] §cImage out of size!");
307 | return;
308 | }
309 | case -3: {
310 | pl->sendText("§l§6[CustomMapX] §cURL is not a Image!");
311 | return;
312 | }
313 | case -4: {
314 | pl->sendText("§l§6[CustomMapX] §cURL Access failure!");
315 | return;
316 | }
317 | case -5: {
318 | pl->sendText("§l§6[CustomMapX] §cImage decoding failure!");
319 | }
320 | case -6: {
321 | pl->sendText("§l§6[CustomMapX] §cImage exceeds maximum allowed size!");
322 | }
323 | }
324 | }
325 | if (imagedata.length() > 0 && data != nullptr) {
326 | auto out = split(data);
327 | if (out.size() == 3) {
328 | int w = atoi(out[0]);
329 | int h = atoi(out[1]);
330 | std::vector image;
331 | image.resize(w * h * 4);
332 | memcpy(image.data(), (void*)out[2], w * h * 4);
333 | isChange = std::make_tuple(true, image, w, h, plname);
334 | if(!pl->isOP())
335 | tempList[plname] = getTimeStamp();
336 | return;
337 | }
338 | }
339 | isChange = std::make_tuple(false, std::vector(), 0, 0, "");
340 | if (pl) {
341 | pl->sendText("§l§6[CustomMapX] §cAdd Map Error!");
342 | }
343 | return;
344 | }
345 | catch (...) {
346 | auto pl = Global->getPlayer(plname);
347 | if (pl) {
348 | isChange = std::make_tuple(false, std::vector(), 0, 0, "");
349 | pl->sendText("§l§6[CustomMapX] §cAdd Map Error!");
350 | }
351 | }
352 | }
353 |
354 | vector CuttingImages(std::vector image, int width, int height) {
355 | vector images;
356 | auto wcut = width / 128;
357 | auto hcut = height / 128;
358 | if (width % 128 != 0) {
359 | wcut++;
360 | }
361 |
362 | if (height % 128 != 0) {
363 | hcut++;
364 | }
365 | for (auto h = 0; h < hcut; h++) {
366 | for (auto w = 0; w < wcut; w++) {
367 | vector img;
368 | for (auto a = h * 128; a < h * 128 + 128; a++) {
369 | for (auto b = w * 128; b < w * 128 + 128; b++) {
370 | if (a * width + b < image.size() && b * height + a < image.size()) {
371 | img.push_back(image[a * width + b]);
372 | }
373 | else {
374 | img.push_back(mce::Color(0xff, 0xff, 0xff, 0));
375 | }
376 | }
377 | }
378 | images.push_back(Image2D(128, 128, img));
379 | }
380 | }
381 | return images;
382 | }
383 |
384 | void createImg(std::vector data, unsigned w, unsigned h, ServerPlayer* sp, string picfile) {
385 | if (data.size() == 0) return;
386 | vector Colorlist;
387 | for (int y = 0; y < h; y++)
388 | {
389 | for (int x = 0; x < w; x++)
390 | {
391 | mce::Color img((float)data[(y * w + x) * 4 + 0] / 255, (float)data[(y * w + x) * 4 + 1] / 255, (float)data[(y * w + x) * 4 + 2] / 255, (float)data[(y * w + x) * 4 + 3] / 255);
392 | Colorlist.push_back(img);
393 | }
394 | }
395 | auto datalist = Helper::CuttingImages(Colorlist, w, h);
396 | int xtemp = 0;
397 | int ytemp = 0;
398 | for (auto data : datalist) {
399 | auto mapitem = ItemStack::create("minecraft:filled_map");
400 | //auto MapIndex = sp->getMapIndex();
401 | //sp->setMapIndex(MapIndex + 1);
402 | MapIndex++;
403 | MapItem::setMapNameIndex(*mapitem, MapIndex);
404 | auto& mapdate = Global->_createMapSavedData(MapIndex);
405 | mapdate.setLocked();
406 | for (int x = 0; x < 128; x++) {
407 | for (int y = 0; y < 128; y++) {
408 | mapdate.setPixel(data.rawColor[y + x * 128].toABGR(), y, x);
409 | }
410 | }
411 | mapdate.save(*Global);
412 | MapItem::setItemInstanceInfo(*mapitem, mapdate);
413 | auto sizetest = sqrt(datalist.size());
414 | mapitem->setCustomName(picfile + "-" + std::to_string(xtemp) + "_" + std::to_string(ytemp));
415 | Spawner* sps = &Global->getSpawner();
416 | ItemActor* ac = sps->spawnItem(sp->getRegion(), *mapitem, nullptr, sp->getPos(), 0);
417 | delete mapitem;
418 | ytemp++;
419 | if (ytemp == sizetest) {
420 | xtemp++;
421 | ytemp = 0;
422 | }
423 | }
424 | sp->sendText("§l§6[CustomMapX] §aAdd Map Success!(" + std::to_string(datalist.size()) + ")");
425 | }
426 |
427 | string rand_str(const int len)
428 | {
429 | string str;
430 | char c;
431 | int idx;
432 | for (idx = 0; idx < len; idx++)
433 | {
434 | c = 'a' + rand() % 26;
435 | str.push_back(c);
436 | }
437 | return str;
438 | }
439 | }
440 |
441 | void Change() {
442 | Schedule::repeat([] {
443 | auto [isChnage, data, w,h,plname] = isChange;
444 | if (isChnage) {
445 | isChange = std::make_tuple(false, std::vector(), 0, 0,"");
446 | auto sp = Global->getPlayer(plname);
447 | if (sp->isPlayer()) {
448 | Helper::createImg(data, w, h, (ServerPlayer*)sp, Helper::rand_str(5));
449 | }
450 | }
451 | }, 20);
452 | }
453 |
454 |
455 | void RegCommand()
456 | {
457 | using ParamType = DynamicCommand::ParameterType;
458 |
459 | vector out;
460 | getAllFiles(".\\plugins\\CustomMapX\\picture", out);
461 |
462 | auto command = DynamicCommand::createCommand("map", "CustomMapX", CommandPermissionLevel::Any);
463 | auto& MapReloadEnum = command->setEnum("MapReloadEnum", { "reload" });
464 | auto& MaphelpEnum = command->setEnum("MaphelpEnum", {"help" });
465 | auto& MapAddEnum = command->setEnum("MapAddEnum", { "add"});
466 | auto& MapUrlEnum = command->setEnum("MapUrlEnum", { "download" });
467 |
468 | command->mandatory("MapsEnum", ParamType::Enum, MaphelpEnum, CommandParameterOption::EnumAutocompleteExpansion);
469 | command->mandatory("MapsEnum", ParamType::Enum, MapAddEnum, CommandParameterOption::EnumAutocompleteExpansion);
470 | command->mandatory("MapsEnum", ParamType::Enum, MapUrlEnum, CommandParameterOption::EnumAutocompleteExpansion);
471 | command->mandatory("MapsEnum", ParamType::Enum, MapReloadEnum, CommandParameterOption::EnumAutocompleteExpansion);
472 | command->mandatory("MapSoftEnum", ParamType::SoftEnum, command->setSoftEnum("MapENameList", out));
473 | command->mandatory("UrlStr", ParamType::String);
474 |
475 | command->addOverload({ MapAddEnum,"MapSoftEnum"});
476 | command->addOverload({ MaphelpEnum });
477 | command->addOverload({ MapReloadEnum });
478 | command->addOverload({ MapUrlEnum, "UrlStr"});
479 |
480 | command->setCallback([](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, std::unordered_map& results) {
481 | auto action = results["MapsEnum"].get();
482 | string str = "";
483 | ServerPlayer* sp = origin.getPlayer();
484 | switch (do_hash(action.c_str()))
485 | {
486 | case do_hash("add"): {
487 | if (sp) {
488 | if (tempList.find(sp->getRealName()) == tempList.end()) {
489 | if (sp->isOP() || Settings::LocalImg::allowmember) {
490 | auto picfile = results["MapSoftEnum"].get();
491 | if (!picfile.empty()) {
492 | auto [data, w, h] = Helper::Png2Pix(".\\plugins\\CustomMapX\\picture\\" + picfile, sp);
493 | Helper::createImg(data, w, h, sp, picfile);
494 | }
495 | }
496 | else {
497 | sp->sendText("§l§6[CustomMapX] §cYou are not allowed to add img map!");
498 | }
499 | }
500 | else {
501 | sp->sendText("§l§6[CustomMapX] §cFrequent operation, please try again later!\n§gRemaining time:" + std::to_string(Settings::memberRateLimit - ((getTimeStamp() - tempList[sp->getRealName()]) / 1000)) + "s");
502 | }
503 | }
504 | break;
505 | }
506 | case do_hash("download"): {
507 | if (sp) {
508 | if (tempList.find(sp->getRealName()) == tempList.end()) {
509 | if (sp->isOP() || Settings::DownloadImg::allowmember) {
510 | auto url = results["UrlStr"].getRaw();
511 | std::thread th(Helper::Url2Pix, url, sp->getRealName());
512 | th.detach();
513 | output.success("§l§6[CustomMapX] §aGenerating, please wait!");
514 | }
515 | else {
516 | sp->sendText("§l§6[CustomMapX] §cYou are not allowed to download img map!");
517 | }
518 | }
519 | else {
520 | sp->sendText("§l§6[CustomMapX] §cFrequent operation, please try again later!\n§gRemaining time:" + std::to_string(Settings::memberRateLimit - ((getTimeStamp() - tempList[sp->getRealName()]) / 1000)) + "s");
521 | }
522 | }
523 | break;
524 | }
525 | case do_hash("reload"): {
526 | if ((int)origin.getPermissionsLevel() > 0) {
527 | vector out;
528 | getAllFiles(".\\plugins\\CustomMapX\\picture", out);
529 | command.getInstance()->addSoftEnumValues("MapENameList", out);
530 | Settings::LoadConfigFromJson(JsonFile);
531 | output.success("§l§6[CustomMapX] §aReload Success!");
532 | }
533 | break;
534 | }
535 | case do_hash("help"): {
536 | output.success(
537 | "§l§e>§6CustomMapX§e<\n"
538 | "§b/map add §a §gAdd maps\n"
539 | "§b/map download §a §gDownload maps\n"
540 | "§b/map reload §gRefresh picture path\n"
541 | "§b/map help\n"
542 | "§l§e>§6CustomMapX§e<");
543 | break;
544 | }
545 | default:
546 | break;
547 | }
548 | });
549 | DynamicCommand::setup(std::move(command));
550 | }
551 |
552 | void Sche() {
553 | Schedule::repeat([] {
554 | if (tempList.size() > 0) {
555 | auto nowtime = getTimeStamp();
556 | for (auto& [name, time] : tempList) {
557 | if (nowtime - time > Settings::memberRateLimit * 1000) {
558 | tempList.erase(name);
559 | }
560 | }
561 | }
562 | }, 20);
563 | }
564 |
565 |
566 | void loadCfg() {
567 | //config
568 | if (!std::filesystem::exists("plugins/CustomMapX"))
569 | std::filesystem::create_directories("plugins/CustomMapX");
570 | if (std::filesystem::exists(JsonFile)) {
571 | try {
572 | Settings::LoadConfigFromJson(JsonFile);
573 | }
574 | catch (std::exception& e) {
575 | logger.error("Config File isInvalid, Err {}", e.what());
576 | //Sleep(1000 * 100);
577 | exit(1);
578 | }
579 | catch (...) {
580 | logger.error("Config File isInvalid");
581 | //Sleep(1000 * 100);
582 | exit(1);
583 | }
584 | }
585 | else {
586 | logger.info("Config with default values created");
587 | Settings::WriteDefaultConfig(JsonFile);
588 | }
589 | }
590 |
591 |
592 | void PluginInit()
593 | {
594 | srand(NULL);
595 | MapIndex = getTimeStamp2()/rand()* getTimeStamp2();
596 | loadCfg();
597 | golang();
598 | Logger().info(" ___ _ _____ __ ");
599 | Logger().info(" / __\\/\\/\\ /_\\ / _ \\ \\/ / ");
600 | Logger().info(" / / / \\ //_\\\\ / /_)/\\ / \033[38;5;221mVersion:{}", PLUGIN_VERSION_STRING);
601 | Logger().info("/ /__/ /\\/\\ \\/ _ \\/ ___/ / \\ \033[38;5;218mGithub:{}", "https://github.com/dreamguxiang/CustomMapX");
602 | Logger().info("\\____|/ \\/\\_/ \\_/\\/ /_/\\_\\ ");
603 | Logger().info("");
604 | if (!std::filesystem::exists("plugins/CustomMapX"))
605 | std::filesystem::create_directories("plugins/CustomMapX");
606 | if (!std::filesystem::exists("plugins/CustomMapX/picture"))
607 | std::filesystem::create_directories("plugins/CustomMapX/picture");
608 | RegCommand();
609 | Event::ServerStartedEvent::subscribe([] (const Event::ServerStartedEvent& ev) {
610 | Change();
611 | Sche();
612 | return true;
613 | });
614 | }
615 |
616 | inline vector split(string a1,char a) {
617 | vector out;
618 | std::stringstream ss(a1);
619 | string temp;
620 | while (getline(ss, temp, a)) {
621 | out.push_back(temp);
622 | }
623 | return out;
624 | }
625 |
626 |
627 | bool isNextImage1(string name,string newname) {
628 |
629 | auto oldoutlist = split(name,'-');
630 | auto newoutlist = split(newname, '-');
631 | if (oldoutlist.empty() || newoutlist.empty()) return false;
632 | if (newname.find(oldoutlist[0]) != newname.npos) {
633 | auto oldnumlist = split(oldoutlist[1], '_');
634 | auto newnumlist = split(newoutlist[1], '_');
635 |
636 | auto oldfir = atoi(oldnumlist[0].c_str());
637 | auto oldsec = atoi(oldnumlist[1].c_str());
638 |
639 | auto newfir = atoi(newnumlist[0].c_str());
640 | auto newsec = atoi(newnumlist[1].c_str());
641 | if (oldsec + 1 == newsec) {
642 | if (oldfir == newfir) {
643 | return true;
644 | }
645 | }
646 | }
647 | return false;
648 | }
649 |
650 | bool isNextImage2(string name, string newname) {
651 |
652 | auto oldoutlist = split(name, '-');
653 | auto newoutlist = split(newname, '-');
654 | if (oldoutlist.empty() || newoutlist.empty()) return false;
655 | if (newname.find(oldoutlist[0]) != newname.npos) {
656 | auto oldnumlist = split(oldoutlist[1], '_');
657 | auto newnumlist = split(newoutlist[1], '_');
658 |
659 | auto oldfir = atoi(oldnumlist[0].c_str());
660 | auto oldsec = atoi(oldnumlist[1].c_str());
661 |
662 | auto newfir = atoi(newnumlist[0].c_str());
663 | auto newsec = atoi(newnumlist[1].c_str());
664 | if(oldfir+1 == newfir) {
665 | if (newsec == 0) {
666 | return true;
667 | }
668 | }
669 | }
670 | return false;
671 | }
672 |
673 | bool UseItemSupply(Player* sp, ItemStackBase& item, string itemname, short aux) {
674 | auto& plinv = sp->getSupplies();
675 | auto slotnum = dAccess(&plinv);
676 | auto& uid = sp->getUniqueID();
677 | if (item.getCount() == 0) {
678 | auto& inv = sp->getInventory();
679 | bool isgive = 0;
680 | for (int i = 0; i <= inv.getSize(); i++) {
681 | auto& item = inv.getItem(i);
682 | if (!item.isNull()) {
683 | if (item.getItem()->getSerializedName() == "minecraft:filled_map") {
684 | if (i == slotnum) continue;
685 | bool isgive = 0;
686 | if (isNextImage1(itemname, item.getCustomName())) {
687 | isgive = 1;
688 | }
689 | if (isgive) {
690 | auto snbt = const_cast(&item)->getNbt()->toBinaryNBT();
691 | Schedule::delay([snbt, uid, slotnum, i] {
692 | auto newitem = ItemStack::create(CompoundTag::fromBinaryNBT(snbt));
693 | auto sp = Global->getPlayer(uid);
694 | if (sp) {
695 | if (sp->getHandSlot()->isNull()) {
696 | auto& inv = sp->getInventory();
697 | inv.setItem(i, ItemStack::EMPTY_ITEM);
698 | auto& plinv = sp->getSupplies();
699 | inv.setItem(slotnum, *newitem);
700 | sp->refreshInventory();
701 | }
702 | }
703 | delete newitem;
704 | }, 1);
705 | }
706 |
707 | }
708 | }
709 | }
710 | Schedule::delay([isgive, uid, slotnum, itemname] {
711 | auto sp = Global->getPlayer(uid);
712 | auto& inv = sp->getInventory();
713 | if (!isgive) {
714 | for (int i = 0; i <= inv.getSize(); i++) {
715 | auto& item = inv.getItem(i);
716 | if (!item.isNull()) {
717 | if (item.getItem()->getSerializedName() == "minecraft:filled_map") {
718 |
719 | if (i == slotnum) continue;
720 | bool isgive2 = 0;
721 | if (isNextImage2(itemname, item.getCustomName())) {
722 | isgive2 = 1;
723 | }
724 | if (isgive2) {
725 | auto snbt = const_cast(&item)->getNbt()->toBinaryNBT();
726 | auto& uid = sp->getUniqueID();
727 | Schedule::delay([snbt, uid, slotnum, i] {
728 | auto newitem = ItemStack::create(CompoundTag::fromBinaryNBT(snbt));
729 | auto sp = Global->getPlayer(uid);
730 | if (sp) {
731 | if (sp->getHandSlot()->isNull()) {
732 | auto& inv = sp->getInventory();
733 | inv.setItem(i, ItemStack::EMPTY_ITEM);
734 | auto& plinv = sp->getSupplies();
735 | inv.setItem(slotnum, *newitem);
736 | sp->refreshInventory();
737 | }
738 | }
739 | delete newitem;
740 | }, 1);
741 | }
742 |
743 | }
744 | }
745 | }
746 | }
747 | },1);
748 | }
749 | }
750 |
751 |
752 | TInstanceHook(void, "?useItem@Player@@UEAAXAEAVItemStackBase@@W4ItemUseMethod@@_N@Z", Player, ItemStackBase& item, int a2, bool a3)
753 | {
754 | auto itemname = item.getCustomName();
755 | auto itemname2 = item.getItem()->getSerializedName();
756 | auto aux = item.getAuxValue();
757 | original(this, item, a2, a3);
758 | try {
759 | if (itemname2 == "minecraft:filled_map") {
760 | UseItemSupply(this, item, itemname, aux);
761 | }
762 | }
763 | catch (...) {
764 | return;
765 | }
766 | }
767 |
768 |
--------------------------------------------------------------------------------
/Template/Resource.rc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dreamguxiang/CustomMapX/3b1a585adb6786e0c0b136e6861c3a962f050b05/Template/Resource.rc
--------------------------------------------------------------------------------
/Template/Setting.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | #define JSON2(key1,key2,val) \
5 | if (json.find(key1) != json.end()) { \
6 | if (json.at(key1).find(key2) != json.at(key1).end()) {\
7 | const nlohmann::json& out2 = json.at(key1).at(key2); \
8 | out2.get_to(val);}} \
9 |
10 | #define JSON1(key,val) \
11 | if (json.find(key) != json.end()) { \
12 | const nlohmann::json& out = json.at(key); \
13 | out.get_to(val);} \
14 |
15 | namespace Settings {
16 |
17 | int memberRateLimit = 60;
18 | namespace DownloadImg {
19 | bool allowmember = false;
20 | }
21 | namespace LocalImg {
22 | bool allowmember = false;
23 | }
24 | namespace ImgSize {
25 | int maxWidth = 1408;
26 | int maxHeight = 1408;
27 | int maxFileSize = 15;
28 | }
29 |
30 | nlohmann::json globaljson() {
31 | nlohmann::json json;
32 | json["MemberRateLimit"] = memberRateLimit;
33 | json["DownloadImg"]["Allow-Member"] = DownloadImg::allowmember;
34 | json["LocalImg"]["Allow-Member"] = LocalImg::allowmember;
35 | json["ImgSize"]["maxWidth"] = ImgSize::maxWidth;
36 | json["ImgSize"]["maxHeight"] = ImgSize::maxHeight;
37 | json["ImgSize"]["maxFileSize"] = ImgSize::maxFileSize;
38 | return json;
39 | }
40 |
41 | void initjson(nlohmann::json json) {
42 | JSON1("MemberRateLimit", memberRateLimit);
43 | JSON2("DownloadImg", "Allow-Member", DownloadImg::allowmember);
44 | JSON2("LocalImg", "Allow-Member", LocalImg::allowmember);
45 | JSON2("ImgSize", "maxWidth", ImgSize::maxWidth);
46 | JSON2("ImgSize", "maxHeight", ImgSize::maxHeight);
47 | JSON2("ImgSize", "maxFileSize", ImgSize::maxFileSize);
48 | }
49 |
50 | void WriteDefaultConfig(const std::string& fileName) {
51 | std::ofstream file(fileName);
52 | if (!file.is_open()) {
53 | Logger("CustomMapX").error("Can't open file ",fileName);
54 | return;
55 | }
56 | auto json = globaljson();
57 | file << json.dump(4);
58 | file.close();
59 | }
60 |
61 | void LoadConfigFromJson(const std::string& fileName) {
62 | std::ifstream file(fileName);
63 | if (!file.is_open()) {
64 | Logger("CustomMapX").error("Can't open file ", fileName);
65 | return;
66 | }
67 | nlohmann::json json;
68 | file >> json;
69 | file.close();
70 | initjson(json);
71 | WriteDefaultConfig(fileName);
72 | }
73 |
74 | void reloadJson(const std::string& fileName) {
75 | std::ofstream file(fileName);
76 | if (file)
77 | {
78 | file << globaljson().dump(4);
79 | }
80 | else
81 | {
82 | Logger("CustomMapX").error("Configuration File Creation failed!");
83 | }
84 | file.close();
85 | }
86 | } // namespace Settings
87 |
88 |
89 |
--------------------------------------------------------------------------------
/Template/Setting.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "llapi/Global.h"
3 | #include
4 |
5 |
6 | namespace Settings {
7 | extern int memberRateLimit;
8 | namespace DownloadImg {
9 | extern bool allowmember;
10 | }
11 | namespace LocalImg {
12 | extern bool allowmember;
13 | }
14 |
15 |
16 | nlohmann::json globaljson();
17 | void initjson(nlohmann::json json);
18 | void WriteDefaultConfig(const std::string& fileName);
19 | void LoadConfigFromJson(const std::string& fileName);
20 | void reloadJson(const std::string& fileName);
21 | }
--------------------------------------------------------------------------------
/Template/Template.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Release
6 | x64
7 |
8 |
9 |
10 | 16.0
11 | Win32Proj
12 | {abeb5558-c92f-473e-8bdf-90f58bd3811c}
13 | Template
14 | 10.0
15 | CustomMapX
16 |
17 |
18 |
19 | DynamicLibrary
20 | false
21 | v143
22 | true
23 | Unicode
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 | false
36 | $(SolutionDir)SDK/include;$(SolutionDir)SDK\include/llapi;$(VC_IncludePath);$(WindowsSDK_IncludePath)
37 |
38 |
39 |
40 | TurnOffAllWarnings
41 | true
42 | true
43 | true
44 | true
45 | Use
46 | pch.h
47 | stdcpp20
48 | NDEBUG;TEMPLATE_EXPORTS;WIN32_LEAN_AND_MEAN;_CRT_SECURE_NO_WARNINGS;_WINDOWS;_USRDLL;_AMD64_;NOMINMAX;%(PreprocessorDefinitions)
49 | /utf-8 %(AdditionalOptions)
50 | $(SolutionDir)SDK\Header\third-party;$(SolutionDir)SDK\Header;$(VC_IncludePath);$(WindowsSDK_IncludePath);%(AdditionalIncludeDirectories)
51 | true
52 | Async
53 |
54 |
55 | Windows
56 | true
57 | true
58 | true
59 | false
60 | bedrock_server.dll
61 |
62 |
63 | if not exist "$(SolutionDir)SDK\Lib\bedrock_server_api.lib" goto process
64 | if not exist "$(SolutionDir)SDK\Lib\bedrock_server_api.lib" goto process
65 | goto end
66 |
67 | :process
68 | cd /d "$(SolutionDir)\SDK\Tools\"
69 | if exist "$(LocalDebuggerWorkingDirectory)\bedrock_server.pdb" (
70 | LibraryBuilder.exe -o ..\Lib\ "$(LocalDebuggerWorkingDirectory)"
71 | ) else (
72 | LibraryBuilder.exe -o ..\Lib\
73 | )
74 |
75 | :end
76 |
77 |
78 |
79 | if exist "$(LocalDebuggerWorkingDirectory)\plugins\" (
80 | copy /Y "$(TargetPath)" "$(LocalDebuggerWorkingDirectory)\plugins\"
81 | )
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 | NotUsing
95 |
96 |
97 | NotUsing
98 |
99 |
100 | NotUsing
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
--------------------------------------------------------------------------------
/Template/Template.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
6 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
7 |
8 |
9 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
10 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 | Header
20 |
21 |
22 | Source
23 |
24 |
25 | Resourse
26 |
27 |
28 | Header
29 |
30 |
31 | Header
32 |
33 |
34 | Header
35 |
36 |
37 |
38 |
39 | Source
40 |
41 |
42 | Source
43 |
44 |
45 | Source
46 |
47 |
48 |
49 |
50 | Resourse
51 |
52 |
53 |
--------------------------------------------------------------------------------
/Template/Version.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #define PLUGIN_VERSION_DEV 0
4 | #define PLUGIN_VERSION_BETA 1
5 | #define PLUGIN_VERSION_RELEASE 2
6 | #define JsonFile "plugins/CustomMapX/config.json"
7 | // Plugin Information, used in dllmain.cpp for register plugin
8 | #define PLUGIN_NAME "CustomMapX"
9 | #define PLUGIN_INTRODUCTION "A Custom Map Plugins"
10 | #define PLUGIN_AUTHOR "QingYu"
11 | #define PLUGIN_VERSION_MAJOR 1
12 | #define PLUGIN_VERSION_MINOR 1
13 | #define PLUGIN_VERSION_REVISION 3
14 | #define PLUGIN_VERSION_BUILD 0
15 | #define PLUGIN_VERSION_STATUS PLUGIN_VERSION_DEV
16 | #define PLUGIN_VERSION_STRING TO_VERSION_STRING(PLUGIN_VERSION_MAJOR.PLUGIN_VERSION_MINOR.PLUGIN_VERSION_REVISION)
17 | //#define TARGET_BDS_PROTOCOL_VERSION 503
18 | // used by github actions(TODO)
19 | //#define TARGET_BDS_VERSION 1.18.30.04
20 |
21 | // File Version Information, used in Resource.rc
22 | #define __TO_VERSION_STRING(ver) #ver
23 | #define TO_VERSION_STRING(ver) __TO_VERSION_STRING(ver)
24 |
25 | #if PLUGIN_VERSION_STATUS == PLUGIN_VERSION_BETA
26 | #define PLUGIN_FILE_VERSION_FLAG VS_FF_DEBUG
27 | #define PLUGIN_LLVERSION_STATUS LL::Version::Beta
28 | #define PLUGIN_FILE_VERSION_STRING TO_VERSION_STRING(PLUGIN_VERSION_MAJOR.PLUGIN_VERSION_MINOR.PLUGIN_VERSION_REVISION.PLUGIN_VERSION_ACTIONS BETA)
29 | #elif PLUGIN_VERSION_STATUS == PLUGIN_VERSION_DEV
30 | #define PLUGIN_FILE_VERSION_FLAG VS_FF_DEBUG
31 | #define PLUGIN_LLVERSION_STATUS ll::Version::Dev
32 | #define PLUGIN_FILE_VERSION_STRING TO_VERSION_STRING(PLUGIN_VERSION_MAJOR.PLUGIN_VERSION_MINOR.PLUGIN_VERSION_REVISION.PLUGIN_VERSION_ACTIONS DEV)
33 | #else
34 | #define PLUGIN_FILE_VERSION_FLAG 0x0L
35 | #define PLUGIN_LLVERSION_STATUS LL::Version::Release
36 | #define PLUGIN_FILE_VERSION_STRING TO_VERSION_STRING(PLUGIN_VERSION_MAJOR.PLUGIN_VERSION_MINOR.PLUGIN_VERSION_REVISION.PLUGIN_VERSION_ACTIONS)
37 | #endif
38 |
39 | #define FILE_VERSION_BLOCK_HEADER 0x04004B0L
40 | #define FILE_VERSION_COMPANY_NAME PLUGIN_AUTHOR
41 | #define FILE_VERSION_LEGAL_COPYRIGHT "Copyright (C) 2022"
42 | #define FILE_VERSION_FILE_DESCRIPTION PLUGIN_INTRODUCTION
43 | #define FILE_VERSION_FILE_VERSION_STRING PLUGIN_FILE_VERSION_STRING
44 | #define FILE_VERSION_INTERNAL_NAME PLUGIN_NAME
45 | #define FILE_VERSION_ORIGINAL_FILENAME PLUGIN_NAME ".dll"
46 | #define FILE_VERSION_PRODUCT_NAME FILE_VERSION_INTERNAL_NAME
47 | #define FILE_VERSION_PRODUCT_VERSION_STRING PLUGIN_FILE_VERSION_STRING
48 | #define FILE_VERSION_FILE_VERSION PLUGIN_VERSION_MAJOR, PLUGIN_VERSION_MINOR, PLUGIN_VERSION_REVISION, PLUGIN_VERSION_BUILD
49 | #define FILE_VERSION_PRODUCT_VERSION FILE_VERSION_FILE_VERSION
50 |
--------------------------------------------------------------------------------
/Template/dllmain.cpp:
--------------------------------------------------------------------------------
1 | // dllmain.cpp : 定义 DLL 应用程序的入口点。
2 | #include
3 | #include "Version.h"
4 | #pragma comment(lib, "../SDK/Lib/bedrock_server_api.lib")
5 | #pragma comment(lib, "../SDK/Lib/bedrock_server_var.lib")
6 | #pragma comment(lib, "../SDK/Lib/SymDBHelper.lib")
7 | #pragma comment(lib, "../SDK/Lib/LiteLoader.lib")
8 |
9 | HMODULE DllMainPtr;
10 | BOOL APIENTRY DllMain( HMODULE hModule,
11 | DWORD ul_reason_for_call,
12 | LPVOID lpReserved
13 | )
14 | {
15 | DllMainPtr = hModule;
16 | switch (ul_reason_for_call)
17 | {
18 | case DLL_PROCESS_ATTACH:
19 | ll::registerPlugin(
20 | PLUGIN_NAME,
21 | PLUGIN_INTRODUCTION,
22 | ll::Version(PLUGIN_VERSION_MAJOR, PLUGIN_VERSION_MINOR, PLUGIN_VERSION_REVISION, PLUGIN_LLVERSION_STATUS),
23 | std::map {
24 | #ifdef PLUGIN_AUTHOR
25 | { "QingYu", PLUGIN_AUTHOR },
26 | #endif // PLUGIN_AUTHOR
27 | //{ "Key", "Value" }
28 | }
29 | );
30 | break;
31 | case DLL_THREAD_ATTACH:
32 | case DLL_THREAD_DETACH:
33 | case DLL_PROCESS_DETACH:
34 | break;
35 | }
36 | return TRUE;
37 | }
38 |
39 | void PluginInit();
40 |
41 | extern "C" {
42 | // Do something after all the plugins loaded
43 | _declspec(dllexport) void onPostInit() {
44 | std::ios::sync_with_stdio(false);
45 | PluginInit();
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/Template/framework.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #define WIN32_LEAN_AND_MEAN // 从 Windows 头文件中排除极少使用的内容
4 | // Windows 头文件
5 | #include
6 |
--------------------------------------------------------------------------------
/Template/godef.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 |
7 | #ifndef GO_CGO_EXPORT_PROLOGUE_H
8 | #define GO_CGO_EXPORT_PROLOGUE_H
9 |
10 | #ifndef GO_CGO_GOSTRING_TYPEDEF
11 | typedef struct {
12 | const char* p;
13 | ptrdiff_t n;
14 | } _GoString_;
15 | #endif
16 |
17 | #endif
18 |
19 | #ifndef GO_CGO_PROLOGUE_H
20 | #define GO_CGO_PROLOGUE_H
21 |
22 | typedef signed char GoInt8;
23 | typedef unsigned char GoUint8;
24 | typedef short GoInt16;
25 | typedef unsigned short GoUint16;
26 | typedef int GoInt32;
27 | typedef unsigned int GoUint32;
28 | typedef long long GoInt64;
29 | typedef unsigned long long GoUint64;
30 | typedef GoInt64 GoInt;
31 | typedef GoUint64 GoUint;
32 | typedef float GoFloat32;
33 | typedef double GoFloat64;
34 |
35 | /*
36 | static assertion to make sure the file is being used on architecture
37 | at least with matching size of GoInt.
38 | */
39 | typedef char _check_for_64_bit_pointer_matching_GoInt[sizeof(void*) == 64 / 8 ? 1 : -1];
40 |
41 | #ifndef GO_CGO_GOSTRING_TYPEDEF
42 | typedef _GoString_ GoString;
43 | #endif
44 | typedef void* GoMap;
45 | typedef void* GoChan;
46 | typedef struct {
47 | void* t;
48 | void* v;
49 | } GoInterface;
50 | template
51 | struct GoSlice {
52 | T* _data;
53 | GoInt _len;
54 | GoInt _cap;
55 | constexpr GoSlice(const std::vector& vec) {
56 | _data = vec._data();
57 | _len = vec.size();
58 | _cap = vec.capacity();
59 | }
60 | constexpr GoSlice(const size_t cap) {
61 | _data = new T[cap];
62 | _len = cap;
63 | _cap = cap;
64 | }
65 | constexpr GoSlice(T* data, size_t len, size_t cap) {
66 | _data = data;
67 | _len = len;
68 | _cap = cap;
69 | }
70 | constexpr GoSlice() {
71 | _data = nullptr;
72 | _len = 0;
73 | _cap = 0;
74 | }
75 | constexpr void push_back(const T& v) {
76 | resize(_len + 1);
77 | _data[_len + 1] = v;
78 | _len++;
79 | }
80 | constexpr void resize(size_t new_size) {
81 | if (new_size <= _cap)
82 | return;
83 | T* new_data = new T[new_size];
84 | memcpy_s(new_data, new_size, _data, _len);
85 | delete[] _data;
86 | _data = new_data;
87 | _cap = new_size;
88 | }
89 | constexpr T& operator[](size_t n) {
90 | return _data[n];
91 | }
92 | constexpr size_t length() {
93 | return _len;
94 | }
95 | constexpr T* data() {
96 | return _data;
97 | }
98 | constexpr void shrink_to_fit() {
99 | if (_data)
100 | delete[] _data;
101 | }
102 | };
103 | #endif
--------------------------------------------------------------------------------
/Template/resource.h:
--------------------------------------------------------------------------------
1 |
2 | #define MAPModule 4
3 | #define IDR_DLL1 101
4 |
5 | // Next default values for new objects
6 | //
7 | #ifdef APSTUDIO_INVOKED
8 | #ifndef APSTUDIO_READONLY_SYMBOLS
9 | #define _APS_NEXT_RESOURCE_VALUE 101
10 | #define _APS_NEXT_COMMAND_VALUE 40001
11 | #define _APS_NEXT_CONTROL_VALUE 1001
12 | #define _APS_NEXT_SYMED_VALUE 101
13 | #endif
14 | #endif
15 |
--------------------------------------------------------------------------------
/build.bat:
--------------------------------------------------------------------------------
1 | cd GOHelper
2 | go build -v -ldflags "-s -w" -trimpath -buildmode=c-shared -o MAP_Golang_Module.dll
--------------------------------------------------------------------------------
/fetchSDK.cmd:
--------------------------------------------------------------------------------
1 | @echo off
2 | setlocal enabledelayedexpansion
3 |
4 | rem Process System Proxy
5 | for /f "tokens=3* delims= " %%i in ('Reg query "HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings" /v ProxyEnable') do (
6 | if %%i==0x1 (
7 | echo [INFO] System Proxy enabled. Adapting Settings...
8 | for /f "tokens=3* delims= " %%a in ('Reg query "HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings" /v ProxyServer') do set PROXY_ADDR=%%a
9 | set http_proxy=http://!PROXY_ADDR!
10 | set https_proxy=http://!PROXY_ADDR!
11 | echo [INFO] System Proxy enabled. Adapting Settings finished.
12 | echo.
13 | )
14 | )
15 |
16 | git submodule update --init --recursive
17 |
18 | echo.
19 | echo [INFO] Upgrading LiteLoaderSDK from GitHub finished.
20 |
21 | pause
--------------------------------------------------------------------------------
/prepareLib.cmd:
--------------------------------------------------------------------------------
1 | if not exist %1\SDK\Lib\bedrock_server_api.lib goto process
2 | if not exist %1\SDK\Lib\bedrock_server_var.lib goto process
3 | goto end
4 |
5 | :process
6 | cd /d %1\SDK\Tools\
7 | LibraryBuilder.exe -o ..\Lib\
8 | :end
9 |
--------------------------------------------------------------------------------