返回提交历史
Modified
build.gradle
+1
-1
Modified
gradle.properties
+1
-1
Modified
src/main/java/com/xfestudio/mydimension/MyDimensionEvents.java
+1
-1
Modified
src/main/java/com/xfestudio/mydimension/client/RiftActionScreen.java
+109
-54
Modified
src/main/java/com/xfestudio/mydimension/item/RiftAction.java
+35
-11
Modified
src/main/java/com/xfestudio/mydimension/item/RiftItem.java
+108
-11
Modified
src/main/java/com/xfestudio/mydimension/world/MindInstances.java
+7
-2
Modified
src/main/resources/assets/mydimension/lang/en_us.json
+29
-4
Modified
src/main/resources/assets/mydimension/lang/zh_cn.json
+22
-0
Modified
src/main/resources/data/mydimension/advancements/recipes/misc/rift.json
+16
-3
Added
src/main/resources/data/mydimension/dimension/ethereal_mind.json
+26
-0
Added
src/main/resources/data/mydimension/dimension/mirror_mind.json
+11
-0
Added
src/main/resources/data/mydimension/dimension/nature_mind.json
+26
-0
Added
src/main/resources/data/mydimension/dimension/water_mind.json
+26
-0
Modified
src/main/resources/data/mydimension/recipes/rift.json
+11
-5
XFEstudio/MyDimension
优化UI显示等多个修改
e3fe034
代码差异
15 个文件
+429
-93
@@ -122,7 +122,7 @@ tasks.register('generatePlayerMindDimensions') {
122
122
]
123
123
]
124
124
125
(0..<32).each { slot ->
125
(0..<128).each { slot ->
126
126
dimensions.each { name, json ->
127
127
def file = new File(dimensionDir, "slot_${slot}/${name}.json")
128
128
file.parentFile.mkdirs()
@@ -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=1.3.9
14
mod_version=2.0.0
15
15
mod_group_id=com.xfestudio.mydimension
16
16
maven_group=com.xfestudio
17
17
archives_base_name=mydimension
@@ -235,7 +235,7 @@ public class MyDimensionEvents {
235
235
event.setCanceled(true);
236
236
237
237
if (!player.level().isClientSide()) {
238
RiftItem.sendToMind(player, target, stack, action.targetDimension());
238
RiftItem.sendToMind(player, target, stack, action);
239
239
}
240
240
}
241
241
@@ -17,18 +17,23 @@ import net.minecraft.resources.ResourceLocation;
17
17
import net.minecraft.util.Mth;
18
18
import net.minecraft.world.item.ItemStack;
19
19
20
import java.util.ArrayList;
21
import java.util.List;
22
20
23
public class RiftActionScreen extends Screen {
21
24
private static final int BUTTON_HEIGHT = 26;
22
private static final int BUTTON_GAP = 22;
23
private static final int ROW_GAP = 82;
25
private static final int BUTTON_GAP = 18;
24
26
private static final int TRAVEL_COLOR = 0xFF3E8DB8;
25
27
private static final int MOB_COLOR = 0xFF8B58C8;
26
28
private static final int ANCHOR_COLOR = 0xFFD6A23E;
29
private static final int COPY_COLOR = 0xFF4EBA7A;
27
30
private static final ResourceLocation RIFT_ICON = new ResourceLocation(MyDimension.MOD_ID, "textures/item/rift.png");
28
31
private static final ResourceLocation PORTAL_ICON = new ResourceLocation("minecraft", "textures/block/nether_portal.png");
29
32
private static final ResourceLocation ANCHOR_ICON = new ResourceLocation(MyDimension.MOD_ID, "textures/gui/rift_anchor_icon.png");
30
33
34
private Page page = Page.TRAVEL_PRIVATE;
31
35
private boolean inMindDimension;
36
private boolean creative;
32
37
33
38
public RiftActionScreen() {
34
39
super(Component.translatable("screen.mydimension.rift_actions"));
@@ -37,24 +42,14 @@ public class RiftActionScreen extends Screen {
37
42
@Override
38
43
protected void init() {
39
44
inMindDimension = minecraft != null && minecraft.player != null && ModDimensions.isMindDimension(minecraft.player.level().dimension());
45
creative = minecraft != null && minecraft.player != null && minecraft.player.isCreative();
40
46
41
RiftAction[] travelActions = new RiftAction[] {
42
RiftAction.ETHEREAL_MIND,
43
RiftAction.MIRROR_MIND,
44
RiftAction.WATER_MIND,
45
RiftAction.NATURE_MIND
46
};
47
addActionRow(travelActions, height / 2 - ROW_GAP);
48
47
int centerX = width / 2;
48
int centerY = height / 2;
49
addTabs(centerX, centerY - 108);
50
addActionGrid(currentActions(), centerY - 32);
49
51
if (inMindDimension) {
50
addCenteredActionButton(RiftAction.SET_ANCHOR, height / 2 + ROW_GAP - BUTTON_HEIGHT / 2);
51
} else {
52
addActionRow(new RiftAction[] {
53
RiftAction.SEND_MOB_ETHEREAL,
54
RiftAction.SEND_MOB_MIRROR,
55
RiftAction.SEND_MOB_WATER,
56
RiftAction.SEND_MOB_NATURE
57
}, height / 2 + ROW_GAP);
52
addCenteredActionButton(RiftAction.SET_ANCHOR, centerY + 78);
58
53
}
59
54
}
60
55
@@ -62,7 +57,6 @@ public class RiftActionScreen extends Screen {
62
57
public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTick) {
63
58
graphics.fillGradient(0, 0, width, height, 0xD0101218, 0xE0181026);
64
59
renderCenterPanel(graphics);
65
renderGuideLines(graphics);
66
60
super.render(graphics, mouseX, mouseY, partialTick);
67
61
}
68
62
@@ -71,53 +65,71 @@ public class RiftActionScreen extends Screen {
71
65
return false;
72
66
}
73
67
74
private void addActionRow(RiftAction[] actions, int centerY) {
75
int columns = actions.length;
76
int buttonWidth = rowButtonWidth(columns);
77
int totalWidth = columns * buttonWidth + (columns - 1) * BUTTON_GAP;
78
int x = width / 2 - totalWidth / 2;
79
int y = centerY - BUTTON_HEIGHT / 2;
68
private void addTabs(int centerX, int y) {
69
List<Page> pages = visiblePages();
70
int tabWidth = Math.max(68, Math.min(94, (width - 48 - (pages.size() - 1) * 8) / pages.size()));
71
int totalWidth = pages.size() * tabWidth + (pages.size() - 1) * 8;
72
int x = centerX - totalWidth / 2;
73
for (Page tab : pages) {
74
addRenderableWidget(new PageButton(x, y, tabWidth, tab));
75
x += tabWidth + 8;
76
}
77
}
80
78
81
for (RiftAction action : actions) {
82
addRenderableWidget(new ActionButton(x, y, buttonWidth, action, getSelectedAction() == action));
83
x += buttonWidth + BUTTON_GAP;
79
private List<Page> visiblePages() {
80
List<Page> pages = new ArrayList<>(List.of(Page.TRAVEL_PRIVATE, Page.TRAVEL_SHARED, Page.MOB_PRIVATE, Page.MOB_SHARED));
81
if (creative) {
82
pages.add(Page.COPY_SHARED);
83
} else if (page == Page.COPY_SHARED) {
84
page = Page.TRAVEL_PRIVATE;
85
}
86
return pages;
87
}
88
89
private RiftAction[] currentActions() {
90
return switch (page) {
91
case TRAVEL_PRIVATE -> new RiftAction[] {RiftAction.ETHEREAL_MIND, RiftAction.MIRROR_MIND, RiftAction.WATER_MIND, RiftAction.NATURE_MIND};
92
case TRAVEL_SHARED -> new RiftAction[] {RiftAction.SHARED_ETHEREAL_MIND, RiftAction.SHARED_MIRROR_MIND, RiftAction.SHARED_WATER_MIND, RiftAction.SHARED_NATURE_MIND};
93
case MOB_PRIVATE -> new RiftAction[] {RiftAction.SEND_MOB_ETHEREAL, RiftAction.SEND_MOB_MIRROR, RiftAction.SEND_MOB_WATER, RiftAction.SEND_MOB_NATURE};
94
case MOB_SHARED -> new RiftAction[] {RiftAction.SEND_MOB_SHARED_ETHEREAL, RiftAction.SEND_MOB_SHARED_MIRROR, RiftAction.SEND_MOB_SHARED_WATER, RiftAction.SEND_MOB_SHARED_NATURE};
95
case COPY_SHARED -> new RiftAction[] {RiftAction.COPY_SHARED_ETHEREAL, RiftAction.COPY_SHARED_MIRROR, RiftAction.COPY_SHARED_WATER, RiftAction.COPY_SHARED_NATURE};
96
};
97
}
98
99
private void addActionGrid(RiftAction[] actions, int top) {
100
int buttonWidth = rowButtonWidth(2);
101
int totalWidth = buttonWidth * 2 + BUTTON_GAP;
102
int left = width / 2 - totalWidth / 2;
103
for (int i = 0; i < actions.length; i++) {
104
int x = left + (i % 2) * (buttonWidth + BUTTON_GAP);
105
int y = top + (i / 2) * 42;
106
addRenderableWidget(new ActionButton(x, y, buttonWidth, actions[i], getSelectedAction() == actions[i]));
84
107
}
85
108
}
86
109
87
110
private void addCenteredActionButton(RiftAction action, int y) {
88
int buttonWidth = Mth.clamp(width / 4, 132, 176);
111
int buttonWidth = Mth.clamp(width / 4, 140, 190);
89
112
addRenderableWidget(new ActionButton(width / 2 - buttonWidth / 2, y, buttonWidth, action, getSelectedAction() == action));
90
113
}
91
114
92
115
private int rowButtonWidth(int columns) {
93
116
int available = Math.max(96, width - 64);
94
117
int maxByWidth = (available - (columns - 1) * BUTTON_GAP) / columns;
95
return Mth.clamp(maxByWidth, 92, 150);
118
return Mth.clamp(maxByWidth, 116, 178);
96
119
}
97
120
98
121
private void renderCenterPanel(GuiGraphics graphics) {
99
122
int centerX = width / 2;
100
123
int centerY = height / 2;
101
int left = centerX - 90;
102
int top = centerY - 37;
103
int right = centerX + 90;
104
int bottom = centerY + 37;
124
int left = centerX - 120;
125
int top = centerY - 72;
126
int right = centerX + 120;
127
int bottom = centerY + 64;
105
128
106
fillRoundedRect(graphics, left, top, right, bottom, 7, 0xB0060A12);
129
fillRoundedRect(graphics, left, top, right, bottom, 7, 0x99060A12);
107
130
drawRoundedBorder(graphics, left, top, right, bottom, 7, 0xFF85D6F7);
108
graphics.drawCenteredString(font, title, centerX, centerY - 25, 0xFFEAFBFF);
109
110
Component mode = Component.translatable(inMindDimension ? "screen.mydimension.rift_actions.mode_mind" : "screen.mydimension.rift_actions.mode_outside");
111
Component selected = Component.translatable("screen.mydimension.rift_actions.selected", getSelectedAction().displayName());
112
graphics.drawCenteredString(font, mode, centerX, centerY - 4, inMindDimension ? 0xFFFFE0A3 : 0xFFD0B6FF);
113
graphics.drawCenteredString(font, selected, centerX, centerY + 14, 0xFF9DDBFF);
114
}
115
116
private void renderGuideLines(GuiGraphics graphics) {
117
int centerX = width / 2;
118
int centerY = height / 2;
119
graphics.fill(centerX - 1, centerY - ROW_GAP + BUTTON_HEIGHT / 2 + 8, centerX + 1, centerY - 43, 0x4485D6F7);
120
graphics.fill(centerX - 1, centerY + 43, centerX + 1, centerY + ROW_GAP - BUTTON_HEIGHT / 2 - 8, inMindDimension ? 0x55FFE0A3 : 0x447F53B9);
131
graphics.drawCenteredString(font, title, centerX, centerY - 61, 0xFFEAFBFF);
132
graphics.drawCenteredString(font, page.title(), centerX, centerY + 43, page == Page.COPY_SHARED ? 0xFFB8FFD2 : 0xFF9DDBFF);
121
133
}
122
134
123
135
private RiftAction getSelectedAction() {
@@ -160,6 +172,44 @@ public class RiftActionScreen extends Screen {
160
172
graphics.fill(right - radius, bottom - 2, right - 1, bottom - 1, color);
161
173
}
162
174
175
private enum Page {
176
TRAVEL_PRIVATE("screen.mydimension.rift_actions.page.travel_private"),
177
TRAVEL_SHARED("screen.mydimension.rift_actions.page.travel_shared"),
178
MOB_PRIVATE("screen.mydimension.rift_actions.page.mob_private"),
179
MOB_SHARED("screen.mydimension.rift_actions.page.mob_shared"),
180
COPY_SHARED("screen.mydimension.rift_actions.page.copy_shared");
181
182
private final String translationKey;
183
184
Page(String translationKey) {
185
this.translationKey = translationKey;
186
}
187
188
private Component title() {
189
return Component.translatable(translationKey);
190
}
191
}
192
193
private class PageButton extends Button {
194
private final Page targetPage;
195
196
private PageButton(int x, int y, int width, Page targetPage) {
197
super(x, y, width, 20, targetPage.title(), button -> {
198
page = targetPage;
199
rebuildWidgets();
200
}, DEFAULT_NARRATION);
201
this.targetPage = targetPage;
202
}
203
204
@Override
205
protected void renderWidget(GuiGraphics graphics, int mouseX, int mouseY, float partialTick) {
206
int fill = targetPage == page ? 0xD6D6A23E : (isHoveredOrFocused() ? 0xC83E8DB8 : 0x963E8DB8);
207
fillRoundedRect(graphics, getX(), getY(), getX() + getWidth(), getY() + getHeight(), 5, fill);
208
drawRoundedBorder(graphics, getX(), getY(), getX() + getWidth(), getY() + getHeight(), 5, targetPage == page ? 0xFFFFF4A8 : 0xFFB8F0FF);
209
drawCenteredFittingText(graphics, Minecraft.getInstance().font, getMessage(), getX(), getY(), getWidth(), getHeight(), 0xFFEAFBFF);
210
}
211
}
212
163
213
private class ActionButton extends Button {
164
214
private final RiftAction action;
165
215
private final boolean selected;
@@ -176,9 +226,9 @@ public class RiftActionScreen extends Screen {
176
226
int top = getY();
177
227
int right = left + getWidth();
178
228
int bottom = top + getHeight();
179
int base = action == RiftAction.SET_ANCHOR ? ANCHOR_COLOR : (action.sendsMob() ? MOB_COLOR : TRAVEL_COLOR);
229
int base = action == RiftAction.SET_ANCHOR ? ANCHOR_COLOR : (action.copiesSharedDimension() ? COPY_COLOR : (action.sendsMob() ? MOB_COLOR : TRAVEL_COLOR));
180
230
int fill = withAlpha(base, isHoveredOrFocused() ? 226 : 174);
181
int edge = selected ? 0xFFFFF4A8 : (action == RiftAction.SET_ANCHOR ? 0xFFFFE0A3 : (action.sendsMob() ? 0xFFD8C1FF : 0xFFB8F0FF));
231
int edge = selected ? 0xFFFFF4A8 : (action == RiftAction.SET_ANCHOR ? 0xFFFFE0A3 : (action.copiesSharedDimension() ? 0xFFB8FFD2 : (action.sendsMob() ? 0xFFD8C1FF : 0xFFB8F0FF)));
182
232
183
233
fillRoundedRect(graphics, left, top, right, bottom, 7, darken(fill));
184
234
fillRoundedRect(graphics, left + 1, top + 1, right - 1, bottom - 1, 6, fill);
@@ -213,10 +263,15 @@ public class RiftActionScreen extends Screen {
213
263
int blue = (int) ((color & 0xFF) * 0.58F);
214
264
return alpha | (red << 16) | (green << 8) | blue;
215
265
}
266
}
216
267
217
private void drawFittingText(GuiGraphics graphics, Font font, Component text, int left, int top, int width, int height, int color) {
218
String label = font.plainSubstrByWidth(text.getString(), width);
219
graphics.drawString(font, label, left, top + (height - 8) / 2, color);
220
}
268
private static void drawCenteredFittingText(GuiGraphics graphics, Font font, Component text, int left, int top, int width, int height, int color) {
269
String label = font.plainSubstrByWidth(text.getString(), width - 8);
270
graphics.drawCenteredString(font, label, left + width / 2, top + (height - 8) / 2, color);
271
}
272
273
private static void drawFittingText(GuiGraphics graphics, Font font, Component text, int left, int top, int width, int height, int color) {
274
String label = font.plainSubstrByWidth(text.getString(), width);
275
graphics.drawString(font, label, left, top + (height - 8) / 2, color);
221
276
}
222
277
}
@@ -8,26 +8,42 @@ import net.minecraft.world.level.Level;
8
8
import java.util.Locale;
9
9
10
10
public enum RiftAction {
11
ETHEREAL_MIND("ethereal_mind", "action.mydimension.ethereal_mind", ModDimensions.ETHEREAL_MIND, false),
12
MIRROR_MIND("mirror_mind", "action.mydimension.mirror_mind", ModDimensions.MIRROR_MIND, false),
13
WATER_MIND("water_mind", "action.mydimension.water_mind", ModDimensions.WATER_MIND, false),
14
NATURE_MIND("nature_mind", "action.mydimension.nature_mind", ModDimensions.NATURE_MIND, false),
15
SEND_MOB_ETHEREAL("send_mob_ethereal", "action.mydimension.send_mob_ethereal", ModDimensions.ETHEREAL_MIND, true),
16
SEND_MOB_MIRROR("send_mob_mirror", "action.mydimension.send_mob_mirror", ModDimensions.MIRROR_MIND, true),
17
SEND_MOB_WATER("send_mob_water", "action.mydimension.send_mob_water", ModDimensions.WATER_MIND, true),
18
SEND_MOB_NATURE("send_mob_nature", "action.mydimension.send_mob_nature", ModDimensions.NATURE_MIND, true),
19
SET_ANCHOR("set_anchor", "action.mydimension.set_anchor", null, false);
11
ETHEREAL_MIND("ethereal_mind", "action.mydimension.ethereal_mind", ModDimensions.ETHEREAL_MIND, false, false, false),
12
MIRROR_MIND("mirror_mind", "action.mydimension.mirror_mind", ModDimensions.MIRROR_MIND, false, false, false),
13
WATER_MIND("water_mind", "action.mydimension.water_mind", ModDimensions.WATER_MIND, false, false, false),
14
NATURE_MIND("nature_mind", "action.mydimension.nature_mind", ModDimensions.NATURE_MIND, false, false, false),
15
SHARED_ETHEREAL_MIND("shared_ethereal_mind", "action.mydimension.shared_ethereal_mind", ModDimensions.ETHEREAL_MIND, false, true, false),
16
SHARED_MIRROR_MIND("shared_mirror_mind", "action.mydimension.shared_mirror_mind", ModDimensions.MIRROR_MIND, false, true, false),
17
SHARED_WATER_MIND("shared_water_mind", "action.mydimension.shared_water_mind", ModDimensions.WATER_MIND, false, true, false),
18
SHARED_NATURE_MIND("shared_nature_mind", "action.mydimension.shared_nature_mind", ModDimensions.NATURE_MIND, false, true, false),
19
SEND_MOB_ETHEREAL("send_mob_ethereal", "action.mydimension.send_mob_ethereal", ModDimensions.ETHEREAL_MIND, true, false, false),
20
SEND_MOB_MIRROR("send_mob_mirror", "action.mydimension.send_mob_mirror", ModDimensions.MIRROR_MIND, true, false, false),
21
SEND_MOB_WATER("send_mob_water", "action.mydimension.send_mob_water", ModDimensions.WATER_MIND, true, false, false),
22
SEND_MOB_NATURE("send_mob_nature", "action.mydimension.send_mob_nature", ModDimensions.NATURE_MIND, true, false, false),
23
SEND_MOB_SHARED_ETHEREAL("send_mob_shared_ethereal", "action.mydimension.send_mob_shared_ethereal", ModDimensions.ETHEREAL_MIND, true, true, false),
24
SEND_MOB_SHARED_MIRROR("send_mob_shared_mirror", "action.mydimension.send_mob_shared_mirror", ModDimensions.MIRROR_MIND, true, true, false),
25
SEND_MOB_SHARED_WATER("send_mob_shared_water", "action.mydimension.send_mob_shared_water", ModDimensions.WATER_MIND, true, true, false),
26
SEND_MOB_SHARED_NATURE("send_mob_shared_nature", "action.mydimension.send_mob_shared_nature", ModDimensions.NATURE_MIND, true, true, false),
27
COPY_SHARED_ETHEREAL("copy_shared_ethereal", "action.mydimension.copy_shared_ethereal", ModDimensions.ETHEREAL_MIND, false, false, true),
28
COPY_SHARED_MIRROR("copy_shared_mirror", "action.mydimension.copy_shared_mirror", ModDimensions.MIRROR_MIND, false, false, true),
29
COPY_SHARED_WATER("copy_shared_water", "action.mydimension.copy_shared_water", ModDimensions.WATER_MIND, false, false, true),
30
COPY_SHARED_NATURE("copy_shared_nature", "action.mydimension.copy_shared_nature", ModDimensions.NATURE_MIND, false, false, true),
31
SET_ANCHOR("set_anchor", "action.mydimension.set_anchor", null, false, false, false);
20
32
21
33
private final String id;
22
34
private final String translationKey;
23
35
private final ResourceKey<Level> targetDimension;
24
36
private final boolean sendsMob;
37
private final boolean sharedDimension;
38
private final boolean copiesSharedDimension;
25
39
26
RiftAction(String id, String translationKey, ResourceKey<Level> targetDimension, boolean sendsMob) {
40
RiftAction(String id, String translationKey, ResourceKey<Level> targetDimension, boolean sendsMob, boolean sharedDimension, boolean copiesSharedDimension) {
27
41
this.id = id;
28
42
this.translationKey = translationKey;
29
43
this.targetDimension = targetDimension;
30
44
this.sendsMob = sendsMob;
45
this.sharedDimension = sharedDimension;
46
this.copiesSharedDimension = copiesSharedDimension;
31
47
}
32
48
33
49
public String id() {
@@ -43,13 +59,21 @@ public enum RiftAction {
43
59
}
44
60
45
61
public boolean teleportsPlayer() {
46
return targetDimension != null && !sendsMob;
62
return targetDimension != null && !sendsMob && !copiesSharedDimension;
47
63
}
48
64
49
65
public boolean sendsMob() {
50
66
return sendsMob;
51
67
}
52
68
69
public boolean usesSharedDimension() {
70
return sharedDimension;
71
}
72
73
public boolean copiesSharedDimension() {
74
return copiesSharedDimension;
75
}
76
53
77
public static RiftAction byId(String id) {
54
78
if ("send_mob".equals(id)) {
55
79
return SEND_MOB_ETHEREAL;
@@ -9,6 +9,7 @@ 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;
12
13
import net.minecraft.server.level.ServerLevel;
13
14
import net.minecraft.server.level.ServerPlayer;
14
15
import net.minecraft.sounds.SoundEvents;
@@ -23,8 +24,10 @@ import net.minecraft.world.entity.projectile.ProjectileUtil;
23
24
import net.minecraft.world.item.Item;
24
25
import net.minecraft.world.item.ItemStack;
25
26
import net.minecraft.world.level.Level;
27
import net.minecraft.world.level.dimension.DimensionType;
26
28
import net.minecraft.world.level.levelgen.Heightmap;
27
29
import net.minecraft.world.level.portal.PortalInfo;
30
import net.minecraft.world.level.storage.LevelResource;
28
31
import net.minecraft.world.phys.AABB;
29
32
import net.minecraft.world.phys.EntityHitResult;
30
33
import net.minecraft.world.phys.Vec3;
@@ -32,6 +35,12 @@ import net.minecraftforge.api.distmarker.Dist;
32
35
import net.minecraftforge.common.util.ITeleporter;
33
36
import net.minecraftforge.fml.DistExecutor;
34
37
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;
35
44
import java.util.function.Function;
36
45
37
46
public class RiftItem extends Item {
@@ -100,7 +109,7 @@ public class RiftItem extends Item {
100
109
}
101
110
102
111
if (player instanceof ServerPlayer serverPlayer) {
103
sendToMind(serverPlayer, target, stack, action.targetDimension());
112
sendToMind(serverPlayer, target, stack, action);
104
113
}
105
114
106
115
return InteractionResult.CONSUME;
@@ -126,26 +135,32 @@ public class RiftItem extends Item {
126
135
return;
127
136
}
128
137
138
if (action.copiesSharedDimension()) {
139
copySharedDimension(player, action);
140
return;
141
}
142
129
143
if (action.sendsMob()) {
130
144
LivingEntity target = findLookedAtLivingEntity(player);
131
if (target == null || !sendToMind(player, target, stack, action.targetDimension())) {
145
if (target == null || !sendToMind(player, target, stack, action)) {
132
146
player.displayClientMessage(Component.translatable("message.mydimension.no_mob_target"), true);
133
147
}
134
148
return;
135
149
}
136
150
137
teleport(player, stack, action.targetDimension());
151
teleport(player, stack, action);
138
152
}
139
153
140
private static void teleport(ServerPlayer player, ItemStack stack, ResourceKey<Level> selectedDimension) {
154
private static void teleport(ServerPlayer player, ItemStack stack, RiftAction action) {
155
ResourceKey<Level> selectedDimension = action.targetDimension();
141
156
ServerLevel currentLevel = player.serverLevel();
142
157
ResourceKey<Level> currentDimension = currentLevel.dimension();
143
158
ResourceKey<Level> currentMindBase = ModDimensions.baseMindDimension(currentDimension);
144
boolean returningFromSelectedMind = selectedDimension.equals(currentMindBase);
159
ResourceKey<Level> actualTargetDimension = action.usesSharedDimension() ? selectedDimension : MindInstances.dimensionFor(player, selectedDimension);
160
boolean returningFromSelectedMind = currentDimension.equals(actualTargetDimension) && selectedDimension.equals(currentMindBase);
145
161
ReturnPoint returnPoint = returningFromSelectedMind ? readPoint(stack, RETURN_POINT_TAG) : null;
146
ResourceKey<Level> targetDimension = returningFromSelectedMind ? null : MindInstances.dimensionFor(player, selectedDimension);
147
ReturnPoint mindPoint = returningFromSelectedMind ? null : readMindPoint(stack, targetDimension);
148
ServerLevel targetLevel = returningFromSelectedMind ? getReturnLevel(player, returnPoint) : player.getServer().getLevel(targetDimension);
162
ReturnPoint mindPoint = returningFromSelectedMind ? null : readMindPoint(stack, actualTargetDimension);
163
ServerLevel targetLevel = returningFromSelectedMind ? getReturnLevel(player, returnPoint) : player.getServer().getLevel(actualTargetDimension);
149
164
150
165
if (targetLevel == null) {
151
166
player.displayClientMessage(Component.translatable("message.mydimension.missing_dimension"), true);
@@ -154,7 +169,7 @@ public class RiftItem extends Item {
154
169
155
170
double x = player.getX();
156
171
double z = player.getZ();
157
double y = returningFromSelectedMind ? overworldSpawnY(targetLevel) : safeEntryY(targetLevel, targetDimension, x, z);
172
double y = returningFromSelectedMind ? overworldSpawnY(targetLevel) : safeEntryY(targetLevel, actualTargetDimension, x, z);
158
173
float yRot = player.getYRot();
159
174
float xRot = player.getXRot();
160
175
@@ -210,8 +225,9 @@ public class RiftItem extends Item {
210
225
return ModDimensions.entryHeight(dimension);
211
226
}
212
227
213
public static boolean sendToMind(ServerPlayer player, LivingEntity target, ItemStack stack, ResourceKey<Level> targetDimension) {
214
ResourceKey<Level> actualTargetDimension = MindInstances.dimensionFor(player, targetDimension);
228
public static boolean sendToMind(ServerPlayer player, LivingEntity target, ItemStack stack, RiftAction action) {
229
ResourceKey<Level> targetDimension = action.targetDimension();
230
ResourceKey<Level> actualTargetDimension = action.usesSharedDimension() ? targetDimension : MindInstances.dimensionFor(player, targetDimension);
215
231
ServerLevel targetLevel = player.getServer().getLevel(actualTargetDimension);
216
232
if (targetLevel == null) {
217
233
player.displayClientMessage(Component.translatable("message.mydimension.missing_dimension"), true);
@@ -243,6 +259,87 @@ public class RiftItem extends Item {
243
259
return false;
244
260
}
245
261
262
private static void copySharedDimension(ServerPlayer player, RiftAction action) {
263
if (!player.isCreative()) {
264
player.displayClientMessage(Component.translatable("message.mydimension.copy_creative_only"), true);
265
return;
266
}
267
268
ResourceKey<Level> sourceDimension = action.targetDimension();
269
ResourceKey<Level> targetDimension = MindInstances.dimensionFor(player, sourceDimension);
270
if (sourceDimension.equals(targetDimension)) {
271
player.displayClientMessage(Component.translatable("message.mydimension.copy_private_unavailable"), true);
272
return;
273
}
274
275
MinecraftServer server = player.getServer();
276
if (server == null || server.getLevel(sourceDimension) == null || server.getLevel(targetDimension) == null) {
277
player.displayClientMessage(Component.translatable("message.mydimension.missing_dimension"), true);
278
return;
279
}
280
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
}
290
291
if (!Files.exists(source)) {
292
player.displayClientMessage(Component.translatable("message.mydimension.copy_missing_shared"), true);
293
return;
294
}
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
}
302
}
303
304
private static void deleteDirectory(Path path) throws IOException {
305
if (!Files.exists(path)) {
306
return;
307
}
308
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
}
334
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
});
341
}
342
246
343
private static LivingEntity findLookedAtLivingEntity(ServerPlayer player) {
247
344
double reach = 6.0D;
248
345
Vec3 eye = player.getEyePosition();
@@ -12,13 +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 = 32;
15
public static final int MAX_PLAYER_SLOTS = 128;
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
return ModDimensions.playerDimension(baseDimension, slotFor(player));
21
int slot = slotFor(player);
22
return slot < 0 ? baseDimension : ModDimensions.playerDimension(baseDimension, slot);
22
23
}
23
24
24
25
public static int slotFor(ServerPlayer player) {
@@ -63,6 +64,10 @@ public class MindInstances {
63
64
return existing;
64
65
}
65
66
67
if (nextSlot >= MAX_PLAYER_SLOTS) {
68
return -1;
69
}
70
66
71
int slot = nextSlot++;
67
72
slots.put(owner, slot);
68
73
setDirty();
@@ -5,22 +5,47 @@
5
5
"dimension.mydimension.water_mind": "Water Mind",
6
6
"dimension.mydimension.nature_mind": "Nature Mind",
7
7
"screen.mydimension.rift_actions": "Rift",
8
"screen.mydimension.rift_actions.travel": "Inner: Travel",
9
"screen.mydimension.rift_actions.mob": "Outer: Send Mob",
10
"screen.mydimension.rift_actions.anchor": "Center: Set Anchor",
8
"screen.mydimension.rift_actions.travel": "Travel",
9
"screen.mydimension.rift_actions.mob": "Send Mob",
10
"screen.mydimension.rift_actions.anchor": "Set Anchor",
11
"screen.mydimension.rift_actions.mode_mind": "Mind: Travel or Set Anchor",
12
"screen.mydimension.rift_actions.mode_outside": "Outside: Travel or Send Mob",
13
"screen.mydimension.rift_actions.selected": "Selected: %s",
14
"screen.mydimension.rift_actions.page.travel_private": "Travel",
15
"screen.mydimension.rift_actions.page.travel_shared": "Shared",
16
"screen.mydimension.rift_actions.page.mob_private": "Send",
17
"screen.mydimension.rift_actions.page.mob_shared": "Send Shared",
18
"screen.mydimension.rift_actions.page.copy_shared": "Copy Shared",
11
19
"action.mydimension.ethereal_mind": "Go to Ethereal Mind",
12
20
"action.mydimension.mirror_mind": "Go to Mirror Mind",
13
21
"action.mydimension.water_mind": "Go to Water Mind",
14
22
"action.mydimension.nature_mind": "Go to Nature Mind",
23
"action.mydimension.shared_ethereal_mind": "Go to Shared Ethereal",
24
"action.mydimension.shared_mirror_mind": "Go to Shared Mirror",
25
"action.mydimension.shared_water_mind": "Go to Shared Water",
26
"action.mydimension.shared_nature_mind": "Go to Shared Nature",
15
27
"action.mydimension.send_mob_ethereal": "Send Mob to Ethereal",
16
28
"action.mydimension.send_mob_mirror": "Send Mob to Mirror",
17
29
"action.mydimension.send_mob_water": "Send Mob to Water",
18
30
"action.mydimension.send_mob_nature": "Send Mob to Nature",
31
"action.mydimension.send_mob_shared_ethereal": "Send Mob to Shared Ethereal",
32
"action.mydimension.send_mob_shared_mirror": "Send Mob to Shared Mirror",
33
"action.mydimension.send_mob_shared_water": "Send Mob to Shared Water",
34
"action.mydimension.send_mob_shared_nature": "Send Mob to Shared Nature",
35
"action.mydimension.copy_shared_ethereal": "Copy Shared Ethereal",
36
"action.mydimension.copy_shared_mirror": "Copy Shared Mirror",
37
"action.mydimension.copy_shared_water": "Copy Shared Water",
38
"action.mydimension.copy_shared_nature": "Copy Shared Nature",
19
39
"action.mydimension.set_anchor": "Set Teleport Anchor",
20
40
"message.mydimension.already_in_target_mind": "That mob is already in the target mind dimension",
21
41
"message.mydimension.anchor_only_mind": "Teleport anchors can only be set in mind dimensions",
22
42
"message.mydimension.anchor_set": "Teleport anchor set for this mind dimension",
23
43
"message.mydimension.no_mob_target": "No mob target selected",
24
44
"message.mydimension.missing_dimension": "The target mind dimension is not loaded",
25
"message.mydimension.protected_tp": "%s is in a mind dimension and cannot be teleported by another player"
45
"message.mydimension.protected_tp": "%s is in a mind dimension and cannot be teleported by another player",
46
"message.mydimension.copy_creative_only": "Only creative players can copy shared mind saves",
47
"message.mydimension.copy_private_unavailable": "No private mind slot is available, so the shared save cannot be copied",
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",
50
"message.mydimension.copy_failed": "Failed to copy shared mind save"
26
51
}
@@ -11,14 +11,31 @@
11
11
"screen.mydimension.rift_actions.mode_mind": "心境内:前往或设置锚点",
12
12
"screen.mydimension.rift_actions.mode_outside": "外界:前往或传送生物",
13
13
"screen.mydimension.rift_actions.selected": "当前:%s",
14
"screen.mydimension.rift_actions.page.travel_private": "前往",
15
"screen.mydimension.rift_actions.page.travel_shared": "前往共享",
16
"screen.mydimension.rift_actions.page.mob_private": "传送",
17
"screen.mydimension.rift_actions.page.mob_shared": "传送共享",
18
"screen.mydimension.rift_actions.page.copy_shared": "复制公共",
14
19
"action.mydimension.ethereal_mind": "前往空灵心境",
15
20
"action.mydimension.mirror_mind": "前往镜之心境",
16
21
"action.mydimension.water_mind": "前往水之心境",
17
22
"action.mydimension.nature_mind": "前往自然心境",
23
"action.mydimension.shared_ethereal_mind": "前往共享空灵",
24
"action.mydimension.shared_mirror_mind": "前往共享镜",
25
"action.mydimension.shared_water_mind": "前往共享水",
26
"action.mydimension.shared_nature_mind": "前往共享自然",
18
27
"action.mydimension.send_mob_ethereal": "传送生物到空灵",
19
28
"action.mydimension.send_mob_mirror": "传送生物到镜",
20
29
"action.mydimension.send_mob_water": "传送生物到水",
21
30
"action.mydimension.send_mob_nature": "传送生物到自然",
31
"action.mydimension.send_mob_shared_ethereal": "传送生物到共享空灵",
32
"action.mydimension.send_mob_shared_mirror": "传送生物到共享镜",
33
"action.mydimension.send_mob_shared_water": "传送生物到共享水",
34
"action.mydimension.send_mob_shared_nature": "传送生物到共享自然",
35
"action.mydimension.copy_shared_ethereal": "复制公共空灵",
36
"action.mydimension.copy_shared_mirror": "复制公共镜",
37
"action.mydimension.copy_shared_water": "复制公共水",
38
"action.mydimension.copy_shared_nature": "复制公共自然",
22
39
"action.mydimension.set_anchor": "设置传送锚点",
23
40
"message.mydimension.already_in_target_mind": "该生物已经在目标心境中",
24
41
"message.mydimension.anchor_only_mind": "只能在心境维度中设置传送锚点",
@@ -26,5 +43,10 @@
26
43
"message.mydimension.no_mob_target": "没有瞄准可传送的生物",
27
44
"message.mydimension.missing_dimension": "目标心境维度未加载",
28
45
"message.mydimension.protected_tp": "%s 正处于心境维度,无法被其他玩家传送",
46
"message.mydimension.copy_creative_only": "只有创造模式玩家可以复制公共心境存档",
47
"message.mydimension.copy_private_unavailable": "私有心境槽位不足,无法复制公共存档",
48
"message.mydimension.copy_missing_shared": "公共心境尚未生成存档,无法复制",
49
"message.mydimension.copy_done": "已复制公共心境存档到你的私有心境",
50
"message.mydimension.copy_failed": "复制公共心境存档失败",
29
51
"itemGroup.mydimension": "我的维度"
30
52
}
@@ -1,13 +1,25 @@
1
1
{
2
2
"parent": "minecraft:recipes/root",
3
3
"criteria": {
4
"has_black_glazed_terracotta": {
4
"has_clock": {
5
5
"trigger": "minecraft:inventory_changed",
6
6
"conditions": {
7
7
"items": [
8
8
{
9
9
"items": [
10
"minecraft:black_glazed_terracotta"
10
"minecraft:clock"
11
]
12
}
13
]
14
}
15
},
16
"has_ender_pearl": {
17
"trigger": "minecraft:inventory_changed",
18
"conditions": {
19
"items": [
20
{
21
"items": [
22
"minecraft:ender_pearl"
11
23
]
12
24
}
13
25
]
@@ -22,7 +34,8 @@
22
34
},
23
35
"requirements": [
24
36
[
25
"has_black_glazed_terracotta",
37
"has_clock",
38
"has_ender_pearl",
26
39
"has_the_recipe"
27
40
]
28
41
],
@@ -0,0 +1,26 @@
1
{
2
"type": "mydimension:ethereal_mind",
3
"generator": {
4
"type": "minecraft:flat",
5
"settings": {
6
"biome": "mydimension:ethereal_mind",
7
"features": false,
8
"lakes": false,
9
"layers": [
10
{
11
"block": "minecraft:stone",
12
"height": 60
13
},
14
{
15
"block": "minecraft:dirt",
16
"height": 3
17
},
18
{
19
"block": "minecraft:quartz_block",
20
"height": 3
21
}
22
],
23
"structure_overrides": []
24
}
25
}
26
}
@@ -0,0 +1,11 @@
1
{
2
"type": "mydimension:mirror_mind",
3
"generator": {
4
"type": "mydimension:no_structure_noise",
5
"biome_source": {
6
"type": "minecraft:multi_noise",
7
"preset": "minecraft:overworld"
8
},
9
"settings": "minecraft:overworld"
10
}
11
}