Skip to content

Commit 653ba34

Browse files
committed
Add structure-like support for multiblock shapes
1 parent d9917de commit 653ba34

File tree

40 files changed

+2036
-2
lines changed

40 files changed

+2036
-2
lines changed

src/client/java/aztech/modern_industrialization/MIClient.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import aztech.modern_industrialization.blocks.storage.barrel.DeferredBarrelTextRenderer;
3030
import aztech.modern_industrialization.blocks.storage.barrel.client.BarrelTooltipComponent;
3131
import aztech.modern_industrialization.blocks.storage.tank.TankRenderer;
32+
import aztech.modern_industrialization.blocks.structure.StructureMultiblockControllerBER;
3233
import aztech.modern_industrialization.datagen.MIDatagenClient;
3334
import aztech.modern_industrialization.datagen.MIDatagenServer;
3435
import aztech.modern_industrialization.datagen.model.DelegatingModelBuilder;
@@ -234,6 +235,7 @@ private static void registerBlockEntityRenderers(FMLClientSetupEvent event) {
234235

235236
BlockEntityRenderers.register(MIRegistries.CREATIVE_BARREL_BE.get(), context -> new BarrelRenderer(0x000000));
236237
BlockEntityRenderers.register(MIRegistries.CREATIVE_TANK_BE.get(), context -> new TankRenderer(0x000000));
238+
BlockEntityRenderers.register(MIRegistries.STRUCTURE_MULTIBLOCK_CONTROLLER_BE.get(), context -> new StructureMultiblockControllerBER());
237239

238240
blockEntityRendererRegistrations.forEach(Runnable::run);
239241
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* MIT License
3+
*
4+
* Copyright (c) 2020 Azercoco & Technici4n
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in all
14+
* copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
* SOFTWARE.
23+
*/
24+
package aztech.modern_industrialization.blocks.structure;
25+
26+
import com.mojang.blaze3d.vertex.PoseStack;
27+
import com.mojang.blaze3d.vertex.VertexConsumer;
28+
import net.minecraft.client.renderer.LevelRenderer;
29+
import net.minecraft.client.renderer.MultiBufferSource;
30+
import net.minecraft.client.renderer.RenderType;
31+
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer;
32+
import net.minecraft.core.BlockPos;
33+
import net.minecraft.world.level.levelgen.structure.BoundingBox;
34+
import net.minecraft.world.phys.AABB;
35+
36+
public class StructureMultiblockControllerBER implements BlockEntityRenderer<StructureMultiblockControllerBlockEntity> {
37+
@Override
38+
public void render(StructureMultiblockControllerBlockEntity controller, float tickDelta, PoseStack matrices, MultiBufferSource vcs, int light,
39+
int overlay) {
40+
BlockPos pos = controller.getBlockPos();
41+
BoundingBox bounds = controller.getBounds();
42+
if (bounds == null) {
43+
bounds = new BoundingBox(0, 0, 0, 0, 0, 0);
44+
}
45+
matrices.pushPose();
46+
VertexConsumer buffer = vcs.getBuffer(RenderType.lines());
47+
AABB box = AABB.of(bounds);
48+
// MI.LOGGER.info("box: {}", box);
49+
LevelRenderer.renderLineBox(matrices, buffer, box, 1, 1, 1, 1);
50+
matrices.popPose();
51+
}
52+
53+
@Override
54+
public boolean shouldRenderOffScreen(StructureMultiblockControllerBlockEntity controller) {
55+
return true;
56+
}
57+
58+
@Override
59+
public AABB getRenderBoundingBox(StructureMultiblockControllerBlockEntity controller) {
60+
return AABB.INFINITE;
61+
}
62+
}
Lines changed: 273 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,273 @@
1+
/*
2+
* MIT License
3+
*
4+
* Copyright (c) 2020 Azercoco & Technici4n
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in all
14+
* copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
* SOFTWARE.
23+
*/
24+
package aztech.modern_industrialization.gui.structure;
25+
26+
import aztech.modern_industrialization.MIBlock;
27+
import aztech.modern_industrialization.MIText;
28+
import aztech.modern_industrialization.blocks.structure.StructureMultiblockControllerBlockEntity;
29+
import aztech.modern_industrialization.machines.models.MachineCasing;
30+
import aztech.modern_industrialization.network.structure.StructureSaveControllerPacket;
31+
import aztech.modern_industrialization.network.structure.StructureUpdateControllerPacket;
32+
import com.mojang.blaze3d.platform.InputConstants;
33+
import java.util.Optional;
34+
import net.minecraft.client.Minecraft;
35+
import net.minecraft.client.gui.GuiGraphics;
36+
import net.minecraft.client.gui.components.Button;
37+
import net.minecraft.client.gui.components.EditBox;
38+
import net.minecraft.client.gui.screens.Screen;
39+
import net.minecraft.core.BlockPos;
40+
import net.minecraft.network.chat.CommonComponents;
41+
import net.minecraft.network.chat.Component;
42+
import net.minecraft.resources.ResourceLocation;
43+
import net.minecraft.world.level.levelgen.structure.BoundingBox;
44+
45+
public class StructureMultiblockControllerEditScreen extends Screen {
46+
private static final int VALID_TEXT_COLOR = 0xE0E0E0;
47+
private static final int INVALID_TEXT_COLOR = 0xE07272;
48+
49+
private final StructureMultiblockControllerBlockEntity controller;
50+
51+
private Button doneButton;
52+
private Button cancelButton;
53+
private Button saveButton;
54+
55+
private EditBox idBox;
56+
private EditBox casingBox;
57+
58+
private EditBox posX;
59+
private EditBox posY;
60+
private EditBox posZ;
61+
private EditBox sizeX;
62+
private EditBox sizeY;
63+
private EditBox sizeZ;
64+
65+
public StructureMultiblockControllerEditScreen(StructureMultiblockControllerBlockEntity controller) {
66+
super(Component.translatable(MIBlock.STRUCTURE_MULTIBLOCK_CONTROLLER.asBlock().getDescriptionId()));
67+
this.controller = controller;
68+
}
69+
70+
private Optional<ResourceLocation> getId() {
71+
return Optional.ofNullable(ResourceLocation.tryParse(idBox.getValue()));
72+
}
73+
74+
private Optional<MachineCasing> getCasing() {
75+
return Optional.ofNullable(StructureMultiblockControllerBlockEntity.formatCasing(casingBox.getValue()));
76+
}
77+
78+
// TODO this needs to be reworked to allow for negative sizes and whatnot
79+
private Optional<BoundingBox> getBoundingBox() {
80+
try {
81+
int minX = Integer.parseInt(posX.getValue());
82+
int minY = Integer.parseInt(posY.getValue());
83+
int minZ = Integer.parseInt(posZ.getValue());
84+
BlockPos min = new BlockPos(minX, minY, minZ);
85+
int maxX = Integer.parseInt(sizeX.getValue()) + minX - 1;
86+
int maxY = Integer.parseInt(sizeY.getValue()) + minY - 1;
87+
int maxZ = Integer.parseInt(sizeZ.getValue()) + minZ - 1;
88+
BlockPos max = new BlockPos(maxX, maxY, maxZ);
89+
return Optional.of(BoundingBox.fromCorners(min, max));
90+
} catch (NumberFormatException ignored) {
91+
return Optional.empty();
92+
}
93+
}
94+
95+
private void updateId() {
96+
boolean validId = idBox.getValue().isEmpty() || this.getId().isPresent();
97+
idBox.setTextColor(validId ? VALID_TEXT_COLOR : INVALID_TEXT_COLOR);
98+
}
99+
100+
private void updateCasing() {
101+
boolean validCasing = casingBox.getValue().isEmpty() || this.getCasing().isPresent();
102+
casingBox.setTextColor(validCasing ? VALID_TEXT_COLOR : INVALID_TEXT_COLOR);
103+
}
104+
105+
private void updateAll() {
106+
this.updateId();
107+
this.updateCasing();
108+
}
109+
110+
private void done() {
111+
this.sendToServer();
112+
minecraft.setScreen(null);
113+
}
114+
115+
private void sendToServer() {
116+
minecraft.getConnection().send(new StructureUpdateControllerPacket(
117+
controller.getBlockPos(),
118+
idBox.getValue(),
119+
casingBox.getValue(),
120+
this.getBoundingBox().orElse(new BoundingBox(0, 0, 0, 0, 0, 0))));
121+
}
122+
123+
private void cancel() {
124+
minecraft.setScreen(null);
125+
}
126+
127+
private void save() {
128+
this.sendToServer();
129+
minecraft.getConnection().send(new StructureSaveControllerPacket(controller.getBlockPos()));
130+
}
131+
132+
@Override
133+
protected void init() {
134+
this.addRenderableWidget(
135+
doneButton = Button.builder(CommonComponents.GUI_DONE, button -> this.done()).bounds(width / 2 - 4 - 150, 210, 150, 20).build());
136+
this.addRenderableWidget(
137+
cancelButton = Button.builder(CommonComponents.GUI_CANCEL, button -> this.cancel()).bounds(width / 2 + 4, 210, 150, 20).build());
138+
this.addRenderableWidget(
139+
saveButton = Button.builder(Component.translatable("structure_block.button.save"), button -> this.save())
140+
.bounds(width / 2 + 4 + 100, 185, 50, 20).build());
141+
142+
idBox = new EditBox(font, width / 2 - 152, 50, 304, 20, MIText.StructureMultiblockStructureName.text()) {
143+
@Override
144+
public boolean charTyped(char codePoint, int modifiers) {
145+
return ResourceLocation.isAllowedInResourceLocation(codePoint) && super.charTyped(codePoint, modifiers);
146+
}
147+
};
148+
idBox.setMaxLength(Short.MAX_VALUE);
149+
idBox.setValue(controller.getInputId());
150+
idBox.setResponder(text -> this.updateId());
151+
this.addRenderableWidget(idBox);
152+
153+
casingBox = new EditBox(font, width / 2 - 152, 90, 304, 20, MIText.StructureMultiblockHatchCasing.text()) {
154+
@Override
155+
public boolean charTyped(char codePoint, int modifiers) {
156+
return ResourceLocation.isAllowedInResourceLocation(codePoint) && super.charTyped(codePoint, modifiers);
157+
}
158+
};
159+
casingBox.setMaxLength(Short.MAX_VALUE);
160+
casingBox.setValue(controller.getInputCasing());
161+
casingBox.setResponder(text -> this.updateCasing());
162+
this.addRenderableWidget(casingBox);
163+
164+
BoundingBox bounds = controller.getBounds();
165+
if (bounds == null) {
166+
bounds = new BoundingBox(0, 0, 0, 0, 0, 0);
167+
}
168+
169+
posX = new EditBox(font, width / 2 - 152, 130, 80, 20, Component.translatable("structure_block.position.x"));
170+
posX.setMaxLength(15);
171+
posX.setValue(Integer.toString(bounds.minX()));
172+
this.addRenderableWidget(posX);
173+
posY = new EditBox(font, width / 2 - 72, 130, 80, 20, Component.translatable("structure_block.position.y"));
174+
posY.setMaxLength(15);
175+
posY.setValue(Integer.toString(bounds.minY()));
176+
this.addRenderableWidget(posY);
177+
posZ = new EditBox(font, width / 2 + 8, 130, 80, 20, Component.translatable("structure_block.position.z"));
178+
posZ.setMaxLength(15);
179+
posZ.setValue(Integer.toString(bounds.minZ()));
180+
this.addRenderableWidget(posZ);
181+
182+
sizeX = new EditBox(font, width / 2 - 152, 170, 80, 20, Component.translatable("structure_block.size.x"));
183+
sizeX.setMaxLength(15);
184+
sizeX.setValue(Integer.toString(bounds.maxX() - bounds.minX() + 1));
185+
this.addRenderableWidget(sizeX);
186+
sizeY = new EditBox(font, width / 2 - 72, 170, 80, 20, Component.translatable("structure_block.size.y"));
187+
sizeY.setMaxLength(15);
188+
sizeY.setValue(Integer.toString(bounds.maxY() - bounds.minY() + 1));
189+
this.addRenderableWidget(sizeY);
190+
sizeZ = new EditBox(font, width / 2 + 8, 170, 80, 20, Component.translatable("structure_block.size.z"));
191+
sizeZ.setMaxLength(15);
192+
sizeZ.setValue(Integer.toString(bounds.maxZ() - bounds.minZ() + 1));
193+
this.addRenderableWidget(sizeZ);
194+
195+
this.updateAll();
196+
}
197+
198+
@Override
199+
public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTick) {
200+
super.render(graphics, mouseX, mouseY, partialTick);
201+
202+
graphics.drawCenteredString(font, title, width / 2, 20, 0xFFFFFF);
203+
204+
graphics.drawString(font, MIText.StructureMultiblockStructureName.text(), width / 2 - 153, 40, 0xA0A0A0);
205+
206+
graphics.drawString(font, MIText.StructureMultiblockHatchCasing.text(), width / 2 - 153, 80, 0xA0A0A0);
207+
208+
graphics.drawString(font, Component.translatable("structure_block.position"), width / 2 - 153, 120, 0xA0A0A0);
209+
210+
graphics.drawString(font, Component.translatable("structure_block.size"), width / 2 - 153, 160, 0xA0A0A0);
211+
}
212+
213+
@Override
214+
public void renderBackground(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) {
215+
this.renderTransparentBackground(guiGraphics);
216+
}
217+
218+
@Override
219+
protected void setInitialFocus() {
220+
this.setInitialFocus(idBox);
221+
}
222+
223+
@Override
224+
public void resize(Minecraft minecraft, int width, int height) {
225+
String idBoxValue = idBox.getValue();
226+
String casingBoxValue = casingBox.getValue();
227+
String posXValue = posX.getValue();
228+
String posYValue = posY.getValue();
229+
String posZValue = posZ.getValue();
230+
String sizeXValue = sizeX.getValue();
231+
String sizeYValue = sizeY.getValue();
232+
String sizeZValue = sizeZ.getValue();
233+
234+
this.init(minecraft, width, height);
235+
236+
idBox.setValue(idBoxValue);
237+
casingBox.setValue(casingBoxValue);
238+
posX.setValue(posXValue);
239+
posY.setValue(posYValue);
240+
posZ.setValue(posZValue);
241+
sizeX.setValue(sizeXValue);
242+
sizeY.setValue(sizeYValue);
243+
sizeZ.setValue(sizeZValue);
244+
}
245+
246+
@Override
247+
public void onClose() {
248+
this.cancel();
249+
}
250+
251+
@Override
252+
public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
253+
if (super.keyPressed(keyCode, scanCode, modifiers)) {
254+
return true;
255+
} else if (keyCode == InputConstants.KEY_RETURN || keyCode == InputConstants.KEY_NUMPADENTER) {
256+
this.done();
257+
return true;
258+
}
259+
return false;
260+
}
261+
262+
@Override
263+
public boolean isPauseScreen() {
264+
return false;
265+
}
266+
267+
@Override
268+
public void tick() {
269+
if (controller.isRemoved()) {
270+
this.onClose();
271+
}
272+
}
273+
}

0 commit comments

Comments
 (0)