XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

MyDimension

【Java】我的维度模组

公开
关注 0 Fork 0 Star 0
返回提交历史

XFEstudio/MyDimension

优化维度加载机制

a3d108a
XFE工作室室长 <mail@xfegzs.com>
提交于

代码差异

3 个文件 +202 -4
Modified build.gradle +1 -1
@@ -146,7 +146,7 @@ tasks.register('generatePlayerMindDimensions') {
146 146 ]
147 147 ]
148 148
149 (0..<64).each { slot ->
149 (0..<2).each { slot ->
150 150 dimensions.each { name, json ->
151 151 def file = new File(dimensionDir, "slot_${slot}/${name}.json")
152 152 file.parentFile.mkdirs()
Modified gradle.properties +1 -1
@@ -11,7 +11,7 @@ loader_version_range=[47,)
11 11 mod_id=mydimension
12 12 mod_name=\u6211\u7684\u7ef4\u5ea6
13 13 mod_license=CC0-1.0
14 mod_version=2.1.1
14 mod_version=2.2.0
15 15 mod_group_id=com.xfestudio.mydimension
16 16 maven_group=com.xfestudio
17 17 archives_base_name=mydimension
Modified src/main/java/com/xfestudio/mydimension/world/MindInstances.java +200 -2
@@ -1,29 +1,56 @@
1 1 package com.xfestudio.mydimension.world;
2 2
3 import com.xfestudio.mydimension.MyDimension;
3 4 import net.minecraft.nbt.CompoundTag;
4 5 import net.minecraft.resources.ResourceKey;
5 6 import net.minecraft.server.MinecraftServer;
6 7 import net.minecraft.server.level.ServerPlayer;
7 8 import net.minecraft.world.level.Level;
8 9 import net.minecraft.world.level.saveddata.SavedData;
10 import net.minecraft.world.level.storage.LevelResource;
9 11
12 import java.io.IOException;
13 import java.nio.charset.StandardCharsets;
14 import java.nio.file.Files;
15 import java.nio.file.Path;
16 import java.util.Comparator;
10 17 import java.util.HashMap;
11 18 import java.util.Map;
12 19 import java.util.UUID;
13 20
14 21 public class MindInstances {
15 22 public static final int MAX_PLAYER_SLOTS = 64;
23 public static final int BUILT_IN_PLAYER_SLOTS = 2;
16 24 private static final String DATA_NAME = "mydimension_mind_instances";
17 25 private static final String NEXT_SLOT_TAG = "NextSlot";
26 private static final String REQUESTED_SLOTS_TAG = "RequestedSlots";
18 27 private static final String SLOTS_TAG = "Slots";
28 private static final String GENERATED_DATAPACK_NAME = "mydimension_dynamic_player_minds";
19 29
20 30 public static ResourceKey<Level> dimensionFor(ServerPlayer player, ResourceKey<Level> baseDimension) {
21 31 int slot = slotFor(player);
22 return slot < 0 || slot >= MAX_PLAYER_SLOTS ? baseDimension : ModDimensions.playerDimension(baseDimension, slot);
32 if (slot < 0 || slot >= MAX_PLAYER_SLOTS) {
33 return baseDimension;
34 }
35
36 MinecraftServer server = player.getServer();
37 ResourceKey<Level> privateDimension = ModDimensions.playerDimension(baseDimension, slot);
38 if (server.getLevel(privateDimension) != null) {
39 return privateDimension;
40 }
41
42 data(server).requestSlots(server, slot + 1);
43 return baseDimension;
23 44 }
24 45
25 46 public static int slotFor(ServerPlayer player) {
26 return data(player.getServer()).slotFor(player.getUUID());
47 MinecraftServer server = player.getServer();
48 MindInstanceData data = data(server);
49 int slot = data.slotFor(player.getUUID());
50 if (slot >= BUILT_IN_PLAYER_SLOTS) {
51 data.requestSlots(server, slot + 1);
52 }
53 return slot;
27 54 }
28 55
29 56 private static MindInstanceData data(MinecraftServer server) {
@@ -33,10 +60,12 @@ public class MindInstances {
33 60 public static class MindInstanceData extends SavedData {
34 61 private final Map<UUID, Integer> slots = new HashMap<>();
35 62 private int nextSlot;
63 private int requestedSlots = BUILT_IN_PLAYER_SLOTS;
36 64
37 65 public static MindInstanceData load(CompoundTag tag) {
38 66 MindInstanceData data = new MindInstanceData();
39 67 data.nextSlot = tag.getInt(NEXT_SLOT_TAG);
68 data.requestedSlots = Math.max(BUILT_IN_PLAYER_SLOTS, tag.contains(REQUESTED_SLOTS_TAG) ? tag.getInt(REQUESTED_SLOTS_TAG) : data.nextSlot);
40 69 CompoundTag slotsTag = tag.getCompound(SLOTS_TAG);
41 70 for (String key : slotsTag.getAllKeys()) {
42 71 try {
@@ -50,6 +79,7 @@ public class MindInstances {
50 79 @Override
51 80 public CompoundTag save(CompoundTag tag) {
52 81 tag.putInt(NEXT_SLOT_TAG, nextSlot);
82 tag.putInt(REQUESTED_SLOTS_TAG, requestedSlots);
53 83 CompoundTag slotsTag = new CompoundTag();
54 84 for (Map.Entry<UUID, Integer> entry : slots.entrySet()) {
55 85 slotsTag.putInt(entry.getKey().toString(), entry.getValue());
@@ -73,5 +103,173 @@ public class MindInstances {
73 103 setDirty();
74 104 return slot;
75 105 }
106
107 private void requestSlots(MinecraftServer server, int slotsNeeded) {
108 int clampedSlots = Math.min(Math.max(slotsNeeded, BUILT_IN_PLAYER_SLOTS), MAX_PLAYER_SLOTS);
109 if (clampedSlots > requestedSlots) {
110 requestedSlots = clampedSlots;
111 setDirty();
112 }
113
114 if (clampedSlots > BUILT_IN_PLAYER_SLOTS) {
115 writeGeneratedDatapack(server, clampedSlots);
116 }
117 }
118 }
119
120 private static void writeGeneratedDatapack(MinecraftServer server, int slotsNeeded) {
121 Path datapackRoot = server.getWorldPath(LevelResource.DATAPACK_DIR).resolve(GENERATED_DATAPACK_NAME);
122 Path dimensionDir = datapackRoot.resolve("data").resolve(MyDimension.MOD_ID).resolve("dimension").resolve("player_minds");
123 try {
124 deleteDirectory(dimensionDir);
125 Files.createDirectories(dimensionDir);
126 Files.writeString(datapackRoot.resolve("pack.mcmeta"), """
127 {
128 "pack": {
129 "description": "My Dimension dynamic private mind dimensions",
130 "pack_format": 15
131 }
132 }
133 """, StandardCharsets.UTF_8);
134
135 for (int slot = BUILT_IN_PLAYER_SLOTS; slot < slotsNeeded; slot++) {
136 writeSlotDimensions(dimensionDir, slot);
137 }
138 } catch (IOException exception) {
139 MyDimension.LOGGER.warn("Failed to write dynamic player mind dimension datapack", exception);
140 }
141 }
142
143 private static void writeSlotDimensions(Path dimensionDir, int slot) throws IOException {
144 Path slotDir = dimensionDir.resolve("slot_" + slot);
145 Files.createDirectories(slotDir);
146 Files.writeString(slotDir.resolve("ethereal_mind.json"), etherealMindJson(), StandardCharsets.UTF_8);
147 Files.writeString(slotDir.resolve("mirror_mind.json"), mirrorMindJson(), StandardCharsets.UTF_8);
148 Files.writeString(slotDir.resolve("water_mind.json"), waterMindJson(), StandardCharsets.UTF_8);
149 Files.writeString(slotDir.resolve("nature_mind.json"), natureMindJson(), StandardCharsets.UTF_8);
150 Files.writeString(slotDir.resolve("soaring_mind.json"), soaringMindJson(), StandardCharsets.UTF_8);
151 }
152
153 private static void deleteDirectory(Path directory) throws IOException {
154 if (!Files.exists(directory)) {
155 return;
156 }
157
158 try (var paths = Files.walk(directory)) {
159 for (Path path : paths.sorted(Comparator.reverseOrder()).toList()) {
160 Files.deleteIfExists(path);
161 }
162 }
163 }
164
165 private static String etherealMindJson() {
166 return """
167 {
168 "type": "mydimension:ethereal_mind",
169 "generator": {
170 "type": "minecraft:flat",
171 "settings": {
172 "biome": "mydimension:ethereal_mind",
173 "features": false,
174 "lakes": false,
175 "layers": [
176 { "block": "minecraft:stone", "height": 60 },
177 { "block": "minecraft:dirt", "height": 3 },
178 { "block": "minecraft:quartz_block", "height": 3 }
179 ],
180 "structure_overrides": []
181 }
182 }
183 }
184 """;
185 }
186
187 private static String mirrorMindJson() {
188 return """
189 {
190 "type": "mydimension:mirror_mind",
191 "generator": {
192 "type": "mydimension:no_structure_noise",
193 "biome_source": {
194 "type": "minecraft:multi_noise",
195 "preset": "minecraft:overworld"
196 },
197 "settings": "minecraft:overworld"
198 }
199 }
200 """;
201 }
202
203 private static String waterMindJson() {
204 return """
205 {
206 "type": "mydimension:water_mind",
207 "generator": {
208 "type": "minecraft:flat",
209 "settings": {
210 "biome": "mydimension:water_mind",
211 "features": false,
212 "lakes": false,
213 "layers": [
214 { "block": "minecraft:stone", "height": 20 },
215 { "block": "minecraft:gravel", "height": 5 },
216 { "block": "minecraft:water", "height": 50 }
217 ],
218 "structure_overrides": []
219 }
220 }
221 }
222 """;
223 }
224
225 private static String natureMindJson() {
226 return """
227 {
228 "type": "mydimension:nature_mind",
229 "generator": {
230 "type": "minecraft:flat",
231 "settings": {
232 "biome": "mydimension:nature_mind",
233 "features": true,
234 "lakes": false,
235 "layers": [
236 { "block": "minecraft:stone", "height": 50 },
237 { "block": "minecraft:dirt", "height": 9 },
238 { "block": "minecraft:grass_block", "height": 1 }
239 ],
240 "structure_overrides": []
241 }
242 }
243 }
244 """;
245 }
246
247 private static String soaringMindJson() {
248 return """
249 {
250 "type": "mydimension:soaring_mind",
251 "generator": {
252 "type": "mydimension:soaring_islands",
253 "biome_source": {
254 "type": "minecraft:checkerboard",
255 "biomes": [
256 "minecraft:plains",
257 "minecraft:forest",
258 "minecraft:flower_forest",
259 "minecraft:birch_forest",
260 "minecraft:meadow",
261 "minecraft:cherry_grove",
262 "minecraft:snowy_plains",
263 "minecraft:grove",
264 "minecraft:desert",
265 "minecraft:savanna",
266 "minecraft:jungle",
267 "minecraft:windswept_hills"
268 ],
269 "scale": 3
270 }
271 }
272 }
273 """;
76 274 }
77 275 }