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

MyDimension

【Java】我的维度模组

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

XFEstudio/MyDimension

优化复制逻辑

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

代码差异

6 个文件 +57 -68
Modified build.gradle +1 -1
@@ -122,7 +122,7 @@ tasks.register('generatePlayerMindDimensions') {
122 122 ]
123 123 ]
124 124
125 (0..<128).each { slot ->
125 (0..<64).each { slot ->
126 126 dimensions.each { name, json ->
127 127 def file = new File(dimensionDir, "slot_${slot}/${name}.json")
128 128 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.0.0
14 mod_version=2.0.2
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/item/RiftItem.java +51 -62
@@ -9,7 +9,6 @@ import net.minecraft.nbt.CompoundTag;
9 9 import net.minecraft.network.chat.Component;
10 10 import net.minecraft.resources.ResourceKey;
11 11 import net.minecraft.resources.ResourceLocation;
12 import net.minecraft.server.MinecraftServer;
13 12 import net.minecraft.server.level.ServerLevel;
14 13 import net.minecraft.server.level.ServerPlayer;
15 14 import net.minecraft.sounds.SoundEvents;
@@ -24,10 +23,9 @@ import net.minecraft.world.entity.projectile.ProjectileUtil;
24 23 import net.minecraft.world.item.Item;
25 24 import net.minecraft.world.item.ItemStack;
26 25 import net.minecraft.world.level.Level;
27 import net.minecraft.world.level.dimension.DimensionType;
26 import net.minecraft.world.level.block.entity.BlockEntity;
28 27 import net.minecraft.world.level.levelgen.Heightmap;
29 28 import net.minecraft.world.level.portal.PortalInfo;
30 import net.minecraft.world.level.storage.LevelResource;
31 29 import net.minecraft.world.phys.AABB;
32 30 import net.minecraft.world.phys.EntityHitResult;
33 31 import net.minecraft.world.phys.Vec3;
@@ -35,17 +33,12 @@ import net.minecraftforge.api.distmarker.Dist;
35 33 import net.minecraftforge.common.util.ITeleporter;
36 34 import net.minecraftforge.fml.DistExecutor;
37 35
38 import java.io.IOException;
39 import java.nio.file.FileVisitResult;
40 import java.nio.file.Files;
41 import java.nio.file.Path;
42 import java.nio.file.SimpleFileVisitor;
43 import java.nio.file.attribute.BasicFileAttributes;
44 36 import java.util.function.Function;
45 37
46 38 public class RiftItem extends Item {
47 39 public static final double ETHEREAL_SURFACE_Y = 66.0D;
48 40 public static final String IMPORTED_TO_ETHEREAL_MIND = "mydimension_imported_to_ethereal_mind";
41 private static final int COPY_CHUNK_RADIUS = 1;
49 42 private static final String SELECTED_ACTION_TAG = "SelectedAction";
50 43 private static final String RETURN_POINT_TAG = "ReturnPoint";
51 44 private static final String MIND_POINTS_TAG = "MindPoints";
@@ -272,72 +265,68 @@ public class RiftItem extends Item {
272 265 return;
273 266 }
274 267
275 MinecraftServer server = player.getServer();
276 if (server == null || server.getLevel(sourceDimension) == null || server.getLevel(targetDimension) == null) {
268 ServerLevel sourceLevel = player.getServer().getLevel(sourceDimension);
269 ServerLevel targetLevel = player.getServer().getLevel(targetDimension);
270 if (sourceLevel == null || targetLevel == null) {
277 271 player.displayClientMessage(Component.translatable("message.mydimension.missing_dimension"), true);
278 272 return;
279 273 }
280 274
281 try {
282 server.saveEverything(false, true, false);
283 Path worldRoot = server.getWorldPath(LevelResource.ROOT).normalize();
284 Path source = DimensionType.getStorageFolder(sourceDimension, worldRoot).normalize();
285 Path target = DimensionType.getStorageFolder(targetDimension, worldRoot).normalize();
286 if (!source.startsWith(worldRoot) || !target.startsWith(worldRoot) || source.equals(target)) {
287 player.displayClientMessage(Component.translatable("message.mydimension.copy_failed"), true);
288 return;
289 }
275 int copiedBlocks = copyNearbyBlocks(sourceLevel, targetLevel, player.blockPosition());
276 player.displayClientMessage(Component.translatable("message.mydimension.copy_done", copiedBlocks), true);
277 }
290 278
291 if (!Files.exists(source)) {
292 player.displayClientMessage(Component.translatable("message.mydimension.copy_missing_shared"), true);
293 return;
279 private static int copyNearbyBlocks(ServerLevel sourceLevel, ServerLevel targetLevel, BlockPos center) {
280 int centerChunkX = center.getX() >> 4;
281 int centerChunkZ = center.getZ() >> 4;
282 int minY = Math.max(sourceLevel.getMinBuildHeight(), targetLevel.getMinBuildHeight());
283 int maxY = Math.min(sourceLevel.getMaxBuildHeight(), targetLevel.getMaxBuildHeight());
284 BlockPos.MutableBlockPos sourcePos = new BlockPos.MutableBlockPos();
285 BlockPos.MutableBlockPos targetPos = new BlockPos.MutableBlockPos();
286 int copied = 0;
287
288 for (int chunkX = centerChunkX - COPY_CHUNK_RADIUS; chunkX <= centerChunkX + COPY_CHUNK_RADIUS; chunkX++) {
289 for (int chunkZ = centerChunkZ - COPY_CHUNK_RADIUS; chunkZ <= centerChunkZ + COPY_CHUNK_RADIUS; chunkZ++) {
290 sourceLevel.getChunk(chunkX, chunkZ);
291 targetLevel.getChunk(chunkX, chunkZ);
292
293 int minX = chunkX << 4;
294 int minZ = chunkZ << 4;
295 for (int x = minX; x < minX + 16; x++) {
296 for (int z = minZ; z < minZ + 16; z++) {
297 for (int y = minY; y < maxY; y++) {
298 sourcePos.set(x, y, z);
299 targetPos.set(x, y, z);
300 var state = sourceLevel.getBlockState(sourcePos);
301 targetLevel.setBlock(targetPos, state, 2);
302 copyBlockEntity(sourceLevel, targetLevel, sourcePos, targetPos);
303 copied++;
304 }
305 }
306 }
294 307 }
295
296 deleteDirectory(target);
297 copyDirectory(source, target);
298 player.displayClientMessage(Component.translatable("message.mydimension.copy_done"), true);
299 } catch (IOException exception) {
300 player.displayClientMessage(Component.translatable("message.mydimension.copy_failed"), true);
301 308 }
309
310 return copied;
302 311 }
303 312
304 private static void deleteDirectory(Path path) throws IOException {
305 if (!Files.exists(path)) {
313 private static void copyBlockEntity(ServerLevel sourceLevel, ServerLevel targetLevel, BlockPos sourcePos, BlockPos targetPos) {
314 BlockEntity sourceBlockEntity = sourceLevel.getBlockEntity(sourcePos);
315 if (sourceBlockEntity == null) {
306 316 return;
307 317 }
308 318
309 Files.walkFileTree(path, new SimpleFileVisitor<>() {
310 @Override
311 public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
312 Files.delete(file);
313 return FileVisitResult.CONTINUE;
314 }
315
316 @Override
317 public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
318 if (exc != null) {
319 throw exc;
320 }
321 Files.delete(dir);
322 return FileVisitResult.CONTINUE;
323 }
324 });
325 }
326
327 private static void copyDirectory(Path source, Path target) throws IOException {
328 Files.walkFileTree(source, new SimpleFileVisitor<>() {
329 @Override
330 public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
331 Files.createDirectories(target.resolve(source.relativize(dir)));
332 return FileVisitResult.CONTINUE;
333 }
319 BlockEntity targetBlockEntity = targetLevel.getBlockEntity(targetPos);
320 if (targetBlockEntity == null) {
321 return;
322 }
334 323
335 @Override
336 public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
337 Files.copy(file, target.resolve(source.relativize(file)));
338 return FileVisitResult.CONTINUE;
339 }
340 });
324 CompoundTag tag = sourceBlockEntity.saveWithFullMetadata();
325 tag.putInt("x", targetPos.getX());
326 tag.putInt("y", targetPos.getY());
327 tag.putInt("z", targetPos.getZ());
328 targetBlockEntity.load(tag);
329 targetBlockEntity.setChanged();
341 330 }
342 331
343 332 private static LivingEntity findLookedAtLivingEntity(ServerPlayer player) {
Modified src/main/java/com/xfestudio/mydimension/world/MindInstances.java +2 -2
@@ -12,14 +12,14 @@ import java.util.Map;
12 12 import java.util.UUID;
13 13
14 14 public class MindInstances {
15 public static final int MAX_PLAYER_SLOTS = 128;
15 public static final int MAX_PLAYER_SLOTS = 64;
16 16 private static final String DATA_NAME = "mydimension_mind_instances";
17 17 private static final String NEXT_SLOT_TAG = "NextSlot";
18 18 private static final String SLOTS_TAG = "Slots";
19 19
20 20 public static ResourceKey<Level> dimensionFor(ServerPlayer player, ResourceKey<Level> baseDimension) {
21 21 int slot = slotFor(player);
22 return slot < 0 ? baseDimension : ModDimensions.playerDimension(baseDimension, slot);
22 return slot < 0 || slot >= MAX_PLAYER_SLOTS ? baseDimension : ModDimensions.playerDimension(baseDimension, slot);
23 23 }
24 24
25 25 public static int slotFor(ServerPlayer player) {
Modified src/main/resources/assets/mydimension/lang/en_us.json +1 -1
@@ -46,6 +46,6 @@
46 46 "message.mydimension.copy_creative_only": "Only creative players can copy shared mind saves",
47 47 "message.mydimension.copy_private_unavailable": "No private mind slot is available, so the shared save cannot be copied",
48 48 "message.mydimension.copy_missing_shared": "The shared mind has no saved world data to copy yet",
49 "message.mydimension.copy_done": "Copied the shared mind save to your private mind",
49 "message.mydimension.copy_done": "Copied nearby shared mind blocks to your private mind: %s blocks",
50 50 "message.mydimension.copy_failed": "Failed to copy shared mind save"
51 51 }
Modified src/main/resources/assets/mydimension/lang/zh_cn.json +1 -1
@@ -46,7 +46,7 @@
46 46 "message.mydimension.copy_creative_only": "只有创造模式玩家可以复制公共心境存档",
47 47 "message.mydimension.copy_private_unavailable": "私有心境槽位不足,无法复制公共存档",
48 48 "message.mydimension.copy_missing_shared": "公共心境尚未生成存档,无法复制",
49 "message.mydimension.copy_done": "已复制公共心境存档到你的私有心境",
49 "message.mydimension.copy_done": "已复制公共心境附近方块到你的私有心境:%s 个方块",
50 50 "message.mydimension.copy_failed": "复制公共心境存档失败",
51 51 "itemGroup.mydimension": "我的维度"
52 52 }