Skip to content

Commit 56cc6a3

Browse files
Fix bugs/crashes, allow data driven parts to work properly, add ability to dump resources
1 parent 820087c commit 56cc6a3

21 files changed

+238
-99
lines changed

.github/workflows/build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,4 @@ jobs:
2626
uses: actions/upload-artifact@v4
2727
with:
2828
name: Artifacts
29-
path: fabric/build/libs/
29+
path: fabric/build/libs/ # FIXME when NeoForge port is complete

common/src/main/java/io/github/foundationgames/automobility/Automobility.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,12 @@
1515
import io.github.foundationgames.automobility.screen.SingleSlotScreenHandler;
1616
import io.github.foundationgames.automobility.sound.AutomobilitySounds;
1717
import io.github.foundationgames.automobility.util.AUtils;
18+
import io.github.foundationgames.automobility.util.AutomobilityClientResourceDumper;
1819
import io.github.foundationgames.automobility.util.Eventual;
1920
import io.github.foundationgames.automobility.util.InitlessConstants;
2021
import io.github.foundationgames.automobility.util.RegistryQueue;
2122
import io.github.foundationgames.automobility.util.network.CommonPackets;
23+
import net.minecraft.core.HolderLookup;
2224
import net.minecraft.core.registries.BuiltInRegistries;
2325
import net.minecraft.core.registries.Registries;
2426
import net.minecraft.network.syncher.EntityDataSerializers;
@@ -29,6 +31,8 @@
2931
import org.apache.logging.log4j.LogManager;
3032
import org.apache.logging.log4j.Logger;
3133

34+
import java.io.IOException;
35+
3236
public class Automobility {
3337
public static final String MOD_ID = InitlessConstants.AUTOMOBILITY;
3438
public static final Logger LOG = LogManager.getLogger("Automobility");
@@ -74,4 +78,10 @@ public static void initOther() {
7478
public static ResourceLocation rl(String path) {
7579
return ResourceLocation.fromNamespaceAndPath(MOD_ID, path);
7680
}
81+
82+
public static void dumpDynamicRegistries(HolderLookup.Provider registries) throws IOException {
83+
AutomobilityClientResourceDumper.dumpDynamicRegistry(registries, AutomobileFrame.REGISTRY, AutomobileFrame.DIRECT_CODEC);
84+
AutomobilityClientResourceDumper.dumpDynamicRegistry(registries, AutomobileWheel.REGISTRY, AutomobileWheel.DIRECT_CODEC);
85+
AutomobilityClientResourceDumper.dumpDynamicRegistry(registries, AutomobileEngine.REGISTRY, AutomobileEngine.DIRECT_CODEC);
86+
}
7787
}

common/src/main/java/io/github/foundationgames/automobility/AutomobilityClient.java

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package io.github.foundationgames.automobility;
22

3+
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
34
import io.github.foundationgames.automobility.automobile.AutomobileComponent;
45
import io.github.foundationgames.automobility.automobile.AutomobileEngine;
56
import io.github.foundationgames.automobility.automobile.AutomobileFrame;
@@ -25,9 +26,13 @@
2526
import net.minecraft.client.color.item.ItemColor;
2627
import net.minecraft.client.model.Model;
2728
import net.minecraft.client.renderer.BiomeColors;
29+
import net.minecraft.commands.SharedSuggestionProvider;
30+
import net.minecraft.core.HolderLookup;
31+
import net.minecraft.network.chat.Component;
2832
import net.minecraft.resources.ResourceLocation;
2933
import net.minecraft.world.level.GrassColor;
3034

35+
import java.io.IOException;
3136
import java.util.function.Function;
3237

3338
public class AutomobilityClient {
@@ -46,6 +51,22 @@ public static void init() {
4651

4752
Platform.get().registerMenuScreen(Automobility.AUTO_MECHANIC_SCREEN.require(), AutoMechanicTableScreen::new);
4853
Platform.get().registerMenuScreen(Automobility.SINGLE_SLOT_SCREEN.require(), SingleSlotScreen::new);
54+
55+
Platform.get().registerClientCommand((dispatcher, registries) ->
56+
dispatcher.register(LiteralArgumentBuilder.<SharedSuggestionProvider>literal("automobilityc")
57+
.then(LiteralArgumentBuilder.<SharedSuggestionProvider>literal("dump")
58+
.executes(ctx -> {
59+
if (tryDumpBuiltinResources(registries)) {
60+
sendClientMessage("Dumped all resources to .minecraft/automobility_dump/");
61+
return 0;
62+
} else {
63+
sendClientMessage("Error dumping resources! See game log for details.");
64+
return 1;
65+
}
66+
})
67+
)
68+
)
69+
);
4970
}
5071

5172
public static void initBlocks() {
@@ -100,6 +121,8 @@ public static <T extends AutomobileComponent<T>, V> void componentItemRenderer(A
100121
var component = item.getComponent(stack, lvl.registryAccess());
101122
if (item.isVisible(component)) {
102123
var model = modelProvider.apply(component);
124+
if (model == null) return;
125+
103126
float scale = scaleProvider.apply(component);
104127
matrices.translate(0.5, 0, 0.5);
105128
matrices.scale(scale, -scale, -scale);
@@ -136,4 +159,23 @@ public static double modifyBoostFov(Minecraft client, double old, float tickDelt
136159

137160
return old;
138161
}
162+
163+
public static boolean tryDumpBuiltinResources(HolderLookup.Provider registries) {
164+
try {
165+
AutomobileModels.dump();
166+
Automobility.dumpDynamicRegistries(registries);
167+
168+
return true;
169+
} catch (IOException ex) {
170+
Automobility.LOG.error("Error dumping Automobility resources: ", ex);
171+
}
172+
return false;
173+
}
174+
175+
public static void sendClientMessage(String message) {
176+
var mc = Minecraft.getInstance();
177+
var txt = Component.literal(message);
178+
mc.gui.getChat().addMessage(txt);
179+
mc.getNarrator().sayNow(txt);
180+
}
139181
}

common/src/main/java/io/github/foundationgames/automobility/automobile/AutomobileData.java

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,30 +14,38 @@
1414
import net.minecraft.world.item.ItemStack;
1515
import net.minecraft.world.item.TooltipFlag;
1616
import net.minecraft.world.item.component.TooltipProvider;
17-
import org.jetbrains.annotations.Nullable;
1817

18+
import java.util.Optional;
1919
import java.util.function.Consumer;
2020

21-
public record AutomobileData(@Nullable ResourceLocation prefabName,
21+
public record AutomobileData(Optional<ResourceLocation> prefabName,
2222
ResourceKey<AutomobileFrame> frame,
2323
ResourceKey<AutomobileWheel> wheel,
2424
ResourceKey<AutomobileEngine> engine) implements TooltipProvider {
2525
public static final Codec<AutomobileData> CODEC = RecordCodecBuilder.create(inst -> inst.group(
26-
ResourceLocation.CODEC.optionalFieldOf("prefab_id", null).forGetter(AutomobileData::prefabName),
26+
ResourceLocation.CODEC.optionalFieldOf("prefab_id").forGetter(AutomobileData::prefabName),
2727
AutomobileFrame.CODEC.fieldOf("frame").forGetter(AutomobileData::frame),
2828
AutomobileWheel.CODEC.fieldOf("wheels").forGetter(AutomobileData::wheel),
2929
AutomobileEngine.CODEC.fieldOf("engine").forGetter(AutomobileData::engine)
3030
).apply(inst, AutomobileData::new));
3131

3232
private static final AutomobileStats stats = new AutomobileStats();
3333

34+
public static AutomobileData prefab(ResourceLocation prefabName,
35+
ResourceKey<AutomobileFrame> frame,
36+
ResourceKey<AutomobileWheel> wheel,
37+
ResourceKey<AutomobileEngine> engine) {
38+
return new AutomobileData(Optional.of(prefabName), frame, wheel, engine);
39+
}
40+
3441
public ItemStack asStack() {
3542
var stack = AutomobilityItems.AUTOMOBILE.require().getDefaultInstance();
3643
stack.set(AutomobilityItems.COMPONENT_AUTOMOBILE_DATA.require(), this);
3744

38-
if (this.prefabName() != null) {
45+
if (this.prefabName().isPresent()) {
46+
var name = this.prefabName().get();
3947
stack.set(DataComponents.ITEM_NAME, Component.translatable(String.format(
40-
"prefab.%s.%s", this.prefabName().getNamespace(), this.prefabName().getPath()
48+
"prefab.%s.%s", name.getNamespace(), name.getPath()
4149
)));
4250
}
4351

common/src/main/java/io/github/foundationgames/automobility/automobile/render/AutomobileModels.java

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,12 @@
1414
import io.github.foundationgames.automobility.automobile.render.attachment.rear.GrindstoneRearAttachmentModel;
1515
import io.github.foundationgames.automobility.automobile.render.attachment.rear.PlowRearAttachmentModel;
1616
import io.github.foundationgames.automobility.automobile.render.attachment.rear.StonecutterRearAttachmentModel;
17+
import io.github.foundationgames.automobility.util.AutomobilityClientResourceDumper;
1718
import io.github.foundationgames.automobility.util.EntityRenderHelper;
1819
import net.minecraft.ResourceLocationException;
1920
import net.minecraft.client.model.Model;
2021
import net.minecraft.client.model.geom.ModelLayerLocation;
22+
import net.minecraft.client.renderer.entity.EntityRendererProvider;
2123
import net.minecraft.resources.FileToIdConverter;
2224
import net.minecraft.resources.ResourceLocation;
2325
import net.minecraft.server.packs.resources.ResourceManager;
@@ -38,7 +40,8 @@ public class AutomobileModels implements ResourceManagerReloadListener {
3840
private static Model skidEffect = new EmptyModel();
3941
private static Model exhaustFumes = new EmptyModel();
4042

41-
private static final Map<ResourceLocation, ModelDefinition> modelProviders = new HashMap<>();
43+
private static final Map<ResourceLocation, ModelDefinition> modelDefinitions = new HashMap<>();
44+
private static EntityRendererProvider.Context modelProvider = null;
4245
private static final Map<ResourceLocation, Model> models = new HashMap<>();
4346

4447
public static final ModelDefinition FRAME_STANDARD = ModelDefinition.ofYaw(
@@ -170,17 +173,13 @@ public static Model getExhaustFumesModel() {
170173
}
171174

172175
public static void register(ResourceLocation location, ModelDefinition model) {
173-
modelProviders.put(location, model);
176+
modelDefinitions.put(location, model);
174177
}
175178

176179
public static void init() {
177180
EntityRenderHelper.registerContextListener(ctx -> {
178181
models.clear();
179-
models.put(EMPTY, new EmptyModel());
180-
181-
for (var entry : modelProviders.entrySet()) {
182-
models.put(entry.getKey(), entry.getValue().createModel(ctx));
183-
}
182+
modelProvider = ctx;
184183

185184
skidEffect = new SkidEffectModel(ctx);
186185
exhaustFumes = new ExhaustFumesModel(ctx);
@@ -224,7 +223,16 @@ public static void registerDefaults() {
224223
}
225224

226225
public static Model getModelOrNull(ResourceLocation location) {
227-
return models.get(location);
226+
if (modelProvider == null) {
227+
return null;
228+
}
229+
230+
var def = modelDefinitions.get(location);
231+
if (def == null) {
232+
return null;
233+
}
234+
235+
return models.computeIfAbsent(location, l -> def.createModel(modelProvider));
228236
}
229237

230238
public static Model getModel(ResourceLocation location) {
@@ -247,16 +255,29 @@ public static Optional<ModelDefinition> readJson(InputStream data) {
247255

248256
@Override
249257
public void onResourceManagerReload(ResourceManager resourceManager) {
258+
modelDefinitions.clear();
259+
AutomobileModels.registerDefaults();
260+
250261
FileToIdConverter.json("automobile_models").listMatchingResources(resourceManager).forEach((rl, res) -> {
251-
models.clear();
252-
AutomobileModels.registerDefaults();
262+
var ns = rl.getNamespace();
263+
var pt = rl.getPath().replaceAll("automobile_models/", "").replaceAll(".json", "");
253264

254265
try (var in = res.open()) {
255266
var data = AutomobileModels.readJson(in);
256-
data.ifPresent(model -> AutomobileModels.register(rl, model));
267+
data.ifPresent(model -> AutomobileModels.register(ResourceLocation.fromNamespaceAndPath(ns, pt), model));
257268
} catch (IOException | ResourceLocationException e) {
258269
Automobility.LOG.error(e);
259270
}
260271
});
261272
}
273+
274+
public static void dump() throws IOException {
275+
var dumpRoot = "assets";
276+
var subFolder = "automobile_models";
277+
var codec = ModelDefinition.CODEC;
278+
279+
for (var e : modelDefinitions.entrySet()) {
280+
AutomobilityClientResourceDumper.dumpJsonResource(dumpRoot, subFolder, e.getKey(), e.getValue(), codec);
281+
}
282+
}
262283
}

common/src/main/java/io/github/foundationgames/automobility/automobile/render/AutomobileRenderer.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ public static void render(
9191

9292
// Rear Attachment
9393
var rearAtt = automobile.getRearAttachmentType();
94-
if (!rearAtt.isEmpty()) {
94+
if (!rearAtt.isEmpty() && rearAttachmentModel != null) {
9595
pose.pushPose();
9696
pose.translate(0, chassisRaise, frame.model().rearAttachmentPos() / 16);
9797
pose.mulPose(Axis.YN.rotationDegrees(automobile.getAutomobileYaw(tickDelta) - automobile.getRearAttachmentYaw(tickDelta)));
@@ -109,7 +109,7 @@ public static void render(
109109

110110
// Front Attachment
111111
var frontAtt = automobile.getFrontAttachmentType();
112-
if (!frontAtt.isEmpty()) {
112+
if (!frontAtt.isEmpty() && frontAttachmentModel != null) {
113113
pose.pushPose();
114114
pose.translate(0, 0, frame.model().frontAttachmentPos() / -16);
115115

@@ -126,7 +126,7 @@ public static void render(
126126
// WHEELS ----------------------------------------
127127
var wPoses = frame.model().wheelBase().wheels();
128128

129-
if (!wheels.isEmpty()) {
129+
if (!wheels.isEmpty() && wheelModel != null) {
130130
var wheelBuffer = buffers.getBuffer(wheelModel.renderType(wheels.model().texture()));
131131
float wheelAngle = automobile.getWheelAngle(tickDelta);
132132
int wheelCount = automobile.getWheelCount();

common/src/main/java/io/github/foundationgames/automobility/automobile/render/BaseModel.java

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,18 @@
1111
import net.minecraft.client.renderer.entity.EntityRendererProvider;
1212
import org.joml.Vector3f;
1313

14+
import java.util.List;
15+
import java.util.Map;
16+
import java.util.NoSuchElementException;
17+
1418
public class BaseModel extends Model {
1519
protected final ModelPart root;
1620
protected final Vector3f translation;
1721
protected final Vector3f rotation;
1822
protected final Vector3f scale;
1923

24+
public static final ModelPart PART_EMPTY = new ModelPart(List.of(), Map.of());
25+
2026
public BaseModel(EntityRendererProvider.Context ctx,
2127
ModelDefinition.RenderMaterial material,
2228
ModelLayerLocation layer,
@@ -25,7 +31,21 @@ public BaseModel(EntityRendererProvider.Context ctx,
2531
this.translation = translation;
2632
this.rotation = rotation;
2733
this.scale = scale;
28-
this.root = ctx.bakeLayer(layer).getChild("main");
34+
35+
var head = ctx.bakeLayer(layer);
36+
var root = getChildSafe(head, "main");
37+
if (root == PART_EMPTY) {
38+
root = head;
39+
}
40+
this.root = root;
41+
}
42+
43+
protected static ModelPart getChildSafe(ModelPart parent, String child) {
44+
try {
45+
return parent.getChild(child);
46+
} catch (NoSuchElementException ex) {
47+
return PART_EMPTY;
48+
}
2949
}
3050

3151
protected void prepare(PoseStack matrices) {

common/src/main/java/io/github/foundationgames/automobility/automobile/render/attachment/front/FrontAttachmentRenderModel.java

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@
1111
import org.jetbrains.annotations.Nullable;
1212
import org.joml.Vector3f;
1313

14-
import java.util.NoSuchElementException;
15-
1614
public class FrontAttachmentRenderModel extends BaseModel {
1715
protected final @Nullable ModelPart ground;
1816
private float groundHeight = 0;
@@ -22,13 +20,7 @@ public FrontAttachmentRenderModel(EntityRendererProvider.Context ctx,
2220
ModelLayerLocation layer,
2321
Vector3f translation, Vector3f rotation, Vector3f scale) {
2422
super(ctx, material, layer, translation, rotation, scale);
25-
ModelPart ground;
26-
try {
27-
ground = ctx.bakeLayer(layer).getChild("ground");
28-
} catch (NoSuchElementException ignored) {
29-
ground = null;
30-
}
31-
this.ground = ground;
23+
this.ground = getChildSafe(ctx.bakeLayer(layer), "ground");
3224
}
3325

3426
public void setRenderState(@Nullable FrontAttachment attachment, float groundHeight, float tickDelta) {

common/src/main/java/io/github/foundationgames/automobility/automobile/render/attachment/front/HarvesterFrontAttachmentModel.java

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,7 @@ public HarvesterFrontAttachmentModel(EntityRendererProvider.Context ctx,
1919
ModelLayerLocation layer,
2020
Vector3f translation, Vector3f rotation, Vector3f scale) {
2121
super(ctx, material, layer, translation, rotation, scale);
22-
23-
if (this.ground != null) {
24-
this.roller = this.ground.getChild("roller");
25-
} else {
26-
this.roller = null;
27-
}
22+
this.roller = getChildSafe(this.ground, "roller");
2823
}
2924

3025
@Override

common/src/main/java/io/github/foundationgames/automobility/automobile/render/attachment/rear/BannerPostRearAttachmentModel.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,13 @@ public BannerPostRearAttachmentModel(EntityRendererProvider.Context ctx,
3838
Vector3f translation, Vector3f rotation, Vector3f scale) {
3939
super(ctx, material, layer, translation, rotation, scale);
4040

41-
this.fakePole = this.root.getChild("fake_pole");
42-
this.pole = this.root.getChild("pole");
43-
this.bar = this.pole.getChild("bar");
41+
this.fakePole = getChildSafe(this.root, "fake_pole");
42+
this.pole = getChildSafe(this.root, "pole");
43+
this.bar = getChildSafe(this.pole, "bar");
4444

45-
this.flagPole = this.root.getChild("flag_pole");
46-
this.flagBar = this.flagPole.getChild("flag_bar");
47-
this.flag = this.flagBar.getChild("flag");
45+
this.flagPole = getChildSafe(this.root, "flag_pole");
46+
this.flagBar = getChildSafe(this.flagPole, "flag_bar");
47+
this.flag = getChildSafe(this.flagBar, "flag");
4848

4949
this.flagPole.visible = false;
5050
this.pole.visible = false;

0 commit comments

Comments
 (0)