├── .clang-format
├── .clang-tidy
├── .clangd
├── .github
├── ISSUE_TEMPLATE
│ ├── bug_report.yml
│ └── feature_request.yml
├── PULL_REQUEST_TEMPLATE.md
└── workflows
│ ├── build.yml
│ ├── release.yml
│ └── test_build.yml
├── CHANGELOG.md
├── COPYING
├── COPYING.LESSER
├── README.md
├── manifest.json
├── src
├── more_dimensions
│ ├── MemoryOperators.cpp
│ ├── MoreDimenison.cpp
│ ├── MoreDimenison.h
│ ├── api
│ │ └── dimension
│ │ │ ├── CustomDimensionManager.cpp
│ │ │ ├── CustomDimensionManager.h
│ │ │ ├── SimpleCustomDimension.cpp
│ │ │ └── SimpleCustomDimension.h
│ └── core
│ │ ├── Macros.h
│ │ └── dimension
│ │ ├── CustomDimensionConfig.cpp
│ │ ├── CustomDimensionConfig.h
│ │ ├── FakeDimensionId.cpp
│ │ ├── FakeDimensionId.h
│ │ └── MoreDimensionsPatch.h
└── test
│ ├── TestCustomDimension.cpp
│ ├── generator
│ ├── flat-gen-village
│ │ ├── FlatVillageDimension.cpp
│ │ ├── FlatVillageDimension.h
│ │ ├── FlatVillageGenerator.cpp
│ │ └── FlatVillageGenerator.h
│ ├── generator-custom-structure
│ │ ├── CustomStructure.cpp
│ │ ├── CustomStructure.h
│ │ ├── README.md
│ │ ├── dimension
│ │ │ ├── CustomStructureDimension.cpp
│ │ │ └── CustomStructureDimension.h
│ │ ├── generator
│ │ │ ├── CustomStructureGenerator.cpp
│ │ │ └── CustomStructureGenerator.h
│ │ ├── structure-files
│ │ │ ├── README.md
│ │ │ └── custom
│ │ │ │ ├── 21room.mcstructure
│ │ │ │ ├── beds5x5int.mcstructure
│ │ │ │ ├── chestcarpet5x5int.mcstructure
│ │ │ │ ├── ewcap.mcstructure
│ │ │ │ ├── ewhall.mcstructure
│ │ │ │ ├── kitchen5x5int.mcstructure
│ │ │ │ ├── nbt
│ │ │ │ ├── back_bridge_bottom.nbt
│ │ │ │ ├── back_bridge_top.nbt
│ │ │ │ └── bridge.nbt
│ │ │ │ ├── nscap.mcstructure
│ │ │ │ └── nshall.mcstructure
│ │ └── structure
│ │ │ ├── CustomStructureFeature.cpp
│ │ │ ├── CustomStructureFeature.h
│ │ │ ├── CustomStructurePiece.cpp
│ │ │ ├── CustomStructurePiece.h
│ │ │ ├── CustomStructureStart.cpp
│ │ │ └── CustomStructureStart.h
│ └── generator-terrain
│ │ ├── NxnBorderTerrainDimension.cpp
│ │ ├── NxnBorderTerrainDimension.h
│ │ ├── NxnBorderTerrainGenerator.cpp
│ │ └── NxnBorderTerrainGenerator.h
│ └── mc
│ ├── FixedBiomeSource.h
│ ├── JigsawJunction.h
│ ├── JigsawPlacement.h
│ ├── PoolAliasBinding.h
│ ├── PoolElementStructurePiece.h
│ ├── StructurePiece.h
│ ├── StructurePoolBlockPredicateBlockMatchRandom.h
│ ├── StructurePoolBlockRule.h
│ ├── StructureTemplatePool.h
│ ├── StructureTemplateRegistrationContext.h
│ └── WeightedStructureTemplateRegistration.h
├── tooth.json
└── xmake.lua
/.clang-format:
--------------------------------------------------------------------------------
1 | BasedOnStyle: LLVM
2 | AccessModifierOffset: -4
3 | AlignAfterOpenBracket: BlockIndent
4 | AlignArrayOfStructures: Left
5 | AlignConsecutiveDeclarations:
6 | Enabled: true
7 | AcrossEmptyLines: false
8 | AcrossComments: false
9 | AlignConsecutiveAssignments:
10 | Enabled: true
11 | AcrossEmptyLines: false
12 | AcrossComments: false
13 | AlignCompound: true
14 | PadOperators: true
15 | AlignConsecutiveMacros:
16 | Enabled: true
17 | AcrossEmptyLines: false
18 | AcrossComments: false
19 | AllowAllParametersOfDeclarationOnNextLine: false
20 | AllowAllArgumentsOnNextLine: false
21 | AlignOperands: AlignAfterOperator
22 | AlignConsecutiveBitFields:
23 | Enabled: true
24 | AcrossEmptyLines: false
25 | AcrossComments: false
26 | AllowShortLambdasOnASingleLine: All
27 | AllowShortBlocksOnASingleLine: Empty
28 | AllowShortIfStatementsOnASingleLine: AllIfsAndElse
29 | AllowShortLoopsOnASingleLine: true
30 | AlwaysBreakAfterDefinitionReturnType: None
31 | AlwaysBreakTemplateDeclarations: "Yes"
32 | BinPackArguments: false
33 | BinPackParameters: false
34 | BreakBeforeBraces: Custom
35 | BreakBeforeBinaryOperators: NonAssignment
36 | ColumnLimit: 120
37 | CommentPragmas: "^ IWYU pragma:"
38 | ConstructorInitializerIndentWidth: 0
39 | IndentWidth: 4
40 | Language: Cpp
41 | MaxEmptyLinesToKeep: 2
42 | PackConstructorInitializers: CurrentLine
43 | PointerAlignment: Left
44 | TabWidth: 4
45 | UseTab: Never
46 | SortIncludes: CaseSensitive
47 |
--------------------------------------------------------------------------------
/.clang-tidy:
--------------------------------------------------------------------------------
1 | ---
2 | Checks: '-*,
3 | bugprone-argument-comment,
4 | bugprone-assert-side-effect,
5 | bugprone-bad-signal-to-kill-thread,
6 | bugprone-branch-clone,
7 | bugprone-copy-constructor-init,
8 | bugprone-dangling-handle,
9 | bugprone-dynamic-static-initializers,
10 | bugprone-fold-init-type,
11 | bugprone-forward-declaration-namespace,
12 | bugprone-forwarding-reference-overload,
13 | bugprone-inaccurate-erase,
14 | bugprone-incorrect-roundings,
15 | bugprone-integer-division,
16 | bugprone-lambda-function-name,
17 | bugprone-macro-parentheses,
18 | bugprone-macro-repeated-side-effects,
19 | bugprone-misplaced-operator-in-strlen-in-alloc,
20 | bugprone-misplaced-pointer-arithmetic-in-alloc,
21 | bugprone-misplaced-widening-cast,
22 | bugprone-move-forwarding-reference,
23 | bugprone-multiple-statement-macro,
24 | bugprone-no-escape,
25 | bugprone-not-null-terminated-result,
26 | bugprone-parent-virtual-call,
27 | bugprone-posix-return,
28 | bugprone-reserved-identifier,
29 | bugprone-sizeof-container,
30 | bugprone-sizeof-expression,
31 | bugprone-spuriously-wake-up-functions,
32 | bugprone-string-constructor,
33 | bugprone-string-integer-assignment,
34 | bugprone-string-literal-with-embedded-nul,
35 | bugprone-suspicious-enum-usage,
36 | bugprone-suspicious-include,
37 | bugprone-suspicious-memory-comparison,
38 | bugprone-suspicious-memset-usage,
39 | bugprone-suspicious-missing-comma,
40 | bugprone-suspicious-semicolon,
41 | bugprone-suspicious-string-compare,
42 | bugprone-swapped-arguments,
43 | bugprone-terminating-continue,
44 | bugprone-throw-keyword-missing,
45 | bugprone-too-small-loop-variable,
46 | bugprone-undefined-memory-manipulation,
47 | bugprone-undelegated-constructor,
48 | bugprone-unhandled-self-assignment,
49 | bugprone-unused-raii,
50 | bugprone-unused-return-value,
51 | bugprone-use-after-move,
52 | bugprone-virtual-near-miss,
53 | cert-dcl21-cpp,
54 | cert-dcl58-cpp,
55 | cert-err34-c,
56 | cert-err52-cpp,
57 | cert-err60-cpp,
58 | cert-flp30-c,
59 | cert-msc50-cpp,
60 | cert-msc51-cpp,
61 | cert-str34-c,
62 | cppcoreguidelines-interfaces-global-init,
63 | cppcoreguidelines-narrowing-conversions,
64 | cppcoreguidelines-pro-type-member-init,
65 | cppcoreguidelines-slicing,
66 | google-default-arguments,
67 | google-explicit-constructor,
68 | google-runtime-operator,
69 | hicpp-exception-baseclass,
70 | hicpp-multiway-paths-covered,
71 | misc-misplaced-const,
72 | misc-new-delete-overloads,
73 | misc-non-copyable-objects,
74 | misc-throw-by-value-catch-by-reference,
75 | misc-unconventional-assign-operator,
76 | misc-uniqueptr-reset-release,
77 | modernize-avoid-bind,
78 | modernize-concat-nested-namespaces,
79 | modernize-deprecated-headers,
80 | modernize-deprecated-ios-base-aliases,
81 | modernize-loop-convert,
82 | modernize-make-shared,
83 | modernize-make-unique,
84 | modernize-pass-by-value,
85 | modernize-raw-string-literal,
86 | modernize-redundant-void-arg,
87 | modernize-replace-auto-ptr,
88 | modernize-replace-disallow-copy-and-assign-macro,
89 | modernize-replace-random-shuffle,
90 | modernize-return-braced-init-list,
91 | modernize-shrink-to-fit,
92 | modernize-unary-static-assert,
93 | modernize-use-auto,
94 | modernize-use-bool-literals,
95 | modernize-use-emplace,
96 | modernize-use-equals-default,
97 | modernize-use-equals-delete,
98 | modernize-use-nodiscard,
99 | modernize-use-noexcept,
100 | modernize-use-nullptr,
101 | modernize-use-override,
102 | modernize-use-transparent-functors,
103 | modernize-use-uncaught-exceptions,
104 | mpi-buffer-deref,
105 | mpi-type-mismatch,
106 | openmp-use-default-none,
107 | performance-faster-string-find,
108 | performance-for-range-copy,
109 | performance-implicit-conversion-in-loop,
110 | performance-inefficient-algorithm,
111 | performance-inefficient-string-concatenation,
112 | performance-inefficient-vector-operation,
113 | performance-move-const-arg,
114 | performance-move-constructor-init,
115 | performance-no-automatic-move,
116 | performance-noexcept-move-constructor,
117 | performance-trivially-destructible,
118 | performance-type-promotion-in-math-fn,
119 | performance-unnecessary-copy-initialization,
120 | performance-unnecessary-value-param,
121 | portability-simd-intrinsics,
122 | readability-avoid-const-params-in-decls,
123 | readability-const-return-type,
124 | readability-container-size-empty,
125 | readability-delete-null-pointer,
126 | readability-deleted-default,
127 | readability-inconsistent-declaration-parameter-name,
128 | readability-make-member-function-const,
129 | readability-misleading-indentation,
130 | readability-misplaced-array-index,
131 | readability-non-const-parameter,
132 | readability-redundant-control-flow,
133 | readability-redundant-declaration,
134 | readability-redundant-function-ptr-dereference,
135 | readability-redundant-smartptr-get,
136 | readability-redundant-string-cstr,
137 | readability-redundant-string-init,
138 | readability-simplify-subscript-expr,
139 | readability-static-accessed-through-instance,
140 | readability-static-definition-in-anonymous-namespace,
141 | readability-string-compare,
142 | readability-uniqueptr-delete-release,
143 | readability-use-anyofallof'
144 | ...
145 |
--------------------------------------------------------------------------------
/.clangd:
--------------------------------------------------------------------------------
1 | Diagnostics:
2 | Suppress:
3 | - "-Wmicrosoft-enum-forward-reference"
4 | - "-Wc++11-narrowing"
5 | - "-Wc++2b-extensions"
6 | - "-Wmicrosoft-cast"
7 | CompileFlags:
8 | Add:
9 | - "-ferror-limit=0"
10 | - '-D__FUNCTION__="dummy"'
11 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.yml:
--------------------------------------------------------------------------------
1 | name: Bug Report
2 | description: Create a report to help us improve
3 | title: "[Bug]: "
4 | labels: ["bug"]
5 | body:
6 | - type: textarea
7 | attributes:
8 | label: Describe the bug
9 | description: A clear and concise description of what the bug is.
10 | validations:
11 | required: true
12 |
13 | - type: textarea
14 | attributes:
15 | label: To Reproduce
16 | description: Steps to reproduce the behavior.
17 | validations:
18 | required: true
19 |
20 | - type: textarea
21 | attributes:
22 | label: Expected behavior
23 | description: A clear and concise description of what you expected to happen.
24 | validations:
25 | required: true
26 |
27 | - type: textarea
28 | attributes:
29 | label: Screenshots
30 | description: If applicable, add screenshots to help explain your problem.
31 |
32 | - type: input
33 | attributes:
34 | label: Platform
35 | description: The platform you are using. (e.g. Windows 10)
36 |
37 | - type: input
38 | attributes:
39 | label: BDS Version
40 | description: The version of BDS you are using. (e.g. 1.20.32.1)
41 |
42 | - type: input
43 | attributes:
44 | label: LeviLamina Version
45 | description: The version of LeviLamina you are using. (e.g. 1.0.0)
46 |
47 | - type: input
48 | attributes:
49 | label: Version
50 | description: The version of the plugin you are using. (e.g. 1.0.0)
51 |
52 | - type: textarea
53 | attributes:
54 | label: Additional context
55 | description: Add any other context about the problem here.
56 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.yml:
--------------------------------------------------------------------------------
1 | name: Feature request
2 | description: Suggest an idea for this project
3 | title: "[Feature]: "
4 | labels: ["enhancement"]
5 | body:
6 | - type: textarea
7 | attributes:
8 | label: Is your feature request related to a problem? Please describe.
9 | description: A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
10 | validations:
11 | required: true
12 |
13 | - type: textarea
14 | attributes:
15 | label: Describe the solution you'd like
16 | description: A clear and concise description of what you want to happen.
17 | validations:
18 | required: true
19 |
20 | - type: textarea
21 | attributes:
22 | label: Describe alternatives you've considered
23 | description: A clear and concise description of any alternative solutions or features you've considered.
24 |
25 | - type: textarea
26 | attributes:
27 | label: Additional context
28 | description: Add any other context or screenshots about the feature request here.
29 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ## What does this PR do?
2 |
3 |
4 |
5 | ## Which issues does this PR resolve?
6 |
7 |
8 |
9 | ## Checklist before merging
10 |
11 | Thank you for your contribution to the repository.
12 | Before submitting this PR, please make sure:
13 |
14 | - [ ] Your code builds clean without any errors or warnings
15 | - [ ] Your code follows [LeviLamina C++ Style Guide](https://github.com/LiteLDev/LeviLamina/wiki/CPP-Style-Guide)
16 | - [ ] You have tested all functions
17 | - [ ] You have not used code without license
18 | - [ ] You have added statement for third-party code
19 |
--------------------------------------------------------------------------------
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | on:
2 | pull_request:
3 | push:
4 | paths:
5 | - 'src/more_dimensions/**.cpp'
6 | - 'src/more_dimensions/**.h'
7 | workflow_dispatch:
8 |
9 | jobs:
10 | build:
11 | runs-on: windows-latest
12 | steps:
13 | - uses: actions/checkout@v4
14 |
15 | - uses: xmake-io/github-action-setup-xmake@v1
16 |
17 | - uses: actions/cache@v4
18 | with:
19 | path: |
20 | ~/AppData/Local/.xmake
21 | key: xmake-${{ hashFiles('xmake.lua') }}
22 | restore-keys: |
23 | xmake-
24 |
25 | - run: |
26 | xmake repo -u
27 |
28 | - run: |
29 | xmake f -a x64 -m release -p windows -v -y
30 |
31 | - run: |
32 | xmake -v -w -y
33 |
34 | - uses: actions/upload-artifact@v4
35 | with:
36 | name: more-dimensions-windows-x64-${{ github.sha }}
37 | path: |
38 | bin/
39 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | on:
2 | push:
3 | tags:
4 | - "v*.*.*"
5 |
6 | jobs:
7 | build:
8 | runs-on: windows-latest
9 | steps:
10 | - uses: actions/checkout@v4
11 |
12 | - uses: xmake-io/github-action-setup-xmake@v1
13 |
14 | - uses: actions/cache@v4
15 | with:
16 | path: |
17 | ~/AppData/Local/.xmake
18 | key: xmake-${{ hashFiles('xmake.lua') }}
19 | restore-keys: |
20 | xmake-
21 |
22 | - run: |
23 | xmake repo -u
24 |
25 | - run: |
26 | xmake f -a x64 -m release -p windows -v -y
27 |
28 | - run: |
29 | xmake -v -w -y
30 |
31 | - uses: actions/upload-artifact@v4
32 | with:
33 | name: more-dimensions-windows-x64-${{ github.sha }}
34 | path: |
35 | bin/
36 |
37 | update-release-notes:
38 | permissions:
39 | contents: write
40 | runs-on: ubuntu-latest
41 | steps:
42 | - uses: actions/checkout@v4
43 |
44 | - id: extract-release-notes
45 | uses: ffurrer2/extract-release-notes@v2
46 |
47 | - uses: softprops/action-gh-release@v1
48 | with:
49 | body: |
50 | ${{ steps.extract-release-notes.outputs.release_notes }}
51 |
52 | upload-to-release:
53 | needs:
54 | - build
55 | - update-release-notes
56 | permissions:
57 | contents: write
58 | runs-on: ubuntu-latest
59 | steps:
60 | - uses: actions/checkout@v4
61 |
62 | - uses: actions/download-artifact@v4
63 | with:
64 | name: more-dimensions-windows-x64-${{ github.sha }}
65 | path: artifact
66 |
67 | - run: |
68 | cp CHANGELOG.md COPYING COPYING.LESSER README.md artifact/
69 |
70 | - run: |
71 | zip -r ../more-dimensions-windows-x64-${{ github.ref_name }}.zip *
72 | working-directory: artifact
73 |
74 | - uses: softprops/action-gh-release@v1
75 | with:
76 | files: |
77 | more-dimensions-windows-x64-${{ github.ref_name }}.zip
78 |
--------------------------------------------------------------------------------
/.github/workflows/test_build.yml:
--------------------------------------------------------------------------------
1 | on:
2 | push:
3 | paths:
4 | - 'src/test/**.cpp'
5 | - 'src/test/**.h'
6 | workflow_dispatch:
7 |
8 | jobs:
9 | build:
10 | runs-on: windows-latest
11 | steps:
12 | - uses: actions/checkout@v4
13 |
14 | - uses: xmake-io/github-action-setup-xmake@v1
15 |
16 | - uses: actions/cache@v4
17 | with:
18 | path: |
19 | ~/AppData/Local/.xmake
20 | key: xmake-${{ hashFiles('xmake.lua') }}
21 | restore-keys: |
22 | xmake-
23 |
24 | - run: |
25 | xmake repo -u
26 |
27 | - run: |
28 | xmake f --tests=y -a x64 -m release -p windows -v -y
29 |
30 | - run: |
31 | xmake -v -w -y
32 |
33 | - uses: actions/upload-artifact@v4
34 | with:
35 | name: more-dimensions-test-windows-x64-${{ github.sha }}
36 | path: |
37 | bin/
38 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | All notable changes to this project will be documented in this file.
4 |
5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7 |
8 | ## [Unreleased]
9 |
10 | ## [0.7.0] - 2025-06-02
11 |
12 | ### Changed
13 |
14 | - Adapt to LeviLamina 1.2.0(BDS-1.21.70.04)
15 | - Deprecate `base64Nbt` in `dimension_config.json` files and add `sNbt` configuration. Improve the readability of configuration files
16 |
17 | ## [0.6.1] - 2025-03-05
18 |
19 | ### Fixed
20 |
21 | - Fixed tooth
22 |
23 | ## [0.6.0] - 2025-03-04
24 |
25 | ### Changed
26 |
27 | - Adapt to LeviLamina 1.1.0
28 |
29 | ## [0.5.0] - 2025-02-01
30 |
31 | ### Changed
32 |
33 | - Adapt to LeviLamina 1.0.0
34 |
35 | ## [0.4.1] - 2024-07-24
36 |
37 | ### Changed
38 |
39 | - Adapt to LeviLamina 0.13.4
40 |
41 | ## [0.4.0] - 2024-06-19
42 |
43 | ### Added
44 |
45 | - Adapt to LeviLamina 0.13.x
46 |
47 | ## [0.3.1] - 2024-06-02
48 |
49 | ### Fixed
50 |
51 | - Fix vanilla dimension can't create when the number of dimensions exceeds nine.
52 |
53 | ## [0.3.0] - 2024-06-01
54 |
55 | ### Added
56 |
57 | - Adapted to LeviLamina `0.12.x`
58 |
59 | ## [0.2.1] - 2024-04-13
60 |
61 | ### Added
62 |
63 | - Adapted to LeviLamina `0.11.x`
64 |
65 | ## [0.2.0] - 2024-03-27
66 |
67 | ### Added
68 |
69 | - Adapted to BDS version `1.20.7x`
70 | - Support Levilamina `v0.10.x`
71 |
72 | ### Changed
73 |
74 | - Changed namespace `ll::dimension` to `more_dimensions`.
75 | - Use new plugin template.
76 |
77 | ### Fixed
78 |
79 | - Fix `PropertiesSettings::isClientSideGenEnabled` hook no trigger.
80 |
81 | ## [0.1.2] - 2024-03-10
82 |
83 | ### Fixed
84 |
85 | - Fix: fix api symbols exports error
86 |
87 | ## [0.1.1] - 2024-03-10
88 |
89 | ### Fixed
90 |
91 | - Fix: fix xmake packages install directory no files
92 |
93 | ## [0.1.0] - 2024-03-07
94 |
95 | ### Added
96 |
97 | - Release the first version
98 |
99 | [Unreleased]: https://github.com/LiteLDev/MoreDimensions/compare/v0.7.0...HEAD
100 | [0.7.0]: https://github.com/LiteLDev/MoreDimensions/compare/v0.6.1...v0.7.0
101 | [0.6.1]: https://github.com/LiteLDev/MoreDimensions/compare/v0.6.0...v0.6.1
102 | [0.6.0]: https://github.com/LiteLDev/MoreDimensions/compare/v0.5.0...v0.6.0
103 | [0.5.0]: https://github.com/LiteLDev/MoreDimensions/compare/v0.4.1...v0.5.0
104 | [0.4.1]: https://github.com/LiteLDev/MoreDimensions/compare/v0.4.0...v0.4.1
105 | [0.4.0]: https://github.com/LiteLDev/MoreDimensions/compare/v0.3.1...v0.4.0
106 | [0.3.1]: https://github.com/LiteLDev/MoreDimensions/compare/v0.3.0...v0.3.1
107 | [0.3.0]: https://github.com/LiteLDev/MoreDimensions/compare/v0.2.1...v0.3.0
108 | [0.2.1]: https://github.com/LiteLDev/MoreDimensions/compare/v0.2.0...v0.2.1
109 | [0.2.0]: https://github.com/LiteLDev/MoreDimensions/compare/v0.1.2...v0.2.0
110 | [0.1.2]: https://github.com/LiteLDev/MoreDimensions/compare/v0.1.1...v0.1.2
111 | [0.1.1]: https://github.com/LiteLDev/MoreDimensions/compare/v0.1.0...v0.1.1
112 | [0.1.0]: https://github.com/LiteLDev/MoreDimensions/releases/tag/v0.1.0
113 |
--------------------------------------------------------------------------------
/COPYING.LESSER:
--------------------------------------------------------------------------------
1 | GNU LESSER GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 |
9 | This version of the GNU Lesser General Public License incorporates
10 | the terms and conditions of version 3 of the GNU General Public
11 | License, supplemented by the additional permissions listed below.
12 |
13 | 0. Additional Definitions.
14 |
15 | As used herein, "this License" refers to version 3 of the GNU Lesser
16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU
17 | General Public License.
18 |
19 | "The Library" refers to a covered work governed by this License,
20 | other than an Application or a Combined Work as defined below.
21 |
22 | An "Application" is any work that makes use of an interface provided
23 | by the Library, but which is not otherwise based on the Library.
24 | Defining a subclass of a class defined by the Library is deemed a mode
25 | of using an interface provided by the Library.
26 |
27 | A "Combined Work" is a work produced by combining or linking an
28 | Application with the Library. The particular version of the Library
29 | with which the Combined Work was made is also called the "Linked
30 | Version".
31 |
32 | The "Minimal Corresponding Source" for a Combined Work means the
33 | Corresponding Source for the Combined Work, excluding any source code
34 | for portions of the Combined Work that, considered in isolation, are
35 | based on the Application, and not on the Linked Version.
36 |
37 | The "Corresponding Application Code" for a Combined Work means the
38 | object code and/or source code for the Application, including any data
39 | and utility programs needed for reproducing the Combined Work from the
40 | Application, but excluding the System Libraries of the Combined Work.
41 |
42 | 1. Exception to Section 3 of the GNU GPL.
43 |
44 | You may convey a covered work under sections 3 and 4 of this License
45 | without being bound by section 3 of the GNU GPL.
46 |
47 | 2. Conveying Modified Versions.
48 |
49 | If you modify a copy of the Library, and, in your modifications, a
50 | facility refers to a function or data to be supplied by an Application
51 | that uses the facility (other than as an argument passed when the
52 | facility is invoked), then you may convey a copy of the modified
53 | version:
54 |
55 | a) under this License, provided that you make a good faith effort to
56 | ensure that, in the event an Application does not supply the
57 | function or data, the facility still operates, and performs
58 | whatever part of its purpose remains meaningful, or
59 |
60 | b) under the GNU GPL, with none of the additional permissions of
61 | this License applicable to that copy.
62 |
63 | 3. Object Code Incorporating Material from Library Header Files.
64 |
65 | The object code form of an Application may incorporate material from
66 | a header file that is part of the Library. You may convey such object
67 | code under terms of your choice, provided that, if the incorporated
68 | material is not limited to numerical parameters, data structure
69 | layouts and accessors, or small macros, inline functions and templates
70 | (ten or fewer lines in length), you do both of the following:
71 |
72 | a) Give prominent notice with each copy of the object code that the
73 | Library is used in it and that the Library and its use are
74 | covered by this License.
75 |
76 | b) Accompany the object code with a copy of the GNU GPL and this license
77 | document.
78 |
79 | 4. Combined Works.
80 |
81 | You may convey a Combined Work under terms of your choice that,
82 | taken together, effectively do not restrict modification of the
83 | portions of the Library contained in the Combined Work and reverse
84 | engineering for debugging such modifications, if you also do each of
85 | the following:
86 |
87 | a) Give prominent notice with each copy of the Combined Work that
88 | the Library is used in it and that the Library and its use are
89 | covered by this License.
90 |
91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license
92 | document.
93 |
94 | c) For a Combined Work that displays copyright notices during
95 | execution, include the copyright notice for the Library among
96 | these notices, as well as a reference directing the user to the
97 | copies of the GNU GPL and this license document.
98 |
99 | d) Do one of the following:
100 |
101 | 0) Convey the Minimal Corresponding Source under the terms of this
102 | License, and the Corresponding Application Code in a form
103 | suitable for, and under terms that permit, the user to
104 | recombine or relink the Application with a modified version of
105 | the Linked Version to produce a modified Combined Work, in the
106 | manner specified by section 6 of the GNU GPL for conveying
107 | Corresponding Source.
108 |
109 | 1) Use a suitable shared library mechanism for linking with the
110 | Library. A suitable mechanism is one that (a) uses at run time
111 | a copy of the Library already present on the user's computer
112 | system, and (b) will operate properly with a modified version
113 | of the Library that is interface-compatible with the Linked
114 | Version.
115 |
116 | e) Provide Installation Information, but only if you would otherwise
117 | be required to provide such information under section 6 of the
118 | GNU GPL, and only to the extent that such information is
119 | necessary to install and execute a modified version of the
120 | Combined Work produced by recombining or relinking the
121 | Application with a modified version of the Linked Version. (If
122 | you use option 4d0, the Installation Information must accompany
123 | the Minimal Corresponding Source and Corresponding Application
124 | Code. If you use option 4d1, you must provide the Installation
125 | Information in the manner specified by section 6 of the GNU GPL
126 | for conveying Corresponding Source.)
127 |
128 | 5. Combined Libraries.
129 |
130 | You may place library facilities that are a work based on the
131 | Library side by side in a single library together with other library
132 | facilities that are not Applications and are not covered by this
133 | License, and convey such a combined library under terms of your
134 | choice, if you do both of the following:
135 |
136 | a) Accompany the combined library with a copy of the same work based
137 | on the Library, uncombined with any other library facilities,
138 | conveyed under the terms of this License.
139 |
140 | b) Give prominent notice with the combined library that part of it
141 | is a work based on the Library, and explaining where to find the
142 | accompanying uncombined form of the same work.
143 |
144 | 6. Revised Versions of the GNU Lesser General Public License.
145 |
146 | The Free Software Foundation may publish revised and/or new versions
147 | of the GNU Lesser General Public License from time to time. Such new
148 | versions will be similar in spirit to the present version, but may
149 | differ in detail to address new problems or concerns.
150 |
151 | Each version is given a distinguishing version number. If the
152 | Library as you received it specifies that a certain numbered version
153 | of the GNU Lesser General Public License "or any later version"
154 | applies to it, you have the option of following the terms and
155 | conditions either of that published version or of any later version
156 | published by the Free Software Foundation. If the Library as you
157 | received it does not specify a version number of the GNU Lesser
158 | General Public License, you may choose any version of the GNU Lesser
159 | General Public License ever published by the Free Software Foundation.
160 |
161 | If the Library as you received it specifies that a proxy can decide
162 | whether future versions of the GNU Lesser General Public License shall
163 | apply, that proxy's public statement of acceptance of any version is
164 | permanent authorization for you to choose that version for the
165 | Library.
166 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # MoreDimensions
2 |
3 | More than three dimensions on BDS!
4 |
5 | **Note: This mod only provides API. If you only install this mod, the dimensions will not be created.**
6 |
7 | ## Install
8 |
9 | Install with [lip](https://github.com/futrime/lip):
10 |
11 | ```sh
12 | lip install github.com/LiteLDev/MoreDimensions
13 | ```
14 |
15 | ## Usage
16 |
17 | Wiki: [Chinese and English](https://github.com/LiteLDev/MoreDimensions/wiki)
18 |
19 | ## Contributing
20 |
21 | Ask questions by creating an issue.
22 |
23 | PRs accepted.
24 |
25 | ## License
26 |
27 | LGPL-3.0-or-later © LeviMC(LiteLDev)
28 |
--------------------------------------------------------------------------------
/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "${modName}",
3 | "entry": "${modFile}",
4 | "type": "native",
5 | "version": "${modVersion}",
6 | "author": "LiteLDev"
7 | }
8 |
--------------------------------------------------------------------------------
/src/more_dimensions/MemoryOperators.cpp:
--------------------------------------------------------------------------------
1 | // This file will make your plugin use LeviLamina's memory operators by default.
2 | // This improves the memory management of your plugin and is recommended to use.
3 |
4 | #define LL_MEMORY_OPERATORS
5 |
6 | #include "ll/api/memory/MemoryOperators.h" // IWYU pragma: keep
7 |
--------------------------------------------------------------------------------
/src/more_dimensions/MoreDimenison.cpp:
--------------------------------------------------------------------------------
1 | #include "MoreDimenison.h"
2 |
3 | #include "ll/api/Versions.h"
4 | #include "ll/api/mod/RegisterHelper.h"
5 | #include "more_dimensions/core/dimension/MoreDimensionsPatch.h"
6 |
7 | namespace more_dimensions {
8 |
9 | MoreDimenison& MoreDimenison::getInstance() {
10 | static MoreDimenison instance;
11 | return instance;
12 | }
13 |
14 | bool MoreDimenison::load() {
15 | getSelf().getLogger().info("Loading...");
16 | if (ll::getLoaderVersion() < ll::data::Version{0, 8, 3}) {
17 | getSelf().getLogger().error(
18 | "The LeviLamina version requires 0.8.3 or higher, now is {}",
19 | ll::getLoaderVersion().to_string()
20 | );
21 | return false;
22 | }
23 | injectNaticeCode();
24 | getSelf().getLogger().info("More dimension is loaded");
25 | getSelf().getLogger().info("Version: {}, Developer: LiteLDev", getSelf().getManifest().version->to_string());
26 | return true;
27 | }
28 |
29 | bool MoreDimenison::enable() {
30 | getSelf().getLogger().info("Enabling...");
31 | return true;
32 | }
33 |
34 | bool MoreDimenison::disable() {
35 | getSelf().getLogger().info("Disabling...");
36 | return true;
37 | }
38 |
39 | } // namespace more_dimensions
40 |
41 | LL_REGISTER_MOD(more_dimensions::MoreDimenison, more_dimensions::MoreDimenison::getInstance());
42 |
--------------------------------------------------------------------------------
/src/more_dimensions/MoreDimenison.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "ll/api/mod/NativeMod.h"
4 |
5 | namespace more_dimensions {
6 |
7 | class MoreDimenison {
8 |
9 | public:
10 | static MoreDimenison& getInstance();
11 |
12 | MoreDimenison() : mSelf(*ll::mod::NativeMod::current()) {}
13 |
14 | [[nodiscard]] ll::mod::NativeMod& getSelf() const { return mSelf; }
15 |
16 | /// @return True if the plugin is loaded successfully.
17 | bool load();
18 |
19 | /// @return True if the plugin is enabled successfully.
20 | bool enable();
21 |
22 | /// @return True if the plugin is disabled successfully.
23 | bool disable();
24 |
25 | // TODO: Implement this method if you need to unload the plugin.
26 | // /// @return True if the plugin is unloaded successfully.
27 | // bool unload();
28 |
29 | private:
30 | ll::mod::NativeMod& mSelf;
31 | };
32 |
33 | } // namespace more_dimensions
34 |
--------------------------------------------------------------------------------
/src/more_dimensions/api/dimension/CustomDimensionManager.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include "CustomDimensionManager.h"
3 |
4 | #include "mc/nbt/Tag.h"
5 | #include "more_dimensions/MoreDimenison.h"
6 | #include "more_dimensions/core/dimension/CustomDimensionConfig.h"
7 | #include "more_dimensions/core/dimension/FakeDimensionId.h"
8 |
9 | #include "snappy.h"
10 |
11 | #include "ll/api/command/CommandRegistrar.h"
12 | #include "ll/api/memory/Hook.h"
13 | #include "ll/api/service/Bedrock.h"
14 | #include "ll/api/utils/Base64Utils.h"
15 | #include "ll/api/utils/StringUtils.h"
16 |
17 | #include "mc/deps/core/math/Vec3.h"
18 | #include "mc/server/DedicatedServer.h"
19 | #include "mc/server/PropertiesSettings.h"
20 | #include "mc/util/BidirectionalUnorderedMap.h"
21 | #include "mc/world/actor/player/Player.h"
22 | #include "mc/world/level/Level.h"
23 | #include "mc/world/level/dimension/Dimension.h"
24 | #include "mc/world/level/dimension/VanillaDimensions.h"
25 | #include "mc/world/level/storage/LevelStorage.h"
26 |
27 |
28 | class Scheduler;
29 |
30 | namespace more_dimensions {
31 |
32 | std::string compress(std::string_view sv) {
33 | std::string res;
34 | snappy::Compress(sv.data(), sv.size(), &res);
35 | return res;
36 | }
37 |
38 | std::string decompress(std::string_view sv) {
39 | std::string res;
40 | snappy::Uncompress(sv.data(), sv.size(), &res);
41 | return res;
42 | }
43 |
44 | // static ll::Logger loggerMoreDimMag("CustomDimensionManager");
45 | auto& loggerMoreDimMag = MoreDimenison::getInstance().getSelf().getLogger();
46 |
47 | namespace CustomDimensionHookList {
48 | LL_TYPE_STATIC_HOOK(
49 | VanillaDimensionsConverHook,
50 | HookPriority::Normal,
51 | VanillaDimensions,
52 | VanillaDimensions::convertPointBetweenDimensions,
53 | bool,
54 | Vec3 const& oldPos,
55 | Vec3& toPos,
56 | DimensionType oldDim,
57 | DimensionType toDim,
58 | DimensionConversionData const& data
59 | ) {
60 | if (oldDim <= 2 && toDim <= 2) return origin(oldPos, toPos, oldDim, toDim, data);
61 | toPos = oldPos;
62 | return true;
63 | };
64 |
65 | LL_TYPE_STATIC_HOOK(
66 | VanillaDimensionsFromSerializedIntHook,
67 | HookPriority::Normal,
68 | VanillaDimensions,
69 | VanillaDimensions::fromSerializedInt,
70 | Bedrock::Result,
71 | Bedrock::Result&& dim
72 | ) {
73 | if (!VanillaDimensions::DimensionMap().mLeft.contains(*dim)) {
74 | return VanillaDimensions::Undefined();
75 | }
76 | return *dim;
77 | };
78 |
79 | LL_TYPE_STATIC_HOOK(
80 | VanillaDimensionsFromSerializedIntHookI,
81 | HookPriority::Normal,
82 | VanillaDimensions,
83 | VanillaDimensions::fromSerializedInt,
84 | DimensionType,
85 | int dimId
86 | ) {
87 | if (!VanillaDimensions::DimensionMap().mLeft.contains(dimId)) {
88 | return VanillaDimensions::Undefined();
89 | }
90 | return {dimId};
91 | }
92 |
93 | // inline function use patch
94 | // -->PropertiesSettingsisClientSideGenEnabledHook
95 | //
96 | // LL_TYPE_STATIC_HOOK(
97 | // VanillaDimensionsToSerializedIntHook,
98 | // HookPriority::Normal,
99 | // VanillaDimensions,
100 | // VanillaDimensions::toSerializedInt,
101 | // int,
102 | // DimensionType const& dim
103 | // ) {
104 | // if (dim <= 2) return origin(dim);
105 | // return dim.id;
106 | // }
107 |
108 | // 当玩家加入服务器时,生成时的维度不存在,并且维度id不是Undefined时,把玩家放到主世界
109 | LL_TYPE_INSTANCE_HOOK(
110 | LevelStorageloadServerPlayerDataHook,
111 | HookPriority::Normal,
112 | LevelStorage,
113 | &LevelStorage::loadServerPlayerData,
114 | std::unique_ptr,
115 | Player const& client,
116 | bool isXboxLive
117 | ) {
118 |
119 | auto result = origin(client, isXboxLive);
120 | if (!result) return result;
121 | auto spawnDimension = result->at("DimensionId");
122 | if (!VanillaDimensions::DimensionMap().mLeft.contains(AutomaticID(spawnDimension))) {
123 | result->at("Pos")[1] = FloatTag{0x7fff};
124 | }
125 | return result;
126 | }
127 |
128 | // 由于这个的调用在维度注册之前,所以使用AUTO
129 | LL_AUTO_TYPE_INSTANCE_HOOK(
130 | PropertiesSettingsisClientSideGenEnabledHook,
131 | HookPriority::Normal,
132 | DedicatedServer,
133 | &DedicatedServer::runDedicatedServerLoop,
134 | DedicatedServer::StartResult,
135 | Core::FilePathManager& filePathManager,
136 | PropertiesSettings& properties,
137 | LevelSettings& settings,
138 | AllowListFile& userAllowList,
139 | std::unique_ptr& permissionsFile,
140 | Bedrock::ActivationArguments const& args,
141 | TestConfig& testConfig
142 | ) {
143 | properties.mClientSideGenerationEnabled = false;
144 | return origin(filePathManager, properties, settings, userAllowList, permissionsFile, args, testConfig);
145 | }
146 |
147 | // 1.21.50.10 unnecessary
148 | // registry dimensoin when in ll, must reload Dimension::getWeakRef
149 | // LL_TYPE_INSTANCE_HOOK(DimensionGetWeakRefHook, HookPriority::Normal, Dimension, &Dimension::getWeakRef,
150 | // WeakRef) {
151 | // if (getDimensionId().id > 2 && getDimensionId() != VanillaDimensions::Undefined()) return weak_from_this();
152 | // return origin();
153 | // };
154 |
155 | using HookReg = ll::memory::HookRegistrar<
156 | VanillaDimensionsConverHook,
157 | VanillaDimensionsFromSerializedIntHook,
158 | VanillaDimensionsFromSerializedIntHookI,
159 | // VanillaDimensionsToSerializedIntHook,
160 | LevelStorageloadServerPlayerDataHook,
161 | PropertiesSettingsisClientSideGenEnabledHook>;
162 |
163 | } // namespace CustomDimensionHookList
164 |
165 | struct CustomDimensionManager::Impl {
166 | std::atomic mNewDimensionId{3};
167 | std::mutex mMapMutex;
168 |
169 | struct DimensionInfo {
170 | DimensionType id;
171 | CompoundTag nbt;
172 | };
173 | std::unordered_map customDimensionMap;
174 | std::unordered_set registeredDimension;
175 | };
176 |
177 | CustomDimensionManager::CustomDimensionManager() : impl(std::make_unique()) {
178 | std::lock_guard lock{impl->mMapMutex};
179 | CustomDimensionConfig::setDimensionConfigPath();
180 | CustomDimensionConfig::loadConfigFile();
181 | if (!CustomDimensionConfig::getConfig().dimensionList.empty()) {
182 | for (auto& [name, info] : CustomDimensionConfig::getConfig().dimensionList) {
183 | impl->customDimensionMap.emplace(
184 | name,
185 | Impl::DimensionInfo{
186 | info.dimId,
187 | *CompoundTag::fromSnbt(info.sNbt)
188 | }
189 | );
190 | }
191 | impl->mNewDimensionId += static_cast(impl->customDimensionMap.size());
192 | }
193 | FakeDimensionId::getInstance();
194 | CustomDimensionHookList::HookReg::hook();
195 | };
196 |
197 | CustomDimensionManager::~CustomDimensionManager() { CustomDimensionHookList::HookReg::unhook(); }
198 |
199 | CustomDimensionManager& CustomDimensionManager::getInstance() {
200 | static CustomDimensionManager instance{};
201 | return instance;
202 | }
203 |
204 | DimensionType CustomDimensionManager::getDimensionIdFromName(std::string const& dimName) {
205 | return VanillaDimensions::fromString(dimName);
206 | }
207 |
208 | DimensionType CustomDimensionManager::addDimension(
209 | std::string const& dimName,
210 | std::function factory,
211 | std::function const& data
212 | ) {
213 | std::lock_guard lock{impl->mMapMutex};
214 | Impl::DimensionInfo info;
215 | bool newDim{};
216 | if (impl->customDimensionMap.contains(dimName)) {
217 | info = impl->customDimensionMap.at(dimName);
218 | loggerMoreDimMag.info(
219 | "The dimension already registry. use old id, name: {}, id: {}, \ndata: {}",
220 | dimName,
221 | info.id.id,
222 | info.nbt.toSnbt()
223 | );
224 | } else {
225 | // Assign new id
226 | info.id = impl->mNewDimensionId++;
227 | info.nbt = data();
228 | newDim = true;
229 | loggerMoreDimMag
230 | .info("registry new dimension, name: {}, id: {}, \ndata: {}", dimName, info.id.id, info.nbt.toSnbt());
231 | };
232 |
233 | // registry create dimension function
234 | if (!ll::service::getLevel()) {
235 | throw std::runtime_error("Level is nullptr, cannot registry new dimension " + dimName);
236 | }
237 | ll::service::getLevel()->getDimensionFactory().mFactoryMap.emplace(
238 | dimName,
239 | [dimName, info, factory = std::move(factory)](ILevel& ilevel, Scheduler& scheduler) -> OwnerPtr {
240 | loggerMoreDimMag.debug("Create dimension, name: {}, id: {}", dimName, info.id.id);
241 | return factory(DimensionFactoryInfo{ilevel, scheduler, info.nbt, info.id});
242 | }
243 | );
244 |
245 | // modify default dimension map
246 | loggerMoreDimMag.debug("Add new dimension to DimensionMap");
247 | ll::memory::modify(VanillaDimensions::DimensionMap(), [&](auto& dimMap) {
248 | loggerMoreDimMag.debug("Add new dimension: name->{}, id->{} to DimensionMap", dimName, info.id.id);
249 | dimMap.insert_or_assign(dimName, info.id);
250 | });
251 |
252 | // modify default Undefined dimension id
253 | ll::memory::modify(VanillaDimensions::Undefined(), [&](auto& uid) {
254 | uid.id = impl->mNewDimensionId;
255 | loggerMoreDimMag.debug("Set VanillaDimensions::Undefined to {}", uid.id);
256 | loggerMoreDimMag.debug("Now VanillaDimensions::Undefined is {}", VanillaDimensions::Undefined().id);
257 | });
258 |
259 | // config
260 | impl->registeredDimension.emplace(dimName);
261 | if (newDim) {
262 | impl->customDimensionMap.emplace(dimName, info);
263 | CustomDimensionConfig::getConfig().dimensionList.emplace(
264 | dimName,
265 | CustomDimensionConfig::Config::Info{info.id, info.nbt.toSnbt(SnbtFormat::Minimize)}
266 | );
267 | CustomDimensionConfig::saveConfigFile();
268 | }
269 |
270 | // add to command enum
271 |
272 | ll::command::CommandRegistrar::getInstance().addEnumValues(
273 | "Dimension",
274 | {
275 | {dimName, info.id}
276 | },
277 | Bedrock::type_id()
278 | );
279 |
280 | return info.id;
281 | }
282 | } // namespace more_dimensions
283 |
--------------------------------------------------------------------------------
/src/more_dimensions/api/dimension/CustomDimensionManager.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "more_dimensions/core/Macros.h"
4 |
5 | #include "mc/deps/core/utility/AutomaticID.h"
6 | #include "mc/nbt/CompoundTag.h"
7 | #include "mc/world/level/GeneratorType.h"
8 |
9 | class Dimension;
10 | class ILevel;
11 | class Scheduler;
12 |
13 | namespace more_dimensions {
14 |
15 | struct DimensionFactoryInfo {
16 | ILevel& level;
17 | Scheduler& scheduler;
18 | CompoundTag const& data;
19 | DimensionType dimId;
20 | };
21 |
22 | class CustomDimensionManager {
23 | struct Impl;
24 | std::unique_ptr impl;
25 |
26 | CustomDimensionManager();
27 | ~CustomDimensionManager();
28 |
29 | public:
30 | using DimensionFactoryT = std::shared_ptr(DimensionFactoryInfo const&);
31 |
32 | protected:
33 | MORE_DIMENSIONS_API DimensionType addDimension(
34 | std::string const& dimName,
35 | std::function factory,
36 | std::function const& newData
37 | );
38 |
39 | public:
40 | MORE_DIMENSIONS_API static CustomDimensionManager& getInstance();
41 |
42 | [[deprecated("please use VanillaDimensions::fromString")]] MORE_DIMENSIONS_API static DimensionType
43 | getDimensionIdFromName(std::string const& dimName);
44 |
45 | template D, class... Args>
46 | DimensionType addDimension(std::string const& dimName, Args&&... args) {
47 | return addDimension(
48 | dimName,
49 | [dimName](more_dimensions::DimensionFactoryInfo const& info) -> std::shared_ptr {
50 | return std::make_shared(dimName, info);
51 | },
52 | [&] { return D::generateNewData(std::forward(args)...); }
53 | );
54 | }
55 | };
56 |
57 | // Dimension need to test virtual tables
58 |
59 | /* Dimension related virtual tables
60 | *
61 | * ∕-- IDimension
62 | * OverworldDimension --∖ ∕-- LevelListener --- BlockSourceListener
63 | * NetherDimension --- Dimension --- SavedData
64 | * TheEndDimension --∕ ∖-- Bedrock::EnableNonOwnerReferences
65 | * ∖-- std::enable_shared_from_this
66 | *
67 | */
68 |
69 | /* WorldGenerator related virtual tables
70 | *
71 | * FlatWorldGenerator --∖
72 | * NetherGenerator --∖
73 | * OverworldGenerator2d --- OverworldGenerator2d --- WorldGenerator --- ChunkSource ---
74 | * Bedrock::EnableNonOwnerReferences TheEndGenerator --∕ ∖-- IPreliminarySurfaceProvider
75 | * VoidGenerator --∕
76 | *
77 | */
78 |
79 | /* DimensionBrightnessRamp related virtual tables
80 | *
81 | * NetherBrightnessRamp --∖
82 | * OverworldBrightnessRamp --- DimensionBrightnessRamp
83 | *
84 | */
85 |
86 | /* BlockSource related virtual tables
87 | *
88 | * BlockSource --- IBlockSource --- IConstBlockSource
89 | * ∖-- std::enable_shared_from_this
90 | *
91 | */
92 |
93 | /* BiomeSource related virtual tables
94 | *
95 | * FixedBiomeSource --- BiomeSource
96 | *
97 | */
98 |
99 | } // namespace more_dimensions
100 |
--------------------------------------------------------------------------------
/src/more_dimensions/api/dimension/SimpleCustomDimension.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include "SimpleCustomDimension.h"
3 |
4 | #include "more_dimensions/MoreDimenison.h"
5 |
6 | #include "magic_enum.hpp"
7 |
8 | #include "ll/api/memory/Memory.h"
9 | #include "ll/api/service/Bedrock.h"
10 |
11 | #include "mc/common/Brightness.h"
12 | #include "mc/common/BrightnessPair.h"
13 | #include "mc/deps/core/math/Color.h"
14 | #include "mc/deps/core/string/HashedString.h"
15 | #include "mc/world/level/BlockSource.h"
16 | #include "mc/world/level/DimensionConversionData.h"
17 | #include "mc/world/level/Level.h"
18 | #include "mc/world/level/LevelSeed64.h"
19 | #include "mc/world/level/biome/registry/BiomeRegistry.h"
20 | #include "mc/world/level/biome/registry/VanillaBiomeNames.h"
21 | #include "mc/world/level/biome/source/BiomeSource.h"
22 | #include "mc/world/level/biome/source/FixedBiomeSource.h"
23 | #include "mc/world/level/block/BlockVolume.h"
24 | #include "mc/world/level/chunk/vanilla_level_chunk_upgrade/VanillaLevelChunkUpgrade.h"
25 | #include "mc/world/level/dimension/DimensionHeightRange.h"
26 | #include "mc/world/level/dimension/NetherBrightnessRamp.h"
27 | #include "mc/world/level/dimension/OverworldBrightnessRamp.h"
28 | #include "mc/world/level/dimension/VanillaDimensions.h"
29 | #include "mc/world/level/levelgen/flat/FlatWorldGenerator.h"
30 | #include "mc/world/level/levelgen/structure/EndCityFeature.h"
31 | #include "mc/world/level/levelgen/structure/StructureFeatureRegistry.h"
32 | #include "mc/world/level/levelgen/structure/registry/StructureSetRegistry.h"
33 | #include "mc/world/level/levelgen/synth/PerlinNoise.h"
34 | #include "mc/world/level/levelgen/synth/PerlinSimplexNoise.h"
35 | #include "mc/world/level/levelgen/synth/SimplexNoise.h"
36 | #include "mc/world/level/levelgen/v1/NetherGenerator.h"
37 | #include "mc/world/level/levelgen/v1/OverworldGeneratorMultinoise.h"
38 | #include "mc/world/level/levelgen/v1/TheEndGenerator.h"
39 | #include "mc/world/level/levelgen/v1/VoidGenerator.h"
40 | #include "mc/world/level/levelgen/v2/ChunkGeneratorStructureState.h"
41 | #include "mc/world/level/storage/Experiments.h"
42 | #include "mc/world/level/storage/LevelData.h"
43 |
44 | #include
45 | #include
46 |
47 |
48 | namespace more_dimensions {
49 |
50 |
51 | namespace {
52 | using namespace ll::memory_literals;
53 |
54 | DWORD overworld_addStructureFeatures_rva = 0x2C6640;
55 | DWORD nethrer_addStructureFeatures_rva = 0x2C4F90;
56 |
57 | HMODULE hModule = GetModuleHandle(L"bedrock_server_mod.exe");
58 |
59 | static void* overworldAddress = (void*)((BYTE*)hModule + overworld_addStructureFeatures_rva);
60 | static void* netherAddress = (void*)((BYTE*)hModule + nethrer_addStructureFeatures_rva);
61 |
62 | // static auto* overworldAddress =
63 | // "`anonymous namespace'::unity_5c986e6b9d6571cc96912b0bfa0329e2::addStructureFeatures"_symp;
64 | // static auto* netherAddress = "`anonymous namespace'::unity_3da1d4c9fa90b4b1becbca96840255a5::addStructureFeatures"_symp;
65 |
66 | void overworldAddStructureFeatures(
67 | StructureFeatureRegistry& registry,
68 | uint seed,
69 | bool isLegacy,
70 | BaseGameVersion const& baseGameVersion
71 | ) {
72 | ll::memory::addressCall(
73 | overworldAddress,
74 | registry,
75 | seed,
76 | isLegacy,
77 | baseGameVersion
78 | );
79 | };
80 |
81 | void netherAddStructureFeatures(
82 | StructureFeatureRegistry& registry,
83 | uint seed,
84 | BaseGameVersion const& baseGameVersion,
85 | Experiments const& experiments
86 | ) {
87 | ll::memory::addressCall(
88 | netherAddress,
89 | registry,
90 | seed,
91 | baseGameVersion,
92 | experiments
93 | );
94 | };
95 | } // namespace
96 |
97 | // static ll::Logger loggerMoreDim("SimpleCustomDim");
98 | auto& loggerMoreDim = MoreDimenison::getInstance().getSelf().getLogger();
99 |
100 | SimpleCustomDimension::SimpleCustomDimension(std::string const& name, DimensionFactoryInfo const& info)
101 | : Dimension(info.level, info.dimId, {-64, 320}, info.scheduler, name) {
102 | loggerMoreDim.debug("{} dimension name:{}", __FUNCTION__, name);
103 | mDefaultBrightness->sky = Brightness::MAX();
104 | generatorType = *magic_enum::enum_cast((std::string_view)info.data["generatorType"]);
105 | seed = info.data["seed"];
106 | switch (generatorType) {
107 | case GeneratorType::TheEnd: {
108 | mSeaLevel = 63;
109 | mHasWeather = false;
110 | mDimensionBrightnessRamp = std::make_unique();
111 | }
112 | case GeneratorType::Nether: {
113 | mSeaLevel = 32;
114 | mHasWeather = false;
115 | mDimensionBrightnessRamp = std::make_unique();
116 | }
117 | default:
118 | mSeaLevel = 63;
119 | mHasWeather = true;
120 | mDimensionBrightnessRamp = std::make_unique();
121 | }
122 | mDimensionBrightnessRamp->buildBrightnessRamp();
123 | }
124 |
125 | CompoundTag SimpleCustomDimension::generateNewData(uint seed, GeneratorType generatorType) {
126 | CompoundTag result;
127 | result["seed"] = seed;
128 | result["generatorType"] = magic_enum::enum_name(generatorType);
129 | return result;
130 | }
131 |
132 | void SimpleCustomDimension::init(br::worldgen::StructureSetRegistry const& structureSetRegistry) {
133 | loggerMoreDim.debug(__FUNCTION__);
134 | mHasSkylight = false;
135 | Dimension::init(structureSetRegistry);
136 | }
137 |
138 | std::unique_ptr
139 | SimpleCustomDimension::createGenerator(br::worldgen::StructureSetRegistry const& structureSetRegistry) {
140 | loggerMoreDim.debug(__FUNCTION__);
141 | auto& level = mLevel;
142 | auto& levelData = level.getLevelData();
143 | auto biome = level.getBiomeRegistry().lookupByName(levelData.mBiomeOverride);
144 |
145 | std::unique_ptr worldGenerator;
146 |
147 | switch (generatorType) {
148 | case GeneratorType::Overworld: {
149 | worldGenerator = std::make_unique(*this, LevelSeed64{seed}, biome);
150 | worldGenerator->mStructureFeatureRegistry->mGeneratorState =
151 | br::worldgen::ChunkGeneratorStructureState::createNormal(
152 | seed,
153 | worldGenerator->getBiomeSource(),
154 | structureSetRegistry
155 | );
156 | overworldAddStructureFeatures(
157 | *worldGenerator->mStructureFeatureRegistry,
158 | seed,
159 | false,
160 | levelData.getBaseGameVersion()
161 | );
162 | break;
163 | }
164 | case GeneratorType::Nether: {
165 | worldGenerator = std::make_unique(*this, seed, biome);
166 | worldGenerator->mStructureFeatureRegistry->mGeneratorState =
167 | br::worldgen::ChunkGeneratorStructureState::createNormal(
168 | seed,
169 | worldGenerator->getBiomeSource(),
170 | structureSetRegistry
171 | );
172 | netherAddStructureFeatures(
173 | *worldGenerator->mStructureFeatureRegistry,
174 | seed,
175 | levelData.getBaseGameVersion(),
176 | static_cast(levelData.mExperiments.get())
177 | );
178 | break;
179 | }
180 | case GeneratorType::TheEnd: {
181 | worldGenerator = std::make_unique(*this, seed, biome);
182 | worldGenerator->mStructureFeatureRegistry->mGeneratorState =
183 | br::worldgen::ChunkGeneratorStructureState::createNormal(
184 | seed,
185 | worldGenerator->getBiomeSource(),
186 | structureSetRegistry
187 | );
188 |
189 | // worldGenerator->mStructureFeatureRegistry->mStructureFeatures->emplace_back(
190 | // std::make_unique(*this, seed)
191 | // );
192 | break;
193 | }
194 | case GeneratorType::Flat: {
195 | worldGenerator = std::make_unique(*this, seed, levelData.mFlatWorldOptions);
196 | worldGenerator->mStructureFeatureRegistry->mGeneratorState =
197 | br::worldgen::ChunkGeneratorStructureState::createFlat(seed, worldGenerator->getBiomeSource(), {});
198 | break;
199 | }
200 | default: {
201 | auto generator = std::make_unique(*this);
202 | generator->mBiome = level.getBiomeRegistry().lookupByHash(VanillaBiomeNames::Ocean());
203 | worldGenerator = std::move(generator);
204 | worldGenerator->mStructureFeatureRegistry->mGeneratorState->mLevelSeed = seed;
205 | worldGenerator->mStructureFeatureRegistry->mGeneratorState->mRingsSeed = seed;
206 | }
207 | }
208 | // worldGenerator->init();
209 | return std::move(worldGenerator);
210 | }
211 |
212 | void SimpleCustomDimension::upgradeLevelChunk(ChunkSource& cs, LevelChunk& lc, LevelChunk& generatedChunk) {
213 | loggerMoreDim.debug(__FUNCTION__);
214 | auto blockSource = BlockSource(static_cast(mLevel), *this, cs, false, true, false);
215 | VanillaLevelChunkUpgrade::_upgradeLevelChunkViaMetaData(lc, generatedChunk, blockSource);
216 | VanillaLevelChunkUpgrade::_upgradeLevelChunkLegacy(lc, blockSource);
217 | }
218 |
219 | void SimpleCustomDimension::fixWallChunk(ChunkSource& cs, LevelChunk& lc) {
220 | loggerMoreDim.debug(__FUNCTION__);
221 | auto blockSource = BlockSource(static_cast(mLevel), *this, cs, false, true, false);
222 | VanillaLevelChunkUpgrade::fixWallChunk(lc, blockSource);
223 | }
224 |
225 | bool SimpleCustomDimension::levelChunkNeedsUpgrade(LevelChunk const& lc) const {
226 | loggerMoreDim.debug(__FUNCTION__);
227 | return VanillaLevelChunkUpgrade::levelChunkNeedsUpgrade(lc);
228 | }
229 | void SimpleCustomDimension::_upgradeOldLimboEntity(CompoundTag& tag, ::LimboEntitiesVersion vers) {
230 | loggerMoreDim.debug(__FUNCTION__);
231 | auto isTemplate = mLevel.getLevelData().mIsFromLockedTemplate;
232 | return VanillaLevelChunkUpgrade::upgradeOldLimboEntity(tag, vers, isTemplate);
233 | }
234 |
235 | Vec3 SimpleCustomDimension::translatePosAcrossDimension(Vec3 const& fromPos, DimensionType fromId) const {
236 | loggerMoreDim.debug(__FUNCTION__);
237 | Vec3 topos;
238 | VanillaDimensions::convertPointBetweenDimensions(fromPos, topos, fromId, mId, mLevel.getDimensionConversionData());
239 | constexpr auto clampVal = 32000000.0f - 128.0f;
240 |
241 | topos.x = std::clamp(topos.x, -clampVal, clampVal);
242 | topos.z = std::clamp(topos.z, -clampVal, clampVal);
243 |
244 | return topos;
245 | }
246 |
247 | short SimpleCustomDimension::getCloudHeight() const { return 192; }
248 |
249 |
250 | std::unique_ptr
251 | SimpleCustomDimension::_wrapStorageForVersionCompatibility(std::unique_ptr cs, ::StorageVersion /*ver*/) {
252 | loggerMoreDim.debug(__FUNCTION__);
253 | return cs;
254 | }
255 |
256 | mce::Color SimpleCustomDimension::getBrightnessDependentFogColor(mce::Color const& color, float brightness) const {
257 | loggerMoreDim.debug(__FUNCTION__);
258 | float temp = (brightness * 0.94f) + 0.06f;
259 | float temp2 = (brightness * 0.91f) + 0.09f;
260 | auto result = color;
261 | result.r = color.r * temp;
262 | result.g = color.g * temp;
263 | result.b = color.b * temp2;
264 | return result;
265 | };
266 |
267 | } // namespace more_dimensions
268 |
--------------------------------------------------------------------------------
/src/more_dimensions/api/dimension/SimpleCustomDimension.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "more_dimensions/api/dimension/CustomDimensionManager.h"
4 | #include "more_dimensions/core/Macros.h"
5 |
6 | #include "mc/world/level/dimension/Dimension.h"
7 |
8 |
9 | class ChunkSource;
10 | class LevelChunk;
11 |
12 | namespace more_dimensions {
13 |
14 | class SimpleCustomDimension : public Dimension {
15 | uint seed;
16 | GeneratorType generatorType;
17 |
18 | public:
19 | MORE_DIMENSIONS_API SimpleCustomDimension(std::string const& name, DimensionFactoryInfo const& info);
20 |
21 | MORE_DIMENSIONS_API static CompoundTag
22 | generateNewData(uint seed = 123, GeneratorType generatorType = GeneratorType::Overworld);
23 |
24 | MORE_DIMENSIONS_API void init(br::worldgen::StructureSetRegistry const&) override;
25 |
26 | MORE_DIMENSIONS_API std::unique_ptr
27 | createGenerator(br::worldgen::StructureSetRegistry const&) override;
28 |
29 | MORE_DIMENSIONS_API void upgradeLevelChunk(ChunkSource& chunkSource, LevelChunk& oldLc, LevelChunk& newLc) override;
30 |
31 | MORE_DIMENSIONS_API void fixWallChunk(ChunkSource& cs, LevelChunk& lc) override;
32 |
33 | MORE_DIMENSIONS_API bool levelChunkNeedsUpgrade(LevelChunk const& lc) const override;
34 |
35 | MORE_DIMENSIONS_API void _upgradeOldLimboEntity(CompoundTag& tag, ::LimboEntitiesVersion vers) override;
36 |
37 | MORE_DIMENSIONS_API Vec3 translatePosAcrossDimension(Vec3 const& pos, DimensionType did) const override;
38 |
39 | MORE_DIMENSIONS_API std::unique_ptr
40 | _wrapStorageForVersionCompatibility(std::unique_ptr cs, ::StorageVersion ver) override;
41 |
42 | MORE_DIMENSIONS_API mce::Color
43 | getBrightnessDependentFogColor(mce::Color const& color, float brightness) const override;
44 |
45 | MORE_DIMENSIONS_API short getCloudHeight() const override;
46 |
47 | };
48 | } // namespace more_dimensions
49 |
--------------------------------------------------------------------------------
/src/more_dimensions/core/Macros.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #ifdef MORE_DIMENSIONS_EXPORTS
4 |
5 | #define MORE_DIMENSIONS_API __declspec(dllexport)
6 |
7 | #else
8 |
9 | #define MORE_DIMENSIONS_API __declspec(dllimport)
10 |
11 | #endif
12 |
--------------------------------------------------------------------------------
/src/more_dimensions/core/dimension/CustomDimensionConfig.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include "CustomDimensionConfig.h"
3 |
4 | #include "mc/nbt/Tag.h"
5 | #include "more_dimensions/MoreDimenison.h"
6 |
7 | #include "snappy.h"
8 |
9 | #include "ll/api/Config.h"
10 | #include "ll/api/service/Bedrock.h"
11 | #include "ll/api/utils/Base64Utils.h"
12 | #include "ll/api/utils/ErrorUtils.h"
13 |
14 | #include "mc/nbt/CompoundTag.h"
15 | #include "mc/server/PropertiesSettings.h"
16 |
17 |
18 | namespace more_dimensions::CustomDimensionConfig {
19 |
20 | // static ll::Logger logger("CustomDimensionConfig");
21 | auto& logger = MoreDimenison::getInstance().getSelf().getLogger();
22 |
23 | std::string compress(std::string_view sv) {
24 | std::string res;
25 | snappy::Compress(sv.data(), sv.size(), &res);
26 | return res;
27 | }
28 |
29 | std::string decompress(std::string_view sv) {
30 | std::string res;
31 | snappy::Uncompress(sv.data(), sv.size(), &res);
32 | return res;
33 | }
34 |
35 | static std::filesystem::path dimensionConfigPath{u8"./worlds"};
36 |
37 | void setDimensionConfigPath() {
38 | if (!ll::service::getLevel()) {
39 | throw std::runtime_error("Level nullptr");
40 | }
41 | dimensionConfigPath /= ll::string_utils::str2u8str(ll::service::getPropertiesSettings()->mLevelName);
42 | dimensionConfigPath /= u8"dimension_config.json";
43 | }
44 |
45 | bool loadConfigFile() {
46 | if (std::ifstream(dimensionConfigPath).good()) {
47 | try {
48 | if (ll::config::loadConfig(
49 | getConfig(),
50 | dimensionConfigPath,
51 | [](Config& config, nlohmann::ordered_json& data) {
52 | if (data["version"] < config.version) {
53 | for (auto& item : data["dimensionList"]) {
54 | item["sNbt"] =
55 | CompoundTag::fromBinaryNbt(decompress(ll::base64_utils::decode(item["base64Nbt"])))
56 | ->toSnbt(SnbtFormat::Minimize);
57 | item.erase("base64Nbt");
58 | }
59 | }
60 | data.erase("version");
61 | auto patch = ll::reflection::serialize(config);
62 | patch.value().merge_patch(data);
63 | data = *std::move(patch);
64 | return true;
65 | }
66 | )) {
67 | logger.info("Config file load success!");
68 | return true;
69 | }
70 | } catch (...) {
71 | logger.error("Config file load fail, will rewrite!");
72 | ll::error_utils::printCurrentException(logger);
73 | }
74 | }
75 | try {
76 | if (ll::config::saveConfig(getConfig(), dimensionConfigPath)) {
77 | logger.warn("Config file rewrite success!");
78 | return true;
79 | } else {
80 | logger.error("Config rewrite failed!");
81 | }
82 | } catch (...) {
83 | logger.error("Config rewrite failed!");
84 | ll::error_utils::printCurrentException(logger);
85 | }
86 | return false;
87 | }
88 |
89 | bool saveConfigFile() {
90 | bool result{};
91 | try {
92 | result = ll::config::saveConfig(getConfig(), dimensionConfigPath);
93 | } catch (...) {
94 | result = false;
95 | ll::error_utils::printCurrentException(logger);
96 | }
97 | if (!result) {
98 | logger.error("Config file save fail!");
99 | return false;
100 | }
101 | return true;
102 | }
103 |
104 | // void updateConfigVersion() {
105 | // if (getConfig().version < 4) {
106 | // logger.info("Config need update");
107 | // auto config = getConfig();
108 | // for (auto& item : config.dimensionList) {
109 | // auto oldStrNbt = item.second.base64Nbt;
110 | // item.second.base64Nbt = CompoundTag::fromBinaryNbt(decompress(ll::base64_utils::decode(oldStrNbt)))
111 | // ->toSnbt(SnbtFormat::Minimize);
112 | // }
113 | // saveConfigFile();
114 | // }
115 | // }
116 | } // namespace more_dimensions::CustomDimensionConfig
117 |
--------------------------------------------------------------------------------
/src/more_dimensions/core/dimension/CustomDimensionConfig.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 |
7 | namespace more_dimensions::CustomDimensionConfig {
8 | struct Config {
9 | struct Info {
10 | int dimId{};
11 | std::string sNbt;
12 | };
13 | int version = 4;
14 | std::unordered_map dimensionList{};
15 | };
16 |
17 | inline Config& getConfig() {
18 | static Config instance;
19 | return instance;
20 | }
21 |
22 | void setDimensionConfigPath();
23 | bool loadConfigFile();
24 | bool saveConfigFile();
25 | }; // namespace more_dimensions::CustomDimensionConfig
26 |
--------------------------------------------------------------------------------
/src/more_dimensions/core/dimension/FakeDimensionId.cpp:
--------------------------------------------------------------------------------
1 | #include "FakeDimensionId.h"
2 |
3 | #include "more_dimensions//api/dimension/CustomDimensionManager.h"
4 | #include "more_dimensions/MoreDimenison.h"
5 |
6 | #include "ll/api/memory/Hook.h"
7 | #include "ll/api/service/Bedrock.h"
8 |
9 | #include "mc/deps/core/math/Vec3.h"
10 | #include "mc/deps/core/utility/BinaryStream.h"
11 | #include "mc/deps/ecs/gamerefs_entity/EntityContext.h"
12 | #include "mc/entity/components/IPlayerTickPolicy.h"
13 | #include "mc/entity/components/MovementPackets.h"
14 | #include "mc/entity/components/ServerPlayerMovementComponent.h"
15 | #include "mc/legacy/ActorRuntimeID.h"
16 | #include "mc/legacy/ActorUniqueID.h"
17 | #include "mc/network//LoopbackPacketSender.h"
18 | #include "mc/network/MinecraftPacketIds.h"
19 | #include "mc/network/NetworkBlockPosition.h"
20 | #include "mc/network/NetworkIdentifierWithSubId.h"
21 | #include "mc/network/ServerNetworkHandler.h"
22 | #include "mc/network/packet/AddVolumeEntityPacket.h"
23 | #include "mc/network/packet/ChangeDimensionPacket.h"
24 | #include "mc/network/packet/InteractPacket.h"
25 | #include "mc/network/packet/InventoryTransactionPacket.h"
26 | #include "mc/network/packet/LevelChunkPacket.h"
27 | #include "mc/network/packet/PlayerActionPacket.h"
28 | #include "mc/network/packet/PlayerActionType.h"
29 | #include "mc/network/packet/PlayerAuthInputPacket.h"
30 | #include "mc/network/packet/RemoveVolumeEntityPacket.h"
31 | #include "mc/network/packet/SpawnParticleEffectPacket.h"
32 | #include "mc/network/packet/StartGamePacket.h"
33 | #include "mc/network/packet/SubChunkPacket.h"
34 | #include "mc/network/packet/SubChunkRequestPacket.h"
35 | #include "mc/network/packet/UpdateBlockPacket.h"
36 | #include "mc/server/ServerPlayer.h"
37 | #include "mc/util/MolangVariableMap.h"
38 | #include "mc/util/VarIntDataOutput.h"
39 | #include "mc/world/actor/ActorDataIDs.h"
40 | #include "mc/world/actor/SynchedActorDataEntityWrapper.h"
41 | #include "mc/world/level/ChangeDimensionRequest.h"
42 | #include "mc/world/level/ChunkPos.h"
43 | #include "mc/world/level/Level.h"
44 | #include "mc/world/level/LoadingScreenIdManager.h"
45 | #include "mc/world/level/SpawnSettings.h"
46 | #include "mc/world/level/dimension/VanillaDimensions.h"
47 | #include "mc/world/level/levelSettings.h"
48 |
49 |
50 | // ChangeDimensionPacket.java
51 | // ClientboundMapItemDataPacket.java
52 | // RemoveVolumeEntityPacket.java
53 | // StartGamePacket.java
54 | // AddVolumeEntityPacket.java
55 | // SpawnParticleEffectPacket.java
56 | // SubChunkPacket.java
57 | // SubChunkRequestPacket.java
58 |
59 | namespace more_dimensions {
60 |
61 | // static ll::Logger logger("FakeDimensionId");
62 | auto& logger = MoreDimenison::getInstance().getSelf().getLogger();
63 |
64 | static void sendEmptyChunk(const NetworkIdentifier& netId, int chunkX, int chunkZ, bool forceUpdate) {
65 | std::array biome{};
66 | LevelChunkPacket levelChunkPacket;
67 | BinaryStream binaryStream{levelChunkPacket.mSerializedChunk, false};
68 | VarIntDataOutput varIntDataOutput(binaryStream);
69 |
70 | varIntDataOutput.writeBytes(&biome, 4096); // write void biome
71 | for (int i = 1; i <= 8; i++) {
72 | varIntDataOutput.writeByte(255ui8);
73 | }
74 | varIntDataOutput.mStream.writeByte(0, "Byte", 0); // write border blocks
75 |
76 | levelChunkPacket.mPos->x = chunkX;
77 | levelChunkPacket.mPos->z = chunkZ;
78 | levelChunkPacket.mDimensionId = FakeDimensionId::temporaryDimId;
79 | levelChunkPacket.mCacheEnabled = false;
80 | levelChunkPacket.mSubChunksCount = 0;
81 |
82 | ll::service::getLevel()->getPacketSender()->sendToClient(netId, levelChunkPacket, SubClientId::PrimaryClient);
83 |
84 | if (forceUpdate) {
85 | NetworkBlockPosition pos{
86 | BlockPos{chunkX << 4, 80, chunkZ << 4}
87 | };
88 | UpdateBlockPacket blockPacket;
89 | blockPacket.mPos = pos;
90 | blockPacket.mLayer = 0;
91 | blockPacket.mUpdateFlags = 1;
92 | ll::service::getLevel()->getPacketSender()->sendToClient(netId, blockPacket, SubClientId::PrimaryClient);
93 | }
94 | }
95 |
96 | static void sendEmptyChunks(const NetworkIdentifier& netId, const Vec3& position, int radius, bool forceUpdate) {
97 | int chunkX = (int)(position.x) >> 4;
98 | int chunkZ = (int)(position.z) >> 4;
99 | for (int x = -radius; x <= radius; x++) {
100 | for (int z = -radius; z <= radius; z++) {
101 | sendEmptyChunk(netId, chunkX + x, chunkZ + z, forceUpdate);
102 | }
103 | }
104 | }
105 |
106 | static void fakeChangeDimension(
107 | const NetworkIdentifier& netId,
108 | ActorRuntimeID runtimeId,
109 | DimensionType fakeDimId,
110 | const Vec3& pos,
111 | std::optional screedId
112 | ) {
113 | // ChangeDimensionPacket changeDimensionPacket{fakeDimId, pos, true, {std::nullopt}};
114 | ChangeDimensionPacket changeDimensionPacket;
115 | changeDimensionPacket.mDimensionId = fakeDimId;
116 | changeDimensionPacket.mPos = pos;
117 | changeDimensionPacket.mRespawn = true;
118 | changeDimensionPacket.mLoadingScreenId = {screedId};
119 | ll::service::getLevel()->getPacketSender()->sendToClient(netId, changeDimensionPacket, SubClientId::PrimaryClient);
120 | PlayerActionPacket playerActionPacket;
121 | playerActionPacket.mAction = PlayerActionType::ChangeDimensionAck;
122 | playerActionPacket.mRuntimeId = runtimeId;
123 | ll::service::getLevel()->getPacketSender()->sendToClient(netId, playerActionPacket, SubClientId::PrimaryClient);
124 | sendEmptyChunks(netId, pos, 3, true);
125 | }
126 |
127 | namespace CustomDimensionHookList {
128 |
129 | namespace sendpackethook {
130 |
131 | LL_TYPE_INSTANCE_HOOK(
132 | LoopbackPacketSendersendToClientHandler1,
133 | HookPriority::Normal,
134 | LoopbackPacketSender,
135 | &LoopbackPacketSender::$sendToClient,
136 | void,
137 | NetworkIdentifier const& netId,
138 | Packet const& packet,
139 | ::SubClientId subId
140 | ) {
141 | auto player = ll::service::getServerNetworkHandler()->_getServerPlayer(netId, subId);
142 | if (player && player->getDimensionId() >= 3 && packet.getId() != MinecraftPacketIds::ChangeDimension
143 | && packet.getId() != MinecraftPacketIds::PlayerAction
144 | && packet.getId() != MinecraftPacketIds::SpawnParticleEffect) {
145 | FakeDimensionId::changePacketDimension(const_cast(packet));
146 | }
147 | if (player && player->getDimensionId() >= 3 && packet.getId() == MinecraftPacketIds::FullChunkData) {
148 | auto& modifPacket = (LevelChunkPacket&)packet;
149 | if (modifPacket.mDimensionId->id >= 3) {
150 | modifPacket.mDimensionId = 0;
151 | }
152 | if (modifPacket.mDimensionId->id == VanillaDimensions::Undefined().id) {
153 | modifPacket.mDimensionId->id = 3;
154 | }
155 | if (modifPacket.mClientRequestSubChunkLimit <= 8) {
156 | modifPacket.mClientRequestSubChunkLimit = 11;
157 | }
158 | }
159 | return origin(netId, packet, subId);
160 | };
161 |
162 | LL_TYPE_INSTANCE_HOOK(
163 | LoopbackPacketSendersendToClientHandler2,
164 | HookPriority::Normal,
165 | LoopbackPacketSender,
166 | &LoopbackPacketSender::$sendToClient,
167 | void,
168 | UserEntityIdentifierComponent const* comp,
169 | Packet const& packet
170 | ) {
171 | auto player = ll::service::getServerNetworkHandler()->_getServerPlayer(comp->mNetworkId, comp->mClientSubId);
172 | if (!player) return origin(comp, packet);
173 | auto uuid = player->getUuid();
174 | if (player && player->getDimensionId() >= 3 && packet.getId() != MinecraftPacketIds::ChangeDimension
175 | && packet.getId() != MinecraftPacketIds::PlayerAction
176 | && packet.getId() != MinecraftPacketIds::SpawnParticleEffect) {
177 | FakeDimensionId::changePacketDimension(const_cast(packet));
178 | }
179 |
180 | // remove send changeDimensionPacket to client when player die
181 | if (FakeDimensionId::getInstance().isNeedRemove(uuid) && packet.getId() == MinecraftPacketIds::ChangeDimension) {
182 | return;
183 | }
184 | // remove level event packet, event id is 9801, LevelEvent is SleepingPlayers
185 | if (packet.getId() == MinecraftPacketIds::LevelEventGeneric && FakeDimensionId::getInstance().isNeedRemove(uuid)) {
186 | return;
187 | }
188 | // remove send changedimension success action packet to client when player die
189 | if (FakeDimensionId::getInstance().isNeedRemove(uuid) && packet.getId() == MinecraftPacketIds::PlayerAction) {
190 | auto& actionPacket = (PlayerActionPacket&)packet;
191 | if (actionPacket.mAction == PlayerActionType::ChangeDimensionAck) {
192 | return;
193 | }
194 | }
195 | // use fake dimension id when player go to custom dimension
196 | if (packet.getId() == MinecraftPacketIds::ChangeDimension) {
197 | auto& modifPacket = (ChangeDimensionPacket&)packet;
198 | if (modifPacket.mDimensionId->id > 2) {
199 | modifPacket.mDimensionId->id = FakeDimensionId::fakeDim;
200 | }
201 | }
202 | return origin(comp, packet);
203 | };
204 |
205 | LL_TYPE_INSTANCE_HOOK(
206 | LoopbackPacketSendersendToClientsHandler,
207 | HookPriority::Normal,
208 | LoopbackPacketSender,
209 | &LoopbackPacketSender::$sendToClients,
210 | void,
211 | std::vector const& subIds,
212 | Packet const& packet
213 | ) {
214 | if (packet.getId() == MinecraftPacketIds::RemoveVolumeEntityPacket
215 | || packet.getId() == MinecraftPacketIds::AddVolumeEntityPacket) {
216 | for (auto& subId : subIds) {
217 | auto player =
218 | ll::service::getServerNetworkHandler()->_getServerPlayer(subId.id, SubClientId::PrimaryClient);
219 | if (player && player->getDimensionId() >= 3) {
220 | FakeDimensionId::changePacketDimension(const_cast(packet));
221 | }
222 | packet.sendToClient(subId);
223 | }
224 | return;
225 | }
226 | return origin(subIds, packet);
227 | };
228 |
229 | // StartGamePacket
230 | LL_TYPE_INSTANCE_HOOK(
231 | StartGamePacketHandler,
232 | HookPriority::Normal,
233 | StartGamePacket,
234 | &StartGamePacket::$ctor,
235 | void*,
236 | LevelSettings const& levelSettings,
237 | ActorUniqueID uniqueId,
238 | ActorRuntimeID runtimeId,
239 | ::GameType gameType,
240 | bool unk,
241 | Vec3 const& pos,
242 | Vec2 const& ros,
243 | std::string const& levelId,
244 | std::string const& levelName,
245 | ContentIdentity const& contentIdentity,
246 | std::string const& unk1,
247 | BlockDefinitionGroup const& blockDefinitionGroup,
248 | bool unk2,
249 | CompoundTag compoundTag,
250 | PlayerMovementSettings const& moveSetting,
251 | std::string const& unk3,
252 | mce::UUID const& uuid,
253 | uint64 unk4,
254 | int unk5,
255 | uint64 unk6
256 | ) {
257 | if (levelSettings.getSpawnSettings().dimension->id >= 3) {
258 | SpawnSettings spawnSettings(levelSettings.getSpawnSettings());
259 | spawnSettings.dimension = FakeDimensionId::fakeDim;
260 | const_cast(levelSettings).setSpawnSettings(spawnSettings);
261 | }
262 | return origin(
263 | levelSettings,
264 | uniqueId,
265 | runtimeId,
266 | gameType,
267 | unk,
268 | pos,
269 | ros,
270 | levelId,
271 | levelName,
272 | contentIdentity,
273 | unk1,
274 | blockDefinitionGroup,
275 | unk2,
276 | std::move(compoundTag),
277 | moveSetting,
278 | unk3,
279 | uuid,
280 | unk4,
281 | unk5,
282 | unk6
283 | );
284 | }
285 |
286 | // ChangeDimensionPacket
287 | // inline function use seedtoClient -> line 200
288 | // LL_TYPE_INSTANCE_HOOK(
289 | // ChangeDimensionPacketHandler,
290 | // HookPriority::Normal,
291 | // ChangeDimensionPacket,
292 | // &ChangeDimensionPacket::$ctor,
293 | // void*,
294 | // DimensionType dimId,
295 | // Vec3 pos,
296 | // bool respawn,
297 | // NewType<::std::optional> loadingScreenId
298 | // ) {
299 | // if (dimId > 2) {
300 | // dimId = FakeDimensionId::fakeDim;
301 | // }
302 | // return origin(dimId, pos, respawn, loadingScreenId);
303 | // }
304 |
305 | LL_TYPE_INSTANCE_HOOK(
306 | ChangeDimensionPacketHandler,
307 | HookPriority::Normal,
308 | ChangeDimensionPacket,
309 | &ChangeDimensionPacket::$write,
310 | void,
311 | BinaryStream& stream
312 | ) {
313 | stream.writeVarInt(
314 | this->mDimensionId->id,
315 | "Dimension ID",
316 | "Currently supported: (0 -> Overworld, 1 -> Nether, 2 -> The End, 3 -> Undefined)");
317 | stream.writeFloat(this->mPos->x, "X", 0LL);
318 | stream.writeFloat(this->mPos->y, "Y", 0LL);
319 | stream.writeFloat(this->mPos->z, "Z", 0LL);
320 | stream.writeBool(this->mRespawn, "Respawn", 0LL);
321 | stream.writeBool(this->mLoadingScreenId->mValue.has_value(), "Has Value", "If true, follow with appropriate data type, otherwise nothing");
322 | if (this->mLoadingScreenId->mValue.has_value())
323 | stream.writeUnsignedInt(this->mLoadingScreenId->mValue.value(), "Unsigned Int", 0LL);
324 | }
325 |
326 | // SubChunkPacket and SubChunkRequestPacket
327 | LL_TYPE_INSTANCE_HOOK(
328 | SubChunkPacketHandler,
329 | HookPriority::Highest,
330 | ServerNetworkHandler,
331 | &ServerNetworkHandler::_buildSubChunkPacketData,
332 | void,
333 | NetworkIdentifier const& networkIdentifier,
334 | ServerPlayer const* serverPlayer,
335 | SubChunkRequestPacket const& subChunkRequestPacket,
336 | SubChunkPacket& subChunkPacket,
337 | uint count,
338 | bool isCacheEnabled
339 | ) {
340 | auto inDim = serverPlayer->getDimensionId();
341 | if (inDim >= 3) {
342 | const_cast(subChunkRequestPacket).mDimensionType = inDim;
343 | // dimensionType value of subChunkPacket is not read in this function, so it is changed together.
344 | subChunkPacket.mDimensionType = FakeDimensionId::fakeDim;
345 | };
346 | return origin(networkIdentifier, serverPlayer, subChunkRequestPacket, subChunkPacket, count, isCacheEnabled);
347 | }
348 |
349 | // SpawnParticleEffectPacket
350 | LL_TYPE_INSTANCE_HOOK(
351 | SpawnParticleEffectPacketHandler,
352 | HookPriority::Normal,
353 | SpawnParticleEffectPacket,
354 | &SpawnParticleEffectPacket::$ctor,
355 | void*,
356 | Vec3 const& pos,
357 | std::string const& particle_name,
358 | uchar dimId,
359 | std::optional molang
360 | ) {
361 | if (dimId >= 3) {
362 | dimId = FakeDimensionId::fakeDim.id;
363 | }
364 | return origin(pos, particle_name, dimId, std::move(molang));
365 | }
366 |
367 | } // namespace sendpackethook
368 |
369 | LL_TYPE_INSTANCE_HOOK(
370 | PlayerdieHandler,
371 | HookPriority::Normal,
372 | Player,
373 | &Player::$die,
374 | void,
375 | ActorDamageSource const& actorDamageSource
376 | ) {
377 | if (getDimensionId() >= 3) {
378 | logger.debug("Remove set true");
379 | FakeDimensionId::getInstance().setNeedRemove(getUuid(), true);
380 | }
381 | return origin(actorDamageSource);
382 | }
383 |
384 | namespace receivepackethook {
385 |
386 | // when player in overworld and custom dimension will need
387 | LL_TYPE_INSTANCE_HOOK(
388 | ServerNetworkHandlerPlayerActionPacketHandler,
389 | HookPriority::Normal,
390 | ServerNetworkHandler,
391 | &ServerNetworkHandler::$handle,
392 | void,
393 | NetworkIdentifier const& netId,
394 | PlayerActionPacket const& packet
395 | ) {
396 | auto& handler = ll::memory::dAccess(this, -16);
397 | auto player = handler._getServerPlayer(netId, packet.mSenderSubId);
398 | auto uuid = player->getUuid();
399 | auto& fakeDimensionId = FakeDimensionId::getInstance();
400 | if (packet.mAction == PlayerActionType::Respawn) {
401 | // when player go overworld with die
402 | if (!fakeDimensionId.isNeedRemove(uuid)) {
403 | return origin(netId, packet);
404 | }
405 | fakeDimensionId.setNeedRemove(uuid, false);
406 | auto moveComp = player->getEntityContext().tryGetComponent();
407 | if (moveComp) {
408 | moveComp->mServerHasMovementAuthority = false;
409 | }
410 | fakeDimensionId.onPlayerLeftCustomDimension(uuid, true);
411 | // flash player bounding box
412 | // player->getEntityData().markDirty(fmt::underlying(ActorDataIDs::CollisionBox));
413 | }
414 | return origin(netId, packet);
415 | };
416 | } // namespace receivepackethook
417 |
418 | LL_TYPE_INSTANCE_HOOK(
419 | LevelrequestPlayerChangeDimensionHandler,
420 | HookPriority::Normal,
421 | Level,
422 | &Level::$requestPlayerChangeDimension,
423 | void,
424 | Player& player,
425 | ChangeDimensionRequest&& changeRequest
426 | ) {
427 | auto inId = player.getDimensionId();
428 | if (changeRequest.mToDimensionId->id == 1 || changeRequest.mToDimensionId->id == 2 || inId.id == 1 || inId.id == 2
429 | || player.isDead()) {
430 | return origin(player, std::move(changeRequest));
431 | };
432 | // issue #7
433 | auto loadingScreenIdManager = ll::memory::dAccess(&this->mLoadingScreenIdManager, 8);
434 | auto screedId = loadingScreenIdManager->mUnk7db596.as() + 1;
435 | ++loadingScreenIdManager->mUnk7db596.as();
436 | // screedId.mValue.emplace(screedId.mValue.value() + 1);
437 |
438 | fakeChangeDimension(
439 | player.getNetworkIdentifier(),
440 | player.getRuntimeID(),
441 | more_dimensions::FakeDimensionId::temporaryDimId,
442 | player.getPosition(),
443 | screedId
444 | );
445 | return origin(player, std::move(changeRequest));
446 | }
447 |
448 | using HookReg = ll::memory::HookRegistrar<
449 | sendpackethook::LoopbackPacketSendersendToClientHandler1,
450 | sendpackethook::LoopbackPacketSendersendToClientHandler2,
451 | sendpackethook::LoopbackPacketSendersendToClientsHandler,
452 | // sendpackethook::ChangeDimensionPacketHandler,
453 | sendpackethook::SubChunkPacketHandler,
454 | sendpackethook::SpawnParticleEffectPacketHandler,
455 | sendpackethook::StartGamePacketHandler,
456 | PlayerdieHandler,
457 | LevelrequestPlayerChangeDimensionHandler,
458 | receivepackethook::ServerNetworkHandlerPlayerActionPacketHandler>;
459 |
460 | } // namespace CustomDimensionHookList
461 |
462 | FakeDimensionId::FakeDimensionId() { CustomDimensionHookList::HookReg::hook(); }
463 |
464 | FakeDimensionId::~FakeDimensionId() { CustomDimensionHookList::HookReg::unhook(); }
465 |
466 | FakeDimensionId& FakeDimensionId::getInstance() {
467 | static FakeDimensionId ins{};
468 | return ins;
469 | }
470 |
471 | void FakeDimensionId::changePacketDimension(Packet& packet) {
472 | auto packId = packet.getId();
473 | switch (packId) {
474 | case MinecraftPacketIds::RemoveVolumeEntityPacket: {
475 | auto& tempP = (RemoveVolumeEntityPacket&)packet;
476 | tempP.mDimensionType = fakeDim;
477 | logger.debug("MinecraftPacketIds::RemoveVolumeEntityPacket: dimId change to {}", fakeDim.id);
478 | }
479 | case MinecraftPacketIds::AddVolumeEntityPacket: {
480 | auto& tempP = (AddVolumeEntityPacket&)packet;
481 | tempP.mDimensionType = fakeDim;
482 | logger.debug("MinecraftPacketIds::AddVolumeEntityPacket: dimId change to {}", fakeDim.id);
483 | }
484 | default:
485 | return;
486 | }
487 | }
488 |
489 | void FakeDimensionId::setNeedRemove(mce::UUID uuid, bool needRemove) {
490 | if (mSettingMap.count(uuid)) {
491 | mSettingMap.at(uuid).needRemovePacket = needRemove;
492 | } else {
493 | mSettingMap.emplace(uuid, CustomDimensionIdSetting{needRemove});
494 | }
495 | }
496 |
497 | bool FakeDimensionId::isNeedRemove(mce::UUID uuid) {
498 | if (mSettingMap.count(uuid)) {
499 | return mSettingMap.at(uuid).needRemovePacket;
500 | };
501 | return false;
502 | }
503 |
504 | void FakeDimensionId::onPlayerGoCustomDimension(mce::UUID uuid) {
505 | if (!mSettingMap.count(uuid)) {
506 | std::lock_guard lockGuard{mMapMutex};
507 | mSettingMap.emplace(uuid, CustomDimensionIdSetting{false});
508 | }
509 | }
510 |
511 | void FakeDimensionId::onPlayerLeftCustomDimension(mce::UUID uuid, bool isRespawn) {
512 | std::lock_guard lockGuard{mMapMutex};
513 | if (mSettingMap.count(uuid)) {
514 | if (isRespawn) {
515 | mSettingMap.at(uuid).needRemovePacket = false;
516 | } else {
517 | mSettingMap.erase(uuid);
518 | }
519 | }
520 | }
521 |
522 | } // namespace more_dimensions
523 |
--------------------------------------------------------------------------------
/src/more_dimensions/core/dimension/FakeDimensionId.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "mc/deps/core/utility/AutomaticID.h"
4 | #include "mc/network/packet/Packet.h"
5 | #include "mc/platform/UUID.h"
6 |
7 |
8 | #include
9 | #include
10 |
11 | class ServerPlayer;
12 |
13 | namespace more_dimensions {
14 |
15 | class FakeDimensionId {
16 | struct CustomDimensionIdSetting {
17 | bool needRemovePacket{};
18 | };
19 | std::mutex mMapMutex;
20 |
21 | std::unordered_map mSettingMap; // save in more dimension player
22 | public:
23 | static constexpr AutomaticID fakeDim = 0; // Overworld, Make the client think of the dimension
24 | static constexpr AutomaticID temporaryDimId = 1; // Dimensions of transit
25 |
26 | static FakeDimensionId& getInstance();
27 |
28 | FakeDimensionId();
29 | ~FakeDimensionId();
30 | static void changePacketDimension(Packet& packet);
31 | void setNeedRemove(mce::UUID uuid, bool needRemove);
32 | bool isNeedRemove(mce::UUID uuid);
33 | void onPlayerGoCustomDimension(mce::UUID uuid);
34 | void onPlayerLeftCustomDimension(mce::UUID uuid, bool isRespawn);
35 | };
36 | } // namespace more_dimensions
37 |
--------------------------------------------------------------------------------
/src/more_dimensions/core/dimension/MoreDimensionsPatch.h:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | extern "C" {
7 | __declspec(dllimport) bool pl_notice(void* target);
8 | }
9 | namespace {
10 | struct AddressAndReg {
11 | DWORD func_rva;
12 | DWORD func_rva_start;
13 | DWORD func_rva_end;
14 | const std::vector native_code;
15 | };
16 |
17 | // 0~26 VanillaDimensions::toSerializedInt
18 | // 27~39 VanillaDimensions::fromSerializedInt(int)
19 | std::vector data = {
20 | {0x08440f0, 0x08443cf, 0x08443fa, {0x89, 0xc8} },
21 | {0x262a500, 0x262a5f5, 0x262a617, {0x89, 0xc3} },
22 | {0x104de80, 0x104deb7, 0x104dee0, {0x89, 0xc2} },
23 | {0x10a4f60, 0x10a4fee, 0x10a5017, {0x89, 0xc2} },
24 | {0x1089720, 0x1089770, 0x1089799, {0x89, 0xc2} },
25 | {0x108a620, 0x108a655, 0x108a67e, {0x89, 0xc2} },
26 | {0x0d018e0, 0x0d01ed2, 0x0d01efb, {0x89, 0xc3} },
27 | {0x1062410, 0x10625e3, 0x1062606, {0x89, 0xc3} },
28 | {0x0d93460, 0x0d9347f, 0x0d934a8, {0x89, 0xc2} },
29 | {0x0d71150, 0x0d711a4, 0x0d711cd, {0x89, 0xc2} },
30 | {0x197e0f0, 0x197e4ab, 0x197e4d3, {0x41, 0x88, 0xc9} },
31 | {0x197e670, 0x197e76b, 0x197e78e, {0x88, 0xc8} },
32 | {0x171f790, 0x171fab7, 0x171fadf, {0x41, 0x88, 0xc9} },
33 | {0x25c0140, 0x25c09c7, 0x25c09f2, {0x89, 0xc3} },
34 | {0x2569f20, 0x256a388, 0x256a3b3, {0x89, 0xc3} },
35 | {0x2569f20, 0x256a834, 0x256a860, {0x89, 0xdf} },
36 | {0x2567090, 0x2567841, 0x2567867, {0x41, 0x89, 0xc6} },
37 | {0x2582d50, 0x2582e80, 0x2582ea9, {0x89, 0xc3} },
38 | {0x25825e0, 0x25825f0, 0x258261b, {0x89, 0xd3} },
39 | {0x2d2ca90, 0x2d2ccb2, 0x2d2cce0, {0x41, 0x89, 0xc6} },
40 | {0x2d2faf0, 0x2d2fc40, 0x2d2fc64, {0x89, 0xc7} },
41 | {0x2d3e700, 0x2d3e75e, 0x2d3e781, {0x88, 0xd8} },
42 | {0x2984bf0, 0x2984cb3, 0x2984cd6, {0x89, 0xc3} },
43 | {0x30e4420, 0x30e4432, 0x30e4460, {0x41, 0x89, 0xc3} },
44 | {0x31f7d10, 0x31f7e35, 0x31f7e59, {0x89, 0xcb} },
45 | {0x31f8e10, 0x31f8e8e, 0x31f8eb3, {0x89, 0xdf} },
46 | {0x336cb80, 0x336cccd, 0x336ccf5, {0x40, 0x88, 0xc7} },
47 | {0x25c22a0, 0x25c33dd, 0x25c340d, {0x41, 0x89, 0xc8} },
48 | {0x25e02f0, 0x25e04bc, 0x25e04e8, {0x89, 0xc8} },
49 | {0x0b92a60, 0x0b92d10, 0x0b92d60, {0x89, 0x8e, 0x3c, 0x0, 0x0, 0x0}},
50 | {0x0cbde50, 0x0cbdfc9, 0x0cbdff5, {0x89, 0xcb} },
51 | {0x0d013f0, 0x0d01657, 0x0d01683, {0x89, 0xcf} },
52 | {0x10fef90, 0x10ff015, 0x10ff04d, {0x89, 0xc8} },
53 | {0x25824e0, 0x2582560, 0x25825c2, {0x89, 0xc8} },
54 | {0x2a572d0, 0x25687a5, 0x25687ea, {0x89, 0x8e, 0xe0, 0xa, 0x0, 0x0}},
55 | {0x2d2c450, 0x2d2c5c1, 0x2d2c5ed, {0x89, 0xc8} },
56 | {0x2d2fcd0, 0x2d2fe6e, 0x2d2fe9a, {0x89, 0xc8} },
57 | {0x31ff0b0, 0x31ff164, 0x31ff190, {0x89, 0xc8} },
58 | {0x336e8e0, 0x336e998, 0x336e9c7, {} },
59 | };
60 |
61 | bool PatchFunction(HMODULE hModule, DWORD faddress_start, DWORD faddress_end, const std::vector& native_code) {
62 | LPVOID patchAddress = (LPVOID)((DWORD_PTR)hModule + faddress_start);
63 |
64 |
65 | // Construct the patch
66 | std::vector patch;
67 |
68 | patch.insert(patch.end(), native_code.begin(), native_code.end());
69 |
70 |
71 | // jmp faddress_end
72 | // Calculate the relative offset for the jump
73 | DWORD_PTR offset = (DWORD_PTR)hModule + faddress_end
74 | - ((DWORD_PTR)patchAddress + patch.size() + 5); // +5 for the size of the jmp instruction
75 |
76 | patch.push_back(0xE9); // jmp opcode
77 | patch.push_back((BYTE)(offset & 0xFF));
78 | patch.push_back((BYTE)((offset >> 8) & 0xFF));
79 | patch.push_back((BYTE)((offset >> 16) & 0xFF));
80 | patch.push_back((BYTE)((offset >> 24) & 0xFF));
81 |
82 | HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId());
83 |
84 | // Write the patch to memory
85 | DWORD oldProtect;
86 | if (!VirtualProtect(patchAddress, patch.size(), PAGE_EXECUTE_READWRITE, &oldProtect)) {
87 | std::cerr << "Failed to change memory protection" << std::endl;
88 | return false;
89 | }
90 |
91 | SIZE_T bytesWritten;
92 | if (!WriteProcessMemory(hProcess, patchAddress, patch.data(), patch.size(), &bytesWritten)
93 | || bytesWritten != patch.size()) {
94 | std::cerr << "Failed to write to process memory" << std::endl;
95 | CloseHandle(hProcess);
96 | return false;
97 | }
98 |
99 | if (!VirtualProtect(patchAddress, patch.size(), oldProtect, &oldProtect)) {
100 | std::cerr << "Failed to restore memory protection" << std::endl;
101 | return false; // Though the patch is applied, restoring protection failed.
102 | }
103 |
104 | return true;
105 | }
106 |
107 | void printHexBytes(const void* address, size_t numBytes) {
108 | const unsigned char* start = static_cast(address);
109 |
110 | for (size_t i = 0; i < numBytes; ++i) {
111 | std::cout << std::hex << std::setw(2) << std::setfill('0') << static_cast(start[i]) << " ";
112 | // Optionally add a newline after every 16 bytes for better readability
113 | if ((i + 1) % 16 == 0) {
114 | std::cout << std::endl;
115 | }
116 | }
117 | std::cout << std::dec << std::endl; // Reset to decimal output
118 | }
119 |
120 | } // namespace
121 |
122 |
123 | void injectNaticeCode() {
124 | // Calculate the address in the target process
125 | HMODULE hModule = GetModuleHandle(L"bedrock_server_mod.exe");
126 | if (!hModule) {
127 | std::cerr << "Failed to get module handle for bedrock_server_mod.exe" << std::endl;
128 | return;
129 | }
130 | for (auto& item : data) {
131 | PatchFunction(hModule, item.func_rva_start, item.func_rva_end, item.native_code);
132 | void* funcp = (void*)((BYTE*)hModule + item.func_rva);
133 | pl_notice(funcp);
134 | };
135 | };
136 |
137 | // BOOL APIENTRY DllMain(HMODULE hModule,
138 | // DWORD ul_reason_for_call,
139 | // LPVOID lpReserved
140 | // )
141 | // {
142 | // switch (ul_reason_for_call)
143 | // {
144 | // case DLL_PROCESS_ATTACH:
145 | // injectNaticeCode();
146 | // break;
147 | // case DLL_THREAD_ATTACH:
148 | // case DLL_THREAD_DETACH:
149 | // case DLL_PROCESS_DETACH:
150 | // break;
151 | // }
152 | // return TRUE;
153 | // }
--------------------------------------------------------------------------------
/src/test/TestCustomDimension.cpp:
--------------------------------------------------------------------------------
1 | #include "test/generator/flat-gen-village/FlatVillageDimension.h"
2 | #include "test/generator/generator-custom-structure/dimension/CustomStructureDimension.h"
3 | #include "test/generator/generator-terrain/NxnBorderTerrainDimension.h"
4 |
5 | #include "ll/api/event/EventBus.h"
6 | #include "ll/api/event/server/ServerStartedEvent.h"
7 |
8 | #include "more_dimensions/api/dimension/CustomDimensionManager.h"
9 | #include "more_dimensions/api/dimension/SimpleCustomDimension.h"
10 |
11 | static bool reg = [] {
12 | using namespace ll::event;
13 | EventBus::getInstance().emplaceListener([](ServerStartedEvent&) {
14 | // simplate dimension test
15 | // vanilla overworld type dimension test
16 | more_dimensions::CustomDimensionManager::getInstance().addDimension(
17 | "testNewDimension"
18 | );
19 |
20 | // vanilla flat type dimension test
21 | more_dimensions::CustomDimensionManager::getInstance()
22 | .addDimension("testNewFlatDimension", 345, GeneratorType::Flat);
23 |
24 | // vanilla nether type dimension test
25 | more_dimensions::CustomDimensionManager::getInstance()
26 | .addDimension("testNewNetherDimension", 345, GeneratorType::Nether);
27 |
28 | // vanilla the end type dimension test
29 | more_dimensions::CustomDimensionManager::getInstance()
30 | .addDimension("testNewTheEndDimension", 345, GeneratorType::TheEnd);
31 |
32 | // vanilla void dimension test
33 | more_dimensions::CustomDimensionManager::getInstance()
34 | .addDimension("testNewVoidDimension", 345, GeneratorType::Void);
35 |
36 | // custom diomension test
37 | // flat type generator village dimension test
38 | more_dimensions::CustomDimensionManager::getInstance()
39 | .addDimension("testFlatVillage");
40 |
41 | // flat type custom terrain dimension test
42 | more_dimensions::CustomDimensionManager::getInstance()
43 | .addDimension("testFlatTerrain", 5);
44 |
45 | // flat type custom structure dimension test
46 | more_dimensions::CustomDimensionManager::getInstance()
47 | .addDimension("testCustomStructure");
48 | });
49 | return true;
50 | }();
51 |
52 |
53 | // #include "ll/api/memory/Hook.h"
54 | // #include "mc/world/level/DimensionManager.h"
55 |
56 |
57 | // LL_AUTO_TYPE_INSTANCE_HOOK(
58 | // GetOrCreateDimension,
59 | // HookPriority::Normal,
60 | // DimensionManager,
61 | // &DimensionManager::getOrCreateDimension,
62 | // WeakRef,
63 | // DimensionType dim
64 | // ) {
65 | // std::cout << "getOrCreateDimension->" << dim.id << std::endl;
66 | // return origin(dim);
67 | // };
68 |
69 | // #include "mc/server/commands/standard/TeleportCommand.h"
70 | // #include "mc/server/commands/standard/TeleportTarget.h"
71 | // #include "mc/util/rotation_command_utils/RotationData.h"
72 | // #include "mc/world/level/dimension/VanillaDimensions.h"
73 | // LL_AUTO_TYPE_STATIC_HOOK(
74 | // TeleportCommandTest,
75 | // HookPriority::Normal,
76 | // TeleportCommand,
77 | // &TeleportCommand::computeTarget,
78 | // TeleportTarget,
79 | // ::Actor& victim,
80 | // ::Vec3 destination,
81 | // ::Vec3* facePosition,
82 | // ::DimensionType destinationDimension,
83 | // ::std::optional<::RotationCommandUtils::RotationData> const& rotationData,
84 | // int commandVersion
85 | // ) {
86 | // for(auto& item:VanillaDimensions::DimensionMap().mLeft) {
87 | // std::cout<<"Dimension name: "<" << destinationDimension << std::endl;
93 | // return origin(victim, destination, facePosition, destinationDimension, rotationData, commandVersion);
94 | // };
95 |
96 | //
97 | // LL_AUTO_TYPE_INSTANCE_HOOK(
98 | // DimensonFactory123,
99 | // HookPriority::Normal,
100 | // DimensionFactory,
101 | // "?create@DimensionFactory@@UEBA?AV?$OwnerPtr@VDimension@@@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z",
102 | // OwnerPtr,
103 | // std::string const &name) {
104 | // std::cout<<"Dimension creative->"<getOrCreateDimension(param.p1);
137 | // if (dim.expired()) {
138 | // std::cout<<"他宝贝的,销毁了"<mName<getDimensionManager();
144 | // for (auto& item: dimM.mDimensions) {
145 | // std::cout<<"Dimension have->" <"<"<()
154 | // .required("p1")
155 | // .execute(lambda);
156 | // }
157 |
158 | // #include "mc/world/level/LoadingScreenIdManager.h"
159 | // #include "ll/api/memory/Hook.h"
160 |
161 | // LL_AUTO_TYPE_INSTANCE_HOOK(
162 | // ScreenIdHookTest,
163 | // ll::memory::HookPriority::Normal,
164 | // LoadingScreenIdManager,
165 | // &LoadingScreenIdManager::getNextLoadingScreenId,
166 | // NewType<::std::optional>) {
167 | // auto result = origin();
168 | // if (result.mValue.has_value()){
169 | // std::cout<<"Test screedId: "<sky = Brightness::MAX();
30 | mSeaLevel = -61;
31 | mHasWeather = true;
32 | mDimensionBrightnessRamp = std::make_unique();
33 | mDimensionBrightnessRamp->buildBrightnessRamp();
34 | }
35 |
36 | CompoundTag FlatVillageDimension::generateNewData() { return {}; }
37 |
38 | std::unique_ptr
39 | FlatVillageDimension::createGenerator(br::worldgen::StructureSetRegistry const& structureSetRegistry) {
40 | std::unique_ptr worldGenerator;
41 | uint seed = 2024;
42 | auto& levelData = mLevel.getLevelData();
43 |
44 | // 实例化我们写的Generator类
45 | worldGenerator = std::make_unique(
46 | *this,
47 | seed,
48 | levelData.mFlatWorldOptions
49 | );
50 | // structureSetRegistry里面仅有的土径结构村庄生成需要用到,所以我们拿一下
51 | std::vector> structureMap;
52 | for (auto iter = structureSetRegistry.mStructureSets->begin(); iter != structureSetRegistry.mStructureSets->end();
53 | iter++) {
54 | structureMap.emplace_back(iter->second);
55 | }
56 | worldGenerator->mStructureFeatureRegistry->mGeneratorState->mSeed = seed;
57 | worldGenerator->mStructureFeatureRegistry->mGeneratorState->mSeed64 = LevelSeed64{seed};
58 |
59 | // 这个就相当于在这个生成器里注册结构了
60 | // VillageFeature的第二第三个参数是村庄之间的最大间隔与最小间隔
61 | worldGenerator->mStructureFeatureRegistry->mStructureFeatures->emplace_back(
62 | std::make_unique(seed, 34, 8)
63 | );
64 | // 此为必须,一些结构生成相关
65 | worldGenerator->mStructureFeatureRegistry->mGeneratorState =
66 | br::worldgen::ChunkGeneratorStructureState::createFlat(seed, worldGenerator->getBiomeSource(), structureMap);
67 |
68 | // 必须调用,初始化生成器
69 | // worldGenerator->init();
70 | return std::move(worldGenerator);
71 | }
72 |
73 | void FlatVillageDimension::upgradeLevelChunk(ChunkSource& cs, LevelChunk& lc, LevelChunk& generatedChunk) {
74 | auto blockSource = BlockSource(static_cast(mLevel), *this, cs, false, true, false);
75 | VanillaLevelChunkUpgrade::_upgradeLevelChunkViaMetaData(lc, generatedChunk, blockSource);
76 | VanillaLevelChunkUpgrade::_upgradeLevelChunkLegacy(lc, blockSource);
77 | }
78 |
79 | void FlatVillageDimension::fixWallChunk(ChunkSource& cs, LevelChunk& lc) {
80 | auto blockSource = BlockSource(static_cast(mLevel), *this, cs, false, true, false);
81 | VanillaLevelChunkUpgrade::fixWallChunk(lc, blockSource);
82 | }
83 |
84 | bool FlatVillageDimension::levelChunkNeedsUpgrade(LevelChunk const& lc) const {
85 | return VanillaLevelChunkUpgrade::levelChunkNeedsUpgrade(lc);
86 | }
87 | void FlatVillageDimension::_upgradeOldLimboEntity(CompoundTag& tag, ::LimboEntitiesVersion vers) {
88 | auto isTemplate = mLevel.getLevelData().mIsFromLockedTemplate;
89 | return VanillaLevelChunkUpgrade::upgradeOldLimboEntity(tag, vers, isTemplate);
90 | }
91 |
92 | std::unique_ptr
93 | FlatVillageDimension::_wrapStorageForVersionCompatibility(std::unique_ptr cs, ::StorageVersion /*ver*/) {
94 | return cs;
95 | }
96 |
97 | Vec3 FlatVillageDimension::translatePosAcrossDimension(Vec3 const& fromPos, DimensionType fromId) const {
98 | Vec3 topos;
99 | VanillaDimensions::convertPointBetweenDimensions(
100 | fromPos,
101 | topos,
102 | fromId,
103 | mId,
104 | mLevel.getDimensionConversionData()
105 | );
106 | constexpr auto clampVal = 32000000.0f - 128.0f;
107 |
108 | topos.x = std::clamp(topos.x, -clampVal, clampVal);
109 | topos.z = std::clamp(topos.z, -clampVal, clampVal);
110 |
111 | return topos;
112 | }
113 |
114 | short FlatVillageDimension::getCloudHeight() const { return 192; }
115 |
116 | // bool FlatVillageDimension::hasPrecipitationFog() const { return true; }
117 |
118 | } // namespace flat_village_dimension
--------------------------------------------------------------------------------
/src/test/generator/flat-gen-village/FlatVillageDimension.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "mc/world/level/dimension/Dimension.h" // 新维度类需要继承的类
4 | #include "more_dimensions/api/dimension/CustomDimensionManager.h" // 引入DimensionFactoryInfo的声明
5 |
6 | // 建议是加一个命名空间,避免与其他插件同类名的情况
7 | namespace flat_village_dimension {
8 |
9 | class FlatVillageDimension : public Dimension {
10 | public:
11 | // 建议固定这样写,DimensionFactoryInfo类里面提供了Dimension实例化的基本数据,name就是维度名,多维度是维度名区分不同维度
12 | FlatVillageDimension(std::string const& name, more_dimensions::DimensionFactoryInfo const& info);
13 |
14 | // 多维度需要的一个方法,参数是你需要处理的数据,比如种子,这里不没有这样的需要,后面说原因
15 | static CompoundTag generateNewData();
16 |
17 | // 以下六个是必须重写的函数
18 | // 维度地形的生成器,是本教程主要更改的地方
19 | std::unique_ptr createGenerator(br::worldgen::StructureSetRegistry const&) override;
20 |
21 | // 与本教程无关,按照本教程写的就行,无需留意
22 | void upgradeLevelChunk(ChunkSource& chunkSource, LevelChunk& oldLc, LevelChunk& newLc) override;
23 |
24 | // 与本教程无关,按照本教程写的就行,无需留意
25 | void fixWallChunk(ChunkSource& cs, LevelChunk& lc) override;
26 |
27 | // 与本教程无关,按照本教程写的就行,无需留意
28 | bool levelChunkNeedsUpgrade(LevelChunk const& lc) const override;
29 |
30 | // 与本教程无关,按照本教程写的就行,无需留意
31 | void _upgradeOldLimboEntity(CompoundTag& tag, ::LimboEntitiesVersion vers) override;
32 |
33 | // 与本教程无关,按照本教程写的就行,无需留意
34 | std::unique_ptr
35 | _wrapStorageForVersionCompatibility(std::unique_ptr cs, ::StorageVersion ver) override;
36 |
37 | // 当你转到这个维度时,坐标怎么转换,比如主世界与地狱的
38 | Vec3 translatePosAcrossDimension(Vec3 const& pos, DimensionType did) const override;
39 |
40 | // 云高度,默认是y128,但多维度高度范围是在y-64~320,与主世界相同,重写它,放高些
41 | short getCloudHeight() const override;
42 |
43 | // 非必要。下雨时,可视范围的更改
44 | // bool hasPrecipitationFog() const override;
45 | };
46 |
47 | } // namespace flat_village_dimension
--------------------------------------------------------------------------------
/src/test/generator/flat-gen-village/FlatVillageGenerator.cpp:
--------------------------------------------------------------------------------
1 | #include "FlatVillageGenerator.h"
2 |
3 | #include "mc/world/level/chunk/ChunkState.h"
4 | #include "test/mc/FixedBiomeSource.h"
5 |
6 | #include "mc/deps/core/math/Random.h"
7 | #include "mc/platform/threading/Mutex.h"
8 | #include "mc/util/ThreadOwner.h"
9 | #include "mc/world/level/BlockSource.h"
10 | #include "mc/world/level/ChunkPos.h"
11 | #include "mc/world/level/Level.h"
12 | #include "mc/world/level/biome/registry/BiomeRegistry.h"
13 | #include "mc/world/level/biome/registry/VanillaBiomeNames.h"
14 | #include "mc/world/level/chunk/ChunkViewSource.h"
15 | #include "mc/world/level/chunk/LevelChunk.h"
16 | #include "mc/world/level/chunk/PostprocessingManager.h"
17 | #include "mc/world/level/dimension/Dimension.h"
18 | #include "mc/world/level/levelgen/v1/ChunkLocalNoiseCache.h"
19 |
20 |
21 |
22 |
23 | namespace flat_village_generator {
24 |
25 | FlatVillageGenerator::FlatVillageGenerator(Dimension& dimension, uint seed, Json::Value const& generationOptionsJSON)
26 | : FlatWorldGenerator(dimension, seed, generationOptionsJSON) {
27 | // 值得注意的是,我们是继承的FlatWorldGenerator,后续也会使用其内部成员,所以我们需要调用FlatWorldGenerator的构造
28 | random.mRandom->mObject.mSeed = seed;
29 | mSeed = seed;
30 |
31 | mBiome = mLevel->getBiomeRegistry().lookupByHash(VanillaBiomeNames::Plains());
32 | mBiomeSource = std::make_unique(*mBiome);
33 | }
34 |
35 | bool FlatVillageGenerator::postProcess(ChunkViewSource& neighborhood) {
36 | ChunkPos chunkPos;
37 | chunkPos.x = neighborhood.mArea->mBounds.mMin->x;
38 | chunkPos.z = neighborhood.mArea->mBounds.mMin->z;
39 | auto levelChunk = neighborhood.getExistingChunk(chunkPos);
40 |
41 | auto seed = mSeed;
42 |
43 | // 必须,需要给区块上锁
44 | auto lockChunk =
45 | levelChunk->mDimension.mPostProcessingManager->tryLock(levelChunk->mPosition, neighborhood);
46 |
47 | if (!lockChunk.has_value()) {
48 | return false;
49 | }
50 | BlockSource blockSource(*mLevel, *neighborhood.mDimension, neighborhood, false, true, true);
51 | auto chunkPosL = levelChunk->mPosition;
52 | random.mRandom->mObject.mSeed = seed;
53 | auto one = 2 * (random.nextInt() / 2) + 1;
54 | auto two = 2 * (random.nextInt() / 2) + 1;
55 | random.mRandom->mObject.mSeed = seed ^ (chunkPosL->x * one + chunkPosL->z * two);
56 | // 放置结构体,如果包含有某个结构的区块,就会放置loadChunk准备的结构
57 | WorldGenerator::postProcessStructureFeatures(blockSource, random, chunkPosL->x, chunkPosL->z);
58 | // 处理其它单体结构,比如沉船,这里不是必须
59 | WorldGenerator::postProcessStructures(blockSource, random, chunkPosL->x, chunkPosL->z);
60 | // 1.21.50.10 起,有更改,需添加以下调用
61 | levelChunk->finalizePostProcessing();
62 | return true;
63 | }
64 |
65 | void FlatVillageGenerator::loadChunk(LevelChunk& levelchunk, bool forceImmediateReplacementDataLoad) {
66 | auto chunkPos = levelchunk.mPosition;
67 |
68 | auto blockPos = BlockPos(chunkPos, 0);
69 | DividedPos2d<4> dividedPos2D;
70 | dividedPos2D.x = (blockPos.x >> 31) - ((blockPos.x >> 31) - blockPos.x) / 4;
71 | dividedPos2D.z = (blockPos.z >> 31) - ((blockPos.z >> 31) - blockPos.z) / 4;
72 |
73 | // 处理其它单体结构,比如沉船,这里不是必须
74 | // WorldGenerator::preProcessStructures(getDimension(), chunkPos, getBiomeSource());
75 | // 准备要放置的结构,如果是某个某个结构的区块,就会准备结构
76 | WorldGenerator::prepareStructureFeatureBlueprints(*mDimension, chunkPos, getBiomeSource(), *this);
77 |
78 | // 这里并没有放置结构,只有单纯基本地形
79 | levelchunk.setBlockVolume(mPrototype, 0);
80 |
81 | levelchunk.recomputeHeightMap(0);
82 | ChunkLocalNoiseCache chunkLocalNoiseCache(dividedPos2D, 8);
83 | mBiomeSource->fillBiomes(levelchunk, chunkLocalNoiseCache);
84 | levelchunk.setSaved();
85 | auto loadState = ChunkState::Generating;
86 | levelchunk.mLoadState->compare_exchange_weak(loadState, ChunkState::Generated);
87 | }
88 |
89 | std::optional FlatVillageGenerator::getPreliminarySurfaceLevel(DividedPos2d<4> worldPos) const {
90 | // 超平坦的高度都是一样的,直接返回固定值即可
91 | return -61;
92 | }
93 |
94 | void FlatVillageGenerator::prepareAndComputeHeights(
95 | BlockVolume& box,
96 | ChunkPos const& chunkPos,
97 | std::vector& ZXheights,
98 | bool factorInBeardsAndShavers,
99 | int skipTopN
100 | ) {
101 | auto heightMap = mPrototype->computeHeightMap();
102 | ZXheights.assign(heightMap->begin(), heightMap->end());
103 | }
104 |
105 | void FlatVillageGenerator::prepareHeights(BlockVolume& box, ChunkPos const& chunkPos, bool factorInBeardsAndShavers) {
106 | // 在其它类型世界里,这里是需要对box进行处理,生成地形,超平坦没有这个需要,所以直接赋值即可
107 | box = mPrototype;
108 | };
109 |
110 | HashedString FlatVillageGenerator::findStructureFeatureTypeAt(BlockPos const& blockPos) {
111 | return WorldGenerator::findStructureFeatureTypeAt(blockPos);
112 | };
113 |
114 | bool FlatVillageGenerator::isStructureFeatureTypeAt(const BlockPos& blockPos, ::HashedString type) const {
115 | return WorldGenerator::isStructureFeatureTypeAt(blockPos, type);
116 | }
117 |
118 | bool FlatVillageGenerator::findNearestStructureFeature(
119 | ::HashedString type,
120 | BlockPos const& blockPos,
121 | BlockPos& blockPos1,
122 | bool mustBeInNewChunks,
123 | std::optional hash
124 | ) {
125 | return WorldGenerator::findNearestStructureFeature(type, blockPos, blockPos1, mustBeInNewChunks, hash);
126 | };
127 |
128 | void FlatVillageGenerator::garbageCollectBlueprints(buffer_span activeChunks) {
129 | return WorldGenerator::garbageCollectBlueprints(activeChunks);
130 | };
131 |
132 | } // namespace flat_village_generator
133 |
--------------------------------------------------------------------------------
/src/test/generator/flat-gen-village/FlatVillageGenerator.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "mc/deps/core/string/HashedString.h"
4 | #include "mc/deps/core/utility/buffer_span.h"
5 | #include "mc/util/Random.h"
6 | #include "mc/world/level/BlockPos.h"
7 | #include "mc/world/level/DividedPos2d.h"
8 | #include "mc/world/level/block/BlockVolume.h"
9 | #include "mc/world/level/levelgen/flat/FlatWorldGenerator.h"
10 |
11 |
12 | #include
13 |
14 | class ChunkViewSource;
15 | class LevelChunk;
16 | class ChunkPos;
17 |
18 | // 依旧建议加一个命名空间避免冲突
19 | namespace flat_village_generator {
20 |
21 | // 我们直接继承原版超平坦这个类来写会方便很多
22 | class FlatVillageGenerator : public FlatWorldGenerator {
23 | public:
24 | Random random; // 这个是BDS生成随机数有关的类
25 | uint mSeed;
26 |
27 | // 后面的generationOptionsJSON虽然用不上,但FlatWorldGenerator的实例化需要
28 | FlatVillageGenerator(Dimension& dimension, uint seed, Json::Value const& generationOptionsJSON);
29 |
30 | // 这里是处理结构放置相关的,包括地物,结构,地形
31 | bool postProcess(ChunkViewSource& neighborhood);
32 |
33 | // 这里是初始处理新的单区块的方块生成相关的,比如一些大量的方块(石头,泥土)
34 | void loadChunk(LevelChunk& levelchunk, bool forceImmediateReplacementDataLoad);
35 |
36 | // 判断某个点在哪个结构范围里
37 | HashedString findStructureFeatureTypeAt(BlockPos const&);
38 |
39 | // 判断某个点是否在某个结构范围里
40 | bool isStructureFeatureTypeAt(BlockPos const&, ::HashedString) const;
41 |
42 | // 这里是获取某个坐标的最高方块
43 | std::optional getPreliminarySurfaceLevel(DividedPos2d<4> worldPos) const;
44 |
45 | // 如意,以一个坐标,在一定范围内查找某个类型的结构
46 | bool findNearestStructureFeature(::HashedString, BlockPos const&, BlockPos&, bool, std::optional);
47 |
48 | // 无需在意,照写就行
49 | void garbageCollectBlueprints(buffer_span);
50 |
51 | // 处理地形
52 | void prepareHeights(BlockVolume& box, ChunkPos const& chunkPos, bool factorInBeardsAndShavers);
53 |
54 | // 与prepareHeights一样,不过与之不同的是,还会计算单区块内的高度
55 | void prepareAndComputeHeights(
56 | BlockVolume& box,
57 | ChunkPos const& chunkPos,
58 | std::vector& ZXheights,
59 | bool factorInBeardsAndShavers,
60 | int skipTopN
61 | );
62 |
63 | // 可选,可以不写
64 | BlockPos findSpawnPosition() const { return BlockPos{0, 16, 0}; };
65 | };
66 |
67 | } // namespace flat_village_generator
--------------------------------------------------------------------------------
/src/test/generator/generator-custom-structure/CustomStructure.cpp:
--------------------------------------------------------------------------------
1 | #include "CustomStructure.h"
2 |
3 | #include "ll/api/memory/Hook.h"
4 |
5 | #include "mc/deps/core/threading/WorkerPool.h"
6 | #include "mc/resources/BaseGameVersion.h"
7 | #include "mc/world/level/block/VanillaBlockTypeIds.h"
8 | #include "mc/world/level/block/registry/BlockTypeRegistry.h"
9 | #include "mc/world/level/levelgen/feature/registry/FeatureRegistry.h"
10 | #include "mc/world/level/levelgen/structure/Projection.h"
11 | #include "mc/world/level/levelgen/structure/StructureManager.h"
12 | #include "mc/world/level/levelgen/structure/registry/JigsawStructureBlockRulesRegistry.h"
13 | #include "mc/world/level/levelgen/structure/registry/JigsawStructureElementRegistry.h"
14 | #include "mc/world/level/levelgen/structure/registry/JigsawStructureRegistry.h"
15 | #include "mc/world/level/levelgen/structure/registry/StructurePools.h"
16 | #include "mc/world/level/levelgen/structure/structurepools/StructurePoolBlockPredicateAlwaysTrue.h"
17 | #include "mc/world/level/levelgen/structure/structurepools/StructurePoolElement.h"
18 | #include "mc/world/level/levelgen/structure/structurepools/StructureTemplatePool.h"
19 | #include "mc/world/level/storage/Experiments.h"
20 | #include "test/mc/StructurePoolBlockPredicateBlockMatchRandom.h"
21 | #include "test/mc/StructurePoolBlockRule.h"
22 |
23 | // #include "mc/world/level/storage/Experiments.h"
24 | // #include "test/mc/StructureTemplateRegistrationContext.h"
25 | // #include "test/mc/WeightedStructureTemplateRegistration.h"
26 |
27 | // #include
28 | #include
29 |
30 | namespace custom_structure {
31 |
32 | void CustomJigsawStructureBlockRules::initialize(JigsawStructureRegistry& registry) {
33 | auto& jigsawBlockRulesRegistry = registry.mJigsawBlockRulesRegistry;
34 |
35 | // input_predicate block
36 | auto& stoneBricks = BlockTypeRegistry::getDefaultBlockState(VanillaBlockTypeIds::StoneBricks());
37 |
38 | // output_state blocks
39 | auto& mossyStoneBricks = BlockTypeRegistry::getDefaultBlockState(VanillaBlockTypeIds::MossyStoneBricks());
40 | auto& crackedStoneBricks = BlockTypeRegistry::getDefaultBlockState(VanillaBlockTypeIds::CrackedStoneBricks());
41 | auto& cobblestone = BlockTypeRegistry::getDefaultBlockState(VanillaBlockTypeIds::Cobblestone());
42 |
43 | // input_predicate
44 | std::unique_ptr sourceBlock_pro1 =
45 | std::make_unique(stoneBricks, 0.2);
46 | std::unique_ptr sourceBlock_pro2 =
47 | std::make_unique(stoneBricks, 0.1);
48 |
49 | std::unique_ptr targetBlock =
50 | std::make_unique();
51 |
52 | auto blockRule_1 = std::make_unique(
53 | std::move(sourceBlock_pro1),
54 | std::move(targetBlock),
55 | &mossyStoneBricks
56 | );
57 | auto blockRule_2 = std::make_unique(
58 | std::move(sourceBlock_pro1),
59 | std::move(targetBlock),
60 | &crackedStoneBricks
61 | );
62 | auto blockRule_3 =
63 | std::make_unique(std::move(sourceBlock_pro2), std::move(targetBlock), &cobblestone);
64 |
65 |
66 | auto ruleList = std::make_unique>>();
67 |
68 | ruleList->emplace_back(std::move(blockRule_1));
69 | ruleList->emplace_back(std::move(blockRule_2));
70 | ruleList->emplace_back(std::move(blockRule_3));
71 |
72 | jigsawBlockRulesRegistry->registerBlockRules("mike:stone_brick_replacement", std::move(ruleList));
73 |
74 | // br::worldgen::processors::BlockRules::Test block_test;
75 | // block_test.mData = br::worldgen::processors::BlockRules::RandomBlockMatch(stoneBricks.mLegacyBlock.get(), 0.2);
76 |
77 | // auto blockRule_1 = br::worldgen::processors::RuleSet::from(block_test, mossyStoneBricks);
78 | // auto blockRule_2 = br::worldgen::processors::RuleSet::from(block_test, crackedStoneBricks);
79 | // auto blockRule_3 = br::worldgen::processors::RuleSet::from(block_test, cobblestone);
80 |
81 | // auto ruleList = br::worldgen::StructureProcessor::Rule({blockRule_1, blockRule_2, blockRule_3});
82 | // auto prot = br::worldgen::StructureProcessor::Protected(VanillaBlockTypeIds::RedstoneBlock());
83 | // jigsawBlockRulesRegistry->record("mike:stone_brick_replacement", {ruleList, prot});
84 | }
85 |
86 | void CustomJigsawStructureElements::initialize(
87 | gsl::not_null> manager,
88 | FeatureRegistry& featureRegistry,
89 | JigsawStructureRegistry& jigsawRegistry
90 | ) {
91 | auto& jigsawBlockRulesRegistry = jigsawRegistry.mJigsawBlockRulesRegistry;
92 | auto& jigsawStructureElementRegistry = jigsawRegistry.mJigsawElementRegistry;
93 | auto ruleList = jigsawBlockRulesRegistry->lookupByName("mike:stone_brick_replacement");
94 |
95 | // 每一个结构nbt文件都得这样注册进来,多个nbt结构文件的可以使用同一个Block Rule
96 | // mike:5x5int
97 | jigsawStructureElementRegistry->registerStructureElement(
98 | "mike:5x5intb",
99 | std::make_unique(
100 | manager,
101 | "custom/beds5x5int",
102 | ruleList,
103 | nullptr,
104 | nullptr,
105 | Projection::TerrainMatching,
106 | PostProcessSettings::Beard
107 | )
108 | );
109 | jigsawStructureElementRegistry->registerStructureElement(
110 | "mike:5x5intc",
111 | std::make_unique(
112 | manager,
113 | "custom/chestcarpet5x5int",
114 | ruleList,
115 | nullptr,
116 | nullptr,
117 | Projection::TerrainMatching,
118 | PostProcessSettings::Beard
119 | )
120 | );
121 | jigsawStructureElementRegistry->registerStructureElement(
122 | "mike:5x5intk",
123 | std::make_unique(
124 | manager,
125 | "custom/kitchen5x5int",
126 | ruleList,
127 | nullptr,
128 | nullptr,
129 | Projection::TerrainMatching,
130 | PostProcessSettings::Beard
131 | )
132 | );
133 |
134 | // mike:ew7x4
135 | jigsawStructureElementRegistry->registerStructureElement(
136 | "mike:ew7x4h",
137 | std::make_unique(
138 | manager,
139 | "custom/ewhall",
140 | ruleList,
141 | nullptr,
142 | nullptr,
143 | Projection::TerrainMatching,
144 | PostProcessSettings::Beard
145 | )
146 | );
147 | jigsawStructureElementRegistry->registerStructureElement(
148 | "mike:ew7x4r",
149 | std::make_unique(
150 | manager,
151 | "custom/21room",
152 | ruleList,
153 | nullptr,
154 | nullptr,
155 | Projection::TerrainMatching,
156 | PostProcessSettings::Beard
157 | )
158 | );
159 |
160 | // mike:ns7x4
161 | jigsawStructureElementRegistry->registerStructureElement(
162 | "mike:ns7x4h",
163 | std::make_unique(
164 | manager,
165 | "custom/nshall",
166 | ruleList,
167 | nullptr,
168 | nullptr,
169 | Projection::TerrainMatching,
170 | PostProcessSettings::Beard
171 | )
172 | );
173 | jigsawStructureElementRegistry->registerStructureElement(
174 | "mike:ns7x4r",
175 | std::make_unique(
176 | manager,
177 | "custom/21room",
178 | ruleList,
179 | nullptr,
180 | nullptr,
181 | Projection::TerrainMatching,
182 | PostProcessSettings::Beard
183 | )
184 | );
185 |
186 | // mike:ewcap
187 | jigsawStructureElementRegistry->registerStructureElement(
188 | "mike:ewcap",
189 | std::make_unique(
190 | manager,
191 | "custom/ewcap",
192 | ruleList,
193 | nullptr,
194 | nullptr,
195 | Projection::TerrainMatching,
196 | PostProcessSettings::Beard
197 | )
198 | );
199 |
200 | // mike:nacap
201 | jigsawStructureElementRegistry->registerStructureElement(
202 | "mike:nscap",
203 | std::make_unique(
204 | manager,
205 | "custom/nscap",
206 | ruleList,
207 | nullptr,
208 | nullptr,
209 | Projection::TerrainMatching,
210 | PostProcessSettings::Beard
211 | )
212 | );
213 | }
214 |
215 | void CustomJigsawStructure::initialize(
216 | Bedrock::NotNullNonOwnerPtr<::StructureManager> manager,
217 | FeatureRegistry& featureRegistry,
218 | JigsawStructureRegistry& registry,
219 | BaseGameVersion const& baseGameVersion,
220 | Experiments const& experiments
221 | ) {
222 | CustomJigsawStructureBlockRules::initialize(registry);
223 | CustomJigsawStructureElements::initialize(manager, featureRegistry, registry);
224 | auto& jigsawStructureElementRegistry = registry.mJigsawElementRegistry;
225 |
226 | // auto ruleList = registry.mJigsawBlockRulesRegistry->lookupByName("mike:stone_brick_replacement");
227 |
228 | std::vector> templates_5x5{
229 | {jigsawStructureElementRegistry->lookupByName("mike:5x5intb"), 4},
230 | {jigsawStructureElementRegistry->lookupByName("mike:5x5intc"), 1},
231 | {jigsawStructureElementRegistry->lookupByName("mike:5x5intk"), 1}
232 | };
233 | std::vector> templates_ew{
234 | {jigsawStructureElementRegistry->lookupByName("mike:ew7x4h"), 4},
235 | {jigsawStructureElementRegistry->lookupByName("mike:ew7x4r"), 1}
236 | };
237 | std::vector> templates_ns{
238 | {jigsawStructureElementRegistry->lookupByName("mike:ns7x4h"), 4},
239 | {jigsawStructureElementRegistry->lookupByName("mike:ns7x4r"), 1}
240 | };
241 | std::vector> templates_ewcap{
242 | {jigsawStructureElementRegistry->lookupByName("mike:ewcap"), 4}
243 | };
244 | std::vector> templates_nscap{
245 | {jigsawStructureElementRegistry->lookupByName("mike:nscap"), 4}
246 | };
247 |
248 | registry.registerPool(std::make_unique("mike:5x5int", "empty", templates_5x5));
249 | registry.registerPool(std::make_unique("mike:ew7x4", "mike:ewcap", templates_ew));
250 | registry.registerPool(std::make_unique("mike:ns7x4", "mike:nscap", templates_ns));
251 | registry.registerPool(std::make_unique("mike:ewcap", "empty", templates_ewcap));
252 | registry.registerPool(std::make_unique("mike:nscap", "empty", templates_nscap));
253 |
254 | // StructureTemplateRegistrationContext
255 | // context{manager, jigsawStructureElementRegistry, featureRegistry, baseGameVersion, experiments};
256 |
257 | // std::initializer_list templates_5x5{
258 | // {StructurePoolElement::single("mike:5x5intb", ruleList, {}, {}), 4},
259 | // {StructurePoolElement::single("mike:5x5intc", ruleList, {}, {}), 1},
260 | // {StructurePoolElement::single("mike:5x5intk", ruleList, {}, {}), 1}
261 | // };
262 | // std::initializer_list templates_ew{
263 | // {StructurePoolElement::single("mike:ew7x4h", ruleList, {}, {}), 4},
264 | // {StructurePoolElement::single("mike:ew7x4r", ruleList, {}, {}), 1}
265 | // };
266 | // std::initializer_list templates_ns{
267 | // {StructurePoolElement::single("mike:ns7x4h", ruleList, {}, {}), 4},
268 | // {StructurePoolElement::single("mike:ns7x4r", ruleList, {}, {}), 1}
269 | // };
270 | // std::initializer_list templates_ewcap{
271 | // {StructurePoolElement::single("mike:ewcap", ruleList, {}, {}), 4}
272 | // };
273 | // std::initializer_list templates_nscap{
274 | // {StructurePoolElement::single("mike:nscap", ruleList, {}, {}), 4}
275 | // };
276 |
277 | // registry.registerPool(
278 | // std::make_unique(context, "mike:5x5int", "empty", Projection::Invalid, templates_5x5)
279 | // );
280 | // registry.registerPool(
281 | // std::make_unique(context, "mike:ew7x4", "mike:ewcap", Projection::Invalid, templates_ew)
282 | // );
283 | // registry.registerPool(
284 | // std::make_unique(context, "mike:ns7x4", "mike:nscap", Projection::Invalid, templates_ns)
285 | // );
286 | // registry.registerPool(
287 | // std::make_unique(context, "mike:ewcap", "empty", Projection::Invalid, templates_ewcap)
288 | // );
289 | // registry.registerPool(
290 | // std::make_unique(context, "mike:nscap", "empty", Projection::Invalid, templates_nscap)
291 | // );
292 | }
293 |
294 | } // namespace custom_structure
295 |
296 | LL_AUTO_TYPE_STATIC_HOOK(
297 | InitStructure,
298 | HookPriority::Normal,
299 | br::worldgen::StructurePools,
300 | br::worldgen::StructurePools::bootstrap,
301 | void,
302 | Bedrock::NotNullNonOwnerPtr structureManager,
303 | FeatureRegistry& featureRegistry,
304 | JigsawStructureRegistry& jigsawStructureRegistry,
305 | BaseGameVersion const& baseGameVersion,
306 | Experiments const& experiments
307 | ) {
308 | custom_structure::CustomJigsawStructure::initialize(
309 | structureManager,
310 | featureRegistry,
311 | jigsawStructureRegistry,
312 | baseGameVersion,
313 | experiments
314 | );
315 | origin(structureManager, featureRegistry, jigsawStructureRegistry, baseGameVersion, experiments);
316 | return;
317 | };
--------------------------------------------------------------------------------
/src/test/generator/generator-custom-structure/CustomStructure.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "mc/deps/core/utility/NonOwnerPointer.h"
4 |
5 | #include "gsl/pointers"
6 |
7 | class FeatureRegistry;
8 | class JigsawStructureRegistry;
9 | class WorkerPool;
10 | class StructureManager;
11 | class BaseGameVersion;
12 | class Experiments;
13 |
14 | namespace custom_structure {
15 |
16 | namespace CustomJigsawStructure {
17 |
18 | // 总注册初始化函数
19 | void initialize(
20 | Bedrock::NotNullNonOwnerPtr<::StructureManager> manager,
21 | FeatureRegistry& featureRegistry,
22 | JigsawStructureRegistry& registry,
23 | BaseGameVersion const& baseGameVersion,
24 | Experiments const& experiments
25 | );
26 |
27 | } // namespace CustomJigsawStructure
28 |
29 | namespace CustomJigsawStructureBlockRules {
30 |
31 | void initialize(JigsawStructureRegistry& registry);
32 |
33 | }
34 |
35 | namespace CustomJigsawStructureElements {
36 |
37 | void initialize(
38 | gsl::not_null> manager,
39 | FeatureRegistry& featureRegistry,
40 | JigsawStructureRegistry& jigsawRegistry
41 | );
42 |
43 | }
44 |
45 | } // namespace custom_structure
46 |
--------------------------------------------------------------------------------
/src/test/generator/generator-custom-structure/README.md:
--------------------------------------------------------------------------------
1 | ## You need to copy the files in the `structure-files` folder to this path
2 |
3 | ```
4 | behavior_packs\vanilla\structures\
5 | ```
--------------------------------------------------------------------------------
/src/test/generator/generator-custom-structure/dimension/CustomStructureDimension.cpp:
--------------------------------------------------------------------------------
1 | #include "CustomStructureDimension.h"
2 |
3 | #include "test/generator/generator-custom-structure/generator/CustomStructureGenerator.h"
4 | #include "test/generator/generator-custom-structure/structure/CustomStructureFeature.h"
5 |
6 | #include "mc/common/Brightness.h"
7 | #include "mc/common/BrightnessPair.h"
8 | #include "mc/deps/core/math/Vec3.h"
9 | #include "mc/world/level/BlockSource.h"
10 | #include "mc/world/level/DimensionConversionData.h"
11 | #include "mc/world/level/Level.h"
12 | #include "mc/world/level/LevelSeed64.h"
13 | #include "mc/world/level/chunk/vanilla_level_chunk_upgrade/VanillaLevelChunkUpgrade.h"
14 | #include "mc/world/level/dimension/DimensionBrightnessRamp.h"
15 | #include "mc/world/level/dimension/DimensionHeightRange.h"
16 | #include "mc/world/level/dimension/OverworldBrightnessRamp.h"
17 | #include "mc/world/level/dimension/VanillaDimensions.h"
18 | #include "mc/world/level/levelgen/structure/StructureFeatureRegistry.h"
19 | #include "mc/world/level/levelgen/structure/VillageFeature.h"
20 | #include "mc/world/level/levelgen/structure/registry/StructureSetRegistry.h"
21 | #include "mc/world/level/levelgen/v2/ChunkGeneratorStructureState.h"
22 | #include "mc/world/level/storage/LevelData.h"
23 |
24 |
25 | namespace custom_structure_dimension {
26 |
27 | CustomStructureDimension::CustomStructureDimension(
28 | std::string const& name,
29 | more_dimensions::DimensionFactoryInfo const& info
30 | )
31 | : Dimension(info.level, info.dimId, {-64, 320}, info.scheduler, name) {
32 | // 这里说明下,在DimensionFactoryInfo里面more-dimensions会提供维度id,请不要使用固定维度id,避免id冲突导致维度注册出现异常
33 | mDefaultBrightness->sky = Brightness::MAX();
34 | mSeaLevel = -61;
35 | mHasWeather = true;
36 | mDimensionBrightnessRamp = std::make_unique();
37 | mDimensionBrightnessRamp->buildBrightnessRamp();
38 | }
39 |
40 | CompoundTag CustomStructureDimension::generateNewData() { return {}; }
41 |
42 | std::unique_ptr
43 | CustomStructureDimension::createGenerator(br::worldgen::StructureSetRegistry const& structureSetRegistry) {
44 | std::unique_ptr worldGenerator;
45 | uint seed = 2025;
46 | auto& levelData = mLevel.getLevelData();
47 |
48 | // 实例化我们写的Generator类
49 | worldGenerator = std::make_unique(
50 | *this,
51 | seed,
52 | levelData.mFlatWorldOptions
53 | );
54 | // structureSetRegistry里面仅有的土径结构村庄生成需要用到,所以我们拿一下
55 | std::vector> structureMap;
56 | for (auto iter = structureSetRegistry.mStructureSets->begin(); iter != structureSetRegistry.mStructureSets->end(); iter++) {
57 | structureMap.emplace_back(iter->second);
58 | }
59 | worldGenerator->mStructureFeatureRegistry->mGeneratorState->mSeed = seed;
60 | worldGenerator->mStructureFeatureRegistry->mGeneratorState->mSeed64 =
61 | LevelSeed64(seed);
62 |
63 | // 这个就相当于在这个生成器里注册结构了
64 | // VillageFeature的第二第三个参数是村庄之间的最大间隔与最小间隔
65 | worldGenerator->mStructureFeatureRegistry->mStructureFeatures->emplace_back(
66 | std::make_unique(seed, 34, 8)
67 | );
68 | worldGenerator->mStructureFeatureRegistry->mStructureFeatures->emplace_back(
69 | std::make_unique(seed, 8, 34)
70 | );
71 | // 此为必须,一些结构生成相关
72 | worldGenerator->mStructureFeatureRegistry->mGeneratorState =
73 | br::worldgen::ChunkGeneratorStructureState::createFlat(seed, worldGenerator->getBiomeSource(), structureMap);
74 |
75 | return std::move(worldGenerator);
76 | }
77 |
78 | void CustomStructureDimension::upgradeLevelChunk(ChunkSource& cs, LevelChunk& lc, LevelChunk& generatedChunk) {
79 | auto blockSource = BlockSource(static_cast(mLevel), *this, cs, false, true, false);
80 | VanillaLevelChunkUpgrade::_upgradeLevelChunkViaMetaData(lc, generatedChunk, blockSource);
81 | VanillaLevelChunkUpgrade::_upgradeLevelChunkLegacy(lc, blockSource);
82 | }
83 |
84 | void CustomStructureDimension::fixWallChunk(ChunkSource& cs, LevelChunk& lc) {
85 | auto blockSource = BlockSource(static_cast(mLevel), *this, cs, false, true, false);
86 | VanillaLevelChunkUpgrade::fixWallChunk(lc, blockSource);
87 | }
88 |
89 | bool CustomStructureDimension::levelChunkNeedsUpgrade(LevelChunk const& lc) const {
90 | return VanillaLevelChunkUpgrade::levelChunkNeedsUpgrade(lc);
91 | }
92 | void CustomStructureDimension::_upgradeOldLimboEntity(CompoundTag& tag, ::LimboEntitiesVersion vers) {
93 | auto isTemplate = mLevel.getLevelData().mIsFromLockedTemplate;
94 | return VanillaLevelChunkUpgrade::upgradeOldLimboEntity(tag, vers, isTemplate);
95 | }
96 |
97 | std::unique_ptr CustomStructureDimension::
98 | _wrapStorageForVersionCompatibility(std::unique_ptr cs, ::StorageVersion /*ver*/) {
99 | return cs;
100 | }
101 |
102 | Vec3 CustomStructureDimension::translatePosAcrossDimension(Vec3 const& fromPos, DimensionType fromId) const {
103 | Vec3 topos;
104 | VanillaDimensions::convertPointBetweenDimensions(
105 | fromPos,
106 | topos,
107 | fromId,
108 | mId,
109 | mLevel.getDimensionConversionData()
110 | );
111 | constexpr auto clampVal = 32000000.0f - 128.0f;
112 |
113 | topos.x = std::clamp(topos.x, -clampVal, clampVal);
114 | topos.z = std::clamp(topos.z, -clampVal, clampVal);
115 |
116 | return topos;
117 | }
118 |
119 | short CustomStructureDimension::getCloudHeight() const { return 192; }
120 |
121 | // bool CustomStructureDimension::hasPrecipitationFog() const { return true; }
122 |
123 | } // namespace custom_structure_dimension
--------------------------------------------------------------------------------
/src/test/generator/generator-custom-structure/dimension/CustomStructureDimension.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "mc/world/level/dimension/Dimension.h" // 新维度类需要继承的类
4 | #include "more_dimensions/api/dimension/CustomDimensionManager.h" // 引入DimensionFactoryInfo的声明
5 |
6 | // 建议是加一个命名空间,避免与其他插件同类名的情况
7 | namespace custom_structure_dimension {
8 |
9 | class CustomStructureDimension : public Dimension {
10 | public:
11 | // 建议固定这样写,DimensionFactoryInfo类里面提供了Dimension实例化的基本数据,name就是维度名,多维度是维度名区分不同维度
12 | CustomStructureDimension(std::string const& name, more_dimensions::DimensionFactoryInfo const& info);
13 |
14 | // 多维度需要的一个方法,参数是你需要处理的数据,比如种子,这里不没有这样的需要,后面说原因
15 | static CompoundTag generateNewData();
16 |
17 | // 以下六个是必须重写的函数
18 | // 维度地形的生成器,是本教程主要更改的地方
19 | std::unique_ptr createGenerator(br::worldgen::StructureSetRegistry const&) override;
20 |
21 | // 与本教程无关,按照本教程写的就行,无需留意
22 | void upgradeLevelChunk(ChunkSource& chunkSource, LevelChunk& oldLc, LevelChunk& newLc) override;
23 |
24 | // 与本教程无关,按照本教程写的就行,无需留意
25 | void fixWallChunk(ChunkSource& cs, LevelChunk& lc) override;
26 |
27 | // 与本教程无关,按照本教程写的就行,无需留意
28 | bool levelChunkNeedsUpgrade(LevelChunk const& lc) const override;
29 |
30 | // 与本教程无关,按照本教程写的就行,无需留意
31 | void _upgradeOldLimboEntity(CompoundTag& tag, ::LimboEntitiesVersion vers) override;
32 |
33 | // 与本教程无关,按照本教程写的就行,无需留意
34 | std::unique_ptr
35 | _wrapStorageForVersionCompatibility(std::unique_ptr cs, ::StorageVersion ver) override;
36 |
37 | // 当你转到这个维度时,坐标怎么转换,比如主世界与地狱的
38 | Vec3 translatePosAcrossDimension(Vec3 const& pos, DimensionType did) const override;
39 |
40 | // 云高度,默认是y128,但多维度高度范围是在y-64~320,与主世界相同,重写它,放高些
41 | short getCloudHeight() const override;
42 |
43 | // 非必要。下雨时,可视范围的更改
44 | // bool hasPrecipitationFog() const override;
45 | };
46 |
47 | } // namespace custom_structure_dimension
--------------------------------------------------------------------------------
/src/test/generator/generator-custom-structure/generator/CustomStructureGenerator.cpp:
--------------------------------------------------------------------------------
1 | #include "CustomStructureGenerator.h"
2 |
3 | #include "test/mc/FixedBiomeSource.h"
4 |
5 | #include "mc/deps/core/math/Random.h"
6 | #include "mc/platform/threading/Mutex.h"
7 | #include "mc/util/ThreadOwner.h"
8 | #include "mc/world/level/BlockSource.h"
9 | #include "mc/world/level/ChunkPos.h"
10 | #include "mc/world/level/Level.h"
11 | #include "mc/world/level/biome/registry/BiomeRegistry.h"
12 | #include "mc/world/level/biome/registry/VanillaBiomeNames.h"
13 | #include "mc/world/level/chunk/ChunkViewSource.h"
14 | #include "mc/world/level/chunk/LevelChunk.h"
15 | #include "mc/world/level/chunk/PostprocessingManager.h"
16 | #include "mc/world/level/dimension/Dimension.h"
17 | #include "mc/world/level/levelgen/v1/ChunkLocalNoiseCache.h"
18 |
19 |
20 | namespace custom_structure_generator {
21 |
22 | CustomStructureGenerator::CustomStructureGenerator(
23 | Dimension& dimension,
24 | uint seed,
25 | Json::Value const& generationOptionsJSON
26 | )
27 | : FlatWorldGenerator(dimension, seed, generationOptionsJSON) {
28 | // 值得注意的是,我们是继承的FlatWorldGenerator,后续也会使用其内部成员,所以我们需要调用FlatWorldGenerator的构造
29 | random.mRandom->mObject.mSeed = seed;
30 | mSeed = seed;
31 |
32 | mBiome = mLevel->getBiomeRegistry().lookupByHash(VanillaBiomeNames::Plains());
33 | mBiomeSource = std::make_unique(*mBiome);
34 | }
35 |
36 | bool CustomStructureGenerator::postProcess(ChunkViewSource& neighborhood) {
37 | ChunkPos chunkPos;
38 | chunkPos.x = neighborhood.mArea->mBounds.mMin->x;
39 | chunkPos.z = neighborhood.mArea->mBounds.mMin->z;
40 | auto levelChunk = neighborhood.getExistingChunk(chunkPos);
41 |
42 | auto seed = mSeed;
43 |
44 | // 必须,需要给区块上锁
45 | auto lockChunk =
46 | levelChunk->mDimension.mPostProcessingManager->tryLock(levelChunk->mPosition, neighborhood);
47 |
48 | if (!lockChunk) {
49 | return false;
50 | }
51 | BlockSource blockSource(*mLevel, *neighborhood.mDimension, neighborhood, false, true, true);
52 | auto chunkPosL = levelChunk->mPosition;
53 | random.mRandom->mObject.mSeed = seed;
54 | auto one = 2 * (random.nextInt() / 2) + 1;
55 | auto two = 2 * (random.nextInt() / 2) + 1;
56 | random.mRandom->mObject.mSeed = seed ^ (chunkPosL->x * one + chunkPosL->z * two);
57 | // 放置结构体,如果包含有某个结构的区块,就会放置loadChunk准备的结构
58 | WorldGenerator::postProcessStructureFeatures(blockSource, random, chunkPosL->x, chunkPosL->z);
59 | // 处理其它单体结构,比如沉船,这里不是必须
60 | WorldGenerator::postProcessStructures(blockSource, random, chunkPosL->x, chunkPosL->z);
61 | levelChunk->finalizePostProcessing();
62 | return true;
63 | }
64 |
65 | void CustomStructureGenerator::loadChunk(LevelChunk& levelchunk, bool forceImmediateReplacementDataLoad) {
66 | auto chunkPos = levelchunk.mPosition;
67 |
68 | auto blockPos = BlockPos(chunkPos, 0);
69 | DividedPos2d<4> dividedPos2D;
70 | dividedPos2D.x = (blockPos.x >> 31) - ((blockPos.x >> 31) - blockPos.x) / 4;
71 | dividedPos2D.z = (blockPos.z >> 31) - ((blockPos.z >> 31) - blockPos.z) / 4;
72 |
73 | // 处理其它单体结构,比如沉船,这里不是必须
74 | // WorldGenerator::preProcessStructures(getDimension(), chunkPos, getBiomeSource());
75 | // 准备要放置的结构,如果是某个某个结构的区块,就会准备结构
76 | WorldGenerator::prepareStructureFeatureBlueprints(*mDimension, chunkPos, getBiomeSource(), *this);
77 |
78 | // 这里并没有放置结构,只有单纯基本地形
79 | levelchunk.setBlockVolume(mPrototype, 0);
80 |
81 | levelchunk.recomputeHeightMap(0);
82 | ChunkLocalNoiseCache chunkLocalNoiseCache(dividedPos2D, 8);
83 | mBiomeSource->fillBiomes(levelchunk, chunkLocalNoiseCache);
84 | levelchunk.setSaved();
85 | auto loadState = ChunkState::Generating;
86 | levelchunk.mLoadState->compare_exchange_weak(loadState, ChunkState::Generated);
87 | }
88 |
89 | std::optional CustomStructureGenerator::getPreliminarySurfaceLevel(DividedPos2d<4> worldPos) const {
90 | // 超平坦的高度都是一样的,直接返回固定值即可
91 | return -61;
92 | }
93 |
94 | void CustomStructureGenerator::prepareAndComputeHeights(
95 | BlockVolume& box,
96 | ChunkPos const& chunkPos,
97 | std::vector& ZXheights,
98 | bool factorInBeardsAndShavers,
99 | int skipTopN
100 | ) {
101 | auto heightMap = mPrototype->computeHeightMap();
102 | ZXheights.assign(heightMap->begin(), heightMap->end());
103 | }
104 |
105 | void CustomStructureGenerator::prepareHeights(
106 | BlockVolume& box,
107 | ChunkPos const& chunkPos,
108 | bool factorInBeardsAndShavers
109 | ) {
110 | // 在其它类型世界里,这里是需要对box进行处理,生成地形,超平坦没有这个需要,所以直接赋值即可
111 | box = mPrototype;
112 | };
113 |
114 | HashedString CustomStructureGenerator::findStructureFeatureTypeAt(BlockPos const& blockPos) {
115 | return WorldGenerator::findStructureFeatureTypeAt(blockPos);
116 | };
117 |
118 | bool CustomStructureGenerator::isStructureFeatureTypeAt(const BlockPos& blockPos, ::HashedString type) const {
119 | return WorldGenerator::isStructureFeatureTypeAt(blockPos, type);
120 | }
121 |
122 | bool CustomStructureGenerator::findNearestStructureFeature(
123 | ::HashedString type,
124 | BlockPos const& blockPos,
125 | BlockPos& blockPos1,
126 | bool mustBeInNewChunks,
127 | std::optional hash
128 | ) {
129 | return WorldGenerator::findNearestStructureFeature(type, blockPos, blockPos1, mustBeInNewChunks, hash);
130 | };
131 |
132 | void CustomStructureGenerator::garbageCollectBlueprints(buffer_span activeChunks) {
133 | return WorldGenerator::garbageCollectBlueprints(activeChunks);
134 | };
135 |
136 | } // namespace custom_structure_generator
137 |
--------------------------------------------------------------------------------
/src/test/generator/generator-custom-structure/generator/CustomStructureGenerator.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "mc/deps/core/string/HashedString.h"
4 | #include "mc/deps/core/utility/buffer_span.h"
5 | #include "mc/util/Random.h"
6 | #include "mc/world/level/BlockPos.h"
7 | #include "mc/world/level/DividedPos2d.h"
8 | #include "mc/world/level/block/BlockVolume.h"
9 | #include "mc/world/level/levelgen/flat/FlatWorldGenerator.h"
10 |
11 |
12 | #include
13 |
14 | class ChunkViewSource;
15 | class LevelChunk;
16 | class ChunkPos;
17 |
18 | // 依旧建议加一个命名空间避免冲突
19 | namespace custom_structure_generator {
20 |
21 | // 我们直接继承原版超平坦这个类来写会方便很多
22 | class CustomStructureGenerator : public FlatWorldGenerator {
23 | public:
24 | Random random; // 这个是BDS生成随机数有关的类
25 | uint mSeed;
26 |
27 | // 后面的generationOptionsJSON虽然用不上,但FlatWorldGenerator的实例化需要
28 | CustomStructureGenerator(Dimension& dimension, uint seed, Json::Value const& generationOptionsJSON);
29 |
30 | // 这里是处理结构放置相关的,包括地物,结构,地形
31 | bool postProcess(ChunkViewSource& neighborhood);
32 |
33 | // 这里是初始处理新的单区块的方块生成相关的,比如一些大量的方块(石头,泥土)
34 | void loadChunk(LevelChunk& levelchunk, bool forceImmediateReplacementDataLoad);
35 |
36 | // 判断某个点在哪个结构范围里
37 | HashedString findStructureFeatureTypeAt(BlockPos const&);
38 |
39 | // 判断某个点是否在某个结构范围里
40 | bool isStructureFeatureTypeAt(BlockPos const&, ::HashedString) const;
41 |
42 | // 这里是获取某个坐标的最高方块
43 | std::optional getPreliminarySurfaceLevel(DividedPos2d<4> worldPos) const;
44 |
45 | // 如意,以一个坐标,在一定范围内查找某个类型的结构
46 | bool
47 | findNearestStructureFeature(::HashedString, BlockPos const&, BlockPos&, bool, std::optional);
48 |
49 | // 无需在意,照写就行
50 | void garbageCollectBlueprints(buffer_span);
51 |
52 | // 处理地形
53 | void prepareHeights(BlockVolume& box, ChunkPos const& chunkPos, bool factorInBeardsAndShavers);
54 |
55 | // 与prepareHeights一样,不过与之不同的是,还会计算单区块内的高度
56 | void prepareAndComputeHeights(
57 | BlockVolume& box,
58 | ChunkPos const& chunkPos,
59 | std::vector& ZXheights,
60 | bool factorInBeardsAndShavers,
61 | int skipTopN
62 | );
63 |
64 | // 可选,可以不写
65 | BlockPos findSpawnPosition() const { return {0, 16, 0}; };
66 | };
67 |
68 | } // namespace flat_village_generator
--------------------------------------------------------------------------------
/src/test/generator/generator-custom-structure/structure-files/README.md:
--------------------------------------------------------------------------------
1 | ## You need to copy this folder to this path:
2 |
3 | ```
4 | behavior_packs\vanilla\structures\
5 | ```
--------------------------------------------------------------------------------
/src/test/generator/generator-custom-structure/structure-files/custom/21room.mcstructure:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LiteLDev/MoreDimensions/03587dfe5b9bc820a4df43de99add99a5a9a35ba/src/test/generator/generator-custom-structure/structure-files/custom/21room.mcstructure
--------------------------------------------------------------------------------
/src/test/generator/generator-custom-structure/structure-files/custom/beds5x5int.mcstructure:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LiteLDev/MoreDimensions/03587dfe5b9bc820a4df43de99add99a5a9a35ba/src/test/generator/generator-custom-structure/structure-files/custom/beds5x5int.mcstructure
--------------------------------------------------------------------------------
/src/test/generator/generator-custom-structure/structure-files/custom/chestcarpet5x5int.mcstructure:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LiteLDev/MoreDimensions/03587dfe5b9bc820a4df43de99add99a5a9a35ba/src/test/generator/generator-custom-structure/structure-files/custom/chestcarpet5x5int.mcstructure
--------------------------------------------------------------------------------
/src/test/generator/generator-custom-structure/structure-files/custom/ewcap.mcstructure:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LiteLDev/MoreDimensions/03587dfe5b9bc820a4df43de99add99a5a9a35ba/src/test/generator/generator-custom-structure/structure-files/custom/ewcap.mcstructure
--------------------------------------------------------------------------------
/src/test/generator/generator-custom-structure/structure-files/custom/ewhall.mcstructure:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LiteLDev/MoreDimensions/03587dfe5b9bc820a4df43de99add99a5a9a35ba/src/test/generator/generator-custom-structure/structure-files/custom/ewhall.mcstructure
--------------------------------------------------------------------------------
/src/test/generator/generator-custom-structure/structure-files/custom/kitchen5x5int.mcstructure:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LiteLDev/MoreDimensions/03587dfe5b9bc820a4df43de99add99a5a9a35ba/src/test/generator/generator-custom-structure/structure-files/custom/kitchen5x5int.mcstructure
--------------------------------------------------------------------------------
/src/test/generator/generator-custom-structure/structure-files/custom/nbt/back_bridge_bottom.nbt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LiteLDev/MoreDimensions/03587dfe5b9bc820a4df43de99add99a5a9a35ba/src/test/generator/generator-custom-structure/structure-files/custom/nbt/back_bridge_bottom.nbt
--------------------------------------------------------------------------------
/src/test/generator/generator-custom-structure/structure-files/custom/nbt/back_bridge_top.nbt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LiteLDev/MoreDimensions/03587dfe5b9bc820a4df43de99add99a5a9a35ba/src/test/generator/generator-custom-structure/structure-files/custom/nbt/back_bridge_top.nbt
--------------------------------------------------------------------------------
/src/test/generator/generator-custom-structure/structure-files/custom/nbt/bridge.nbt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LiteLDev/MoreDimensions/03587dfe5b9bc820a4df43de99add99a5a9a35ba/src/test/generator/generator-custom-structure/structure-files/custom/nbt/bridge.nbt
--------------------------------------------------------------------------------
/src/test/generator/generator-custom-structure/structure-files/custom/nscap.mcstructure:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LiteLDev/MoreDimensions/03587dfe5b9bc820a4df43de99add99a5a9a35ba/src/test/generator/generator-custom-structure/structure-files/custom/nscap.mcstructure
--------------------------------------------------------------------------------
/src/test/generator/generator-custom-structure/structure-files/custom/nshall.mcstructure:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LiteLDev/MoreDimensions/03587dfe5b9bc820a4df43de99add99a5a9a35ba/src/test/generator/generator-custom-structure/structure-files/custom/nshall.mcstructure
--------------------------------------------------------------------------------
/src/test/generator/generator-custom-structure/structure/CustomStructureFeature.cpp:
--------------------------------------------------------------------------------
1 | #include "CustomStructureFeature.h"
2 |
3 | #include "test/generator/generator-custom-structure/structure/CustomStructurePiece.h"
4 | #include "test/generator/generator-custom-structure/structure/CustomStructureStart.h"
5 |
6 |
7 | #include "mc/deps/core/math/Random.h"
8 | #include "mc/deps/core/string/HashedString.h"
9 | #include "mc/util/Random.h"
10 | #include "mc/world/level/ChunkPos.h"
11 | #include "mc/world/level/Level.h"
12 | #include "mc/world/level/biome/Biome.h"
13 | #include "mc/world/level/biome/source/BiomeSource.h"
14 | #include "mc/world/level/dimension/Dimension.h"
15 | #include "mc/world/level/levelgen/structure/BoundingBox.h"
16 | #include "mc/world/level/levelgen/structure/StructureStart.h"
17 |
18 |
19 | #include
20 |
21 | namespace custom_structure {
22 | bool CustomStructureFeature::getNearestGeneratedFeature(
23 | ::Dimension& dimension,
24 | ::BiomeSource const& biomeSource,
25 | ::BlockPos const& origin,
26 | ::BlockPos& pos,
27 | ::IPreliminarySurfaceProvider const& preliminarySurfaceLevel,
28 | bool mustBeInNewChunks,
29 | ::std::optional<::HashedString> const& biomeTag
30 | ) {
31 | return StructureFeature::findNearestFeaturePositionBySpacing(dimension, preliminarySurfaceLevel, *this, biomeTag, biomeSource, origin, pos, mMaxSpacing, mMinSpacing, 39281139, true, 0, mustBeInNewChunks);
32 | };
33 |
34 | bool CustomStructureFeature::
35 | isFeatureChunk(::BiomeSource const&, ::Random& random, ::ChunkPos const& cpos, uint, ::IPreliminarySurfaceProvider const&, ::Dimension const&) {
36 | int salt = 39281139;
37 | uint newSeed = mSeed + salt + 0xF1565BD5 * (cpos.z / mMaxSpacing) - 0x66C60AF8 * (cpos.x / mMaxSpacing);
38 | random.mRandom->mObject.mHaveNextNextGaussian = false;
39 | random.mRandom->mObject.mSeed = newSeed;
40 | random.mRandom->mObject.mNextNextGaussian = 0.0;
41 | random.mRandom->mObject.mNextNextGaussianDouble = 0.0;
42 | random.mRandom->mObject._mt[0] = newSeed;
43 |
44 | auto _mtLast = newSeed;
45 | for (int i = 1; i <= 397; i++) {
46 | random.mRandom->mObject._mt[i] = i + 0x6C078965 * (_mtLast ^ (_mtLast >> 30));
47 | _mtLast = i + 0x6C078965 * (_mtLast ^ (_mtLast >> 30));
48 | }
49 | random.mRandom->mObject._mti = 624;
50 | random.mRandom->mObject.mInitedIdx = 398;
51 |
52 | auto able_spacing = mMaxSpacing - mMinSpacing;
53 |
54 | auto random_int_x = (random.nextInt(able_spacing) + random.nextInt(able_spacing)) / 2;
55 | auto random_int_z = (random.nextInt(able_spacing) + random.nextInt(able_spacing)) / 2;
56 |
57 | ChunkPos target_cpos(able_spacing * (cpos.x / able_spacing) + random_int_x, able_spacing * (cpos.z / able_spacing) + random_int_z);
58 | if (cpos != target_cpos) return false;
59 | return true;
60 | };
61 |
62 | std::unique_ptr<::StructureStart> CustomStructureFeature::
63 | createStructureStart(::Dimension& dim, ::BiomeSource const& biomeSource, ::Random& random, ::ChunkPos const& cpos, ::IPreliminarySurfaceProvider const&) {
64 | auto start = std::make_unique();
65 | CustomStructurePiece::addPieces(
66 | {cpos.x * 16, 0, cpos.z * 16},
67 | start->pieces,
68 | random,
69 | dim.mLevel.getJigsawStructureRegistry(),
70 | biomeSource.getBiome(cpos.x * 16, 1, cpos.z * 16)->getBiomeType(),
71 | dim
72 | );
73 | start->calculateBoundingBox();
74 | return std::move(start);
75 | };
76 |
77 | CustomStructureFeature::CustomStructureFeature(uint seed, uint minSpacing, uint maxSpacing)
78 | : StructureFeature(seed, HashedString("mike:basic_dungeon")),
79 | mSeed(seed),
80 | mMinSpacing(minSpacing),
81 | mMaxSpacing(maxSpacing) {}
82 |
83 | } // namespace custom_structure
84 |
--------------------------------------------------------------------------------
/src/test/generator/generator-custom-structure/structure/CustomStructureFeature.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "mc/world/level/levelgen/structure/StructureFeature.h"
4 |
5 | namespace custom_structure {
6 | class CustomStructureFeature : public StructureFeature {
7 | uint mSeed; // 虚函数的参数传过来的都是默认的level种子,自定义就存一下
8 | int mMaxSpacing; // 最大间距
9 | int mMinSpacing; // 最小间距
10 | public:
11 | virtual bool getNearestGeneratedFeature(
12 | ::Dimension& dimension,
13 | ::BiomeSource const& biomeSource,
14 | ::BlockPos const& origin,
15 | ::BlockPos& pos,
16 | ::IPreliminarySurfaceProvider const& preliminarySurfaceLevel,
17 | bool mustBeInNewChunks,
18 | ::std::optional<::HashedString> const& biomeTag
19 | );
20 |
21 | virtual bool
22 | isFeatureChunk(::BiomeSource const&, ::Random&, ::ChunkPos const&, uint, ::IPreliminarySurfaceProvider const&, ::Dimension const&);
23 |
24 | virtual ::std::unique_ptr<::StructureStart>
25 | createStructureStart(::Dimension&, ::BiomeSource const&, ::Random&, ::ChunkPos const&, ::IPreliminarySurfaceProvider const&);
26 |
27 | CustomStructureFeature(uint seed, uint minSpacing, uint maxSpacing);
28 | };
29 |
30 | } // namespace custom_structure
--------------------------------------------------------------------------------
/src/test/generator/generator-custom-structure/structure/CustomStructurePiece.cpp:
--------------------------------------------------------------------------------
1 | #include "CustomStructurePiece.h"
2 |
3 | #include "mc/util/Random.h"
4 | #include "mc/world/level/BlockPos.h"
5 | #include "mc/world/level/block/VanillaBlockTypeIds.h"
6 | #include "mc/world/level/block/registry/BlockTypeRegistry.h"
7 | #include "mc/world/level/dimension/Dimension.h"
8 | #include "mc/world/level/levelgen/structure/BoundingBox.h"
9 | #include "test/mc/JigsawJunction.h"
10 | #include "test/mc/JigsawPlacement.h"
11 | #include "mc/world/level/levelgen/structure/registry/JigsawStructureRegistry.h"
12 | #include "mc/world/level/levelgen/structure/structurepools/StructurePoolElement.h"
13 | #include "test/mc/StructureTemplatePool.h"
14 | #include "test/mc/PoolAliasBinding.h"
15 | #include "mc/world/level/levelgen/v1/AdjustmentEffect.h"
16 |
17 |
18 | #include
19 |
20 |
21 | namespace custom_structure {
22 |
23 | int CustomStructurePiece::
24 | generateHeightAtPosition(BlockPos const&, Dimension& dim, BlockVolume&, std::unordered_map>>&)
25 | const {
26 | return dim.mSeaLevel + 100;
27 | };
28 |
29 | Block const* CustomStructurePiece::getSupportBlock(::BlockSource&, ::BlockPos const&, ::Block const&) const {
30 | return &BlockTypeRegistry::getDefaultBlockState(VanillaBlockTypeIds::GrassBlock());
31 | };
32 |
33 | Block const& CustomStructurePiece::getBeardStabilizeBlock(::Block const&) const {
34 | return BlockTypeRegistry::getDefaultBlockState(VanillaBlockTypeIds::GrassBlock());
35 | };
36 |
37 | AdjustmentEffect CustomStructurePiece::getTerrainAdjustmentEffect() const { return AdjustmentEffect::Beard; };
38 |
39 | CustomStructurePiece::CustomStructurePiece(
40 | ::StructurePoolElement const& element,
41 | ::BlockPos position,
42 | ::Rotation rotation,
43 | int genDepth,
44 | ::JigsawJunction& junction,
45 | ::BoundingBox const& box,
46 | ::BlockPos refPos
47 | )
48 | : PoolElementStructurePiece(element, position, rotation, genDepth, junction, box, refPos) {};
49 |
50 | void CustomStructurePiece::addPieces(
51 | BlockPos position,
52 | std::vector>& pieces,
53 | Random& random,
54 | JigsawStructureRegistry& pools,
55 | VanillaBiomeTypes biomeType,
56 | Dimension& dimension
57 | ) {
58 | auto templates = pools.lookupByName("mike:ns7x4");
59 | // templates.getRandomTemplate(random);
60 |
61 | auto lambda = [](StructurePoolElement const& element,
62 | ::BlockPos const& pos,
63 | ::Rotation const& rot,
64 | int unk,
65 | ::JigsawJunction& jigction,
66 | ::BoundingBox const& bb,
67 | ::BlockPos const& pos1) {
68 | return std::make_unique(element, pos, rot, unk, jigction, bb, pos1);
69 | };
70 | JigsawPlacement place(15, 80, pieces, lambda, random, pools, dimension);
71 |
72 | auto index = random.nextInt(0, templates->mTemplates->size() - 1);
73 | place.addPieces(
74 | *templates->mTemplates->at(index),
75 | position,
76 | Rotation(random.nextInt(4)),
77 | "",
78 | {}
79 | );
80 | }
81 |
82 | } // namespace custom_structure
83 |
--------------------------------------------------------------------------------
/src/test/generator/generator-custom-structure/structure/CustomStructurePiece.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "mc/util/Rotation.h"
4 | #include "mc/world/level/biome/components/vanilla/VanillaBiomeTypes.h"
5 | #include "test/mc/PoolElementStructurePiece.h"
6 |
7 |
8 |
9 | class JigsawStructureRegistry;
10 | class StructurePoolElement;
11 | struct JigsawJunction;
12 |
13 | namespace custom_structure {
14 |
15 | class CustomStructurePiece : public PoolElementStructurePiece {
16 | public:
17 | virtual int
18 | generateHeightAtPosition(::BlockPos const&, ::Dimension&, ::BlockVolume&, ::std::unordered_map<::ChunkPos, ::std::unique_ptr<::std::vector>>&)
19 | const;
20 |
21 | virtual Block const* getSupportBlock(::BlockSource&, ::BlockPos const&, ::Block const&) const;
22 |
23 | virtual Block const& getBeardStabilizeBlock(::Block const&) const;
24 |
25 | virtual AdjustmentEffect getTerrainAdjustmentEffect() const;
26 |
27 | CustomStructurePiece(
28 | ::StructurePoolElement const& element,
29 | ::BlockPos position,
30 | ::Rotation rotation,
31 | int genDepth,
32 | ::JigsawJunction& junction,
33 | ::BoundingBox const& box,
34 | ::BlockPos refPos
35 | );
36 |
37 | static void addPieces(
38 | BlockPos position,
39 | std::vector>& pieces,
40 | Random& random,
41 | JigsawStructureRegistry& pools,
42 | VanillaBiomeTypes biomeType,
43 | Dimension& dimension
44 | );
45 | };
46 |
47 | } // namespace custom_structure
48 |
--------------------------------------------------------------------------------
/src/test/generator/generator-custom-structure/structure/CustomStructureStart.cpp:
--------------------------------------------------------------------------------
1 | #include "CustomStructureStart.h"
2 |
3 | // CustomStructureStart::CustomStructureStart(int chunk_x, int chunk_z) {
4 | // chunkX = chunk_x;
5 | // chunkZ = chunk_z;
6 | // }
--------------------------------------------------------------------------------
/src/test/generator/generator-custom-structure/structure/CustomStructureStart.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "mc/world/level/levelgen/structure/StructureStart.h"
4 |
5 |
6 | class CustomStructureStart : public StructureStart {
7 | public:
8 | CustomStructureStart() = default;
9 | virtual std::string_view getStructureName() const { return "mike:basic_dungeon"; };
10 | };
11 |
--------------------------------------------------------------------------------
/src/test/generator/generator-terrain/NxnBorderTerrainDimension.cpp:
--------------------------------------------------------------------------------
1 | #include "NxnBorderTerrainDimension.h"
2 |
3 | #include "test/generator/generator-terrain/NxnBorderTerrainGenerator.h"
4 |
5 | #include "mc/common/Brightness.h"
6 | #include "mc/common/BrightnessPair.h"
7 | #include "mc/deps/core/math/Vec3.h"
8 | #include "mc/world/level/BlockSource.h"
9 | #include "mc/world/level/DimensionConversionData.h"
10 | #include "mc/world/level/Level.h"
11 | #include "mc/world/level/chunk/vanilla_level_chunk_upgrade/VanillaLevelChunkUpgrade.h"
12 | #include "mc/world/level/dimension/DimensionBrightnessRamp.h"
13 | #include "mc/world/level/dimension/DimensionHeightRange.h"
14 | #include "mc/world/level/dimension/OverworldBrightnessRamp.h"
15 | #include "mc/world/level/dimension/VanillaDimensions.h"
16 | #include "mc/world/level/levelgen/flat/FlatWorldGenerator.h"
17 | #include "mc/world/level/levelgen/structure/StructureFeatureRegistry.h"
18 | #include "mc/world/level/levelgen/structure/VillageFeature.h"
19 | #include "mc/world/level/levelgen/v2/ChunkGeneratorStructureState.h"
20 | #include "mc/world/level/storage/LevelData.h"
21 |
22 |
23 | namespace nxn_border_terrain {
24 |
25 | NxnBorderTerrainDimension::NxnBorderTerrainDimension(
26 | std::string const& name,
27 | more_dimensions::DimensionFactoryInfo const& info
28 | )
29 | : Dimension(info.level, info.dimId, {-64, 320}, info.scheduler, name) {
30 | // 这里说明下,在DimensionFactoryInfo里面more-dimensions会提供维度id,请不要使用固定维度id,避免id冲突导致维度注册出现异常
31 | mDefaultBrightness->sky = Brightness::MAX();
32 | mSeaLevel = -61;
33 | mHasWeather = true;
34 | mDimensionBrightnessRamp = std::make_unique();
35 | mDimensionBrightnessRamp->buildBrightnessRamp();
36 |
37 | // 这个是边长的区块数,是将会传到生成器里面用的
38 | chunkLength = info.data["ChunkLength"];
39 | }
40 |
41 | CompoundTag NxnBorderTerrainDimension::generateNewData(uint chunkLength) {
42 | CompoundTag result;
43 | result["ChunkLength"] = chunkLength;
44 | return result;
45 | }
46 |
47 | std::unique_ptr NxnBorderTerrainDimension::createGenerator(br::worldgen::StructureSetRegistry const&) {
48 |
49 | std::unique_ptr worldGenerator;
50 | auto seed = mLevel.getSeed();
51 | auto& levelData = mLevel.getLevelData();
52 |
53 | // 实例化一个FlatWorldGenerator类
54 | worldGenerator =
55 | std::make_unique(*this, seed, chunkLength, levelData.mFlatWorldOptions);
56 | // 此为必须,一些结构生成相关
57 | worldGenerator->mStructureFeatureRegistry->mGeneratorState =
58 | br::worldgen::ChunkGeneratorStructureState::createFlat(seed, worldGenerator->getBiomeSource(), {});
59 |
60 | return std::move(worldGenerator);
61 | }
62 |
63 | void NxnBorderTerrainDimension::upgradeLevelChunk(ChunkSource& cs, LevelChunk& lc, LevelChunk& generatedChunk) {
64 | auto blockSource = BlockSource(static_cast(mLevel), *this, cs, false, true, false);
65 | VanillaLevelChunkUpgrade::_upgradeLevelChunkViaMetaData(lc, generatedChunk, blockSource);
66 | VanillaLevelChunkUpgrade::_upgradeLevelChunkLegacy(lc, blockSource);
67 | }
68 |
69 | void NxnBorderTerrainDimension::fixWallChunk(ChunkSource& cs, LevelChunk& lc) {
70 | auto blockSource = BlockSource(static_cast(mLevel), *this, cs, false, true, false);
71 | VanillaLevelChunkUpgrade::fixWallChunk(lc, blockSource);
72 | }
73 |
74 | bool NxnBorderTerrainDimension::levelChunkNeedsUpgrade(LevelChunk const& lc) const {
75 | return VanillaLevelChunkUpgrade::levelChunkNeedsUpgrade(lc);
76 | }
77 | void NxnBorderTerrainDimension::_upgradeOldLimboEntity(CompoundTag& tag, ::LimboEntitiesVersion vers) {
78 | auto isTemplate = mLevel.getLevelData().mIsFromLockedTemplate;
79 | return VanillaLevelChunkUpgrade::upgradeOldLimboEntity(tag, vers, isTemplate);
80 | }
81 |
82 | std::unique_ptr NxnBorderTerrainDimension::
83 | _wrapStorageForVersionCompatibility(std::unique_ptr cs, ::StorageVersion /*ver*/) {
84 | return cs;
85 | }
86 |
87 | Vec3 NxnBorderTerrainDimension::translatePosAcrossDimension(Vec3 const& fromPos, DimensionType fromId) const {
88 | Vec3 topos;
89 | VanillaDimensions::convertPointBetweenDimensions(fromPos, topos, fromId, mId, mLevel.getDimensionConversionData());
90 | constexpr auto clampVal = 32000000.0f - 128.0f;
91 |
92 | topos.x = std::clamp(topos.x, -clampVal, clampVal);
93 | topos.z = std::clamp(topos.z, -clampVal, clampVal);
94 |
95 | return topos;
96 | }
97 |
98 | short NxnBorderTerrainDimension::getCloudHeight() const { return 192; }
99 |
100 | // bool NxnBorderTerrainDimension::hasPrecipitationFog() const { return true; }
101 |
102 | } // namespace nxn_border_terrain
--------------------------------------------------------------------------------
/src/test/generator/generator-terrain/NxnBorderTerrainDimension.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "mc/world/level/dimension/Dimension.h" // 新维度类需要继承的类
4 | #include "more_dimensions/api/dimension/CustomDimensionManager.h" // 使用DimensionFactoryInfo的声明
5 |
6 | // 建议是加一个命名空间,避免与其他插件同类名的情况
7 | namespace nxn_border_terrain {
8 |
9 | class NxnBorderTerrainDimension : public Dimension {
10 | uint chunkLength;
11 |
12 | public:
13 | // 建议固定这样写,DimensionFactoryInfo类里面提供了Dimension实例化的基本数据,name就是维度名,多维度是维度名区分不同维度
14 | NxnBorderTerrainDimension(std::string const& name, more_dimensions::DimensionFactoryInfo const& info);
15 |
16 | // 多维度需要的一个方法,参数是你需要的一些额外的数据,比如种子
17 | static CompoundTag generateNewData(uint chunkLength = 4);
18 |
19 | // 以下六个是必须重写的函数
20 | // 维度地形的生成器,是本教程主要更改的地方
21 | std::unique_ptr createGenerator(br::worldgen::StructureSetRegistry const&) override;
22 |
23 | // 与本教程无关,按照本教程写的就行,无需留意
24 | void upgradeLevelChunk(ChunkSource& chunkSource, LevelChunk& oldLc, LevelChunk& newLc) override;
25 |
26 | // 与本教程无关,按照本教程写的就行,无需留意
27 | void fixWallChunk(ChunkSource& cs, LevelChunk& lc) override;
28 |
29 | // 与本教程无关,按照本教程写的就行,无需留意
30 | bool levelChunkNeedsUpgrade(LevelChunk const& lc) const override;
31 |
32 | // 与本教程无关,按照本教程写的就行,无需留意
33 | void _upgradeOldLimboEntity(CompoundTag& tag, ::LimboEntitiesVersion vers) override;
34 |
35 | // 与本教程无关,按照本教程写的就行,无需留意
36 | std::unique_ptr
37 | _wrapStorageForVersionCompatibility(std::unique_ptr cs, ::StorageVersion ver) override;
38 |
39 | // 当你转到这个维度时,坐标怎么转换,比如主世界与地狱的
40 | Vec3 translatePosAcrossDimension(Vec3 const& pos, DimensionType did) const override;
41 |
42 | // 云高度,默认是y128,但多维度高度范围是在y-64~320,与主世界相同,重写它,放高些
43 | short getCloudHeight() const override;
44 |
45 | // 非必要。下雨时,可视范围的更改
46 | // bool hasPrecipitationFog() const override;
47 | };
48 |
49 | } // namespace nxn_border_terrain
--------------------------------------------------------------------------------
/src/test/generator/generator-terrain/NxnBorderTerrainGenerator.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Created by User on 2024/2/22.
3 | //
4 |
5 | #include "NxnBorderTerrainGenerator.h"
6 |
7 | #include "test/mc/FixedBiomeSource.h"
8 |
9 | #include "mc/world/level/ChunkPos.h"
10 | #include "mc/world/level/block/BedrockBlockNames.h"
11 | #include "mc/world/level/block/Block.h"
12 | #include "mc/world/level/block/BlockVolume.h"
13 | #include "mc/world/level/block/VanillaBlockTypeIds.h"
14 | #include "mc/world/level/block/registry/BlockTypeRegistry.h"
15 | #include "mc/world/level/chunk/LevelChunk.h"
16 | #include "mc/world/level/dimension/Dimension.h"
17 | #include "mc/world/level/levelgen/v1/ChunkLocalNoiseCache.h"
18 |
19 | #include "mc/world/level/block/Block.h"
20 |
21 |
22 | namespace nxn_border_terrain {
23 |
24 | NxnBorderTerrainGenerator::NxnBorderTerrainGenerator(
25 | Dimension& dimension,
26 | uint seed,
27 | uint chunkLength,
28 | Json::Value const& generationOptionsJSON
29 | )
30 | : FlatWorldGenerator(dimension, seed, generationOptionsJSON) {
31 | chunk_n = chunkLength;
32 | auto height = mPrototype->mHeight;
33 | auto& roadBlock = BlockTypeRegistry::getDefaultBlockState(VanillaBlockTypeIds::GrassPath());
34 | auto& borderBlock = BlockTypeRegistry::getDefaultBlockState(VanillaBlockTypeIds::SmoothStoneSlab());
35 |
36 | east_side_b.mBlocks = {east_side.data(), east_side.data() + east_side.size()};
37 | south_side_b.mBlocks = {south_side.data(), south_side.data() + south_side.size()};
38 | west_side_b.mBlocks = {west_side.data(), west_side.data() + west_side.size()};
39 | north_side_b.mBlocks = {north_side.data(), north_side.data() + north_side.size()};
40 | n_e_angle_b.mBlocks = {n_e_angle.data(), n_e_angle.data() + n_e_angle.size()};
41 | e_s_angle_b.mBlocks = {e_s_angle.data(), e_s_angle.data() + e_s_angle.size()};
42 | s_w_angle_b.mBlocks = {s_w_angle.data(), s_w_angle.data() + s_w_angle.size()};
43 | w_n_angle_b.mBlocks = {w_n_angle.data(), w_n_angle.data() + w_n_angle.size()};
44 |
45 | for (int i = 0; i < 16; i++) {
46 | // 一般开始的是距离第一个方块的差值,然后是会乘
47 | // i的间隔方块,然后是与另外一条路或者半砖方块的间隔,最后面的是第几层
48 | // 南边
49 | e_s_angle[height * 15 + height * 16 * i + 3] = &roadBlock;
50 |
51 | s_w_angle[height * 15 + height * 16 * i + 3] = &roadBlock;
52 |
53 | south_side[height * 15 + height * 16 * i + 3] = &roadBlock;
54 | south_side[height * 14 + height * 16 * i + 4] = &borderBlock;
55 | // 东边
56 | e_s_angle[height * 16 * 15 + height * i + 3] = &roadBlock;
57 |
58 | n_e_angle[height * 16 * 15 + height * i + 3] = &roadBlock;
59 |
60 | east_side[height * 16 * 15 + height * i + 3] = &roadBlock;
61 | east_side[height * 16 * 14 + height * i + 4] = &borderBlock;
62 | // 西边
63 | s_w_angle[height * i + 3] = &roadBlock;
64 |
65 | w_n_angle[height * i + 3] = &roadBlock;
66 |
67 | west_side[height * i + 3] = &roadBlock;
68 | west_side[height * 16 + height * i + 4] = &borderBlock;
69 | // 北边
70 | n_e_angle[height * 16 * i + 3] = &roadBlock;
71 |
72 | w_n_angle[height * 16 * i + 3] = &roadBlock;
73 |
74 | north_side[height * 16 * i + 3] = &roadBlock;
75 | north_side[height + height * 16 * i + 4] = &borderBlock;
76 |
77 | // 半砖避免放到路上,最后一次循环
78 | if (i < 15) {
79 | // 南
80 | e_s_angle[height * 14 + height * 16 * i + 4] = &borderBlock;
81 | // 东
82 | e_s_angle[height * 16 * 14 + height * i + 4] = &borderBlock;
83 | // 西
84 | s_w_angle[height * 16 + height * i + 4] = &borderBlock;
85 | // 北
86 | n_e_angle[height + height * 16 * i + 4] = &borderBlock;
87 | }
88 | // 第一次循环
89 | if (i > 0) {
90 | // 西
91 | w_n_angle[height * 16 + height * i + 4] = &borderBlock;
92 | // 北
93 | w_n_angle[height + height * 16 * i + 4] = &borderBlock;
94 | // 南
95 | s_w_angle[height * 14 + height * 16 * i + 4] = &borderBlock;
96 | // 东
97 | n_e_angle[height * 16 * 14 + height * i + 4] = &borderBlock;
98 | }
99 | }
100 | }
101 |
102 | void NxnBorderTerrainGenerator::loadChunk(LevelChunk& levelchunk, bool forceImmediateReplacementDataLoad) {
103 | auto chunkPos = levelchunk.mPosition;
104 |
105 | int n = chunk_n;
106 | auto pos_x = (chunkPos->x % n + n) % n;
107 | auto pos_z = (chunkPos->z % n + n) % n;
108 |
109 | if (pos_x == 0) {
110 | if (pos_z == 0) {
111 | levelchunk.setBlockVolume(w_n_angle_b, 0);
112 | } else if (pos_z == (n - 1)) {
113 | levelchunk.setBlockVolume(s_w_angle_b, 0);
114 | } else {
115 | levelchunk.setBlockVolume(west_side_b, 0);
116 | }
117 |
118 | } else if (pos_x == (n - 1)) {
119 | if (pos_z == 0) {
120 | levelchunk.setBlockVolume(n_e_angle_b, 0);
121 | } else if (pos_z == (n - 1)) {
122 | levelchunk.setBlockVolume(e_s_angle_b, 0);
123 | } else {
124 | levelchunk.setBlockVolume(east_side_b, 0);
125 | }
126 | } else if (pos_z == 0) {
127 | levelchunk.setBlockVolume(north_side_b, 0);
128 | } else if (pos_z == (n - 1)) {
129 | levelchunk.setBlockVolume(south_side_b, 0);
130 | } else {
131 | levelchunk.setBlockVolume(mPrototype, 0);
132 | }
133 |
134 | levelchunk.recomputeHeightMap(false);
135 | mBiomeSource = std::make_unique(*mBiome);
136 | DividedPos2d<4> dividedPos2D;
137 | ChunkLocalNoiseCache chunkLocalNoiseCache(dividedPos2D, 8);
138 | mBiomeSource->fillBiomes(levelchunk, chunkLocalNoiseCache);
139 | levelchunk.setSaved();
140 | auto loadState = ChunkState::Generating;
141 | levelchunk.mLoadState->compare_exchange_weak(loadState, ChunkState::Generated);
142 | }
143 |
144 | } // namespace nxn_border_terrain
--------------------------------------------------------------------------------
/src/test/generator/generator-terrain/NxnBorderTerrainGenerator.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "mc/world/level/block/BlockVolume.h"
4 | #include "mc/world/level/levelgen/flat/FlatWorldGenerator.h"
5 |
6 | #include
7 |
8 | namespace nxn_border_terrain {
9 |
10 | class NxnBorderTerrainGenerator : public FlatWorldGenerator {
11 | public:
12 | uint chunk_n = 4; // n * n的区块
13 | std::vector east_side = mPrototypeBlocks;
14 | std::vector south_side = mPrototypeBlocks;
15 | std::vector west_side = mPrototypeBlocks;
16 | std::vector north_side = mPrototypeBlocks;
17 | std::vector n_e_angle = mPrototypeBlocks;
18 | std::vector e_s_angle = mPrototypeBlocks;
19 | std::vector s_w_angle = mPrototypeBlocks;
20 | std::vector w_n_angle = mPrototypeBlocks;
21 | BlockVolume east_side_b = mPrototype;
22 | BlockVolume south_side_b = mPrototype;
23 | BlockVolume west_side_b = mPrototype;
24 | BlockVolume north_side_b = mPrototype;
25 | BlockVolume n_e_angle_b = mPrototype;
26 | BlockVolume e_s_angle_b = mPrototype;
27 | BlockVolume s_w_angle_b = mPrototype;
28 | BlockVolume w_n_angle_b = mPrototype;
29 | NxnBorderTerrainGenerator(
30 | Dimension& dimension,
31 | uint seed,
32 | uint chunkLength,
33 | Json::Value const& generationOptionsJSON
34 | );
35 | void loadChunk(class LevelChunk& levelchunk, bool forceImmediateReplacementDataLoad);
36 | };
37 | } // namespace nxn_border_terrain
--------------------------------------------------------------------------------
/src/test/mc/FixedBiomeSource.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "mc/_HeaderOutputPredefine.h"
4 |
5 | // auto generated inclusion list
6 | #include "mc/world/level/biome/source/BiomeSource.h"
7 |
8 | // auto generated forward declare list
9 | // clang-format off
10 | class Biome;
11 | class BiomeArea;
12 | class BlockPos;
13 | class BoundingBox;
14 | class ChunkLocalNoiseCache;
15 | class LevelChunk;
16 | struct GetBiomeOptions;
17 | // clang-format on
18 |
19 | class FixedBiomeSource : public ::BiomeSource {
20 | public:
21 | // member variables
22 | // NOLINTBEGIN
23 | ::ll::TypedStorage<8, 8, ::Biome const&> mFixedBiome;
24 | // NOLINTEND
25 |
26 | public:
27 | // virtual functions
28 | // NOLINTBEGIN
29 | // vIndex: 1
30 | virtual void fillBiomes(::LevelChunk& levelChunk, ::ChunkLocalNoiseCache const& chunkLocalNoiseCache) const
31 | /*override*/;
32 |
33 | // vIndex: 4
34 | virtual bool containsOnly(int, int, int, int, ::gsl::span allowed) const /*override*/;
35 |
36 | // vIndex: 7
37 | virtual ::Biome const* getBiome(::BlockPos const& blockPos) const /*override*/;
38 |
39 | // vIndex: 6
40 | virtual ::Biome const* getBiome(::GetBiomeOptions const& getBiomeOptions) const /*override*/;
41 |
42 | // vIndex: 5
43 | virtual ::Biome const* getBiome(int blockX, int blockY, int blockZ) const /*override*/;
44 |
45 | // vIndex: 3
46 | virtual ::BiomeArea getBiomeArea(::BoundingBox const& area, uint scale) const /*override*/;
47 |
48 | // vIndex: 2
49 | virtual ::BiomeArea
50 | getBiomeArea(::BoundingBox const& area, uint scale, ::GetBiomeOptions const& getBiomeOptions) const /*override*/;
51 |
52 | // vIndex: 8
53 | virtual bool has(uint64 id) const /*override*/;
54 |
55 | // vIndex: 9
56 | virtual bool hasByHashId(uint64 id) const /*override*/;
57 |
58 | // vIndex: 10
59 | virtual ::BiomeSourceType const getType() const /*override*/;
60 |
61 | // vIndex: 0
62 | virtual ~FixedBiomeSource() /*override*/ = default;
63 | // NOLINTEND
64 |
65 | public:
66 | FixedBiomeSource(Biome const& biome) : mFixedBiome(biome){};
67 | // destructor thunk
68 | // NOLINTBEGIN
69 |
70 | // NOLINTEND
71 |
72 | public:
73 | // virtual function thunks
74 | // NOLINTBEGIN
75 | MCAPI void $fillBiomes(::LevelChunk& levelChunk, ::ChunkLocalNoiseCache const& chunkLocalNoiseCache) const;
76 |
77 | MCAPI bool $containsOnly(int, int, int, int, ::gsl::span allowed) const;
78 |
79 | MCFOLD ::Biome const* $getBiome(::BlockPos const& blockPos) const;
80 |
81 | MCFOLD ::Biome const* $getBiome(::GetBiomeOptions const& getBiomeOptions) const;
82 |
83 | MCFOLD ::Biome const* $getBiome(int blockX, int blockY, int blockZ) const;
84 |
85 | MCAPI ::BiomeArea $getBiomeArea(::BoundingBox const& area, uint scale) const;
86 |
87 | MCAPI ::BiomeArea
88 | $getBiomeArea(::BoundingBox const& area, uint scale, ::GetBiomeOptions const& getBiomeOptions) const;
89 |
90 | MCAPI bool $has(uint64 id) const;
91 |
92 | MCAPI bool $hasByHashId(uint64 id) const;
93 | // NOLINTEND
94 |
95 | public:
96 | // vftables
97 | // NOLINTBEGIN
98 | MCAPI static void** $vftable();
99 | // NOLINTEND
100 | };
101 |
--------------------------------------------------------------------------------
/src/test/mc/JigsawJunction.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "mc/_HeaderOutputPredefine.h"
4 |
5 | #include "mc/world/level/BlockPos.h"
6 | #include "mc/world/level/levelgen/structure/Projection.h"
7 |
8 |
9 | struct JigsawJunction {
10 | public:
11 | // member variables
12 | // NOLINTBEGIN
13 | ::ll::TypedStorage<4, 12, BlockPos> mSourceBlockPos;
14 | ::ll::TypedStorage<4, 4, int> mDeltaSourceY;
15 | ::ll::TypedStorage<4, 4, int> mDeltaTargetY;
16 | ::ll::TypedStorage<1, 1, Projection> mSourceProjection;
17 | ::ll::TypedStorage<1, 1, Projection> mTargetProjection;
18 | // NOLINTEND
19 |
20 | public:
21 | // prevent constructor by default
22 | };
23 |
--------------------------------------------------------------------------------
/src/test/mc/JigsawPlacement.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "mc/_HeaderOutputPredefine.h"
4 |
5 | // auto generated inclusion list
6 | #include "mc/util/Rotation.h"
7 | #include "test/mc/PoolAliasBinding.h"
8 |
9 | // auto generated forward declare list
10 | // clang-format off
11 | class BlockPos;
12 | class BoundingBox;
13 | class Dimension;
14 | class JigsawBlockInfo;
15 | class JigsawStructureRegistry;
16 | class PoolElementStructurePiece;
17 | class Random;
18 | class StructurePiece;
19 | class StructurePoolElement;
20 | class StructureTemplatePool;
21 | struct JigsawJunction;
22 | // clang-format on
23 |
24 | class JigsawPlacement {
25 | public:
26 | // member variables
27 | // NOLINTBEGIN
28 | ::ll::UntypedStorage<4, 4> mUnkcc2c4f;
29 | ::ll::UntypedStorage<4, 4> mUnk230fb5;
30 | ::ll::UntypedStorage<8, 64> mUnk40c5ee;
31 | ::ll::UntypedStorage<8, 8> mUnke0bb10;
32 | ::ll::UntypedStorage<8, 8> mUnk3c1434;
33 | ::ll::UntypedStorage<8, 8> mUnkfa3181;
34 | ::ll::UntypedStorage<8, 8> mUnk2bf1da;
35 | ::ll::UntypedStorage<8, 64> mUnk5862e9;
36 | ::ll::UntypedStorage<8, 40> mUnkdd8234;
37 | ::ll::UntypedStorage<8, 24> mUnkb1b40e;
38 | ::ll::UntypedStorage<8, 24> mUnka60e45;
39 | ::ll::UntypedStorage<8, 40> mUnk747941;
40 | // NOLINTEND
41 |
42 | public:
43 | // prevent constructor by default
44 | JigsawPlacement& operator=(JigsawPlacement const&);
45 | JigsawPlacement(JigsawPlacement const&);
46 | JigsawPlacement();
47 |
48 | public:
49 | // member functions
50 | // NOLINTBEGIN
51 | MCAPI JigsawPlacement(
52 | uint64 maxDepth,
53 | uint64 globalContextSize,
54 | ::std::vector<::std::unique_ptr<::StructurePiece>>& pieceList,
55 | ::std::function<::std::unique_ptr<
56 | ::PoolElementStructurePiece>(::StructurePoolElement const&, ::BlockPos const&, ::Rotation const&, int, ::JigsawJunction&, ::BoundingBox const&, ::BlockPos const&)>
57 | factory,
58 | ::Random& random,
59 | ::JigsawStructureRegistry const& pools,
60 | ::Dimension& dimension
61 | );
62 |
63 | MCAPI void _addPiece(
64 | ::PoolElementStructurePiece const& sourcePiece,
65 | ::BlockPos const& position,
66 | ::Rotation const& rotation,
67 | ::BlockPos const& refPos,
68 | uint64 contextDepth,
69 | ::PoolAliasBinding::PoolAliasLookup const& poolAliasLookup
70 | );
71 |
72 | MCAPI ::BlockPos _findLocalAnchorOffset(
73 | ::StructurePoolElement const& initialElement,
74 | ::BlockPos const& pieceCornerPosition,
75 | ::Rotation const& rotation,
76 | ::std::string_view startAnchorName
77 | ) const;
78 |
79 | MCAPI bool _tryPlacingPiece(
80 | ::PoolElementStructurePiece const& sourcePiece,
81 | ::BoundingBox const& sourceBB,
82 | ::JigsawBlockInfo const& sourceJigsaw,
83 | ::BlockPos const& attachPos,
84 | ::StructureTemplatePool const* targetPool,
85 | ::BlockPos const& refPos,
86 | uint64 contextDepth,
87 | ::PoolAliasBinding::PoolAliasLookup const& poolAliasLookup
88 | );
89 |
90 | MCAPI void addPieces(
91 | ::StructurePoolElement const& initialElement,
92 | ::BlockPos const& startPosition,
93 | ::Rotation const& rotation,
94 | ::std::string_view startAnchorName,
95 | ::PoolAliasBinding::PoolAliasLookup const& poolAliasLookup
96 | );
97 |
98 | MCAPI ~JigsawPlacement();
99 | // NOLINTEND
100 |
101 | public:
102 | // constructor thunks
103 | // NOLINTBEGIN
104 | MCAPI void* $ctor(
105 | uint64 maxDepth,
106 | uint64 globalContextSize,
107 | ::std::vector<::std::unique_ptr<::StructurePiece>>& pieceList,
108 | ::std::function<::std::unique_ptr<
109 | ::PoolElementStructurePiece>(::StructurePoolElement const&, ::BlockPos const&, ::Rotation const&, int, ::JigsawJunction&, ::BoundingBox const&, ::BlockPos const&)>
110 | factory,
111 | ::Random& random,
112 | ::JigsawStructureRegistry const& pools,
113 | ::Dimension& dimension
114 | );
115 | // NOLINTEND
116 |
117 | public:
118 | // destructor thunk
119 | // NOLINTBEGIN
120 | MCAPI void $dtor();
121 | // NOLINTEND
122 | };
123 |
--------------------------------------------------------------------------------
/src/test/mc/PoolAliasBinding.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "mc/_HeaderOutputPredefine.h"
4 |
5 | // auto generated inclusion list
6 | #include "mc/deps/core/math/SimpleWeightedEntry.h"
7 |
8 | // auto generated forward declare list
9 | // clang-format off
10 | class BlockPos;
11 | class IRandom;
12 | // clang-format on
13 |
14 | class PoolAliasBinding {
15 | public:
16 | // PoolAliasBinding inner types declare
17 | // clang-format off
18 | class PoolAliasLookup;
19 | // clang-format on
20 |
21 | // PoolAliasBinding inner types define
22 | class PoolAliasLookup {
23 | public:
24 | // member variables
25 | // NOLINTBEGIN
26 | ::ll::TypedStorage<8, 24, std::vector>> mLookupTable;
27 | // NOLINTEND
28 |
29 | public:
30 | // prevent constructor by default
31 |
32 | public:
33 | // member functions
34 | // NOLINTBEGIN
35 | MCAPI ~PoolAliasLookup();
36 | // NOLINTEND
37 |
38 | public:
39 | // destructor thunk
40 | // NOLINTBEGIN
41 | MCFOLD void $dtor();
42 | // NOLINTEND
43 | };
44 |
45 | public:
46 | // virtual functions
47 | // NOLINTBEGIN
48 | // vIndex: 0
49 | virtual void appendResolvedAliases(::IRandom&, ::PoolAliasBinding::PoolAliasLookup&) const = 0;
50 |
51 | // vIndex: 1
52 | virtual void forAllTargets(::std::function const&) const = 0;
53 |
54 | // vIndex: 2
55 | virtual ~PoolAliasBinding() = default;
56 | // NOLINTEND
57 |
58 | public:
59 | // static functions
60 | // NOLINTBEGIN
61 | MCAPI static ::std::shared_ptr<::PoolAliasBinding> direct(::std::string&& id, ::std::string&& target);
62 |
63 | MCAPI static ::std::shared_ptr<::PoolAliasBinding>
64 | random(::std::string&& id, ::std::vector<::Core::SimpleWeightedEntry<::std::string>>&& targets);
65 |
66 | MCAPI static ::PoolAliasBinding::PoolAliasLookup resolvePoolAliases(
67 | ::std::vector<::std::shared_ptr<::PoolAliasBinding>> const& aliases,
68 | ::BlockPos const& structureStartPosition,
69 | int64 levelSeed
70 | );
71 | // NOLINTEND
72 |
73 | public:
74 | // destructor thunk
75 | // NOLINTBEGIN
76 |
77 | // NOLINTEND
78 |
79 | public:
80 | // virtual function thunks
81 | // NOLINTBEGIN
82 |
83 | // NOLINTEND
84 |
85 | public:
86 | // vftables
87 | // NOLINTBEGIN
88 | MCAPI static void** $vftable();
89 | // NOLINTEND
90 | };
91 |
--------------------------------------------------------------------------------
/src/test/mc/PoolElementStructurePiece.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "mc/_HeaderOutputPredefine.h"
4 |
5 | // auto generated inclusion list
6 | #include "mc/util/Rotation.h"
7 | #include "mc/world/actor/ActorDefinitionIdentifier.h"
8 | #include "mc/world/level/BlockPos.h"
9 | #include "mc/world/level/levelgen/structure/BoundingBox.h"
10 | #include "test/mc/JigsawJunction.h"
11 | #include "mc/world/level/levelgen/structure/structurepools/StructurePoolElement.h"
12 | #include "mc/world/level/levelgen/v1/AdjustmentEffect.h"
13 | #include "test/mc/StructurePiece.h"
14 |
15 |
16 |
17 | // auto generated forward declare list
18 | // clang-format off
19 | class Block;
20 | class BlockSource;
21 | class BlockVolume;
22 | class ChunkPos;
23 | class Dimension;
24 | class Random;
25 | // clang-format on
26 |
27 | class PoolElementStructurePiece : public ::StructurePiece {
28 | public:
29 | // member variables
30 | // NOLINTBEGIN
31 | ::ll::TypedStorage<4, 24, ::BoundingBox> mCachedPieceBounds;
32 | ::ll::TypedStorage<4, 4, int> mCachedPieceBaseY;
33 | ::ll::TypedStorage<4, 4, int> mCachedXCenter;
34 | ::ll::TypedStorage<4, 4, int> mCachedZCenter;
35 | ::ll::TypedStorage<4, 4, float> mCachedMaxRadius;
36 | ::ll::TypedStorage<8, 8, ::StructurePoolElement const&> mElement;
37 | ::ll::TypedStorage<4, 12, ::BlockPos> mPosition;
38 | ::ll::TypedStorage<1, 1, ::Rotation> mRotation;
39 | ::ll::TypedStorage<4, 24, ::JigsawJunction> mJigsawJunction;
40 | ::ll::TypedStorage<8, 64, ::std::unordered_map<::BlockPos, ::std::optional<::ActorDefinitionIdentifier>>>
41 | mEntitiesToPlace;
42 | ::ll::TypedStorage<4, 12, ::BlockPos> mRefPos;
43 | // NOLINTEND
44 |
45 | PoolElementStructurePiece(
46 | ::StructurePoolElement const& element,
47 | ::BlockPos position,
48 | ::Rotation rotation,
49 | int genDepth,
50 | ::JigsawJunction& junction,
51 | ::BoundingBox const& box,
52 | ::BlockPos refPos
53 | )
54 | : mElement(element),
55 | mPosition(position),
56 | mRotation(rotation),
57 | mJigsawJunction(junction),
58 | mRefPos(refPos) {
59 | mBoundingBox = box;
60 | mGenDepth = genDepth;
61 | };
62 |
63 | public:
64 | // virtual functions
65 | // NOLINTBEGIN
66 | // vIndex: 4
67 | virtual bool postProcess(::BlockSource& region, ::Random& random, ::BoundingBox const& chunkBB) /*override*/;
68 |
69 | // vIndex: 5
70 | virtual void postProcessMobsAt(::BlockSource& region, ::Random& random, ::BoundingBox const& chunkBB) /*override*/;
71 |
72 | // vIndex: 1
73 | virtual void moveBoundingBox(int dx, int dy, int dz) /*override*/;
74 |
75 | // vIndex: 13
76 | virtual int
77 | generateHeightAtPosition(::BlockPos const&, ::Dimension&, ::BlockVolume&, ::std::unordered_map<::ChunkPos, ::std::unique_ptr<::std::vector>>&)
78 | const = 0;
79 |
80 | // vIndex: 14
81 | virtual ::Block const* getSupportBlock(::BlockSource&, ::BlockPos const&, ::Block const&) const = 0;
82 |
83 | // vIndex: 15
84 | virtual ::Block const& getBeardStabilizeBlock(::Block const&) const = 0;
85 |
86 | // vIndex: 16
87 | virtual ::AdjustmentEffect getTerrainAdjustmentEffect() const = 0;
88 |
89 | // vIndex: 17
90 | virtual bool _needsPostProcessing(::BlockSource& region);
91 |
92 | // vIndex: 0
93 | virtual ~PoolElementStructurePiece() /*override*/ = default;
94 | // NOLINTEND
95 |
96 | public:
97 | // destructor thunk
98 | // NOLINTBEGIN
99 |
100 | // NOLINTEND
101 |
102 | public:
103 | // virtual function thunks
104 | // NOLINTBEGIN
105 | MCAPI bool $postProcess(::BlockSource& region, ::Random& random, ::BoundingBox const& chunkBB);
106 |
107 | MCAPI void $postProcessMobsAt(::BlockSource& region, ::Random& random, ::BoundingBox const& chunkBB);
108 |
109 | MCAPI void $moveBoundingBox(int dx, int dy, int dz);
110 |
111 | MCFOLD bool $_needsPostProcessing(::BlockSource& region);
112 | // NOLINTEND
113 |
114 | public:
115 | // vftables
116 | // NOLINTBEGIN
117 | MCAPI static void** $vftable();
118 | // NOLINTEND
119 | };
120 |
--------------------------------------------------------------------------------
/src/test/mc/StructurePiece.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "mc/_HeaderOutputPredefine.h"
4 |
5 | // auto generated inclusion list
6 | #include "mc/world/level/levelgen/structure/StructurePieceType.h"
7 |
8 | // auto generated forward declare list
9 | // clang-format off
10 | class Block;
11 | class BlockSelector;
12 | class BlockSource;
13 | class BoundingBox;
14 | class LevelChunk;
15 | class Random;
16 | // clang-format on
17 |
18 | class StructurePiece {
19 | public:
20 | // member variables
21 | // NOLINTBEGIN
22 | ::ll::TypedStorage<4, 24, BoundingBox> mBoundingBox;
23 | ::ll::TypedStorage<4, 4, int> mOrientation;
24 | ::ll::TypedStorage<4, 4, int> mGenDepth;
25 | ::ll::TypedStorage<8, 16, std::shared_ptr> mTerrainAdjustmentToken;
26 | // NOLINTEND
27 |
28 | public:
29 | // prevent constructor by default
30 |
31 | public:
32 | // virtual functions
33 | // NOLINTBEGIN
34 | // vIndex: 0
35 | virtual ~StructurePiece();
36 |
37 | // vIndex: 1
38 | virtual void moveBoundingBox(int dx, int dy, int dz);
39 |
40 | // vIndex: 2
41 | virtual ::StructurePieceType getType() const;
42 |
43 | // vIndex: 3
44 | virtual void addChildren(
45 | ::StructurePiece& startPiece,
46 | ::std::vector<::std::unique_ptr<::StructurePiece>>& pieces,
47 | ::Random& random
48 | );
49 |
50 | // vIndex: 4
51 | virtual bool postProcess(::BlockSource&, ::Random&, ::BoundingBox const&) = 0;
52 |
53 | // vIndex: 5
54 | virtual void postProcessMobsAt(::BlockSource& region, ::Random& random, ::BoundingBox const& chunkBB);
55 |
56 | // vIndex: 6
57 | virtual bool isInInvalidLocation(::BlockSource& region, ::BoundingBox const& chunkBB);
58 |
59 | // vIndex: 7
60 | virtual int getWorldX(int x, int z);
61 |
62 | // vIndex: 8
63 | virtual int getWorldZ(int x, int z);
64 |
65 | // vIndex: 9
66 | virtual void
67 | placeBlock(::BlockSource& region, ::Block const& block, int x, int y, int z, ::BoundingBox const& chunkBB);
68 |
69 | // vIndex: 10
70 | virtual bool canBeReplaced(::BlockSource&, int const, int const, int const, ::BoundingBox const&);
71 |
72 | // vIndex: 11
73 | virtual void generateBox(
74 | ::BlockSource& region,
75 | ::BoundingBox const& chunkBB,
76 | int x0,
77 | int y0,
78 | int z0,
79 | int x1,
80 | int y1,
81 | int z1,
82 | ::Block const& edgeBlock,
83 | ::Block const& fillBlock,
84 | bool skipAir
85 | );
86 |
87 | // vIndex: 12
88 | virtual void addHardcodedSpawnAreas(::LevelChunk& chunk) const;
89 | // NOLINTEND
90 |
91 | public:
92 | // member functions
93 | // NOLINTBEGIN
94 | MCAPI void addTerrainAdjustmentToken(::std::shared_ptr token);
95 |
96 | MCAPI void generateBox(
97 | ::BlockSource& region,
98 | ::BoundingBox const& chunkBB,
99 | int x0,
100 | int y0,
101 | int z0,
102 | int x1,
103 | int y1,
104 | int z1,
105 | bool random,
106 | ::Random& selector,
107 | ::BlockSelector const& skipAir
108 | );
109 |
110 | MCAPI void generateMaybeBox(
111 | ::BlockSource& region,
112 | ::BoundingBox const& chunkBB,
113 | ::Random& random,
114 | float probability,
115 | int x0,
116 | int y0,
117 | int z0,
118 | int x1,
119 | int y1,
120 | int z1,
121 | ::Block const& edgeBlock,
122 | ::Block const& fillBlock,
123 | bool excludeSky,
124 | bool skipAir
125 | );
126 |
127 | MCAPI ::Block const& getBlock(::BlockSource& region, int x, int y, int z, ::BoundingBox const& chunkBB);
128 |
129 | MCAPI ushort getOrientationData(::Block const* block, ushort data);
130 |
131 | MCAPI int getWorldY(int y);
132 |
133 | MCAPI bool isAboveGround(int x0, int y1, int z, ::BlockSource& region);
134 | // NOLINTEND
135 |
136 | public:
137 | // destructor thunk
138 | // NOLINTBEGIN
139 | MCFOLD void $dtor();
140 | // NOLINTEND
141 |
142 | public:
143 | // virtual function thunks
144 | // NOLINTBEGIN
145 | MCAPI void $moveBoundingBox(int dx, int dy, int dz);
146 |
147 | MCFOLD ::StructurePieceType $getType() const;
148 |
149 | MCFOLD void $addChildren(
150 | ::StructurePiece& startPiece,
151 | ::std::vector<::std::unique_ptr<::StructurePiece>>& pieces,
152 | ::Random& random
153 | );
154 |
155 | MCFOLD void $postProcessMobsAt(::BlockSource& region, ::Random& random, ::BoundingBox const& chunkBB);
156 |
157 | MCAPI bool $isInInvalidLocation(::BlockSource& region, ::BoundingBox const& chunkBB);
158 |
159 | MCAPI int $getWorldX(int x, int z);
160 |
161 | MCAPI int $getWorldZ(int x, int z);
162 |
163 | MCAPI void
164 | $placeBlock(::BlockSource& region, ::Block const& block, int x, int y, int z, ::BoundingBox const& chunkBB);
165 |
166 | MCFOLD bool $canBeReplaced(::BlockSource&, int const, int const, int const, ::BoundingBox const&);
167 |
168 | MCAPI void $generateBox(
169 | ::BlockSource& region,
170 | ::BoundingBox const& chunkBB,
171 | int x0,
172 | int y0,
173 | int z0,
174 | int x1,
175 | int y1,
176 | int z1,
177 | ::Block const& edgeBlock,
178 | ::Block const& fillBlock,
179 | bool skipAir
180 | );
181 |
182 | MCFOLD void $addHardcodedSpawnAreas(::LevelChunk& chunk) const;
183 | // NOLINTEND
184 |
185 | public:
186 | // vftables
187 | // NOLINTBEGIN
188 | MCAPI static void** $vftable();
189 | // NOLINTEND
190 | };
191 |
--------------------------------------------------------------------------------
/src/test/mc/StructurePoolBlockPredicateBlockMatchRandom.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "mc/_HeaderOutputPredefine.h"
4 |
5 | // auto generated inclusion list
6 | #include "mc/world/level/levelgen/structure/structurepools/IStructurePoolBlockPredicate.h"
7 | #include "mc/world/level/levelgen/structure/structurepools/StructurePoolBlockPredicateType.h"
8 |
9 | // auto generated forward declare list
10 | // clang-format off
11 | class Block;
12 | class BlockPos;
13 | class Randomize;
14 | namespace Util { class XXHash; }
15 | // clang-format on
16 |
17 | class StructurePoolBlockPredicateBlockMatchRandom : public ::IStructurePoolBlockPredicate {
18 | public:
19 | // member variables
20 | // NOLINTBEGIN
21 | ::ll::TypedStorage<8, 8, Block const*> mBlock;
22 | ::ll::TypedStorage<4, 4, float const> mProbability;
23 | // NOLINTEND
24 |
25 | StructurePoolBlockPredicateBlockMatchRandom(::Block const& block, float probability)
26 | : mBlock(&block),
27 | mProbability(probability){};
28 |
29 | public:
30 | // prevent constructor by default
31 |
32 | public:
33 | // virtual functions
34 | // NOLINTBEGIN
35 | // vIndex: 2
36 | virtual bool test(::Block const& block, ::Randomize& randomize) const /*override*/;
37 |
38 | // vIndex: 1
39 | virtual bool test(::BlockPos const& worldPos, ::BlockPos const& refPos, ::Randomize& randomize) const /*override*/;
40 |
41 | // vIndex: 5
42 | virtual ::StructurePoolBlockPredicateType getType() const /*override*/;
43 |
44 | // vIndex: 6
45 | virtual void appendMetadataKey(::Util::XXHash& hash) const /*override*/;
46 |
47 | // vIndex: 0
48 | virtual ~StructurePoolBlockPredicateBlockMatchRandom() /*override*/ = default;
49 | // NOLINTEND
50 |
51 | public:
52 | // destructor thunk
53 | // NOLINTBEGIN
54 |
55 | // NOLINTEND
56 |
57 | public:
58 | // virtual function thunks
59 | // NOLINTBEGIN
60 | MCAPI bool $test(::Block const& block, ::Randomize& randomize) const;
61 |
62 | MCFOLD bool $test(::BlockPos const& worldPos, ::BlockPos const& refPos, ::Randomize& randomize) const;
63 |
64 | MCFOLD ::StructurePoolBlockPredicateType $getType() const;
65 |
66 | MCAPI void $appendMetadataKey(::Util::XXHash& hash) const;
67 | // NOLINTEND
68 |
69 | public:
70 | // vftables
71 | // NOLINTBEGIN
72 | MCAPI static void** $vftable();
73 | // NOLINTEND
74 | };
75 |
--------------------------------------------------------------------------------
/src/test/mc/StructurePoolBlockRule.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "mc/_HeaderOutputPredefine.h"
4 | #include "mc/world/level/levelgen/structure/structurepools/IStructurePoolBlockPredicate.h"
5 |
6 | // auto generated forward declare list
7 | // clang-format off
8 | class Block;
9 | class BlockPos;
10 | class Random;
11 | // clang-format on
12 |
13 | class StructurePoolBlockRule {
14 | public:
15 | // member variables
16 | // NOLINTBEGIN
17 | ::ll::TypedStorage<8, 8, std::unique_ptr const> mSourcePredicate;
18 | ::ll::TypedStorage<8, 8, std::unique_ptr const> mTargetPredicate;
19 | ::ll::TypedStorage<8, 8, std::unique_ptr const> mPositionPredicate;
20 | ::ll::TypedStorage<8, 8, Block const*> mResultBlock;
21 | // NOLINTEND
22 |
23 | StructurePoolBlockRule(
24 | ::std::unique_ptr<::IStructurePoolBlockPredicate>&& sourceBlockPredicate,
25 | ::std::unique_ptr<::IStructurePoolBlockPredicate>&& targetBlockPredicate,
26 | ::Block const* resultBlock
27 | )
28 | : mSourcePredicate(std::move(sourceBlockPredicate)),
29 | mTargetPredicate(std::move(targetBlockPredicate)),
30 | mResultBlock(resultBlock){};
31 |
32 | public:
33 | // prevent constructor by default
34 |
35 |
36 | public:
37 | // member functions
38 | // NOLINTBEGIN
39 | MCAPI bool processRule(
40 | ::Block const& sourceBlock,
41 | ::Block const& targetBlock,
42 | ::Random& random,
43 | ::Block const*& outputBlock,
44 | ::BlockPos const& worldPos,
45 | ::BlockPos const& refPos
46 | ) const;
47 | // NOLINTEND
48 | };
49 |
--------------------------------------------------------------------------------
/src/test/mc/StructureTemplatePool.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "mc/_HeaderOutputPredefine.h"
4 |
5 | // auto generated inclusion list
6 | #include "mc/world/level/levelgen/structure/Projection.h"
7 |
8 | // auto generated forward declare list
9 | // clang-format off
10 | class Random;
11 | class StructurePoolElement;
12 | struct StructureTemplateRegistrationContext;
13 | struct WeightedStructureTemplateRegistration;
14 | // clang-format on
15 |
16 | class StructureTemplatePool {
17 | public:
18 | // member variables
19 | // NOLINTBEGIN
20 | ::ll::TypedStorage<8, 32, std::string> mName;
21 | ::ll::TypedStorage<8, 24, std::vector> mTemplates;
22 | ::ll::TypedStorage<8, 32, std::string> mFallback;
23 | // NOLINTEND
24 |
25 | public:
26 | // prevent constructor by default
27 |
28 | public:
29 | // member functions
30 | // NOLINTBEGIN
31 | MCAPI StructureTemplatePool(
32 | ::std::string name,
33 | ::std::string fallback,
34 | ::std::vector<::std::pair<::StructurePoolElement const*, int>> const& templates
35 | );
36 |
37 | MCAPI StructureTemplatePool(
38 | ::StructureTemplateRegistrationContext context,
39 | ::std::string_view name,
40 | ::std::string_view fallback,
41 | ::Projection projection,
42 | ::std::initializer_list<::WeightedStructureTemplateRegistration> pieces
43 | );
44 |
45 | MCAPI ::std::vector getShuffledTemplateIndexes(::Random& random) const;
46 |
47 | MCAPI ~StructureTemplatePool();
48 | // NOLINTEND
49 |
50 | public:
51 | // static functions
52 | // NOLINTBEGIN
53 | MCAPI static ::std::unique_ptr<::StructureTemplatePool> create(
54 | ::StructureTemplateRegistrationContext context,
55 | ::std::string_view name,
56 | ::std::string_view fallback,
57 | ::std::initializer_list<::WeightedStructureTemplateRegistration> pieces,
58 | ::Projection projection
59 | );
60 | // NOLINTEND
61 |
62 | public:
63 | // constructor thunks
64 | // NOLINTBEGIN
65 | MCAPI void* $ctor(
66 | ::std::string name,
67 | ::std::string fallback,
68 | ::std::vector<::std::pair<::StructurePoolElement const*, int>> const& templates
69 | );
70 |
71 | MCAPI void* $ctor(
72 | ::StructureTemplateRegistrationContext context,
73 | ::std::string_view name,
74 | ::std::string_view fallback,
75 | ::Projection projection,
76 | ::std::initializer_list<::WeightedStructureTemplateRegistration> pieces
77 | );
78 | // NOLINTEND
79 |
80 | public:
81 | // destructor thunk
82 | // NOLINTBEGIN
83 | MCAPI void $dtor();
84 | // NOLINTEND
85 | };
86 |
--------------------------------------------------------------------------------
/src/test/mc/StructureTemplateRegistrationContext.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "mc/_HeaderOutputPredefine.h"
4 |
5 | // auto generated inclusion list
6 | #include "mc/deps/core/utility/NonOwnerPointer.h"
7 | #include "mc/resources/BaseGameVersion.h"
8 |
9 | // auto generated forward declare list
10 | // clang-format off
11 | class Experiments;
12 | class FeatureRegistry;
13 | class JigsawStructureElementRegistry;
14 | class StructureManager;
15 | // clang-format on
16 |
17 | struct StructureTemplateRegistrationContext {
18 | public:
19 | // member variables
20 | // NOLINTBEGIN
21 | ::ll::TypedStorage<8, 24, ::Bedrock::NotNullNonOwnerPtr<::StructureManager>> mManager;
22 | ::ll::TypedStorage<8, 8, ::JigsawStructureElementRegistry&> mStructureRegistry;
23 | ::ll::TypedStorage<8, 8, ::FeatureRegistry&> mFeatureRegistry;
24 | ::ll::TypedStorage<8, 32, ::BaseGameVersion> mBaseGameVersion;
25 | ::ll::TypedStorage<8, 8, ::Experiments const&> mExperiments;
26 | // NOLINTEND
27 |
28 | StructureTemplateRegistrationContext(
29 | Bedrock::NotNullNonOwnerPtr<::StructureManager> manager,
30 | JigsawStructureElementRegistry& structureRegistry,
31 | FeatureRegistry& featureRegistry,
32 | BaseGameVersion baseGameVersion,
33 | Experiments const& experiments
34 | )
35 | : mManager(manager),
36 | mStructureRegistry(structureRegistry),
37 | mFeatureRegistry(featureRegistry),
38 | mBaseGameVersion(baseGameVersion),
39 | mExperiments(experiments){};
40 |
41 | public:
42 | // prevent constructor by default
43 | StructureTemplateRegistrationContext& operator=(StructureTemplateRegistrationContext const&);
44 | StructureTemplateRegistrationContext();
45 |
46 | public:
47 | // member functions
48 | // NOLINTBEGIN
49 | MCNAPI StructureTemplateRegistrationContext(::StructureTemplateRegistrationContext const&);
50 |
51 | MCNAPI StructureTemplateRegistrationContext(::StructureTemplateRegistrationContext&&);
52 |
53 | MCNAPI ~StructureTemplateRegistrationContext();
54 | // NOLINTEND
55 |
56 | public:
57 | // constructor thunks
58 | // NOLINTBEGIN
59 | MCNAPI void* $ctor(::StructureTemplateRegistrationContext const&);
60 |
61 | MCNAPI void* $ctor(::StructureTemplateRegistrationContext&&);
62 | // NOLINTEND
63 |
64 | public:
65 | // destructor thunk
66 | // NOLINTBEGIN
67 | MCNAPI void $dtor();
68 | // NOLINTEND
69 | };
70 |
--------------------------------------------------------------------------------
/src/test/mc/WeightedStructureTemplateRegistration.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "mc/_HeaderOutputPredefine.h"
4 |
5 | // auto generated inclusion list
6 | #include "mc/world/level/levelgen/structure/Projection.h"
7 |
8 | // auto generated forward declare list
9 | // clang-format off
10 | class StructurePoolElement;
11 | struct StructureTemplateRegistrationContext;
12 | // clang-format on
13 |
14 | struct WeightedStructureTemplateRegistration {
15 | public:
16 | // member variables
17 | // NOLINTBEGIN
18 | std::function<::StructurePoolElement const&(::StructureTemplateRegistrationContext, ::Projection)> mElementFactory;
19 | int mWeight;
20 | // NOLINTEND
21 | };
22 |
--------------------------------------------------------------------------------
/tooth.json:
--------------------------------------------------------------------------------
1 | {
2 | "format_version": 3,
3 | "format_uuid": "289f771f-2c9a-4d73-9f3f-8492495a924d",
4 | "tooth": "github.com/LiteLDev/MoreDimensions",
5 | "version": "0.7.0",
6 | "info": {
7 | "name": "MoreDimensions",
8 | "description": "More than three dimensions on BDS!",
9 | "tags": [
10 | "platform:levilamina",
11 | "library",
12 | "type:mod"
13 | ],
14 | "avatar_url": ""
15 | },
16 | "variants": [
17 | {
18 | "platform": "win-x64",
19 | "assets": [
20 | {
21 | "type": "zip",
22 | "urls": [
23 | "https://{{tooth}}/releases/download/v{{version}}/more-dimensions-windows-x64-v{{version}}.zip"
24 | ],
25 | "dependencies": {
26 | "github.com/LiteLDev/LeviLamina": "1.2.*"
27 | },
28 | "placements": [
29 | {
30 | "type": "dir",
31 | "src": "more-dimensions/",
32 | "dest": "plugins/more-dimensions/"
33 | }
34 | ]
35 | }
36 | ]
37 | }
38 | ]
39 | }
40 |
--------------------------------------------------------------------------------
/xmake.lua:
--------------------------------------------------------------------------------
1 | add_rules("mode.debug", "mode.release")
2 |
3 | add_repositories("liteldev-repo https://github.com/LiteLDev/xmake-repo.git")
4 |
5 | if is_config("target_type", "server") then
6 | add_requires("levilamina ef5b1d2541205b8eb806729237e0e5f30e0b7c90", {configs = {target_type = "server"}})
7 | else
8 | add_requires("levilamina 1.2.0", {configs = {target_type = "client"}})
9 | end
10 |
11 | add_requires("levibuildscript")
12 | add_requires("snappy 1.2.1")
13 | add_requires("preloader 1.15.3")
14 |
15 | if not has_config("vs_runtime") then
16 | set_runtimes("MD")
17 | end
18 |
19 | option("tests")
20 | set_default(false)
21 | set_showmenu(true)
22 | set_description("Enable tests")
23 |
24 | option("target_type")
25 | set_default("server")
26 | set_showmenu(true)
27 | set_values("server", "client")
28 | option_end()
29 |
30 | target("more-dimensions")
31 | add_rules("@levibuildscript/linkrule")
32 | add_rules("@levibuildscript/modpacker")
33 | add_cxflags( "/EHa", "/utf-8", "/W4", "/w44265", "/w44289", "/w44296", "/w45263", "/w44738", "/w45204")
34 | add_defines("NOMINMAX", "UNICODE", "MORE_DIMENSIONS_EXPORTS")
35 | add_packages("levilamina", "snappy", "preloader")
36 | set_exceptions("none")
37 | set_kind("shared")
38 | set_languages("c++20")
39 | set_symbols("debug")
40 | add_files(
41 | "src/more_dimensions/**.cpp"
42 | )
43 | add_includedirs(
44 | "src"
45 | )
46 | add_headerfiles(
47 | "src/(more_dimensions/api/**.h)",
48 | "src/(more_dimensions/core/Macros.h)"
49 | )
50 | if has_config("tests") then
51 | add_files("src/test/TestCustomDimension.cpp",
52 | "src/test/generator/flat-gen-village/**.cpp",
53 | "src/test/generator/generator-terrain/**.cpp",
54 | "src/test/generator/generator-custom-structure/**.cpp"
55 | )
56 | end
--------------------------------------------------------------------------------