diff --git a/docs/content/Modpacks/Changes/v7.4.0.md b/docs/content/Modpacks/Changes/v7.4.0.md index 766793617d0..b12d7e98444 100644 --- a/docs/content/Modpacks/Changes/v7.4.0.md +++ b/docs/content/Modpacks/Changes/v7.4.0.md @@ -24,4 +24,3 @@ to `roll(RecipeCapability cap, List chancedEntries, ChanceBoostFunction boostFunction, int recipeTier, int chanceTier, Object2IntMap cache, int times)` (The chance roll function now also requires the RecipeCapability that is currently being processed to be passed in.) - diff --git a/docs/content/Modpacks/Changes/v7.5.0.md b/docs/content/Modpacks/Changes/v7.5.0.md index 8480fd6014d..efe36c8eadb 100644 --- a/docs/content/Modpacks/Changes/v7.5.0.md +++ b/docs/content/Modpacks/Changes/v7.5.0.md @@ -4,9 +4,11 @@ title: "Version 7.5.0" # Updating from `7.4.1` to `7.5.0` +## Machine Builder Generics +We have added a second Generic argument to our (Multiblock)MachineBuilder. This effectively means that anywhere where you used to store a partially finished `MachineBuilder`, you now need to store a `MachineBuilder`. The same holds for `MultiblockMachineBuilder`. -## MachineBuilder Generics -We have added a second Generic argument to our (Multiblock)MachineBuilder. This effectively means that anywhere where you used to store a partially finished `MachineBuilder`, you now need to store a `MachineBuilder`. The same holds for `MultiblockMachineBuilder`. +## Machine & Cover Copy/Paste System +A new system for copying machines using the Machine Memory Card has been added, see [this page](../Other-Topics/Cover-Machine-Copy-Paste-Support.md) if you want to add extra copy/paste behaviour to your own machines and covers. ## RecipeCondition Generics We have added a Generic argument to `RecipeCondition` describing the condition. @@ -20,14 +22,53 @@ You also need to adjust the generics of `getType()` and `createTemplate()` to ma - public RecipeCondition createTemplate() { + public ExampleCondition createTemplate() { ``` - -## Machine & Cover Copy/Paste System -A new system for copying machines using the Machine Memory Card has been added, see [this page](../Other-Topics/Cover-Machine-Copy-Paste-Support.md) if you want to add extra copy/paste behaviour to your own machines and covers. - ## Mortar Recipe Fix Previously, adding GTToolType.MORTAR to your tool did not automatically generate the recipe. This has been fixed. If you previously generated a recipe using this, you need to remove your manual recipe. +## Pipe rendering changes +_This is only relevant to add-on mods with custom pipe types._ +Addons with custom pipe implementations will have to tweak their code slightly to function with the new rendering code (see example below). + +```patch +-public final PipeModel model = new PipeModel(pipeType.getThickness(), () -> [side texture], () -> [end texture], null, null); +-@Getter +-private final PipeBlockRenderer renderer = new PipeBlockRenderer(model); + + ... + + @Override +-public PipeModel getPipeModel() { +- return model; ++public PipeModel createPipeModel(GTBlockstateProvider provider) { ++ return new PipeModel(this, pipeType.getThickness(), [side texture], [end texture], provider); + } +``` +If your pipe is generated from a material property (or equivalent), you should also call `PipeModel#dynamicModel()` +to have models be generated at runtime. +If so, must also add a **Mod bus** event listener for `RegisterDynamicResourcesEvent`, like so: +```java +@SubscribeEvent +public static void registerDynamicResources(RegisterDynamicResourcesEvent event) { + for (var block : MyBlocks.MY_PIPE_BLOCKS) block.get().createPipeModel(RuntimeExistingFileHelper.INSTANCE).dynamicModel(); +} +``` +Replace `MyBlocks.MY_PIPE_BLOCKS` with a reference to your pipe block array/map value collection. + + +Conversely, if the pipe is **not** generated, but has a constant set of variants (such as optical fiber cables or laser pipes), +you should **NOT** use `PipeModel#dynamicModel()` and instead set the model with `GTBlockBuilder#gtBlockstate` as such: +```java + // on your pipe block builder + ... = REGISTRATE.block(...) + .properties(...) + .gtBlockstate(GTModels::createPipeBlockModel) + ...more builder things... + .item(...) + .model(NonNullBiConsumer.noop()) + ...more builder things... +``` + ## Lamp Predicates Previously, lamps were not useable with the terminal in multiblocks. There are new lamp predicates that will help solve this problem. The predicate to use all lamps is: `Predicates.anyLamp()` -The predicate to use a specific color is: `Predicates.lampsByColor(DyeColor.DYE_COLOR)`. Where DYE_COLOR is the name of the color you want. \ No newline at end of file +The predicate to use a specific color is: `Predicates.lampsByColor(DyeColor.DYE_COLOR)`. Where DYE_COLOR is the name of the color you want. diff --git a/src/generated/resources/assets/gtceu/blockstates/huge_duct_pipe.json b/src/generated/resources/assets/gtceu/blockstates/huge_duct_pipe.json new file mode 100644 index 00000000000..583340f5ea7 --- /dev/null +++ b/src/generated/resources/assets/gtceu/blockstates/huge_duct_pipe.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "gtceu:block/huge_duct_pipe" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/blockstates/large_duct_pipe.json b/src/generated/resources/assets/gtceu/blockstates/large_duct_pipe.json new file mode 100644 index 00000000000..8ddcee59f5a --- /dev/null +++ b/src/generated/resources/assets/gtceu/blockstates/large_duct_pipe.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "gtceu:block/large_duct_pipe" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/blockstates/normal_duct_pipe.json b/src/generated/resources/assets/gtceu/blockstates/normal_duct_pipe.json new file mode 100644 index 00000000000..c12030e7f2f --- /dev/null +++ b/src/generated/resources/assets/gtceu/blockstates/normal_duct_pipe.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "gtceu:block/normal_duct_pipe" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/blockstates/normal_laser_pipe.json b/src/generated/resources/assets/gtceu/blockstates/normal_laser_pipe.json new file mode 100644 index 00000000000..7b77d7b3adb --- /dev/null +++ b/src/generated/resources/assets/gtceu/blockstates/normal_laser_pipe.json @@ -0,0 +1,10 @@ +{ + "variants": { + "active=false": { + "model": "gtceu:block/normal_laser_pipe" + }, + "active=true": { + "model": "gtceu:block/normal_laser_pipe_active" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/blockstates/normal_optical_pipe.json b/src/generated/resources/assets/gtceu/blockstates/normal_optical_pipe.json new file mode 100644 index 00000000000..dcda4258ec6 --- /dev/null +++ b/src/generated/resources/assets/gtceu/blockstates/normal_optical_pipe.json @@ -0,0 +1,10 @@ +{ + "variants": { + "active=false": { + "model": "gtceu:block/normal_optical_pipe" + }, + "active=true": { + "model": "gtceu:block/normal_optical_pipe_active" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/blockstates/small_duct_pipe.json b/src/generated/resources/assets/gtceu/blockstates/small_duct_pipe.json new file mode 100644 index 00000000000..146f5c42cfb --- /dev/null +++ b/src/generated/resources/assets/gtceu/blockstates/small_duct_pipe.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "gtceu:block/small_duct_pipe" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/block/huge_duct_pipe.json b/src/generated/resources/assets/gtceu/models/block/huge_duct_pipe.json new file mode 100644 index 00000000000..e737cf69235 --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/huge_duct_pipe.json @@ -0,0 +1,55 @@ +{ + "parent": "gtceu:block/pipe/huge_duct_pipe/center", + "loader": "gtceu:pipe", + "parts": { + "center": { + "model": "gtceu:block/pipe/huge_duct_pipe/center" + }, + "down": { + "model": "gtceu:block/pipe/huge_duct_pipe/connection" + }, + "east": { + "model": "gtceu:block/pipe/huge_duct_pipe/connection", + "x": 90, + "y": 270 + }, + "north": { + "model": "gtceu:block/pipe/huge_duct_pipe/connection", + "x": 90, + "y": 180 + }, + "south": { + "model": "gtceu:block/pipe/huge_duct_pipe/connection", + "x": 90 + }, + "up": { + "model": "gtceu:block/pipe/huge_duct_pipe/connection", + "x": 180 + }, + "west": { + "model": "gtceu:block/pipe/huge_duct_pipe/connection", + "x": 90, + "y": 90 + } + }, + "restrictors": { + "down": { + "model": "gtceu:block/pipe/restrictor/down/thickness_14.0" + }, + "east": { + "model": "gtceu:block/pipe/restrictor/east/thickness_14.0" + }, + "north": { + "model": "gtceu:block/pipe/restrictor/north/thickness_14.0" + }, + "south": { + "model": "gtceu:block/pipe/restrictor/south/thickness_14.0" + }, + "up": { + "model": "gtceu:block/pipe/restrictor/up/thickness_14.0" + }, + "west": { + "model": "gtceu:block/pipe/restrictor/west/thickness_14.0" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/block/large_duct_pipe.json b/src/generated/resources/assets/gtceu/models/block/large_duct_pipe.json new file mode 100644 index 00000000000..a988ebb1438 --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/large_duct_pipe.json @@ -0,0 +1,55 @@ +{ + "parent": "gtceu:block/pipe/large_duct_pipe/center", + "loader": "gtceu:pipe", + "parts": { + "center": { + "model": "gtceu:block/pipe/large_duct_pipe/center" + }, + "down": { + "model": "gtceu:block/pipe/large_duct_pipe/connection" + }, + "east": { + "model": "gtceu:block/pipe/large_duct_pipe/connection", + "x": 90, + "y": 270 + }, + "north": { + "model": "gtceu:block/pipe/large_duct_pipe/connection", + "x": 90, + "y": 180 + }, + "south": { + "model": "gtceu:block/pipe/large_duct_pipe/connection", + "x": 90 + }, + "up": { + "model": "gtceu:block/pipe/large_duct_pipe/connection", + "x": 180 + }, + "west": { + "model": "gtceu:block/pipe/large_duct_pipe/connection", + "x": 90, + "y": 90 + } + }, + "restrictors": { + "down": { + "model": "gtceu:block/pipe/restrictor/down/thickness_12.0" + }, + "east": { + "model": "gtceu:block/pipe/restrictor/east/thickness_12.0" + }, + "north": { + "model": "gtceu:block/pipe/restrictor/north/thickness_12.0" + }, + "south": { + "model": "gtceu:block/pipe/restrictor/south/thickness_12.0" + }, + "up": { + "model": "gtceu:block/pipe/restrictor/up/thickness_12.0" + }, + "west": { + "model": "gtceu:block/pipe/restrictor/west/thickness_12.0" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/block/normal_duct_pipe.json b/src/generated/resources/assets/gtceu/models/block/normal_duct_pipe.json new file mode 100644 index 00000000000..c17c8d7154b --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/normal_duct_pipe.json @@ -0,0 +1,55 @@ +{ + "parent": "gtceu:block/pipe/normal_duct_pipe/center", + "loader": "gtceu:pipe", + "parts": { + "center": { + "model": "gtceu:block/pipe/normal_duct_pipe/center" + }, + "down": { + "model": "gtceu:block/pipe/normal_duct_pipe/connection" + }, + "east": { + "model": "gtceu:block/pipe/normal_duct_pipe/connection", + "x": 90, + "y": 270 + }, + "north": { + "model": "gtceu:block/pipe/normal_duct_pipe/connection", + "x": 90, + "y": 180 + }, + "south": { + "model": "gtceu:block/pipe/normal_duct_pipe/connection", + "x": 90 + }, + "up": { + "model": "gtceu:block/pipe/normal_duct_pipe/connection", + "x": 180 + }, + "west": { + "model": "gtceu:block/pipe/normal_duct_pipe/connection", + "x": 90, + "y": 90 + } + }, + "restrictors": { + "down": { + "model": "gtceu:block/pipe/restrictor/down/thickness_8.0" + }, + "east": { + "model": "gtceu:block/pipe/restrictor/east/thickness_8.0" + }, + "north": { + "model": "gtceu:block/pipe/restrictor/north/thickness_8.0" + }, + "south": { + "model": "gtceu:block/pipe/restrictor/south/thickness_8.0" + }, + "up": { + "model": "gtceu:block/pipe/restrictor/up/thickness_8.0" + }, + "west": { + "model": "gtceu:block/pipe/restrictor/west/thickness_8.0" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/block/normal_laser_pipe.json b/src/generated/resources/assets/gtceu/models/block/normal_laser_pipe.json new file mode 100644 index 00000000000..164e2ac6fe6 --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/normal_laser_pipe.json @@ -0,0 +1,55 @@ +{ + "parent": "gtceu:block/pipe/normal_laser_pipe/center", + "loader": "gtceu:pipe", + "parts": { + "center": { + "model": "gtceu:block/pipe/normal_laser_pipe/center" + }, + "down": { + "model": "gtceu:block/pipe/normal_laser_pipe/connection" + }, + "east": { + "model": "gtceu:block/pipe/normal_laser_pipe/connection", + "x": 90, + "y": 270 + }, + "north": { + "model": "gtceu:block/pipe/normal_laser_pipe/connection", + "x": 90, + "y": 180 + }, + "south": { + "model": "gtceu:block/pipe/normal_laser_pipe/connection", + "x": 90 + }, + "up": { + "model": "gtceu:block/pipe/normal_laser_pipe/connection", + "x": 180 + }, + "west": { + "model": "gtceu:block/pipe/normal_laser_pipe/connection", + "x": 90, + "y": 90 + } + }, + "restrictors": { + "down": { + "model": "gtceu:block/pipe/restrictor/down/thickness_6.0" + }, + "east": { + "model": "gtceu:block/pipe/restrictor/east/thickness_6.0" + }, + "north": { + "model": "gtceu:block/pipe/restrictor/north/thickness_6.0" + }, + "south": { + "model": "gtceu:block/pipe/restrictor/south/thickness_6.0" + }, + "up": { + "model": "gtceu:block/pipe/restrictor/up/thickness_6.0" + }, + "west": { + "model": "gtceu:block/pipe/restrictor/west/thickness_6.0" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/block/normal_laser_pipe_active.json b/src/generated/resources/assets/gtceu/models/block/normal_laser_pipe_active.json new file mode 100644 index 00000000000..ac6d70b010c --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/normal_laser_pipe_active.json @@ -0,0 +1,55 @@ +{ + "parent": "gtceu:block/pipe/normal_laser_pipe/center_active", + "loader": "gtceu:pipe", + "parts": { + "center": { + "model": "gtceu:block/pipe/normal_laser_pipe/center_active" + }, + "down": { + "model": "gtceu:block/pipe/normal_laser_pipe/connection_active" + }, + "east": { + "model": "gtceu:block/pipe/normal_laser_pipe/connection_active", + "x": 90, + "y": 270 + }, + "north": { + "model": "gtceu:block/pipe/normal_laser_pipe/connection_active", + "x": 90, + "y": 180 + }, + "south": { + "model": "gtceu:block/pipe/normal_laser_pipe/connection_active", + "x": 90 + }, + "up": { + "model": "gtceu:block/pipe/normal_laser_pipe/connection_active", + "x": 180 + }, + "west": { + "model": "gtceu:block/pipe/normal_laser_pipe/connection_active", + "x": 90, + "y": 90 + } + }, + "restrictors": { + "down": { + "model": "gtceu:block/pipe/restrictor/down/thickness_6.0" + }, + "east": { + "model": "gtceu:block/pipe/restrictor/east/thickness_6.0" + }, + "north": { + "model": "gtceu:block/pipe/restrictor/north/thickness_6.0" + }, + "south": { + "model": "gtceu:block/pipe/restrictor/south/thickness_6.0" + }, + "up": { + "model": "gtceu:block/pipe/restrictor/up/thickness_6.0" + }, + "west": { + "model": "gtceu:block/pipe/restrictor/west/thickness_6.0" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/block/normal_optical_pipe.json b/src/generated/resources/assets/gtceu/models/block/normal_optical_pipe.json new file mode 100644 index 00000000000..e03e782ac34 --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/normal_optical_pipe.json @@ -0,0 +1,55 @@ +{ + "parent": "gtceu:block/pipe/normal_optical_pipe/center", + "loader": "gtceu:pipe", + "parts": { + "center": { + "model": "gtceu:block/pipe/normal_optical_pipe/center" + }, + "down": { + "model": "gtceu:block/pipe/normal_optical_pipe/connection" + }, + "east": { + "model": "gtceu:block/pipe/normal_optical_pipe/connection", + "x": 90, + "y": 270 + }, + "north": { + "model": "gtceu:block/pipe/normal_optical_pipe/connection", + "x": 90, + "y": 180 + }, + "south": { + "model": "gtceu:block/pipe/normal_optical_pipe/connection", + "x": 90 + }, + "up": { + "model": "gtceu:block/pipe/normal_optical_pipe/connection", + "x": 180 + }, + "west": { + "model": "gtceu:block/pipe/normal_optical_pipe/connection", + "x": 90, + "y": 90 + } + }, + "restrictors": { + "down": { + "model": "gtceu:block/pipe/restrictor/down/thickness_6.0" + }, + "east": { + "model": "gtceu:block/pipe/restrictor/east/thickness_6.0" + }, + "north": { + "model": "gtceu:block/pipe/restrictor/north/thickness_6.0" + }, + "south": { + "model": "gtceu:block/pipe/restrictor/south/thickness_6.0" + }, + "up": { + "model": "gtceu:block/pipe/restrictor/up/thickness_6.0" + }, + "west": { + "model": "gtceu:block/pipe/restrictor/west/thickness_6.0" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/block/normal_optical_pipe_active.json b/src/generated/resources/assets/gtceu/models/block/normal_optical_pipe_active.json new file mode 100644 index 00000000000..2a727149bb7 --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/normal_optical_pipe_active.json @@ -0,0 +1,55 @@ +{ + "parent": "gtceu:block/pipe/normal_optical_pipe/center_active", + "loader": "gtceu:pipe", + "parts": { + "center": { + "model": "gtceu:block/pipe/normal_optical_pipe/center_active" + }, + "down": { + "model": "gtceu:block/pipe/normal_optical_pipe/connection_active" + }, + "east": { + "model": "gtceu:block/pipe/normal_optical_pipe/connection_active", + "x": 90, + "y": 270 + }, + "north": { + "model": "gtceu:block/pipe/normal_optical_pipe/connection_active", + "x": 90, + "y": 180 + }, + "south": { + "model": "gtceu:block/pipe/normal_optical_pipe/connection_active", + "x": 90 + }, + "up": { + "model": "gtceu:block/pipe/normal_optical_pipe/connection_active", + "x": 180 + }, + "west": { + "model": "gtceu:block/pipe/normal_optical_pipe/connection_active", + "x": 90, + "y": 90 + } + }, + "restrictors": { + "down": { + "model": "gtceu:block/pipe/restrictor/down/thickness_6.0" + }, + "east": { + "model": "gtceu:block/pipe/restrictor/east/thickness_6.0" + }, + "north": { + "model": "gtceu:block/pipe/restrictor/north/thickness_6.0" + }, + "south": { + "model": "gtceu:block/pipe/restrictor/south/thickness_6.0" + }, + "up": { + "model": "gtceu:block/pipe/restrictor/up/thickness_6.0" + }, + "west": { + "model": "gtceu:block/pipe/restrictor/west/thickness_6.0" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/block/pipe/huge_duct_pipe/center.json b/src/generated/resources/assets/gtceu/models/block/pipe/huge_duct_pipe/center.json new file mode 100644 index 00000000000..6318ac6c5b3 --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/pipe/huge_duct_pipe/center.json @@ -0,0 +1,47 @@ +{ + "parent": "minecraft:block/block", + "elements": [ + { + "faces": { + "down": { + "texture": "#side", + "tintindex": 0 + }, + "east": { + "texture": "#side", + "tintindex": 0 + }, + "north": { + "texture": "#side", + "tintindex": 0 + }, + "south": { + "texture": "#side", + "tintindex": 0 + }, + "up": { + "texture": "#side", + "tintindex": 0 + }, + "west": { + "texture": "#side", + "tintindex": 0 + } + }, + "from": [ + 1, + 1, + 1 + ], + "to": [ + 15, + 15, + 15 + ] + } + ], + "textures": { + "end": "gtceu:block/pipe/pipe_duct_in", + "side": "gtceu:block/pipe/pipe_duct_side" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/block/pipe/huge_duct_pipe/connection.json b/src/generated/resources/assets/gtceu/models/block/pipe/huge_duct_pipe/connection.json new file mode 100644 index 00000000000..b5f34317735 --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/pipe/huge_duct_pipe/connection.json @@ -0,0 +1,48 @@ +{ + "parent": "minecraft:block/block", + "elements": [ + { + "faces": { + "down": { + "cullface": "down", + "texture": "#end", + "tintindex": 1 + }, + "east": { + "texture": "#side", + "tintindex": 0 + }, + "north": { + "texture": "#side", + "tintindex": 0 + }, + "south": { + "texture": "#side", + "tintindex": 0 + }, + "up": { + "texture": "#end", + "tintindex": 1 + }, + "west": { + "texture": "#side", + "tintindex": 0 + } + }, + "from": [ + 1, + 0, + 1 + ], + "to": [ + 15, + 1, + 15 + ] + } + ], + "textures": { + "end": "gtceu:block/pipe/pipe_duct_in", + "side": "gtceu:block/pipe/pipe_duct_side" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/block/pipe/large_duct_pipe/center.json b/src/generated/resources/assets/gtceu/models/block/pipe/large_duct_pipe/center.json new file mode 100644 index 00000000000..26aeac6acf3 --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/pipe/large_duct_pipe/center.json @@ -0,0 +1,47 @@ +{ + "parent": "minecraft:block/block", + "elements": [ + { + "faces": { + "down": { + "texture": "#side", + "tintindex": 0 + }, + "east": { + "texture": "#side", + "tintindex": 0 + }, + "north": { + "texture": "#side", + "tintindex": 0 + }, + "south": { + "texture": "#side", + "tintindex": 0 + }, + "up": { + "texture": "#side", + "tintindex": 0 + }, + "west": { + "texture": "#side", + "tintindex": 0 + } + }, + "from": [ + 2, + 2, + 2 + ], + "to": [ + 14, + 14, + 14 + ] + } + ], + "textures": { + "end": "gtceu:block/pipe/pipe_duct_in", + "side": "gtceu:block/pipe/pipe_duct_side" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/block/pipe/large_duct_pipe/connection.json b/src/generated/resources/assets/gtceu/models/block/pipe/large_duct_pipe/connection.json new file mode 100644 index 00000000000..e5504c54c2b --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/pipe/large_duct_pipe/connection.json @@ -0,0 +1,48 @@ +{ + "parent": "minecraft:block/block", + "elements": [ + { + "faces": { + "down": { + "cullface": "down", + "texture": "#end", + "tintindex": 1 + }, + "east": { + "texture": "#side", + "tintindex": 0 + }, + "north": { + "texture": "#side", + "tintindex": 0 + }, + "south": { + "texture": "#side", + "tintindex": 0 + }, + "up": { + "texture": "#end", + "tintindex": 1 + }, + "west": { + "texture": "#side", + "tintindex": 0 + } + }, + "from": [ + 2, + 0, + 2 + ], + "to": [ + 14, + 2, + 14 + ] + } + ], + "textures": { + "end": "gtceu:block/pipe/pipe_duct_in", + "side": "gtceu:block/pipe/pipe_duct_side" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/block/pipe/normal_duct_pipe/center.json b/src/generated/resources/assets/gtceu/models/block/pipe/normal_duct_pipe/center.json new file mode 100644 index 00000000000..55bac017a34 --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/pipe/normal_duct_pipe/center.json @@ -0,0 +1,47 @@ +{ + "parent": "minecraft:block/block", + "elements": [ + { + "faces": { + "down": { + "texture": "#side", + "tintindex": 0 + }, + "east": { + "texture": "#side", + "tintindex": 0 + }, + "north": { + "texture": "#side", + "tintindex": 0 + }, + "south": { + "texture": "#side", + "tintindex": 0 + }, + "up": { + "texture": "#side", + "tintindex": 0 + }, + "west": { + "texture": "#side", + "tintindex": 0 + } + }, + "from": [ + 4, + 4, + 4 + ], + "to": [ + 12, + 12, + 12 + ] + } + ], + "textures": { + "end": "gtceu:block/pipe/pipe_duct_in", + "side": "gtceu:block/pipe/pipe_duct_side" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/block/pipe/normal_duct_pipe/connection.json b/src/generated/resources/assets/gtceu/models/block/pipe/normal_duct_pipe/connection.json new file mode 100644 index 00000000000..c004f0de717 --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/pipe/normal_duct_pipe/connection.json @@ -0,0 +1,48 @@ +{ + "parent": "minecraft:block/block", + "elements": [ + { + "faces": { + "down": { + "cullface": "down", + "texture": "#end", + "tintindex": 1 + }, + "east": { + "texture": "#side", + "tintindex": 0 + }, + "north": { + "texture": "#side", + "tintindex": 0 + }, + "south": { + "texture": "#side", + "tintindex": 0 + }, + "up": { + "texture": "#end", + "tintindex": 1 + }, + "west": { + "texture": "#side", + "tintindex": 0 + } + }, + "from": [ + 4, + 0, + 4 + ], + "to": [ + 12, + 4, + 12 + ] + } + ], + "textures": { + "end": "gtceu:block/pipe/pipe_duct_in", + "side": "gtceu:block/pipe/pipe_duct_side" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/block/pipe/normal_laser_pipe/center.json b/src/generated/resources/assets/gtceu/models/block/pipe/normal_laser_pipe/center.json new file mode 100644 index 00000000000..0cc3032c0e5 --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/pipe/normal_laser_pipe/center.json @@ -0,0 +1,86 @@ +{ + "parent": "minecraft:block/block", + "elements": [ + { + "faces": { + "down": { + "texture": "#side", + "tintindex": 0 + }, + "east": { + "texture": "#side", + "tintindex": 0 + }, + "north": { + "texture": "#side", + "tintindex": 0 + }, + "south": { + "texture": "#side", + "tintindex": 0 + }, + "up": { + "texture": "#side", + "tintindex": 0 + }, + "west": { + "texture": "#side", + "tintindex": 0 + } + }, + "from": [ + 5, + 5, + 5 + ], + "to": [ + 11, + 11, + 11 + ] + }, + { + "faces": { + "down": { + "texture": "#side_overlay", + "tintindex": 2 + }, + "east": { + "texture": "#side_overlay", + "tintindex": 2 + }, + "north": { + "texture": "#side_overlay", + "tintindex": 2 + }, + "south": { + "texture": "#side_overlay", + "tintindex": 2 + }, + "up": { + "texture": "#side_overlay", + "tintindex": 2 + }, + "west": { + "texture": "#side_overlay", + "tintindex": 2 + } + }, + "from": [ + 4.998, + 4.998, + 4.998 + ], + "to": [ + 11.002, + 11.002, + 11.002 + ] + } + ], + "textures": { + "end": "gtceu:block/pipe/pipe_laser_in", + "side": "gtceu:block/pipe/pipe_laser_side", + "side_overlay": "gtceu:block/pipe/pipe_laser_side_overlay" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/block/pipe/normal_laser_pipe/center_active.json b/src/generated/resources/assets/gtceu/models/block/pipe/normal_laser_pipe/center_active.json new file mode 100644 index 00000000000..18781c339d2 --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/pipe/normal_laser_pipe/center_active.json @@ -0,0 +1,6 @@ +{ + "parent": "gtceu:block/pipe/normal_laser_pipe/center", + "textures": { + "side_overlay": "gtceu:block/pipe/pipe_laser_side_overlay_emissive" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/block/pipe/normal_laser_pipe/connection.json b/src/generated/resources/assets/gtceu/models/block/pipe/normal_laser_pipe/connection.json new file mode 100644 index 00000000000..7dc25d11fdd --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/pipe/normal_laser_pipe/connection.json @@ -0,0 +1,79 @@ +{ + "parent": "minecraft:block/block", + "elements": [ + { + "faces": { + "down": { + "cullface": "down", + "texture": "#end", + "tintindex": 1 + }, + "east": { + "texture": "#side", + "tintindex": 0 + }, + "north": { + "texture": "#side", + "tintindex": 0 + }, + "south": { + "texture": "#side", + "tintindex": 0 + }, + "up": { + "texture": "#end", + "tintindex": 1 + }, + "west": { + "texture": "#side", + "tintindex": 0 + } + }, + "from": [ + 5, + 0, + 5 + ], + "to": [ + 11, + 5, + 11 + ] + }, + { + "faces": { + "east": { + "texture": "#side_overlay", + "tintindex": 2 + }, + "north": { + "texture": "#side_overlay", + "tintindex": 2 + }, + "south": { + "texture": "#side_overlay", + "tintindex": 2 + }, + "west": { + "texture": "#side_overlay", + "tintindex": 2 + } + }, + "from": [ + 4.998, + -0.002, + 4.998 + ], + "to": [ + 11.002, + 5.002, + 11.002 + ] + } + ], + "textures": { + "end": "gtceu:block/pipe/pipe_laser_in", + "side": "gtceu:block/pipe/pipe_laser_side", + "side_overlay": "gtceu:block/pipe/pipe_laser_side_overlay" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/block/pipe/normal_laser_pipe/connection_active.json b/src/generated/resources/assets/gtceu/models/block/pipe/normal_laser_pipe/connection_active.json new file mode 100644 index 00000000000..a9170249dab --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/pipe/normal_laser_pipe/connection_active.json @@ -0,0 +1,6 @@ +{ + "parent": "gtceu:block/pipe/normal_laser_pipe/connection", + "textures": { + "side_overlay": "gtceu:block/pipe/pipe_laser_side_overlay_emissive" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/block/pipe/normal_optical_pipe/center.json b/src/generated/resources/assets/gtceu/models/block/pipe/normal_optical_pipe/center.json new file mode 100644 index 00000000000..c5356268055 --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/pipe/normal_optical_pipe/center.json @@ -0,0 +1,86 @@ +{ + "parent": "minecraft:block/block", + "elements": [ + { + "faces": { + "down": { + "texture": "#side", + "tintindex": 0 + }, + "east": { + "texture": "#side", + "tintindex": 0 + }, + "north": { + "texture": "#side", + "tintindex": 0 + }, + "south": { + "texture": "#side", + "tintindex": 0 + }, + "up": { + "texture": "#side", + "tintindex": 0 + }, + "west": { + "texture": "#side", + "tintindex": 0 + } + }, + "from": [ + 5, + 5, + 5 + ], + "to": [ + 11, + 11, + 11 + ] + }, + { + "faces": { + "down": { + "texture": "#side_overlay", + "tintindex": 2 + }, + "east": { + "texture": "#side_overlay", + "tintindex": 2 + }, + "north": { + "texture": "#side_overlay", + "tintindex": 2 + }, + "south": { + "texture": "#side_overlay", + "tintindex": 2 + }, + "up": { + "texture": "#side_overlay", + "tintindex": 2 + }, + "west": { + "texture": "#side_overlay", + "tintindex": 2 + } + }, + "from": [ + 4.998, + 4.998, + 4.998 + ], + "to": [ + 11.002, + 11.002, + 11.002 + ] + } + ], + "textures": { + "end": "gtceu:block/pipe/pipe_optical_in", + "side": "gtceu:block/pipe/pipe_optical_side", + "side_overlay": "gtceu:block/pipe/pipe_optical_side_overlay" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/block/pipe/normal_optical_pipe/center_active.json b/src/generated/resources/assets/gtceu/models/block/pipe/normal_optical_pipe/center_active.json new file mode 100644 index 00000000000..ac513d036e5 --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/pipe/normal_optical_pipe/center_active.json @@ -0,0 +1,6 @@ +{ + "parent": "gtceu:block/pipe/normal_optical_pipe/center", + "textures": { + "side_overlay": "gtceu:block/pipe/pipe_optical_side_overlay_active" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/block/pipe/normal_optical_pipe/connection.json b/src/generated/resources/assets/gtceu/models/block/pipe/normal_optical_pipe/connection.json new file mode 100644 index 00000000000..b7ee34bd7f4 --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/pipe/normal_optical_pipe/connection.json @@ -0,0 +1,79 @@ +{ + "parent": "minecraft:block/block", + "elements": [ + { + "faces": { + "down": { + "cullface": "down", + "texture": "#end", + "tintindex": 1 + }, + "east": { + "texture": "#side", + "tintindex": 0 + }, + "north": { + "texture": "#side", + "tintindex": 0 + }, + "south": { + "texture": "#side", + "tintindex": 0 + }, + "up": { + "texture": "#end", + "tintindex": 1 + }, + "west": { + "texture": "#side", + "tintindex": 0 + } + }, + "from": [ + 5, + 0, + 5 + ], + "to": [ + 11, + 5, + 11 + ] + }, + { + "faces": { + "east": { + "texture": "#side_overlay", + "tintindex": 2 + }, + "north": { + "texture": "#side_overlay", + "tintindex": 2 + }, + "south": { + "texture": "#side_overlay", + "tintindex": 2 + }, + "west": { + "texture": "#side_overlay", + "tintindex": 2 + } + }, + "from": [ + 4.998, + -0.002, + 4.998 + ], + "to": [ + 11.002, + 5.002, + 11.002 + ] + } + ], + "textures": { + "end": "gtceu:block/pipe/pipe_optical_in", + "side": "gtceu:block/pipe/pipe_optical_side", + "side_overlay": "gtceu:block/pipe/pipe_optical_side_overlay" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/block/pipe/normal_optical_pipe/connection_active.json b/src/generated/resources/assets/gtceu/models/block/pipe/normal_optical_pipe/connection_active.json new file mode 100644 index 00000000000..224c446f985 --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/pipe/normal_optical_pipe/connection_active.json @@ -0,0 +1,6 @@ +{ + "parent": "gtceu:block/pipe/normal_optical_pipe/connection", + "textures": { + "side_overlay": "gtceu:block/pipe/pipe_optical_side_overlay_active" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/down/thickness_12.0.json b/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/down/thickness_12.0.json new file mode 100644 index 00000000000..5b9c48b1c26 --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/down/thickness_12.0.json @@ -0,0 +1,33 @@ +{ + "elements": [ + { + "faces": { + "east": { + "texture": "#restrictor" + }, + "north": { + "texture": "#restrictor" + }, + "south": { + "texture": "#restrictor" + }, + "west": { + "texture": "#restrictor" + } + }, + "from": [ + 1.997, + 0, + 1.997 + ], + "to": [ + 14.002999, + 1.997, + 14.002999 + ] + } + ], + "textures": { + "restrictor": "gtceu:block/pipe/blocked/pipe_blocked" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/down/thickness_14.0.json b/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/down/thickness_14.0.json new file mode 100644 index 00000000000..416426ed097 --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/down/thickness_14.0.json @@ -0,0 +1,33 @@ +{ + "elements": [ + { + "faces": { + "east": { + "texture": "#restrictor" + }, + "north": { + "texture": "#restrictor" + }, + "south": { + "texture": "#restrictor" + }, + "west": { + "texture": "#restrictor" + } + }, + "from": [ + 0.997, + 0, + 0.997 + ], + "to": [ + 15.002999, + 0.997, + 15.002999 + ] + } + ], + "textures": { + "restrictor": "gtceu:block/pipe/blocked/pipe_blocked" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/down/thickness_6.0.json b/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/down/thickness_6.0.json new file mode 100644 index 00000000000..f4b1b636e25 --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/down/thickness_6.0.json @@ -0,0 +1,33 @@ +{ + "elements": [ + { + "faces": { + "east": { + "texture": "#restrictor" + }, + "north": { + "texture": "#restrictor" + }, + "south": { + "texture": "#restrictor" + }, + "west": { + "texture": "#restrictor" + } + }, + "from": [ + 4.997, + 0, + 4.997 + ], + "to": [ + 11.002999, + 4.997, + 11.002999 + ] + } + ], + "textures": { + "restrictor": "gtceu:block/pipe/blocked/pipe_blocked" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/down/thickness_8.0.json b/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/down/thickness_8.0.json new file mode 100644 index 00000000000..a3d058279fb --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/down/thickness_8.0.json @@ -0,0 +1,33 @@ +{ + "elements": [ + { + "faces": { + "east": { + "texture": "#restrictor" + }, + "north": { + "texture": "#restrictor" + }, + "south": { + "texture": "#restrictor" + }, + "west": { + "texture": "#restrictor" + } + }, + "from": [ + 3.997, + 0, + 3.997 + ], + "to": [ + 12.002999, + 3.997, + 12.002999 + ] + } + ], + "textures": { + "restrictor": "gtceu:block/pipe/blocked/pipe_blocked" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/east/thickness_12.0.json b/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/east/thickness_12.0.json new file mode 100644 index 00000000000..2da815fb976 --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/east/thickness_12.0.json @@ -0,0 +1,33 @@ +{ + "elements": [ + { + "faces": { + "down": { + "texture": "#restrictor" + }, + "north": { + "texture": "#restrictor" + }, + "south": { + "texture": "#restrictor" + }, + "up": { + "texture": "#restrictor" + } + }, + "from": [ + 14.002999, + 1.997, + 1.997 + ], + "to": [ + 16, + 14.002999, + 14.002999 + ] + } + ], + "textures": { + "restrictor": "gtceu:block/pipe/blocked/pipe_blocked" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/east/thickness_14.0.json b/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/east/thickness_14.0.json new file mode 100644 index 00000000000..37f0d67af2b --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/east/thickness_14.0.json @@ -0,0 +1,33 @@ +{ + "elements": [ + { + "faces": { + "down": { + "texture": "#restrictor" + }, + "north": { + "texture": "#restrictor" + }, + "south": { + "texture": "#restrictor" + }, + "up": { + "texture": "#restrictor" + } + }, + "from": [ + 15.002999, + 0.997, + 0.997 + ], + "to": [ + 16, + 15.002999, + 15.002999 + ] + } + ], + "textures": { + "restrictor": "gtceu:block/pipe/blocked/pipe_blocked" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/east/thickness_6.0.json b/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/east/thickness_6.0.json new file mode 100644 index 00000000000..ec6b20399be --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/east/thickness_6.0.json @@ -0,0 +1,33 @@ +{ + "elements": [ + { + "faces": { + "down": { + "texture": "#restrictor" + }, + "north": { + "texture": "#restrictor" + }, + "south": { + "texture": "#restrictor" + }, + "up": { + "texture": "#restrictor" + } + }, + "from": [ + 11.002999, + 4.997, + 4.997 + ], + "to": [ + 16, + 11.002999, + 11.002999 + ] + } + ], + "textures": { + "restrictor": "gtceu:block/pipe/blocked/pipe_blocked" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/east/thickness_8.0.json b/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/east/thickness_8.0.json new file mode 100644 index 00000000000..1d959d45a40 --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/east/thickness_8.0.json @@ -0,0 +1,33 @@ +{ + "elements": [ + { + "faces": { + "down": { + "texture": "#restrictor" + }, + "north": { + "texture": "#restrictor" + }, + "south": { + "texture": "#restrictor" + }, + "up": { + "texture": "#restrictor" + } + }, + "from": [ + 12.002999, + 3.997, + 3.997 + ], + "to": [ + 16, + 12.002999, + 12.002999 + ] + } + ], + "textures": { + "restrictor": "gtceu:block/pipe/blocked/pipe_blocked" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/north/thickness_12.0.json b/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/north/thickness_12.0.json new file mode 100644 index 00000000000..8868df86dae --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/north/thickness_12.0.json @@ -0,0 +1,33 @@ +{ + "elements": [ + { + "faces": { + "down": { + "texture": "#restrictor" + }, + "east": { + "texture": "#restrictor" + }, + "up": { + "texture": "#restrictor" + }, + "west": { + "texture": "#restrictor" + } + }, + "from": [ + 1.997, + 1.997, + 0 + ], + "to": [ + 14.002999, + 14.002999, + 1.997 + ] + } + ], + "textures": { + "restrictor": "gtceu:block/pipe/blocked/pipe_blocked" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/north/thickness_14.0.json b/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/north/thickness_14.0.json new file mode 100644 index 00000000000..4cd0913b8d2 --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/north/thickness_14.0.json @@ -0,0 +1,33 @@ +{ + "elements": [ + { + "faces": { + "down": { + "texture": "#restrictor" + }, + "east": { + "texture": "#restrictor" + }, + "up": { + "texture": "#restrictor" + }, + "west": { + "texture": "#restrictor" + } + }, + "from": [ + 0.997, + 0.997, + 0 + ], + "to": [ + 15.002999, + 15.002999, + 0.997 + ] + } + ], + "textures": { + "restrictor": "gtceu:block/pipe/blocked/pipe_blocked" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/north/thickness_6.0.json b/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/north/thickness_6.0.json new file mode 100644 index 00000000000..c3e00fbaf0b --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/north/thickness_6.0.json @@ -0,0 +1,33 @@ +{ + "elements": [ + { + "faces": { + "down": { + "texture": "#restrictor" + }, + "east": { + "texture": "#restrictor" + }, + "up": { + "texture": "#restrictor" + }, + "west": { + "texture": "#restrictor" + } + }, + "from": [ + 4.997, + 4.997, + 0 + ], + "to": [ + 11.002999, + 11.002999, + 4.997 + ] + } + ], + "textures": { + "restrictor": "gtceu:block/pipe/blocked/pipe_blocked" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/north/thickness_8.0.json b/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/north/thickness_8.0.json new file mode 100644 index 00000000000..5b9a9154025 --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/north/thickness_8.0.json @@ -0,0 +1,33 @@ +{ + "elements": [ + { + "faces": { + "down": { + "texture": "#restrictor" + }, + "east": { + "texture": "#restrictor" + }, + "up": { + "texture": "#restrictor" + }, + "west": { + "texture": "#restrictor" + } + }, + "from": [ + 3.997, + 3.997, + 0 + ], + "to": [ + 12.002999, + 12.002999, + 3.997 + ] + } + ], + "textures": { + "restrictor": "gtceu:block/pipe/blocked/pipe_blocked" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/south/thickness_12.0.json b/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/south/thickness_12.0.json new file mode 100644 index 00000000000..cbdb82d87be --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/south/thickness_12.0.json @@ -0,0 +1,33 @@ +{ + "elements": [ + { + "faces": { + "down": { + "texture": "#restrictor" + }, + "east": { + "texture": "#restrictor" + }, + "up": { + "texture": "#restrictor" + }, + "west": { + "texture": "#restrictor" + } + }, + "from": [ + 1.997, + 1.997, + 14.002999 + ], + "to": [ + 14.002999, + 14.002999, + 16 + ] + } + ], + "textures": { + "restrictor": "gtceu:block/pipe/blocked/pipe_blocked" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/south/thickness_14.0.json b/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/south/thickness_14.0.json new file mode 100644 index 00000000000..83a2616c294 --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/south/thickness_14.0.json @@ -0,0 +1,33 @@ +{ + "elements": [ + { + "faces": { + "down": { + "texture": "#restrictor" + }, + "east": { + "texture": "#restrictor" + }, + "up": { + "texture": "#restrictor" + }, + "west": { + "texture": "#restrictor" + } + }, + "from": [ + 0.997, + 0.997, + 15.002999 + ], + "to": [ + 15.002999, + 15.002999, + 16 + ] + } + ], + "textures": { + "restrictor": "gtceu:block/pipe/blocked/pipe_blocked" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/south/thickness_6.0.json b/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/south/thickness_6.0.json new file mode 100644 index 00000000000..eaa3a5d4466 --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/south/thickness_6.0.json @@ -0,0 +1,33 @@ +{ + "elements": [ + { + "faces": { + "down": { + "texture": "#restrictor" + }, + "east": { + "texture": "#restrictor" + }, + "up": { + "texture": "#restrictor" + }, + "west": { + "texture": "#restrictor" + } + }, + "from": [ + 4.997, + 4.997, + 11.002999 + ], + "to": [ + 11.002999, + 11.002999, + 16 + ] + } + ], + "textures": { + "restrictor": "gtceu:block/pipe/blocked/pipe_blocked" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/south/thickness_8.0.json b/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/south/thickness_8.0.json new file mode 100644 index 00000000000..4c807280980 --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/south/thickness_8.0.json @@ -0,0 +1,33 @@ +{ + "elements": [ + { + "faces": { + "down": { + "texture": "#restrictor" + }, + "east": { + "texture": "#restrictor" + }, + "up": { + "texture": "#restrictor" + }, + "west": { + "texture": "#restrictor" + } + }, + "from": [ + 3.997, + 3.997, + 12.002999 + ], + "to": [ + 12.002999, + 12.002999, + 16 + ] + } + ], + "textures": { + "restrictor": "gtceu:block/pipe/blocked/pipe_blocked" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/up/thickness_12.0.json b/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/up/thickness_12.0.json new file mode 100644 index 00000000000..258ac3ed5c5 --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/up/thickness_12.0.json @@ -0,0 +1,33 @@ +{ + "elements": [ + { + "faces": { + "east": { + "texture": "#restrictor" + }, + "north": { + "texture": "#restrictor" + }, + "south": { + "texture": "#restrictor" + }, + "west": { + "texture": "#restrictor" + } + }, + "from": [ + 1.997, + 14.002999, + 1.997 + ], + "to": [ + 14.002999, + 16, + 14.002999 + ] + } + ], + "textures": { + "restrictor": "gtceu:block/pipe/blocked/pipe_blocked" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/up/thickness_14.0.json b/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/up/thickness_14.0.json new file mode 100644 index 00000000000..8b6bee1a4e7 --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/up/thickness_14.0.json @@ -0,0 +1,33 @@ +{ + "elements": [ + { + "faces": { + "east": { + "texture": "#restrictor" + }, + "north": { + "texture": "#restrictor" + }, + "south": { + "texture": "#restrictor" + }, + "west": { + "texture": "#restrictor" + } + }, + "from": [ + 0.997, + 15.002999, + 0.997 + ], + "to": [ + 15.002999, + 16, + 15.002999 + ] + } + ], + "textures": { + "restrictor": "gtceu:block/pipe/blocked/pipe_blocked" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/up/thickness_6.0.json b/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/up/thickness_6.0.json new file mode 100644 index 00000000000..4d07bcf8535 --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/up/thickness_6.0.json @@ -0,0 +1,33 @@ +{ + "elements": [ + { + "faces": { + "east": { + "texture": "#restrictor" + }, + "north": { + "texture": "#restrictor" + }, + "south": { + "texture": "#restrictor" + }, + "west": { + "texture": "#restrictor" + } + }, + "from": [ + 4.997, + 11.002999, + 4.997 + ], + "to": [ + 11.002999, + 16, + 11.002999 + ] + } + ], + "textures": { + "restrictor": "gtceu:block/pipe/blocked/pipe_blocked" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/up/thickness_8.0.json b/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/up/thickness_8.0.json new file mode 100644 index 00000000000..9269e828d47 --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/up/thickness_8.0.json @@ -0,0 +1,33 @@ +{ + "elements": [ + { + "faces": { + "east": { + "texture": "#restrictor" + }, + "north": { + "texture": "#restrictor" + }, + "south": { + "texture": "#restrictor" + }, + "west": { + "texture": "#restrictor" + } + }, + "from": [ + 3.997, + 12.002999, + 3.997 + ], + "to": [ + 12.002999, + 16, + 12.002999 + ] + } + ], + "textures": { + "restrictor": "gtceu:block/pipe/blocked/pipe_blocked" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/west/thickness_12.0.json b/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/west/thickness_12.0.json new file mode 100644 index 00000000000..84b76eea7fa --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/west/thickness_12.0.json @@ -0,0 +1,33 @@ +{ + "elements": [ + { + "faces": { + "down": { + "texture": "#restrictor" + }, + "north": { + "texture": "#restrictor" + }, + "south": { + "texture": "#restrictor" + }, + "up": { + "texture": "#restrictor" + } + }, + "from": [ + 0, + 1.997, + 1.997 + ], + "to": [ + 1.997, + 14.002999, + 14.002999 + ] + } + ], + "textures": { + "restrictor": "gtceu:block/pipe/blocked/pipe_blocked" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/west/thickness_14.0.json b/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/west/thickness_14.0.json new file mode 100644 index 00000000000..b0d3d796931 --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/west/thickness_14.0.json @@ -0,0 +1,33 @@ +{ + "elements": [ + { + "faces": { + "down": { + "texture": "#restrictor" + }, + "north": { + "texture": "#restrictor" + }, + "south": { + "texture": "#restrictor" + }, + "up": { + "texture": "#restrictor" + } + }, + "from": [ + 0, + 0.997, + 0.997 + ], + "to": [ + 0.997, + 15.002999, + 15.002999 + ] + } + ], + "textures": { + "restrictor": "gtceu:block/pipe/blocked/pipe_blocked" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/west/thickness_6.0.json b/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/west/thickness_6.0.json new file mode 100644 index 00000000000..61dcdbf9677 --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/west/thickness_6.0.json @@ -0,0 +1,33 @@ +{ + "elements": [ + { + "faces": { + "down": { + "texture": "#restrictor" + }, + "north": { + "texture": "#restrictor" + }, + "south": { + "texture": "#restrictor" + }, + "up": { + "texture": "#restrictor" + } + }, + "from": [ + 0, + 4.997, + 4.997 + ], + "to": [ + 4.997, + 11.002999, + 11.002999 + ] + } + ], + "textures": { + "restrictor": "gtceu:block/pipe/blocked/pipe_blocked" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/west/thickness_8.0.json b/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/west/thickness_8.0.json new file mode 100644 index 00000000000..cca985d934d --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/pipe/restrictor/west/thickness_8.0.json @@ -0,0 +1,33 @@ +{ + "elements": [ + { + "faces": { + "down": { + "texture": "#restrictor" + }, + "north": { + "texture": "#restrictor" + }, + "south": { + "texture": "#restrictor" + }, + "up": { + "texture": "#restrictor" + } + }, + "from": [ + 0, + 3.997, + 3.997 + ], + "to": [ + 3.997, + 12.002999, + 12.002999 + ] + } + ], + "textures": { + "restrictor": "gtceu:block/pipe/blocked/pipe_blocked" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/block/pipe/small_duct_pipe/center.json b/src/generated/resources/assets/gtceu/models/block/pipe/small_duct_pipe/center.json new file mode 100644 index 00000000000..98a31bc47ef --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/pipe/small_duct_pipe/center.json @@ -0,0 +1,47 @@ +{ + "parent": "minecraft:block/block", + "elements": [ + { + "faces": { + "down": { + "texture": "#side", + "tintindex": 0 + }, + "east": { + "texture": "#side", + "tintindex": 0 + }, + "north": { + "texture": "#side", + "tintindex": 0 + }, + "south": { + "texture": "#side", + "tintindex": 0 + }, + "up": { + "texture": "#side", + "tintindex": 0 + }, + "west": { + "texture": "#side", + "tintindex": 0 + } + }, + "from": [ + 5, + 5, + 5 + ], + "to": [ + 11, + 11, + 11 + ] + } + ], + "textures": { + "end": "gtceu:block/pipe/pipe_duct_in", + "side": "gtceu:block/pipe/pipe_duct_side" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/block/pipe/small_duct_pipe/connection.json b/src/generated/resources/assets/gtceu/models/block/pipe/small_duct_pipe/connection.json new file mode 100644 index 00000000000..569180a1fba --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/pipe/small_duct_pipe/connection.json @@ -0,0 +1,48 @@ +{ + "parent": "minecraft:block/block", + "elements": [ + { + "faces": { + "down": { + "cullface": "down", + "texture": "#end", + "tintindex": 1 + }, + "east": { + "texture": "#side", + "tintindex": 0 + }, + "north": { + "texture": "#side", + "tintindex": 0 + }, + "south": { + "texture": "#side", + "tintindex": 0 + }, + "up": { + "texture": "#end", + "tintindex": 1 + }, + "west": { + "texture": "#side", + "tintindex": 0 + } + }, + "from": [ + 5, + 0, + 5 + ], + "to": [ + 11, + 5, + 11 + ] + } + ], + "textures": { + "end": "gtceu:block/pipe/pipe_duct_in", + "side": "gtceu:block/pipe/pipe_duct_side" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/block/small_duct_pipe.json b/src/generated/resources/assets/gtceu/models/block/small_duct_pipe.json new file mode 100644 index 00000000000..bf4e30317f4 --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/small_duct_pipe.json @@ -0,0 +1,55 @@ +{ + "parent": "gtceu:block/pipe/small_duct_pipe/center", + "loader": "gtceu:pipe", + "parts": { + "center": { + "model": "gtceu:block/pipe/small_duct_pipe/center" + }, + "down": { + "model": "gtceu:block/pipe/small_duct_pipe/connection" + }, + "east": { + "model": "gtceu:block/pipe/small_duct_pipe/connection", + "x": 90, + "y": 270 + }, + "north": { + "model": "gtceu:block/pipe/small_duct_pipe/connection", + "x": 90, + "y": 180 + }, + "south": { + "model": "gtceu:block/pipe/small_duct_pipe/connection", + "x": 90 + }, + "up": { + "model": "gtceu:block/pipe/small_duct_pipe/connection", + "x": 180 + }, + "west": { + "model": "gtceu:block/pipe/small_duct_pipe/connection", + "x": 90, + "y": 90 + } + }, + "restrictors": { + "down": { + "model": "gtceu:block/pipe/restrictor/down/thickness_6.0" + }, + "east": { + "model": "gtceu:block/pipe/restrictor/east/thickness_6.0" + }, + "north": { + "model": "gtceu:block/pipe/restrictor/north/thickness_6.0" + }, + "south": { + "model": "gtceu:block/pipe/restrictor/south/thickness_6.0" + }, + "up": { + "model": "gtceu:block/pipe/restrictor/up/thickness_6.0" + }, + "west": { + "model": "gtceu:block/pipe/restrictor/west/thickness_6.0" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/item/huge_duct_pipe.json b/src/generated/resources/assets/gtceu/models/item/huge_duct_pipe.json new file mode 100644 index 00000000000..6446bb669a9 --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/item/huge_duct_pipe.json @@ -0,0 +1,49 @@ +{ + "parent": "gtceu:block/pipe/huge_duct_pipe/center", + "elements": [ + { + "faces": { + "down": { + "texture": "#side", + "tintindex": 0 + }, + "east": { + "texture": "#side", + "tintindex": 0 + }, + "north": { + "cullface": "north", + "texture": "#end", + "tintindex": 1 + }, + "south": { + "cullface": "south", + "texture": "#end", + "tintindex": 1 + }, + "up": { + "texture": "#side", + "tintindex": 0 + }, + "west": { + "texture": "#side", + "tintindex": 0 + } + }, + "from": [ + 1, + 1, + 0 + ], + "to": [ + 15, + 15, + 16 + ] + } + ], + "textures": { + "end": "gtceu:block/pipe/pipe_duct_in", + "side": "gtceu:block/pipe/pipe_duct_side" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/item/large_duct_pipe.json b/src/generated/resources/assets/gtceu/models/item/large_duct_pipe.json new file mode 100644 index 00000000000..8ce685ee51f --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/item/large_duct_pipe.json @@ -0,0 +1,49 @@ +{ + "parent": "gtceu:block/pipe/large_duct_pipe/center", + "elements": [ + { + "faces": { + "down": { + "texture": "#side", + "tintindex": 0 + }, + "east": { + "texture": "#side", + "tintindex": 0 + }, + "north": { + "cullface": "north", + "texture": "#end", + "tintindex": 1 + }, + "south": { + "cullface": "south", + "texture": "#end", + "tintindex": 1 + }, + "up": { + "texture": "#side", + "tintindex": 0 + }, + "west": { + "texture": "#side", + "tintindex": 0 + } + }, + "from": [ + 2, + 2, + 0 + ], + "to": [ + 14, + 14, + 16 + ] + } + ], + "textures": { + "end": "gtceu:block/pipe/pipe_duct_in", + "side": "gtceu:block/pipe/pipe_duct_side" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/item/normal_duct_pipe.json b/src/generated/resources/assets/gtceu/models/item/normal_duct_pipe.json new file mode 100644 index 00000000000..3b362236c0f --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/item/normal_duct_pipe.json @@ -0,0 +1,49 @@ +{ + "parent": "gtceu:block/pipe/normal_duct_pipe/center", + "elements": [ + { + "faces": { + "down": { + "texture": "#side", + "tintindex": 0 + }, + "east": { + "texture": "#side", + "tintindex": 0 + }, + "north": { + "cullface": "north", + "texture": "#end", + "tintindex": 1 + }, + "south": { + "cullface": "south", + "texture": "#end", + "tintindex": 1 + }, + "up": { + "texture": "#side", + "tintindex": 0 + }, + "west": { + "texture": "#side", + "tintindex": 0 + } + }, + "from": [ + 4, + 4, + 0 + ], + "to": [ + 12, + 12, + 16 + ] + } + ], + "textures": { + "end": "gtceu:block/pipe/pipe_duct_in", + "side": "gtceu:block/pipe/pipe_duct_side" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/item/normal_laser_pipe.json b/src/generated/resources/assets/gtceu/models/item/normal_laser_pipe.json new file mode 100644 index 00000000000..112eb3bf581 --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/item/normal_laser_pipe.json @@ -0,0 +1,80 @@ +{ + "parent": "gtceu:block/pipe/normal_laser_pipe/center", + "elements": [ + { + "faces": { + "down": { + "texture": "#side", + "tintindex": 0 + }, + "east": { + "texture": "#side", + "tintindex": 0 + }, + "north": { + "cullface": "north", + "texture": "#end", + "tintindex": 1 + }, + "south": { + "cullface": "south", + "texture": "#end", + "tintindex": 1 + }, + "up": { + "texture": "#side", + "tintindex": 0 + }, + "west": { + "texture": "#side", + "tintindex": 0 + } + }, + "from": [ + 5, + 5, + 0 + ], + "to": [ + 11, + 11, + 16 + ] + }, + { + "faces": { + "down": { + "texture": "#side_overlay", + "tintindex": 2 + }, + "east": { + "texture": "#side_overlay", + "tintindex": 2 + }, + "up": { + "texture": "#side_overlay", + "tintindex": 2 + }, + "west": { + "texture": "#side_overlay", + "tintindex": 2 + } + }, + "from": [ + 4.998, + 4.998, + -0.002 + ], + "to": [ + 11.002, + 11.002, + 16.002 + ] + } + ], + "textures": { + "end": "gtceu:block/pipe/pipe_laser_in", + "side": "gtceu:block/pipe/pipe_laser_side", + "side_overlay": "gtceu:block/pipe/pipe_laser_side_overlay" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/item/normal_optical_pipe.json b/src/generated/resources/assets/gtceu/models/item/normal_optical_pipe.json new file mode 100644 index 00000000000..d57881dac07 --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/item/normal_optical_pipe.json @@ -0,0 +1,80 @@ +{ + "parent": "gtceu:block/pipe/normal_optical_pipe/center", + "elements": [ + { + "faces": { + "down": { + "texture": "#side", + "tintindex": 0 + }, + "east": { + "texture": "#side", + "tintindex": 0 + }, + "north": { + "cullface": "north", + "texture": "#end", + "tintindex": 1 + }, + "south": { + "cullface": "south", + "texture": "#end", + "tintindex": 1 + }, + "up": { + "texture": "#side", + "tintindex": 0 + }, + "west": { + "texture": "#side", + "tintindex": 0 + } + }, + "from": [ + 5, + 5, + 0 + ], + "to": [ + 11, + 11, + 16 + ] + }, + { + "faces": { + "down": { + "texture": "#side_overlay", + "tintindex": 2 + }, + "east": { + "texture": "#side_overlay", + "tintindex": 2 + }, + "up": { + "texture": "#side_overlay", + "tintindex": 2 + }, + "west": { + "texture": "#side_overlay", + "tintindex": 2 + } + }, + "from": [ + 4.998, + 4.998, + -0.002 + ], + "to": [ + 11.002, + 11.002, + 16.002 + ] + } + ], + "textures": { + "end": "gtceu:block/pipe/pipe_optical_in", + "side": "gtceu:block/pipe/pipe_optical_side", + "side_overlay": "gtceu:block/pipe/pipe_optical_side_overlay" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/item/small_duct_pipe.json b/src/generated/resources/assets/gtceu/models/item/small_duct_pipe.json new file mode 100644 index 00000000000..52c2a00a7ee --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/item/small_duct_pipe.json @@ -0,0 +1,49 @@ +{ + "parent": "gtceu:block/pipe/small_duct_pipe/center", + "elements": [ + { + "faces": { + "down": { + "texture": "#side", + "tintindex": 0 + }, + "east": { + "texture": "#side", + "tintindex": 0 + }, + "north": { + "cullface": "north", + "texture": "#end", + "tintindex": 1 + }, + "south": { + "cullface": "south", + "texture": "#end", + "tintindex": 1 + }, + "up": { + "texture": "#side", + "tintindex": 0 + }, + "west": { + "texture": "#side", + "tintindex": 0 + } + }, + "from": [ + 5, + 5, + 0 + ], + "to": [ + 11, + 11, + 16 + ] + } + ], + "textures": { + "end": "gtceu:block/pipe/pipe_duct_in", + "side": "gtceu:block/pipe/pipe_duct_side" + } +} \ No newline at end of file diff --git a/src/main/java/com/gregtechceu/gtceu/GTCEu.java b/src/main/java/com/gregtechceu/gtceu/GTCEu.java index fee2fc2b308..e7b1de43d39 100644 --- a/src/main/java/com/gregtechceu/gtceu/GTCEu.java +++ b/src/main/java/com/gregtechceu/gtceu/GTCEu.java @@ -32,6 +32,8 @@ public class GTCEu { public static final String NAME = "GregTechCEu"; public static final Logger LOGGER = LogManager.getLogger(NAME); + public static final Path GTCEU_FOLDER = getGameDir().resolve("gtceu"); + public GTCEu() { GTCEu.init(); GTCEuAPI.instance = this; diff --git a/src/main/java/com/gregtechceu/gtceu/api/block/MaterialPipeBlock.java b/src/main/java/com/gregtechceu/gtceu/api/block/MaterialPipeBlock.java index 07d640a090f..e47f1e862ec 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/block/MaterialPipeBlock.java +++ b/src/main/java/com/gregtechceu/gtceu/api/block/MaterialPipeBlock.java @@ -3,8 +3,6 @@ import com.gregtechceu.gtceu.api.blockentity.IPaintable; import com.gregtechceu.gtceu.api.data.chemical.material.Material; import com.gregtechceu.gtceu.api.pipenet.*; -import com.gregtechceu.gtceu.client.model.PipeModel; -import com.gregtechceu.gtceu.client.renderer.block.PipeBlockRenderer; import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.client.color.block.BlockColor; @@ -28,14 +26,10 @@ public abstract class MaterialPipeBlock< extends PipeBlock { public final Material material; - public final PipeBlockRenderer renderer; - public final PipeModel model; public MaterialPipeBlock(Properties properties, PipeType pipeType, Material material) { super(properties, pipeType); this.material = material; - this.model = createPipeModel(); - this.renderer = new PipeBlockRenderer(this.model); } @OnlyIn(Dist.CLIENT) @@ -57,11 +51,6 @@ public int tinted(BlockState blockState, @Nullable BlockAndTintGetter level, @Nu return index == 0 || index == 1 ? material.getMaterialRGB() : -1; } - @Override - protected PipeModel getPipeModel() { - return model; - } - @Override public final NodeDataType createRawData(BlockState pState, @Nullable ItemStack pStack) { return createMaterialData(); @@ -80,11 +69,6 @@ public NodeDataType createProperties(IPipeNode pipeTile) protected abstract NodeDataType createProperties(PipeType pipeType, Material material); - @Override - public @Nullable PipeBlockRenderer getRenderer(BlockState state) { - return renderer; - } - @Override public final NodeDataType getFallbackType() { return createMaterialData(); @@ -92,8 +76,6 @@ public final NodeDataType getFallbackType() { protected abstract NodeDataType createMaterialData(); - protected abstract PipeModel createPipeModel(); - @Override public String getDescriptionId() { return pipeType.getTagPrefix().getUnlocalizedName(material); diff --git a/src/main/java/com/gregtechceu/gtceu/api/block/PipeBlock.java b/src/main/java/com/gregtechceu/gtceu/api/block/PipeBlock.java index c4079b9f324..a77fbb5cc62 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/block/PipeBlock.java +++ b/src/main/java/com/gregtechceu/gtceu/api/block/PipeBlock.java @@ -13,17 +13,16 @@ import com.gregtechceu.gtceu.api.pipenet.IPipeType; import com.gregtechceu.gtceu.api.pipenet.LevelPipeNet; import com.gregtechceu.gtceu.api.pipenet.PipeNet; -import com.gregtechceu.gtceu.client.model.PipeModel; -import com.gregtechceu.gtceu.client.renderer.block.PipeBlockRenderer; +import com.gregtechceu.gtceu.api.registry.registrate.provider.GTBlockstateProvider; +import com.gregtechceu.gtceu.client.model.pipe.PipeModel; import com.gregtechceu.gtceu.common.data.GTItems; import com.gregtechceu.gtceu.common.data.GTMaterialBlocks; import com.gregtechceu.gtceu.common.item.CoverPlaceBehavior; import com.gregtechceu.gtceu.config.ConfigHolder; import com.gregtechceu.gtceu.data.recipe.VanillaRecipeHelper; +import com.gregtechceu.gtceu.utils.GTMath; import com.gregtechceu.gtceu.utils.GTUtil; -import com.lowdragmc.lowdraglib.client.renderer.IBlockRendererProvider; - import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -62,10 +61,9 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.joml.Vector3f; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; +import java.util.*; import javax.annotation.ParametersAreNonnullByDefault; @@ -74,19 +72,32 @@ @MethodsReturnNonnullByDefault public abstract class PipeBlock & IPipeType, NodeDataType, WorldPipeNetType extends LevelPipeNet>> extends Block - implements EntityBlock, IBlockRendererProvider, SimpleWaterloggedBlock { + implements EntityBlock, SimpleWaterloggedBlock { public final PipeType pipeType; + protected final Map shapes = new IdentityHashMap<>(); + public PipeBlock(Properties properties, PipeType pipeType) { super(properties); this.pipeType = pipeType; registerDefaultState(defaultBlockState().setValue(BlockStateProperties.WATERLOGGED, false)); + + float min = (16 - pipeType.getThickness() * 16) / 2f; + float max = min + pipeType.getThickness() * 16; + shapes.put(null, Block.box(min, min, min, max, max, max)); + for (Direction dir : GTUtil.DIRECTIONS) { + var coords = GTMath.getCoordinates(dir, min, max); + Vector3f minCoord = coords.getLeft(); + Vector3f maxCoord = coords.getRight(); + shapes.put(dir, Block.box(minCoord.x, minCoord.y, minCoord.z, maxCoord.x, maxCoord.y, maxCoord.z)); + } } @Override protected void createBlockStateDefinition(StateDefinition.Builder builder) { - super.createBlockStateDefinition(builder.add(BlockStateProperties.WATERLOGGED)); + super.createBlockStateDefinition(builder); + builder.add(BlockStateProperties.WATERLOGGED); } @Override @@ -129,11 +140,7 @@ public NodeDataType createProperties(BlockState state, @Nullable ItemStack stack */ public abstract NodeDataType getFallbackType(); - @Nullable - @Override - public abstract PipeBlockRenderer getRenderer(BlockState state); - - protected abstract PipeModel getPipeModel(); + public abstract PipeModel createPipeModel(GTBlockstateProvider provider); public void updateActiveNodeStatus(@NotNull Level worldIn, BlockPos pos, IPipeNode pipeTile) { @@ -400,7 +407,7 @@ public VoxelShape getShape(BlockState pState, BlockGetter pLevel, BlockPos pPos, return Shapes.block(); } connections = pipeNode.getVisualConnections(); - VoxelShape shape = getPipeModel().getShapes(connections); + VoxelShape shape = getShapes(connections); shape = Shapes.or(shape, pipeNode.getCoverContainer().addCoverCollisionBoundingBox()); if (context instanceof EntityCollisionContext entityCtx && entityCtx.getEntity() instanceof Player player) { @@ -424,7 +431,7 @@ public VoxelShape getShape(BlockState pState, BlockGetter pLevel, BlockPos pPos, } return shape; } - return getPipeModel().getShapes(connections); + return getShapes(connections); } @Nullable @@ -475,4 +482,11 @@ public List getDrops(BlockState state, LootParams.Builder builder) { public GTToolType getPipeTuneTool() { return GTToolType.WRENCH; } + + public VoxelShape getShapes(int connections) { + return this.shapes.entrySet().stream() + .filter(entry -> entry.getKey() == null || PipeBlockEntity.isConnected(connections, entry.getKey())) + .map(Map.Entry::getValue) + .reduce(Shapes.empty(), Shapes::or); + } } diff --git a/src/main/java/com/gregtechceu/gtceu/api/blockentity/MetaMachineBlockEntity.java b/src/main/java/com/gregtechceu/gtceu/api/blockentity/MetaMachineBlockEntity.java index db0589bd9c4..380debf6782 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/blockentity/MetaMachineBlockEntity.java +++ b/src/main/java/com/gregtechceu/gtceu/api/blockentity/MetaMachineBlockEntity.java @@ -314,9 +314,9 @@ public AABB getRenderBoundingBox() { BlockRenderDispatcher blockRenderDispatcher = Minecraft.getInstance().getBlockRenderer(); BakedModel model = blockRenderDispatcher.getBlockModel(this.getBlockState()); - if (model instanceof IBlockEntityRendererBakedModel modelWithBER) { - if (modelWithBER.getBlockEntityType() == this.getType()) { - return ((IBlockEntityRendererBakedModel) modelWithBER) + if (model instanceof IBlockEntityRendererBakedModel berModel) { + if (berModel.getBlockEntityType() != null && berModel.getBlockEntityType() == this.getType()) { + return ((IBlockEntityRendererBakedModel) berModel) .getRenderBoundingBox(this); } } diff --git a/src/main/java/com/gregtechceu/gtceu/api/item/DuctPipeBlockItem.java b/src/main/java/com/gregtechceu/gtceu/api/item/DuctPipeBlockItem.java deleted file mode 100644 index 5563d6a4097..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/item/DuctPipeBlockItem.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.gregtechceu.gtceu.api.item; - -import com.gregtechceu.gtceu.common.block.DuctPipeBlock; - -import com.lowdragmc.lowdraglib.client.renderer.IItemRendererProvider; -import com.lowdragmc.lowdraglib.client.renderer.IRenderer; - -import net.minecraft.world.item.ItemStack; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public class DuctPipeBlockItem extends PipeBlockItem implements IItemRendererProvider { - - public DuctPipeBlockItem(DuctPipeBlock block, Properties properties) { - super(block, properties); - } - - @Override - @NotNull - public DuctPipeBlock getBlock() { - return (DuctPipeBlock) super.getBlock(); - } - - @Nullable - @Override - public IRenderer getRenderer(ItemStack stack) { - return getBlock().getRenderer(getBlock().defaultBlockState()); - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/item/LampBlockItem.java b/src/main/java/com/gregtechceu/gtceu/api/item/LampBlockItem.java index f56af127f4a..d07587b9b57 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/item/LampBlockItem.java +++ b/src/main/java/com/gregtechceu/gtceu/api/item/LampBlockItem.java @@ -1,20 +1,29 @@ package com.gregtechceu.gtceu.api.item; +import com.gregtechceu.gtceu.GTCEu; +import com.gregtechceu.gtceu.client.renderer.block.LampItemRenderer; +import com.gregtechceu.gtceu.client.util.ModelUtils; import com.gregtechceu.gtceu.common.block.LampBlock; -import com.lowdragmc.lowdraglib.client.renderer.IItemRendererProvider; -import com.lowdragmc.lowdraglib.client.renderer.IRenderer; - +import net.minecraft.client.renderer.BlockEntityWithoutLevelRenderer; +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.client.resources.model.ModelResourceLocation; import net.minecraft.core.NonNullList; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.CreativeModeTab; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.client.extensions.common.IClientItemExtensions; +import net.minecraftforge.client.model.BakedModelWrapper; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.function.Consumer; + import javax.annotation.ParametersAreNonnullByDefault; import static com.gregtechceu.gtceu.common.block.LampBlock.isBloomEnabled; @@ -22,10 +31,14 @@ import static com.gregtechceu.gtceu.common.block.LampBlock.isLightEnabled; @ParametersAreNonnullByDefault -public class LampBlockItem extends BlockItem implements IItemRendererProvider { +public class LampBlockItem extends BlockItem { public LampBlockItem(LampBlock block, Properties properties) { super(block, properties); + + if (GTCEu.isClientSide()) { + ClientCallWrapper.registerEventListener(this); + } } @NotNull @@ -37,16 +50,19 @@ public LampBlock getBlock() { @Nullable @Override protected BlockState getPlacementState(BlockPlaceContext context) { - BlockState returnValue = super.getPlacementState(context); - ItemStack handItem = context.getItemInHand(); - if (returnValue != null && handItem.hasTag()) { - var tag = handItem.getTag(); - returnValue = returnValue - .setValue(LampBlock.INVERTED, isInverted(tag)) - .setValue(LampBlock.BLOOM, isBloomEnabled(tag)) - .setValue(LampBlock.LIGHT, isLightEnabled(tag)); + BlockState state = super.getPlacementState(context); + return getStateFromStack(context.getItemInHand(), state); + } + + public BlockState getStateFromStack(ItemStack stack, @Nullable BlockState baseState) { + if (!stack.hasTag() || !stack.is(this)) { + return baseState; } - return returnValue; + var tag = stack.getTag(); + return (baseState != null ? baseState : getBlock().defaultBlockState()) + .setValue(LampBlock.INVERTED, isInverted(tag)) + .setValue(LampBlock.BLOOM, isBloomEnabled(tag)) + .setValue(LampBlock.LIGHT, isLightEnabled(tag)); } public void fillItemCategory(CreativeModeTab category, NonNullList items) { @@ -55,17 +71,35 @@ public void fillItemCategory(CreativeModeTab category, NonNullList it } } - @Nullable @Override - public IRenderer getRenderer(ItemStack stack) { - BlockState state = getBlock().defaultBlockState(); - if (stack.hasTag()) { - var tag = stack.getTag(); - state = state - .setValue(LampBlock.INVERTED, isInverted(tag)) - .setValue(LampBlock.BLOOM, isBloomEnabled(tag)) - .setValue(LampBlock.LIGHT, isLightEnabled(tag)); + public void initializeClient(Consumer consumer) { + consumer.accept(new IClientItemExtensions() { + + @Override + public BlockEntityWithoutLevelRenderer getCustomRenderer() { + return LampItemRenderer.INSTANCE; + } + }); + } + + private static class ClientCallWrapper { + + private static void registerEventListener(LampBlockItem item) { + ModelUtils.registerBakeEventListener(false, event -> { + ResourceLocation model = BuiltInRegistries.ITEM.getKey(item).withPrefix("item/"); + BakedModel original = event.getModels().get(model); + if (original == null) { + model = new ModelResourceLocation(model, "inventory"); + original = event.getModels().get(model); + } + event.getModels().put(model, new BakedModelWrapper<>(original) { + + @Override + public boolean isCustomRenderer() { + return true; + } + }); + }); } - return getBlock().getRenderer(state); } } diff --git a/src/main/java/com/gregtechceu/gtceu/api/item/LaserPipeBlockItem.java b/src/main/java/com/gregtechceu/gtceu/api/item/LaserPipeBlockItem.java index dfaef338c15..3f34616dc3c 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/item/LaserPipeBlockItem.java +++ b/src/main/java/com/gregtechceu/gtceu/api/item/LaserPipeBlockItem.java @@ -3,20 +3,14 @@ import com.gregtechceu.gtceu.api.block.PipeBlock; import com.gregtechceu.gtceu.common.block.LaserPipeBlock; -import com.lowdragmc.lowdraglib.client.renderer.IItemRendererProvider; -import com.lowdragmc.lowdraglib.client.renderer.IRenderer; - import net.minecraft.client.color.item.ItemColor; -import net.minecraft.world.item.ItemStack; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; -import org.jetbrains.annotations.Nullable; - import javax.annotation.ParametersAreNonnullByDefault; @ParametersAreNonnullByDefault -public class LaserPipeBlockItem extends PipeBlockItem implements IItemRendererProvider { +public class LaserPipeBlockItem extends PipeBlockItem { public LaserPipeBlockItem(PipeBlock block, Properties properties) { super(block, properties); @@ -37,11 +31,4 @@ public static ItemColor tintColor() { return -1; }; } - - @Nullable - @Override - @OnlyIn(Dist.CLIENT) - public IRenderer getRenderer(ItemStack stack) { - return getBlock().getRenderer(getBlock().defaultBlockState()); - } } diff --git a/src/main/java/com/gregtechceu/gtceu/api/item/MaterialPipeBlockItem.java b/src/main/java/com/gregtechceu/gtceu/api/item/MaterialPipeBlockItem.java index 97851db6697..22f63a6cf8f 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/item/MaterialPipeBlockItem.java +++ b/src/main/java/com/gregtechceu/gtceu/api/item/MaterialPipeBlockItem.java @@ -2,9 +2,6 @@ import com.gregtechceu.gtceu.api.block.MaterialPipeBlock; -import com.lowdragmc.lowdraglib.client.renderer.IItemRendererProvider; -import com.lowdragmc.lowdraglib.client.renderer.IRenderer; - import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.client.color.item.ItemColor; import net.minecraft.network.chat.Component; @@ -13,13 +10,12 @@ import net.minecraftforge.api.distmarker.OnlyIn; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import javax.annotation.ParametersAreNonnullByDefault; @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault -public class MaterialPipeBlockItem extends PipeBlockItem implements IItemRendererProvider { +public class MaterialPipeBlockItem extends PipeBlockItem { public MaterialPipeBlockItem(MaterialPipeBlock block, Properties properties) { super(block, properties); @@ -42,13 +38,6 @@ public static ItemColor tintColor() { }; } - @Nullable - @Override - @OnlyIn(Dist.CLIENT) - public IRenderer getRenderer(ItemStack stack) { - return getBlock().getRenderer(getBlock().defaultBlockState()); - } - @Override public Component getDescription() { return this.getBlock().getName(); diff --git a/src/main/java/com/gregtechceu/gtceu/api/item/OpticalPipeBlockItem.java b/src/main/java/com/gregtechceu/gtceu/api/item/OpticalPipeBlockItem.java deleted file mode 100644 index ed59e05ded9..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/item/OpticalPipeBlockItem.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.gregtechceu.gtceu.api.item; - -import com.gregtechceu.gtceu.common.block.OpticalPipeBlock; - -import com.lowdragmc.lowdraglib.client.renderer.IItemRendererProvider; -import com.lowdragmc.lowdraglib.client.renderer.IRenderer; - -import net.minecraft.world.item.ItemStack; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -import org.jetbrains.annotations.Nullable; - -import javax.annotation.ParametersAreNonnullByDefault; - -@ParametersAreNonnullByDefault -public class OpticalPipeBlockItem extends PipeBlockItem implements IItemRendererProvider { - - public OpticalPipeBlockItem(OpticalPipeBlock block, Properties properties) { - super(block, properties); - } - - @Nullable - @Override - @OnlyIn(Dist.CLIENT) - public IRenderer getRenderer(ItemStack stack) { - return getBlock().getRenderer(getBlock().defaultBlockState()); - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/IMachineBlockEntity.java b/src/main/java/com/gregtechceu/gtceu/api/machine/IMachineBlockEntity.java index df3ff0930d0..187fe5df909 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/IMachineBlockEntity.java +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/IMachineBlockEntity.java @@ -13,12 +13,10 @@ import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.level.BlockAndTintGetter; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraftforge.client.model.data.ModelData; -import net.minecraftforge.client.model.data.ModelProperty; import net.minecraftforge.common.extensions.IForgeBlockEntity; import org.jetbrains.annotations.NotNull; @@ -31,9 +29,6 @@ public interface IMachineBlockEntity extends IToolGridHighlight, IAsyncAutoSyncBlockEntity, IRPCBlockEntity, IAutoPersistBlockEntity, IPaintable, IForgeBlockEntity { - ModelProperty MODEL_DATA_LEVEL = new ModelProperty<>(); - ModelProperty MODEL_DATA_POS = new ModelProperty<>(); - default BlockEntity self() { return (BlockEntity) this; } diff --git a/src/main/java/com/gregtechceu/gtceu/api/registry/registrate/GTBlockBuilder.java b/src/main/java/com/gregtechceu/gtceu/api/registry/registrate/GTBlockBuilder.java index c1ba8744fb0..17dfee8d336 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/registry/registrate/GTBlockBuilder.java +++ b/src/main/java/com/gregtechceu/gtceu/api/registry/registrate/GTBlockBuilder.java @@ -38,6 +38,10 @@ public GTBlockBuilder exBlockstate(NonNullBiConsumer cons.accept(ctx, (GTBlockstateProvider) prov)); } + public GTBlockBuilder gtBlockstate(NonNullBiConsumer, GTBlockstateProvider> cons) { + return setData(ProviderType.BLOCKSTATE, (ctx, prov) -> cons.accept(ctx, (GTBlockstateProvider) prov)); + } + // region default overrides @Override @@ -122,6 +126,11 @@ public GTBlockBuilder setDataGeneric(Provid return this; } + @Override + public GTBlockBuilder setData(ProviderType type, NonNullBiConsumer, D> cons) { + return (GTBlockBuilder) super.setData(type, cons); + } + // spotless:on // endregion } diff --git a/src/main/java/com/gregtechceu/gtceu/api/registry/registrate/MachineBuilder.java b/src/main/java/com/gregtechceu/gtceu/api/registry/registrate/MachineBuilder.java index b676b92f0cb..ee9020c53fc 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/registry/registrate/MachineBuilder.java +++ b/src/main/java/com/gregtechceu/gtceu/api/registry/registrate/MachineBuilder.java @@ -27,6 +27,7 @@ import com.gregtechceu.gtceu.common.data.models.GTMachineModels; import com.gregtechceu.gtceu.config.ConfigHolder; import com.gregtechceu.gtceu.data.model.builder.MachineModelBuilder; +import com.gregtechceu.gtceu.utils.data.RuntimeBlockstateProvider; import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.client.renderer.RenderType; @@ -76,7 +77,6 @@ import javax.annotation.ParametersAreNonnullByDefault; import static com.gregtechceu.gtceu.common.data.models.GTMachineModels.*; -import static com.gregtechceu.gtceu.integration.kjs.GregTechKubeJSPlugin.RUNTIME_BLOCKSTATE_PROVIDER; @SuppressWarnings("unused") @ParametersAreNonnullByDefault @@ -818,9 +818,10 @@ public static void generateAssetJsons(@Nullable As // Fake a data provider for the GT model builders var context = new DataGenContext<>(definition::getBlock, definition.getName(), id); if (builder.blockModel() != null) { - builder.blockModel().accept(context, RUNTIME_BLOCKSTATE_PROVIDER); + builder.blockModel().accept(context, RuntimeBlockstateProvider.INSTANCE); } else { - GTMachineModels.createMachineModel(builder.model()).accept(context, RUNTIME_BLOCKSTATE_PROVIDER); + GTMachineModels.createMachineModel(builder.model()) + .accept(context, RuntimeBlockstateProvider.INSTANCE); } } else { generator.itemModel(id, gen -> gen.parent(id.withPrefix("block/machine/").toString())); diff --git a/src/main/java/com/gregtechceu/gtceu/api/registry/registrate/provider/GTBlockstateProvider.java b/src/main/java/com/gregtechceu/gtceu/api/registry/registrate/provider/GTBlockstateProvider.java index 40bf8542286..6b7789b5159 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/registry/registrate/provider/GTBlockstateProvider.java +++ b/src/main/java/com/gregtechceu/gtceu/api/registry/registrate/provider/GTBlockstateProvider.java @@ -78,14 +78,17 @@ public MultiVariantGenerator multiVariantGenerator(Block block) { public MultiVariantGenerator multiVariantGenerator(Block block, Variant baseVariant) { var multiVariant = MultiVariantGenerator.multiVariant(block, baseVariant); - registeredBlocks.put(block, new BlockStateGeneratorWrapper(multiVariant)); - return multiVariant; + return addVanillaGenerator(block, multiVariant); } public MultiPartGenerator multiPartGenerator(Block block) { var multiPart = MultiPartGenerator.multiPart(block); - registeredBlocks.put(block, new BlockStateGeneratorWrapper(multiPart)); - return multiPart; + return addVanillaGenerator(block, multiPart); + } + + public T addVanillaGenerator(Block block, T generator) { + registeredBlocks.put(block, new BlockStateGeneratorWrapper(generator)); + return generator; } public static @Nullable PropertyDispatch createFacingDispatch(MachineDefinition definition) { diff --git a/src/main/java/com/gregtechceu/gtceu/client/ClientProxy.java b/src/main/java/com/gregtechceu/gtceu/client/ClientProxy.java index 0f3b72535e4..c4bc0f934da 100644 --- a/src/main/java/com/gregtechceu/gtceu/client/ClientProxy.java +++ b/src/main/java/com/gregtechceu/gtceu/client/ClientProxy.java @@ -13,10 +13,18 @@ import com.gregtechceu.gtceu.api.item.QuantumTankMachineItem; import com.gregtechceu.gtceu.client.model.item.FacadeUnbakedModel; import com.gregtechceu.gtceu.client.model.machine.MachineModelLoader; +import com.gregtechceu.gtceu.client.model.pipe.PipeModel; +import com.gregtechceu.gtceu.client.model.pipe.PipeModelLoader; import com.gregtechceu.gtceu.client.particle.HazardParticle; import com.gregtechceu.gtceu.client.particle.MufflerParticle; +import com.gregtechceu.gtceu.client.renderer.block.MaterialBlockRenderer; +import com.gregtechceu.gtceu.client.renderer.block.OreBlockRenderer; +import com.gregtechceu.gtceu.client.renderer.block.SurfaceRockRenderer; import com.gregtechceu.gtceu.client.renderer.entity.GTBoatRenderer; import com.gregtechceu.gtceu.client.renderer.entity.GTExplosiveRenderer; +import com.gregtechceu.gtceu.client.renderer.item.ArmorItemRenderer; +import com.gregtechceu.gtceu.client.renderer.item.TagPrefixItemRenderer; +import com.gregtechceu.gtceu.client.renderer.item.ToolItemRenderer; import com.gregtechceu.gtceu.client.renderer.item.decorator.GTComponentItemDecorator; import com.gregtechceu.gtceu.client.renderer.item.decorator.GTLampItemOverlayRenderer; import com.gregtechceu.gtceu.client.renderer.item.decorator.GTTankItemFluidPreview; @@ -27,17 +35,23 @@ import com.gregtechceu.gtceu.common.CommonProxy; import com.gregtechceu.gtceu.common.data.GTBlockEntities; import com.gregtechceu.gtceu.common.data.GTEntityTypes; +import com.gregtechceu.gtceu.common.data.GTMaterialBlocks; import com.gregtechceu.gtceu.common.data.GTParticleTypes; +import com.gregtechceu.gtceu.common.data.models.GTModels; import com.gregtechceu.gtceu.common.entity.GTBoat; import com.gregtechceu.gtceu.common.machine.owner.MachineOwner; import com.gregtechceu.gtceu.config.ConfigHolder; +import com.gregtechceu.gtceu.data.model.builder.PipeModelBuilder; +import com.gregtechceu.gtceu.data.pack.event.RegisterDynamicResourcesEvent; import com.gregtechceu.gtceu.forge.ForgeCommonEventListener; +import com.gregtechceu.gtceu.integration.kjs.GregTechKubeJSPlugin; import com.gregtechceu.gtceu.integration.map.ClientCacheManager; import com.gregtechceu.gtceu.integration.map.cache.client.GTClientCache; import com.gregtechceu.gtceu.integration.map.ftbchunks.FTBChunksPlugin; import com.gregtechceu.gtceu.integration.map.layer.Layers; import com.gregtechceu.gtceu.integration.map.layer.builtin.FluidRenderLayer; import com.gregtechceu.gtceu.integration.map.layer.builtin.OreRenderLayer; +import com.gregtechceu.gtceu.utils.data.RuntimeBlockstateProvider; import com.gregtechceu.gtceu.utils.input.SyncedKeyMapping; import net.minecraft.client.model.BoatModel; @@ -49,6 +63,7 @@ import net.minecraft.world.item.Item; import net.minecraftforge.client.ForgeHooksClient; import net.minecraftforge.client.event.*; +import net.minecraftforge.eventbus.api.EventPriority; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; import net.minecraftforge.registries.ForgeRegistries; @@ -158,6 +173,50 @@ public static void initializeDynamicRenders() { @SubscribeEvent public void onRegisterModelLoaders(ModelEvent.RegisterGeometryLoaders event) { event.register(MachineModelLoader.ID.getPath(), MachineModelLoader.INSTANCE); + event.register(PipeModelLoader.ID.getPath(), PipeModelLoader.INSTANCE); event.register("facade", FacadeUnbakedModel.Loader.INSTANCE); } + + @SubscribeEvent(priority = EventPriority.HIGHEST) + public void preRegisterDynamicAssets(RegisterDynamicResourcesEvent event) { + PipeModel.DYNAMIC_MODELS.clear(); + } + + @SubscribeEvent + public void registerDynamicAssets(RegisterDynamicResourcesEvent event) { + // regenerate all pipe models in case their textures changed + // cables may do this, others too if something's removed + for (var block : GTMaterialBlocks.CABLE_BLOCKS.values()) { + if (block == null) continue; + block.get().createPipeModel(RuntimeBlockstateProvider.INSTANCE).dynamicModel(); + } + for (var block : GTMaterialBlocks.FLUID_PIPE_BLOCKS.values()) { + if (block == null) continue; + block.get().createPipeModel(RuntimeBlockstateProvider.INSTANCE).dynamicModel(); + } + for (var block : GTMaterialBlocks.ITEM_PIPE_BLOCKS.values()) { + if (block == null) continue; + block.get().createPipeModel(RuntimeBlockstateProvider.INSTANCE).dynamicModel(); + } + + MaterialBlockRenderer.reinitModels(); + TagPrefixItemRenderer.reinitModels(); + OreBlockRenderer.reinitModels(); + ToolItemRenderer.reinitModels(); + ArmorItemRenderer.reinitModels(); + SurfaceRockRenderer.reinitModels(); + GTModels.registerMaterialFluidModels(); + } + + @SubscribeEvent(priority = EventPriority.LOWEST) + public void postRegisterDynamicAssets(RegisterDynamicResourcesEvent event) { + // do this last so addons can easily add new variants to the registered model set + PipeModel.initDynamicModels(); + + if (GTCEu.Mods.isKubeJSLoaded()) { + GregTechKubeJSPlugin.generateMachineBlockModels(); + } + RuntimeBlockstateProvider.INSTANCE.run(); + PipeModelBuilder.clearRestrictorModelCache(); + } } diff --git a/src/main/java/com/gregtechceu/gtceu/client/model/BaseBakedModel.java b/src/main/java/com/gregtechceu/gtceu/client/model/BaseBakedModel.java index f91a52c0b2a..484ee5656e2 100644 --- a/src/main/java/com/gregtechceu/gtceu/client/model/BaseBakedModel.java +++ b/src/main/java/com/gregtechceu/gtceu/client/model/BaseBakedModel.java @@ -9,8 +9,6 @@ import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.client.model.IDynamicBakedModel; -import org.jetbrains.annotations.NotNull; - public abstract class BaseBakedModel implements IDynamicBakedModel { public BaseBakedModel() {} @@ -37,13 +35,13 @@ public boolean isCustomRenderer() { @Override @OnlyIn(Dist.CLIENT) - public @NotNull ItemOverrides getOverrides() { + public ItemOverrides getOverrides() { return ItemOverrides.EMPTY; } @Override @OnlyIn(Dist.CLIENT) - public @NotNull TextureAtlasSprite getParticleIcon() { + public TextureAtlasSprite getParticleIcon() { return Minecraft.getInstance().getTextureAtlas(InventoryMenu.BLOCK_ATLAS) .apply(MissingTextureAtlasSprite.getLocation()); } diff --git a/src/main/java/com/gregtechceu/gtceu/client/model/GTModelProperties.java b/src/main/java/com/gregtechceu/gtceu/client/model/GTModelProperties.java new file mode 100644 index 00000000000..2f58894072b --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/client/model/GTModelProperties.java @@ -0,0 +1,16 @@ +package com.gregtechceu.gtceu.client.model; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraftforge.client.model.data.ModelProperty; + +public class GTModelProperties { + + public static final ModelProperty LEVEL = new ModelProperty<>(); + public static final ModelProperty POS = new ModelProperty<>(); + + public static final ModelProperty PIPE_CONNECTION_MASK = new ModelProperty<>(); + public static final ModelProperty PIPE_BLOCKED_MASK = new ModelProperty<>(); + + public static final ModelProperty PIPE_ACTIVE = new ModelProperty<>(); +} diff --git a/src/main/java/com/gregtechceu/gtceu/client/model/IBlockEntityRendererBakedModel.java b/src/main/java/com/gregtechceu/gtceu/client/model/IBlockEntityRendererBakedModel.java index 6a59d976574..001442720cc 100644 --- a/src/main/java/com/gregtechceu/gtceu/client/model/IBlockEntityRendererBakedModel.java +++ b/src/main/java/com/gregtechceu/gtceu/client/model/IBlockEntityRendererBakedModel.java @@ -12,21 +12,21 @@ import net.minecraftforge.client.model.IDynamicBakedModel; import com.mojang.blaze3d.vertex.PoseStack; -import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public interface IBlockEntityRendererBakedModel extends IDynamicBakedModel, BlockEntityRenderer { + @Nullable BlockEntityType getBlockEntityType(); - void render(@NotNull T blockEntity, float partialTick, - @NotNull PoseStack poseStack, @NotNull MultiBufferSource buffer, + void render(T blockEntity, float partialTick, PoseStack poseStack, MultiBufferSource buffer, int packedLight, int packedOverlay); default void renderByItem(ItemStack stack, ItemDisplayContext displayContext, PoseStack poseStack, MultiBufferSource buffer, int packedLight, int packedOverlay) {} - default boolean shouldRender(T blockEntity, @NotNull Vec3 cameraPos) { + default boolean shouldRender(T blockEntity, Vec3 cameraPos) { return Vec3.atCenterOf(blockEntity.getBlockPos()).closerThan(cameraPos, this.getViewDistance()); } diff --git a/src/main/java/com/gregtechceu/gtceu/client/model/PipeModel.java b/src/main/java/com/gregtechceu/gtceu/client/model/PipeModel.java deleted file mode 100644 index efdff6bb28b..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/client/model/PipeModel.java +++ /dev/null @@ -1,357 +0,0 @@ -package com.gregtechceu.gtceu.client.model; - -import com.gregtechceu.gtceu.GTCEu; -import com.gregtechceu.gtceu.api.blockentity.PipeBlockEntity; -import com.gregtechceu.gtceu.client.util.ModelUtils; -import com.gregtechceu.gtceu.common.data.models.GTModels; -import com.gregtechceu.gtceu.utils.GTUtil; -import com.gregtechceu.gtceu.utils.memoization.GTMemoizer; -import com.gregtechceu.gtceu.utils.memoization.MemoizedSupplier; - -import com.lowdragmc.lowdraglib.client.bakedpipeline.FaceQuad; -import com.lowdragmc.lowdraglib.client.renderer.IItemRendererProvider; - -import net.minecraft.Util; -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.block.model.BakedQuad; -import net.minecraft.client.renderer.texture.TextureAtlas; -import net.minecraft.client.renderer.texture.TextureAtlasSprite; -import net.minecraft.client.resources.model.BakedModel; -import net.minecraft.core.Direction; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.inventory.InventoryMenu; -import net.minecraft.world.item.ItemDisplayContext; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.phys.AABB; -import net.minecraft.world.phys.shapes.Shapes; -import net.minecraft.world.phys.shapes.VoxelShape; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -import com.mojang.blaze3d.vertex.PoseStack; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; -import lombok.Setter; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Supplier; - -public class PipeModel { - - public static final ResourceLocation PIPE_BLOCKED_OVERLAY = GTCEu.id("block/pipe/blocked/pipe_blocked"); - public static final ResourceLocation PIPE_BLOCKED_OVERLAY_UP = GTCEu.id("block/pipe/blocked/pipe_blocked_up"); - public static final ResourceLocation PIPE_BLOCKED_OVERLAY_DOWN = GTCEu.id("block/pipe/blocked/pipe_blocked_down"); - public static final ResourceLocation PIPE_BLOCKED_OVERLAY_LEFT = GTCEu.id("block/pipe/blocked/pipe_blocked_left"); - public static final ResourceLocation PIPE_BLOCKED_OVERLAY_RIGHT = GTCEu.id("block/pipe/blocked/pipe_blocked_right"); - public static final ResourceLocation PIPE_BLOCKED_OVERLAY_NU = GTCEu.id("block/pipe/blocked/pipe_blocked_nu"); - public static final ResourceLocation PIPE_BLOCKED_OVERLAY_ND = GTCEu.id("block/pipe/blocked/pipe_blocked_nd"); - public static final ResourceLocation PIPE_BLOCKED_OVERLAY_NL = GTCEu.id("block/pipe/blocked/pipe_blocked_nl"); - public static final ResourceLocation PIPE_BLOCKED_OVERLAY_NR = GTCEu.id("block/pipe/blocked/pipe_blocked_nr"); - public static final ResourceLocation PIPE_BLOCKED_OVERLAY_UD = GTCEu.id("block/pipe/blocked/pipe_blocked_ud"); - public static final ResourceLocation PIPE_BLOCKED_OVERLAY_UL = GTCEu.id("block/pipe/blocked/pipe_blocked_ul"); - public static final ResourceLocation PIPE_BLOCKED_OVERLAY_UR = GTCEu.id("block/pipe/blocked/pipe_blocked_ur"); - public static final ResourceLocation PIPE_BLOCKED_OVERLAY_DL = GTCEu.id("block/pipe/blocked/pipe_blocked_dl"); - public static final ResourceLocation PIPE_BLOCKED_OVERLAY_DR = GTCEu.id("block/pipe/blocked/pipe_blocked_dr"); - public static final ResourceLocation PIPE_BLOCKED_OVERLAY_LR = GTCEu.id("block/pipe/blocked/pipe_blocked_lr"); - private static final Int2ObjectMap RESTRICTOR_MAP = new Int2ObjectOpenHashMap<>(); - private static boolean isRestrictorInitialized; - - protected static void initializeRestrictor(Function atlas) { - addRestrictor(atlas.apply(PIPE_BLOCKED_OVERLAY_UP), Border.TOP); - addRestrictor(atlas.apply(PIPE_BLOCKED_OVERLAY_DOWN), Border.BOTTOM); - addRestrictor(atlas.apply(PIPE_BLOCKED_OVERLAY_UD), Border.TOP, Border.BOTTOM); - addRestrictor(atlas.apply(PIPE_BLOCKED_OVERLAY_LEFT), Border.LEFT); - addRestrictor(atlas.apply(PIPE_BLOCKED_OVERLAY_UL), Border.TOP, Border.LEFT); - addRestrictor(atlas.apply(PIPE_BLOCKED_OVERLAY_DL), Border.BOTTOM, Border.LEFT); - addRestrictor(atlas.apply(PIPE_BLOCKED_OVERLAY_NR), Border.TOP, Border.BOTTOM, Border.LEFT); - addRestrictor(atlas.apply(PIPE_BLOCKED_OVERLAY_RIGHT), Border.RIGHT); - addRestrictor(atlas.apply(PIPE_BLOCKED_OVERLAY_UR), Border.TOP, Border.RIGHT); - addRestrictor(atlas.apply(PIPE_BLOCKED_OVERLAY_DR), Border.BOTTOM, Border.RIGHT); - addRestrictor(atlas.apply(PIPE_BLOCKED_OVERLAY_NL), Border.TOP, Border.BOTTOM, Border.RIGHT); - addRestrictor(atlas.apply(PIPE_BLOCKED_OVERLAY_LR), Border.LEFT, Border.RIGHT); - addRestrictor(atlas.apply(PIPE_BLOCKED_OVERLAY_ND), Border.TOP, Border.LEFT, Border.RIGHT); - addRestrictor(atlas.apply(PIPE_BLOCKED_OVERLAY_NU), Border.BOTTOM, Border.LEFT, Border.RIGHT); - addRestrictor(atlas.apply(PIPE_BLOCKED_OVERLAY), Border.TOP, Border.BOTTOM, Border.LEFT, Border.RIGHT); - } - - private static final EnumMap> FACE_BORDER_MAP = Util.make(() -> { - EnumMap> map = new EnumMap<>(Direction.class); - - map.put(Direction.DOWN, borderMap(Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)); - map.put(Direction.UP, borderMap(Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)); - map.put(Direction.NORTH, borderMap(Direction.DOWN, Direction.UP, Direction.WEST, Direction.EAST)); - map.put(Direction.SOUTH, borderMap(Direction.DOWN, Direction.UP, Direction.WEST, Direction.EAST)); - map.put(Direction.WEST, borderMap(Direction.DOWN, Direction.UP, Direction.NORTH, Direction.SOUTH)); - map.put(Direction.EAST, borderMap(Direction.DOWN, Direction.UP, Direction.NORTH, Direction.SOUTH)); - - return map; - }); - - public final static int ITEM_CONNECTIONS = 0b001100; - public final float thickness; - public final AABB coreCube; - public final Map sideCubes; - - public MemoizedSupplier sideTexture, endTexture; - @Nullable - public MemoizedSupplier secondarySideTexture, secondaryEndTexture; - @Setter - public @Nullable ResourceLocation sideOverlayTexture, endOverlayTexture; - - @OnlyIn(Dist.CLIENT) - private @Nullable TextureAtlasSprite sideSprite, endSprite; - @OnlyIn(Dist.CLIENT) - private @Nullable TextureAtlasSprite secondarySideSprite, secondaryEndSprite; - @OnlyIn(Dist.CLIENT) - private @Nullable TextureAtlasSprite sideOverlaySprite, endOverlaySprite; - - public PipeModel(float thickness, Supplier sideTexture, Supplier endTexture, - @Nullable Supplier secondarySideTexture, - @Nullable Supplier secondaryEndTexture) { - this.sideTexture = GTMemoizer.memoize(sideTexture); - this.endTexture = GTMemoizer.memoize(endTexture); - this.secondarySideTexture = secondarySideTexture != null ? GTMemoizer.memoize(secondarySideTexture) : - null; - this.secondaryEndTexture = secondaryEndTexture != null ? GTMemoizer.memoize(secondaryEndTexture) : null; - this.thickness = thickness; - double min = (1d - thickness) / 2; - double max = min + thickness; - this.coreCube = new AABB(min, min, min, max, max, max); - this.sideCubes = new EnumMap<>(Direction.class); - for (Direction side : GTUtil.DIRECTIONS) { - var normal = side.getNormal(); - sideCubes.put(side, new AABB( - normal.getX() == 0 ? min : normal.getX() > 0 ? max : 0, - normal.getY() == 0 ? min : normal.getY() > 0 ? max : 0, - normal.getZ() == 0 ? min : normal.getZ() > 0 ? max : 0, - normal.getX() == 0 ? max : normal.getX() > 0 ? 1 : min, - normal.getY() == 0 ? max : normal.getY() > 0 ? 1 : min, - normal.getZ() == 0 ? max : normal.getZ() > 0 ? 1 : min)); - } - - if (!isRestrictorInitialized) { - ModelUtils.registerAtlasStitchedEventListener(false, InventoryMenu.BLOCK_ATLAS, event -> { - initializeRestrictor(event.getAtlas()::getSprite); - }); - - isRestrictorInitialized = true; - } - ModelUtils.registerAtlasStitchedEventListener(false, InventoryMenu.BLOCK_ATLAS, event -> { - TextureAtlas atlas = event.getAtlas(); - - sideSprite = atlas.getSprite(sideTexture.get()); - endSprite = atlas.getSprite(endTexture.get()); - if (secondarySideTexture != null) { - secondarySideSprite = atlas.getSprite(secondarySideTexture.get()); - } - if (secondaryEndTexture != null) { - secondaryEndSprite = atlas.getSprite(secondaryEndTexture.get()); - } - if (sideOverlayTexture != null) { - sideOverlaySprite = atlas.getSprite(sideOverlayTexture); - } - if (endOverlayTexture != null) { - endOverlaySprite = atlas.getSprite(endOverlayTexture); - } - }); - } - - public VoxelShape getShapes(int connections) { - var shapes = new ArrayList(7); - shapes.add(Shapes.create(coreCube)); - for (Direction side : GTUtil.DIRECTIONS) { - if (PipeBlockEntity.isConnected(connections, side)) { - shapes.add(Shapes.create(sideCubes.get(side))); - } - } - return shapes.stream().reduce(Shapes.empty(), Shapes::or); - } - - @OnlyIn(Dist.CLIENT) - public List bakeQuads(@Nullable Direction side, int connections, int blockedConnections) { - if (side != null) { - if (thickness == 1) { // full block - List quads = new LinkedList<>(); - quads.add(FaceQuad.builder(side, sideSprite).cube(coreCube).cubeUV().tintIndex(0).bake()); - if (secondarySideSprite != null) { - quads.add(FaceQuad.builder(side, secondarySideSprite).cube(coreCube).cubeUV().tintIndex(0).bake()); - } - return quads; - } - - if (PipeBlockEntity.isConnected(connections, side)) { // side connected - List quads = new LinkedList<>(); - quads.add(FaceQuad.builder(side, endSprite).cube(sideCubes.get(side).inflate(-0.001)).cubeUV() - .tintIndex(1).bake()); - if (secondaryEndSprite != null) { - quads.add(FaceQuad.builder(side, secondaryEndSprite).cube(sideCubes.get(side)).cubeUV().tintIndex(1) - .bake()); - } - if (endOverlaySprite != null) { - quads.add(FaceQuad.builder(side, endOverlaySprite).cube(sideCubes.get(side)).cubeUV().tintIndex(0) - .bake()); - } - if (sideOverlaySprite != null) { - for (Direction face : GTUtil.DIRECTIONS) { - if (face.getAxis() != side.getAxis()) { - quads.add(FaceQuad.builder(face, sideOverlaySprite).cube(sideCubes.get(side)).cubeUV() - .tintIndex(2).bake()); - } - } - } - int borderMask = computeBorderMask(blockedConnections, connections, side); - if (borderMask != 0) { - quads.add(FaceQuad.builder(side, RESTRICTOR_MAP.get(borderMask)).cube(sideCubes.get(side)).cubeUV() - .bake()); - } - return quads; - } - - return Collections.emptyList(); - } - - List quads = new LinkedList<>(); - if (thickness < 1) { // non full block - // render core cube - for (Direction face : GTUtil.DIRECTIONS) { - if (!PipeBlockEntity.isConnected(connections, face)) { - quads.add(FaceQuad.builder(face, sideSprite).cube(coreCube).cubeUV().tintIndex(0).bake()); - if (secondarySideSprite != null) { - quads.add(FaceQuad.builder(face, secondarySideSprite).cube(coreCube).cubeUV().tintIndex(0) - .bake()); - } - } - // render each connected side - for (Direction facing : GTUtil.DIRECTIONS) { - if (facing.getAxis() != face.getAxis()) { - if (PipeBlockEntity.isConnected(connections, facing)) { - quads.add(FaceQuad.builder(face, sideSprite).cube(sideCubes.get(facing)).cubeUV() - .tintIndex(0).bake()); - if (secondarySideSprite != null) { - quads.add(FaceQuad.builder(face, secondarySideSprite).cube(sideCubes.get(facing)) - .cubeUV().tintIndex(0).bake()); - } - if (sideOverlaySprite != null) { - quads.add(FaceQuad.builder(face, sideOverlaySprite) - .cube(sideCubes.get(facing).inflate(0.001)).cubeUV().tintIndex(2).bake()); - } - int borderMask = computeBorderMask(blockedConnections, connections, face); - if (borderMask != 0) { - quads.add(FaceQuad.builder(face, RESTRICTOR_MAP.get(borderMask)) - .cube(coreCube).cubeUV().bake()); - quads.add(FaceQuad.builder(face, RESTRICTOR_MAP.get(borderMask)) - .cube(sideCubes.get(facing)).cubeUV().bake()); - } - } - } - } - } - } - return quads; - } - - @SuppressWarnings("DataFlowIssue") - @OnlyIn(Dist.CLIENT) - public @NotNull TextureAtlasSprite getParticleTexture() { - return sideSprite; - } - - private final Map, List> itemModelCache = new ConcurrentHashMap<>(); - - @OnlyIn(Dist.CLIENT) - public void renderItem(ItemStack stack, ItemDisplayContext transformType, boolean leftHand, PoseStack matrixStack, - MultiBufferSource buffer, int combinedLight, int combinedOverlay, BakedModel model) { - IItemRendererProvider.disabled.set(true); - Minecraft.getInstance().getItemRenderer().render(stack, transformType, leftHand, matrixStack, buffer, - combinedLight, combinedOverlay, - (ItemBakedModel) (state, direction, random) -> itemModelCache.computeIfAbsent( - Optional.ofNullable(direction), - direction1 -> bakeQuads(direction1.orElse(null), ITEM_CONNECTIONS, 0))); - IItemRendererProvider.disabled.set(false); - } - - @OnlyIn(Dist.CLIENT) - public void registerTextureAtlas(Consumer register) { - itemModelCache.clear(); - sideTexture.invalidate(); - register.accept(sideTexture.get()); - endTexture.invalidate(); - register.accept(endTexture.get()); - if (secondarySideTexture != null) { - secondarySideTexture.invalidate(); - if (secondarySideTexture.get() != GTModels.BLANK_TEXTURE) { - register.accept(secondarySideTexture.get()); - } - } - if (secondaryEndTexture != null) { - secondaryEndTexture.invalidate(); - if (secondaryEndTexture.get() != GTModels.BLANK_TEXTURE) { - register.accept(secondaryEndTexture.get()); - } - } - if (sideOverlayTexture != null) register.accept(sideOverlayTexture); - if (endOverlayTexture != null) register.accept(endOverlayTexture); - sideSprite = null; - endSprite = null; - endOverlaySprite = null; - } - - private static EnumMap borderMap(Direction topSide, Direction bottomSide, Direction leftSide, - Direction rightSide) { - EnumMap sideMap = new EnumMap<>(Border.class); - sideMap.put(Border.TOP, topSide); - sideMap.put(Border.BOTTOM, bottomSide); - sideMap.put(Border.LEFT, leftSide); - sideMap.put(Border.RIGHT, rightSide); - return sideMap; - } - - private static void addRestrictor(TextureAtlasSprite sprite, Border... borders) { - int mask = 0; - for (Border border : borders) { - mask |= border.mask; - } - RESTRICTOR_MAP.put(mask, sprite); - } - - protected static Direction getSideAtBorder(Direction side, Border border) { - return FACE_BORDER_MAP.get(side).get(border); - } - - protected static int computeBorderMask(int blockedConnections, int connections, Direction side) { - int borderMask = 0; - if (blockedConnections != 0) { - for (Border border : Border.VALUES) { - Direction borderSide = getSideAtBorder(side, border); - if (PipeBlockEntity.isFaceBlocked(blockedConnections, borderSide) && - PipeBlockEntity.isConnected(connections, borderSide)) { - // only render when the side is blocked *and* connected - borderMask |= border.mask; - } - } - } - return borderMask; - } - - public enum Border { - - TOP, - BOTTOM, - LEFT, - RIGHT; - - public static final Border[] VALUES = values(); - - public final int mask; - - Border() { - mask = 1 << this.ordinal(); - } - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/client/model/machine/MachineModel.java b/src/main/java/com/gregtechceu/gtceu/client/model/machine/MachineModel.java index c20eb618e68..0b765ceba79 100644 --- a/src/main/java/com/gregtechceu/gtceu/client/model/machine/MachineModel.java +++ b/src/main/java/com/gregtechceu/gtceu/client/model/machine/MachineModel.java @@ -9,6 +9,7 @@ import com.gregtechceu.gtceu.api.machine.feature.multiblock.IMultiController; import com.gregtechceu.gtceu.api.machine.feature.multiblock.IMultiPart; import com.gregtechceu.gtceu.client.model.BaseBakedModel; +import com.gregtechceu.gtceu.client.model.GTModelProperties; import com.gregtechceu.gtceu.client.model.IBlockEntityRendererBakedModel; import com.gregtechceu.gtceu.client.model.TextureOverrideModel; import com.gregtechceu.gtceu.client.model.machine.multipart.MultiPartBakedModel; @@ -52,15 +53,12 @@ import lombok.Getter; import lombok.Setter; import lombok.experimental.Accessors; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; -import static com.gregtechceu.gtceu.api.machine.IMachineBlockEntity.*; - public final class MachineModel extends BaseBakedModel implements ICoverableRenderer, IBlockEntityRendererBakedModel { @@ -138,7 +136,7 @@ public static void initSprites(TextureAtlas atlas) { @SuppressWarnings("deprecation") @Override - public @NotNull TextureAtlasSprite getParticleIcon() { + public TextureAtlasSprite getParticleIcon() { if (particleIcon != null) { return particleIcon; } else if (multiPart != null) { @@ -152,9 +150,9 @@ public static void initSprites(TextureAtlas atlas) { } @Override - public TextureAtlasSprite getParticleIcon(@NotNull ModelData modelData) { - BlockAndTintGetter level = modelData.get(MODEL_DATA_LEVEL); - BlockPos pos = modelData.get(MODEL_DATA_POS); + public TextureAtlasSprite getParticleIcon(ModelData modelData) { + BlockAndTintGetter level = modelData.get(GTModelProperties.LEVEL); + BlockPos pos = modelData.get(GTModelProperties.POS); MetaMachine machine = (level == null || pos == null) ? null : MetaMachine.getMachine(level, pos); MachineRenderState renderState = machine != null ? machine.getRenderState() : @@ -171,11 +169,11 @@ public TextureAtlasSprite getParticleIcon(@NotNull ModelData modelData) { @SuppressWarnings({ "rawtypes", "unchecked" }) @Override - public @NotNull ModelData getModelData(@NotNull BlockAndTintGetter level, @NotNull BlockPos pos, - @NotNull BlockState state, @NotNull ModelData modelData) { + public ModelData getModelData(BlockAndTintGetter level, BlockPos pos, + BlockState state, ModelData modelData) { ModelData.Builder builder = modelData.derive() - .with(MODEL_DATA_LEVEL, level) - .with(MODEL_DATA_POS, pos); + .with(GTModelProperties.LEVEL, level) + .with(GTModelProperties.POS, pos); MetaMachine machine = MetaMachine.getMachine(level, pos); MachineRenderState renderState = machine == null ? definition.defaultRenderState() : machine.getRenderState(); @@ -193,9 +191,9 @@ public TextureAtlasSprite getParticleIcon(@NotNull ModelData modelData) { } @Override - public @NotNull List getQuads(@Nullable BlockState state, @Nullable Direction side, - @NotNull RandomSource rand, - @NotNull ModelData modelData, @Nullable RenderType renderType) { + public List getQuads(@Nullable BlockState state, @Nullable Direction side, + RandomSource rand, + ModelData modelData, @Nullable RenderType renderType) { // If there is a root transform, undo the ModelState transform, apply it, // then re-apply the ModelState transform. // This is necessary because of things like UV locking, which should only respond to the ModelState, @@ -206,7 +204,7 @@ public TextureAtlasSprite getParticleIcon(@NotNull ModelData modelData) { } List quads; - if (modelData.has(MODEL_DATA_LEVEL) && modelData.has(MODEL_DATA_POS)) { + if (modelData.has(GTModelProperties.LEVEL) && modelData.has(GTModelProperties.POS)) { quads = getMachineQuads(state, side, rand, modelData, renderType); } else { // if it doesn't have either of those properties, we're rendering an item. @@ -217,10 +215,10 @@ public TextureAtlasSprite getParticleIcon(@NotNull ModelData modelData) { } public List getMachineQuads(@Nullable BlockState blockState, @Nullable Direction side, - @NotNull RandomSource rand, @NotNull ModelData modelData, + RandomSource rand, ModelData modelData, @Nullable RenderType renderType) { - BlockAndTintGetter level = modelData.get(MODEL_DATA_LEVEL); - BlockPos pos = modelData.get(MODEL_DATA_POS); + BlockAndTintGetter level = modelData.get(GTModelProperties.LEVEL); + BlockPos pos = modelData.get(GTModelProperties.POS); MetaMachine machine = (level == null || pos == null) ? null : MetaMachine.getMachine(level, pos); // render machine quads @@ -261,7 +259,7 @@ public List getMachineQuads(@Nullable BlockState blockState, @Nullabl public List renderMachine(@Nullable MetaMachine machine, @Nullable BlockAndTintGetter level, @Nullable BlockPos pos, @Nullable BlockState blockState, @Nullable Direction side, RandomSource rand, - @NotNull ModelData modelData, @Nullable RenderType renderType) { + ModelData modelData, @Nullable RenderType renderType) { List quads = new LinkedList<>(); MachineRenderState renderState = machine != null ? machine.getRenderState() : definition.defaultRenderState(); @@ -283,9 +281,9 @@ public List renderMachine(@Nullable MetaMachine machine, @Nullable Bl return quads; } - public void renderBaseModel(List quads, @NotNull MachineRenderState renderState, + public void renderBaseModel(List quads, MachineRenderState renderState, @Nullable BlockState blockState, @Nullable Direction side, RandomSource rand, - @NotNull ModelData modelData, @Nullable RenderType renderType) { + ModelData modelData, @Nullable RenderType renderType) { if (multiPart != null) { quads.addAll(multiPart.getMachineQuads(definition, renderState, blockState, side, rand, modelData, renderType)); @@ -387,8 +385,8 @@ public boolean isCustomRenderer() { @SuppressWarnings({ "rawtypes", "unchecked" }) @Override - public void render(@NotNull BlockEntity blockEntity, float partialTick, - @NotNull PoseStack poseStack, @NotNull MultiBufferSource buffer, + public void render(BlockEntity blockEntity, float partialTick, + PoseStack poseStack, MultiBufferSource buffer, int packedLight, int packedOverlay) { if (!(blockEntity instanceof IMachineBlockEntity machineBE)) return; if (machineBE.getDefinition() != getDefinition()) return; @@ -449,7 +447,7 @@ public boolean shouldRenderOffScreen(BlockEntity blockEntity) { @SuppressWarnings({ "rawtypes", "unchecked" }) @Override - public boolean shouldRender(BlockEntity blockEntity, @NotNull Vec3 cameraPos) { + public boolean shouldRender(BlockEntity blockEntity, Vec3 cameraPos) { if (!(blockEntity instanceof IMachineBlockEntity machineBE)) return false; if (machineBE.getDefinition() != getDefinition()) return false; if (machineBE.getMetaMachine().getCoverContainer().hasDynamicCovers()) return true; diff --git a/src/main/java/com/gregtechceu/gtceu/client/model/machine/MachineModelLoader.java b/src/main/java/com/gregtechceu/gtceu/client/model/machine/MachineModelLoader.java index 934b511a0ea..9dc6e3e532a 100644 --- a/src/main/java/com/gregtechceu/gtceu/client/model/machine/MachineModelLoader.java +++ b/src/main/java/com/gregtechceu/gtceu/client/model/machine/MachineModelLoader.java @@ -63,7 +63,7 @@ public class MachineModelLoader implements IGeometryLoader private static final Splitter COMMA_SPLITTER = Splitter.on(','); private static final Splitter EQUAL_SPLITTER = Splitter.on('=').limit(2); - private static final UnbakedModel MISSING_MARKER = new BasicUnbakedModel(); + public static final UnbakedModel MISSING_MARKER = new BasicUnbakedModel(); private MachineModelLoader() {} diff --git a/src/main/java/com/gregtechceu/gtceu/client/model/machine/multipart/MultiPartBakedModel.java b/src/main/java/com/gregtechceu/gtceu/client/model/machine/multipart/MultiPartBakedModel.java index 2835f96414f..ef19e96f369 100644 --- a/src/main/java/com/gregtechceu/gtceu/client/model/machine/multipart/MultiPartBakedModel.java +++ b/src/main/java/com/gregtechceu/gtceu/client/model/machine/multipart/MultiPartBakedModel.java @@ -2,6 +2,7 @@ import com.gregtechceu.gtceu.api.machine.MachineDefinition; import com.gregtechceu.gtceu.api.machine.MetaMachine; +import com.gregtechceu.gtceu.client.model.GTModelProperties; import com.gregtechceu.gtceu.client.model.machine.MachineRenderState; import net.minecraft.Util; @@ -33,8 +34,6 @@ import java.util.*; import java.util.function.Predicate; -import static com.gregtechceu.gtceu.api.machine.IMachineBlockEntity.*; - public class MultiPartBakedModel implements IDynamicBakedModel { private final List, BakedModel>> selectors; @@ -115,8 +114,8 @@ public List getMachineQuads(MachineDefinition definition, MachineRend @Override public ChunkRenderTypeSet getRenderTypes(BlockState state, RandomSource rand, ModelData modelData) { - BlockAndTintGetter level = modelData.get(MODEL_DATA_LEVEL); - BlockPos pos = modelData.get(MODEL_DATA_POS); + BlockAndTintGetter level = modelData.get(GTModelProperties.LEVEL); + BlockPos pos = modelData.get(GTModelProperties.POS); var machine = (level == null || pos == null) ? null : MetaMachine.getMachine(level, pos); if (machine == null) return IDynamicBakedModel.super.getRenderTypes(state, rand, modelData); @@ -137,8 +136,8 @@ public ChunkRenderTypeSet getRenderTypes(BlockState state, RandomSource rand, Mo @Override public ModelData getModelData(BlockAndTintGetter level, BlockPos pos, BlockState state, ModelData modelData) { ModelData.Builder builder = modelData.derive() - .with(MODEL_DATA_LEVEL, level) - .with(MODEL_DATA_POS, pos); + .with(GTModelProperties.LEVEL, level) + .with(GTModelProperties.POS, pos); var machine = MetaMachine.getMachine(level, pos); if (machine == null) return builder.build(); @@ -183,8 +182,8 @@ public boolean isCustomRenderer() { @Override public TextureAtlasSprite getParticleIcon(ModelData modelData) { - BlockAndTintGetter level = modelData.get(MODEL_DATA_LEVEL); - BlockPos pos = modelData.get(MODEL_DATA_POS); + BlockAndTintGetter level = modelData.get(GTModelProperties.LEVEL); + BlockPos pos = modelData.get(GTModelProperties.POS); var machine = (level == null || pos == null) ? null : MetaMachine.getMachine(level, pos); if (machine != null) return getParticleIcon(machine.getRenderState(), modelData); diff --git a/src/main/java/com/gregtechceu/gtceu/client/model/machine/variant/MultiVariantModel.java b/src/main/java/com/gregtechceu/gtceu/client/model/machine/variant/MultiVariantModel.java index dcf7da73340..57e7defb97a 100644 --- a/src/main/java/com/gregtechceu/gtceu/client/model/machine/variant/MultiVariantModel.java +++ b/src/main/java/com/gregtechceu/gtceu/client/model/machine/variant/MultiVariantModel.java @@ -70,8 +70,8 @@ public void resolveParents(@NotNull Function res @OnlyIn(Dist.CLIENT) public static class Deserializer implements JsonDeserializer { - public MultiVariantModel deserialize(JsonElement json, Type type, JsonDeserializationContext context) - throws JsonParseException { + public MultiVariantModel deserialize(JsonElement json, Type type, + JsonDeserializationContext context) throws JsonParseException { List variants = new ArrayList<>(); if (json.isJsonArray()) { JsonArray array = json.getAsJsonArray(); diff --git a/src/main/java/com/gregtechceu/gtceu/client/model/pipe/ActivablePipeModel.java b/src/main/java/com/gregtechceu/gtceu/client/model/pipe/ActivablePipeModel.java new file mode 100644 index 00000000000..dc257bd4770 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/client/model/pipe/ActivablePipeModel.java @@ -0,0 +1,169 @@ +package com.gregtechceu.gtceu.client.model.pipe; + +import com.gregtechceu.gtceu.api.block.PipeBlock; +import com.gregtechceu.gtceu.api.block.property.GTBlockStateProperties; +import com.gregtechceu.gtceu.api.registry.registrate.provider.GTBlockstateProvider; +import com.gregtechceu.gtceu.data.model.builder.PipeModelBuilder; + +import net.minecraft.resources.ResourceLocation; +import net.minecraftforge.client.model.generators.BlockModelBuilder; +import net.minecraftforge.client.model.generators.IGeneratedBlockState; + +import lombok.Setter; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Nullable; + +import java.util.Objects; + +public class ActivablePipeModel extends PipeModel { + + @Setter + public @Nullable ResourceLocation sideActive, endActive; + @Setter + public @Nullable ResourceLocation sideSecondaryActive, endSecondaryActive; + @Setter + public @Nullable ResourceLocation sideOverlayActive, endOverlayActive; + + /// Use {@link #getOrCreateActiveBlockModel()} instead of referencing this field directly. + private BlockModelBuilder activeBlockModel; + /// Use {@link #getOrCreateActiveCenterElement()} instead of referencing this field directly. + private BlockModelBuilder activeCenterElement; + /// Use {@link #getOrCreateActiveConnectionElement()} instead of referencing this field directly. + private BlockModelBuilder activeConnectionElement; + + public ActivablePipeModel(PipeBlock block, float thickness, ResourceLocation side, ResourceLocation end, + GTBlockstateProvider provider) { + super(block, provider, thickness, side, end); + } + + /** + * @see #getOrCreateActiveBlockModel() + * @see #getOrCreateConnectionElement() + * @see #getOrCreateActiveCenterElement() + * @see #getOrCreateActiveConnectionElement() + */ + @Override + public void initModels() { + getOrCreateActiveCenterElement(); + getOrCreateActiveConnectionElement(); + getOrCreateActiveBlockModel(); + + super.initModels(); + } + + /** + * Override this to change the actual model {@link #block this.block} will use. + * + * @return A model builder for the block's actual model. + * @see #getOrCreateBlockModel() + * @see #getOrCreateActiveCenterElement() + * @see #getOrCreateActiveConnectionElement() + */ + @ApiStatus.OverrideOnly + protected BlockModelBuilder getOrCreateActiveBlockModel() { + if (this.activeBlockModel != null) { + return this.activeBlockModel; + } + // spotless:off + return this.activeBlockModel = this.provider.models().getBuilder(this.blockId.withSuffix("_active").toString()) + .parent(this.getOrCreateActiveCenterElement()) + .customLoader(PipeModelBuilder::begin) + .thickness(this.thickness).provider(this.provider) + .centerModels(this.getOrCreateActiveCenterElement().getLocation()) + .connectionModels(this.getOrCreateActiveConnectionElement().getLocation()) + .end(); + // spotless:on + } + + /** + * Override this to change the center element's model for when the pipe is active. + * + * @return A model builder for the center element's model. + * @see #getOrCreateCenterElement() + * @see #getOrCreateActiveConnectionElement() + */ + @ApiStatus.OverrideOnly + protected BlockModelBuilder getOrCreateActiveCenterElement() { + if (this.activeCenterElement != null) { + return this.activeCenterElement; + } + return this.activeCenterElement = makeActiveVariant(this.getOrCreateCenterElement()); + } + + /** + * Override this to change the 'connection' element's model for when the pipe is active.
+ * By default, this is rotated & used for all connected sides of the pipe.
+ * Note that that is not a hard requirement, and that you may set a model per side in + * {@link #getOrCreateBlockModel()}. + * + * @return A model builder for the connection element's model. + * @see #getOrCreateConnectionElement() + * @see #getOrCreateActiveCenterElement() + */ + @ApiStatus.OverrideOnly + protected BlockModelBuilder getOrCreateActiveConnectionElement() { + if (this.activeConnectionElement != null) { + return this.activeConnectionElement; + } + return this.activeConnectionElement = makeActiveVariant(this.getOrCreateConnectionElement()); + } + + protected BlockModelBuilder makeActiveVariant(BlockModelBuilder parentModel) { + BlockModelBuilder model = this.provider.models() + .getBuilder(parentModel.getLocation().withSuffix("_active").toString()) + .parent(parentModel); + // override non-null textures, leave unset ones as is + if (this.sideActive != null) model.texture("side", this.sideActive); + if (this.endActive != null) model.texture("end", this.endActive); + if (this.sideSecondaryActive != null) model.texture("side_secondary", this.sideSecondaryActive); + if (this.endSecondaryActive != null) model.texture("end_secondary", this.endSecondaryActive); + if (this.sideOverlayActive != null) model.texture("side_overlay", this.sideOverlayActive); + if (this.endOverlayActive != null) model.texture("end_overlay", this.endOverlayActive); + + return model; + } + + @Override + public IGeneratedBlockState createBlockState() { + if (!this.getBlock().defaultBlockState().hasProperty(GTBlockStateProperties.ACTIVE)) { + return super.createBlockState(); + } + // spotless:off + return this.provider.getVariantBuilder(this.getBlock()) + .partialState() + .with(GTBlockStateProperties.ACTIVE, false) + .modelForState() + .modelFile(this.provider.models().getExistingFile(this.blockId)) + .addModel() + .partialState() + .with(GTBlockStateProperties.ACTIVE, true) + .modelForState() + .modelFile(this.provider.models().getExistingFile(this.blockId.withSuffix("_active"))) + .addModel(); + // spotless:on + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof ActivablePipeModel pipeModel)) return false; + return super.equals(o) && + Objects.equals(sideActive, pipeModel.sideActive) && + Objects.equals(endActive, pipeModel.endActive) && + Objects.equals(sideSecondaryActive, pipeModel.sideSecondaryActive) && + Objects.equals(endSecondaryActive, pipeModel.endSecondaryActive) && + Objects.equals(sideOverlayActive, pipeModel.sideOverlayActive) && + Objects.equals(endOverlayActive, pipeModel.endOverlayActive); + } + + @Override + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + Objects.hashCode(sideActive); + result = 31 * result + Objects.hashCode(endActive); + result = 31 * result + Objects.hashCode(sideSecondaryActive); + result = 31 * result + Objects.hashCode(endSecondaryActive); + result = 31 * result + Objects.hashCode(sideOverlayActive); + result = 31 * result + Objects.hashCode(endOverlayActive); + return result; + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/client/model/pipe/BakedPipeModel.java b/src/main/java/com/gregtechceu/gtceu/client/model/pipe/BakedPipeModel.java new file mode 100644 index 00000000000..cba98fe97b3 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/client/model/pipe/BakedPipeModel.java @@ -0,0 +1,152 @@ +package com.gregtechceu.gtceu.client.model.pipe; + +import com.gregtechceu.gtceu.api.blockentity.PipeBlockEntity; +import com.gregtechceu.gtceu.api.data.tag.TagPrefix; +import com.gregtechceu.gtceu.api.pipenet.IPipeNode; +import com.gregtechceu.gtceu.api.pipenet.Node; +import com.gregtechceu.gtceu.client.model.BaseBakedModel; +import com.gregtechceu.gtceu.client.model.GTModelProperties; +import com.gregtechceu.gtceu.client.model.IBlockEntityRendererBakedModel; +import com.gregtechceu.gtceu.client.renderer.cover.ICoverableRenderer; +import com.gregtechceu.gtceu.client.util.GTQuadTransformers; +import com.gregtechceu.gtceu.common.data.GTMaterialBlocks; +import com.gregtechceu.gtceu.utils.GTUtil; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.color.block.BlockColors; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.client.model.data.ModelData; + +import com.mojang.blaze3d.vertex.PoseStack; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +public class BakedPipeModel extends BaseBakedModel implements ICoverableRenderer, + IBlockEntityRendererBakedModel> { + + public final static int ITEM_CONNECTIONS = 0b001100; + + private final Map parts; + private final Map restrictors; + + public BakedPipeModel(Map parts, Map restrictors) { + this.parts = parts; + this.restrictors = restrictors; + } + + @Override + public List getQuads(@Nullable BlockState state, @Nullable Direction side, + RandomSource rand, ModelData modelData, @Nullable RenderType renderType) { + List quads = new ArrayList<>(); + + BlockAndTintGetter level = modelData.get(GTModelProperties.LEVEL); + BlockPos pos = modelData.get(GTModelProperties.POS); + Integer connectionMask = modelData.get(GTModelProperties.PIPE_CONNECTION_MASK); + Integer blockedMask = modelData.get(GTModelProperties.PIPE_BLOCKED_MASK); + + if (level == null || pos == null || state == null) { + connectionMask = ITEM_CONNECTIONS; + blockedMask = Node.ALL_CLOSED; + } + if (connectionMask == null || connectionMask != Node.ALL_OPENED) { + quads.addAll(parts.get(null).getQuads(state, side, rand, modelData, renderType)); + if (connectionMask == null) { + // return unconnected base model if the model property isn't set + return quads; + } + } + for (Direction dir : GTUtil.DIRECTIONS) { + if (PipeBlockEntity.isConnected(connectionMask, dir)) { + quads.addAll(parts.get(dir).getQuads(state, side, rand, modelData, renderType)); + if (blockedMask != null && PipeBlockEntity.isFaceBlocked(blockedMask, dir)) { + quads.addAll(restrictors.get(dir).getQuads(state, side, rand, modelData, renderType)); + } + } + } + if (level == null || pos == null || !(level.getBlockEntity(pos) instanceof IPipeNode pipeNode)) { + return quads; + } + ICoverableRenderer.super.renderCovers(quads, pipeNode.getCoverContainer(), pos, level, side, rand, + modelData, renderType); + + if (pipeNode.getFrameMaterial().isNull() || (renderType != null && renderType != RenderType.translucent())) { + return quads; + } + var frameBlockEntry = GTMaterialBlocks.MATERIAL_BLOCKS.get(TagPrefix.frameGt, pipeNode.getFrameMaterial()); + if (frameBlockEntry == null) { + return quads; + } + BlockState frameState = frameBlockEntry.getDefaultState(); + BakedModel frameModel = Minecraft.getInstance().getBlockRenderer().getBlockModel(frameState); + + modelData = frameModel.getModelData(level, pos, frameState, modelData); + + List frameQuads = new LinkedList<>(); + if (side == null || pipeNode.getCoverContainer().getCoverAtSide(side) == null) { + frameQuads.addAll(frameModel.getQuads(state, side, rand, modelData, renderType)); + } + + if (side == null) { + for (Direction face : GTUtil.DIRECTIONS) { + if (pipeNode.getCoverContainer().getCoverAtSide(face) != null) { + continue; + } + frameQuads.addAll(frameModel.getQuads(state, face, rand, modelData, renderType)); + } + } + + // bake all the quads' tint colors into the vertices + BlockColors blockColors = Minecraft.getInstance().getBlockColors(); + for (BakedQuad frameQuad : frameQuads) { + if (frameQuad.isTinted()) { + int color = blockColors.getColor(frameState, level, pos, frameQuad.getTintIndex()); + frameQuad = GTQuadTransformers.setColor(frameQuad, color, true); + } + quads.add(frameQuad); + } + return quads; + } + + @Override + public ModelData getModelData(BlockAndTintGetter level, BlockPos pos, BlockState state, ModelData modelData) { + ModelData.Builder builder = modelData.derive() + .with(GTModelProperties.LEVEL, level) + .with(GTModelProperties.POS, pos); + + if (!(level.getBlockEntity(pos) instanceof PipeBlockEntity blockEntity)) { + return builder.build(); + } + return builder.with(GTModelProperties.PIPE_CONNECTION_MASK, blockEntity.getVisualConnections()) + .with(GTModelProperties.PIPE_BLOCKED_MASK, blockEntity.getBlockedConnections()) + .build(); + } + + @SuppressWarnings("deprecation") + @Override + public TextureAtlasSprite getParticleIcon() { + return parts.get(null).getParticleIcon(); + } + + @Override + public @Nullable BlockEntityType> getBlockEntityType() { + return null; + } + + @Override + public void render(PipeBlockEntity blockEntity, float partialTick, PoseStack poseStack, + MultiBufferSource buffer, int packedLight, int packedOverlay) {} +} diff --git a/src/main/java/com/gregtechceu/gtceu/client/model/pipe/PipeModel.java b/src/main/java/com/gregtechceu/gtceu/client/model/pipe/PipeModel.java new file mode 100644 index 00000000000..83f0ceeb9ca --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/client/model/pipe/PipeModel.java @@ -0,0 +1,377 @@ +package com.gregtechceu.gtceu.client.model.pipe; + +import com.gregtechceu.gtceu.api.block.PipeBlock; +import com.gregtechceu.gtceu.api.block.property.GTBlockStateProperties; +import com.gregtechceu.gtceu.api.registry.registrate.GTBlockBuilder; +import com.gregtechceu.gtceu.api.registry.registrate.provider.GTBlockstateProvider; +import com.gregtechceu.gtceu.data.model.builder.PipeModelBuilder; +import com.gregtechceu.gtceu.data.pack.event.RegisterDynamicResourcesEvent; +import com.gregtechceu.gtceu.utils.GTMath; +import com.gregtechceu.gtceu.utils.GTUtil; + +import net.minecraft.core.Direction; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.data.models.blockstates.MultiVariantGenerator; +import net.minecraft.resources.ResourceLocation; +import net.minecraftforge.client.model.generators.*; + +import com.tterrag.registrate.util.nullness.NonNullBiConsumer; +import it.unimi.dsi.fastutil.objects.Reference2FloatMap; +import it.unimi.dsi.fastutil.objects.Reference2FloatOpenHashMap; +import lombok.Getter; +import lombok.Setter; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.*; + +/** + * This is an automatic pipe model generator. + * + *

For material pipes

+ * If the pipe this model belongs to is generated from a material property (or equivalent), + * you should call {@link #dynamicModel()}, which adds the model to {@link #DYNAMIC_MODELS} + * and automatically processes it as a part of runtime asset generation. + *

+ * NOTE:
+ * You must also initialize the models in an {@link RegisterDynamicResourcesEvent} listener as such: + * + *

+ * {@code
+ * 
+ * // in a @EventBusSubscriber-annotated class
+ * @SubscribeEvent
+ * public static void registerDynamicAssets(RegisterDynamicResourcesEvent event) {
+ *     for (var block : YourBlocks.YOUR_PIPE_BLOCKS.values()) {
+ *         if (block == null) continue;
+ *         block.get().createPipeModel(RuntimeExistingFileHelper.INSTANCE).dynamicModel();
+ *     }
+ * }
+ * }
+ * 
+ * + * Remember to replace {@code YourBlocks.YOUR_PIPE_BLOCKS.values()} with a reference to your pipe block collection! + *

+ * + *

For non-material pipes

+ * Conversely, if the pipe is not generated, but has a constant set of variants (such as optical fiber + * cables), + * you should NOT use {@link #dynamicModel()} and instead set the model with + * {@link GTBlockBuilder#gtBlockstate(NonNullBiConsumer)} as such: + * + *
+ * {@code
+ *     // on your pipe block builder
+ *     ... = REGISTRATE.block(...)
+ *              .properties(...)
+ *              .gtBlockstate(GTModels::createPipeBlockModel)
+ *              ...more builder things...
+ *              .item(...)
+ *              .model(NonNullBiConsumer.noop())
+ *              ...more builder things...
+ * }
+ * 
+ * + * This makes the pipe model(s) be generated for you without having to process them at runtime. + * + */ +public class PipeModel { + + public static final Set DYNAMIC_MODELS = new HashSet<>(); + + public static void initDynamicModels() { + for (PipeModel generator : DYNAMIC_MODELS) { + generator.initModels(); + } + } + + @Getter + private final PipeBlock block; + public final @NotNull ResourceLocation blockId; + protected final GTBlockstateProvider provider; + + /** + * The pipe's "thickness" in the (0,16] voxel range, where 1 is 1 voxel and 16 is a full block thick + */ + protected final float thickness; + /** + * The pipe model's 'minimum' coordinate in the (0,16] voxel range.
+ * This is ex. the height of the center part's bottom edge. + */ + protected final float minCoord; + /** + * The pipe model's 'maximum' coordinate in the (0,16] voxel range.
+ * This is ex. the height of the center part's top edge. + */ + protected final float maxCoord; + @Setter + public ResourceLocation side, end; + @Setter + public @Nullable ResourceLocation sideSecondary, endSecondary; + @Setter + public @Nullable ResourceLocation sideOverlay, endOverlay; + + /// Use {@link #getOrCreateBlockModel()} instead of referencing this field directly. + private BlockModelBuilder blockModel; + /// Use {@link #getOrCreateItemModel()} instead of referencing this field directly. + private ItemModelBuilder itemModel; + + /// Use {@link #getOrCreateCenterElement()} instead of referencing this field directly. + private BlockModelBuilder centerElement; + /// Use {@link #getOrCreateConnectionElement()} instead of referencing this field directly. + private BlockModelBuilder connectionElement; + + public PipeModel(PipeBlock block, GTBlockstateProvider provider, + float thickness, ResourceLocation side, ResourceLocation end) { + this.block = block; + this.blockId = BuiltInRegistries.BLOCK.getKey(this.block); + this.provider = provider; + + // assume thickness is in the 0-1 range + this.thickness = thickness * 16.0f; + this.side = side; + this.end = end; + + this.minCoord = (16.0f - this.thickness) / 2.0f; + this.maxCoord = this.minCoord + this.thickness; + } + + public final void dynamicModel() { + DYNAMIC_MODELS.add(this); + } + + /** + * Initialize all models that are required for this block model to exist.
+ * Order is important! Dependent models must be initialized after their dependencies. + * + * @see #getOrCreateBlockModel() + * @see #getOrCreateCenterElement() + * @see #getOrCreateConnectionElement() + */ + public void initModels() { + getOrCreateCenterElement(); + getOrCreateConnectionElement(); + getOrCreateBlockModel(); + createBlockState(); + + getOrCreateItemModel(); + } + + /** + * Override this to change the actual model {@link #block this.block} will use. + * + * @return A model builder for the block's actual model. + * @see #getOrCreateCenterElement() + * @see #getOrCreateConnectionElement() + */ + @ApiStatus.OverrideOnly + protected BlockModelBuilder getOrCreateBlockModel() { + if (this.blockModel != null) { + return this.blockModel; + } + // spotless:off + return this.blockModel = this.provider.models().getBuilder(this.blockId.toString()) + // make the "default" model be based on the center part's model + .parent(this.getOrCreateCenterElement()) + .customLoader(PipeModelBuilder::begin) + .thickness(this.thickness).provider(this.provider) + .centerModels(this.getOrCreateCenterElement().getLocation()) + .connectionModels(this.getOrCreateConnectionElement().getLocation()) + .end(); + // spotless:on + } + + /** + * Override this to change the center element's model. + * + * @return A model builder for the center element's model. + * @see #getOrCreateBlockModel() + * @see #getOrCreateConnectionElement() + */ + @ApiStatus.OverrideOnly + protected BlockModelBuilder getOrCreateCenterElement() { + if (this.centerElement != null) { + return this.centerElement; + } + return this.centerElement = makeElementModel(this.blockId.withPath(path -> "block/pipe/" + path + "/center"), + null, minCoord, minCoord, minCoord, maxCoord, maxCoord, maxCoord); + } + + /** + * Override this to change the 'connection' element's model.
+ * By default, this is rotated & used for all connected sides of the pipe.
+ * Note that that is not a hard requirement, and that you may set a model per side in + * {@link #getOrCreateBlockModel()}. + * + * @return A model builder for the connection element's model. + * @see #getOrCreateBlockModel() + * @see #getOrCreateCenterElement() + */ + @ApiStatus.OverrideOnly + protected BlockModelBuilder getOrCreateConnectionElement() { + if (this.connectionElement != null) { + return this.connectionElement; + } + return this.connectionElement = makeElementModel( + this.blockId.withPath(path -> "block/pipe/" + path + "/connection"), + Direction.DOWN, minCoord, 0, minCoord, maxCoord, minCoord, maxCoord); + } + + /** + * Override this to change the item model.
+ * By default, this creates a version of the pipe block model with the north & south sides 'connected'. + * + * @return The item model builder. + * @see #getOrCreateBlockModel() + */ + @ApiStatus.OverrideOnly + protected ItemModelBuilder getOrCreateItemModel() { + return createItemModel(this.blockId, this.minCoord, this.maxCoord); + } + + /** + * Override this to change the block state set {@link #block this.block} will use.
+ * By default, this creates a simple block state with no properties.
+ * The activable pipes (laser & optical) use this to add a model for the + * {@link GTBlockStateProperties#ACTIVE "active"} state of the blocks. + * + * @return The block state generator, usually a {@link MultiVariantGenerator}. + * @see #getOrCreateBlockModel() + * @see ActivablePipeModel#createBlockState() + */ + @ApiStatus.OverrideOnly + public IGeneratedBlockState createBlockState() { + // spotless:off + return this.provider.getVariantBuilder(this.getBlock()) + .partialState() + .modelForState() + .modelFile(this.provider.models().getExistingFile(this.blockId)) + .addModel(); + // spotless:on + } + + /** + * Creates an item model based on the block model that extends to the north/south end of the block space. + * + * @param name The resulting model's path. + * @param min The minimum X/Y coordinate. + * @param max The maximum X/Y coordinate. + * @return An item model builder. + */ + protected ItemModelBuilder createItemModel(ResourceLocation name, float min, float max) { + Reference2FloatMap faceEndpoints = new Reference2FloatOpenHashMap<>(); + faceEndpoints.put(Direction.DOWN, min); + faceEndpoints.put(Direction.UP, max); + faceEndpoints.put(Direction.NORTH, 0); + faceEndpoints.put(Direction.SOUTH, 16); + faceEndpoints.put(Direction.WEST, min); + faceEndpoints.put(Direction.EAST, max); + + ItemModelBuilder model = this.provider.itemModels().getBuilder(name.toString()) + .parent(this.getOrCreateCenterElement()); + makePartModelElement(model, Direction.NORTH, false, faceEndpoints, 0.0f, 0, 1, + min, min, 0, max, max, 16, this.side, this.end, "side", "end"); + makePartModelElement(model, Direction.NORTH, true, faceEndpoints, 0.001f, 0, 1, + min, min, 0, max, max, 16, this.sideSecondary, this.endSecondary, "side_secondary", "end_secondary"); + makePartModelElement(model, Direction.NORTH, true, faceEndpoints, 0.002f, 2, 2, + min, min, 0, max, max, 16, this.sideOverlay, this.endOverlay, "side_overlay", "end_overlay"); + return model; + } + + /** + * Fills out a model builder with applicable pipe model elements and returns it for further use + * + * @param name the resulting model's path + * @param endFace the model face that's being created + * @param x1 min X coordinate in the range [-16,32] + * @param y1 min Y coordinate in the range [-16,32] + * @param z1 min Z coordinate in the range [-16,32] + * @param x2 max X coordinate in the range [-16,32] + * @param y2 max Y coordinate in the range [-16,32] + * @param z2 max Z coordinate in the range [-16,32] + * @implNote The coordinates must be in the correct order or the resulting model's cubes will be inside out! + */ + protected BlockModelBuilder makeElementModel(ResourceLocation name, @Nullable Direction endFace, + final float x1, final float y1, final float z1, + final float x2, final float y2, final float z2) { + Reference2FloatMap faceEndpoints = new Reference2FloatOpenHashMap<>(); + faceEndpoints.defaultReturnValue(GTMath.max(x1, y1, z1, x2, y2, z2)); + for (Direction dir : GTUtil.DIRECTIONS) { + faceEndpoints.put(dir, switch (dir) { + case DOWN -> Math.min(y1, y2); + case UP -> Math.max(y1, y2); + case NORTH -> Math.min(z1, z2); + case SOUTH -> Math.max(z1, z2); + case WEST -> Math.min(x1, x2); + case EAST -> Math.max(x1, x2); + }); + } + + BlockModelBuilder model = this.provider.models().getBuilder(name.toString()) + .parent(new ModelFile.UncheckedModelFile("block/block")); + makePartModelElement(model, endFace, false, faceEndpoints, 0.0f, 0, 1, + x1, y1, z1, x2, y2, z2, this.side, this.end, "side", "end"); + makePartModelElement(model, endFace, true, faceEndpoints, 0.001f, 0, 1, + x1, y1, z1, x2, y2, z2, this.sideSecondary, this.endSecondary, "side_secondary", "end_secondary"); + makePartModelElement(model, endFace, true, faceEndpoints, 0.002f, 2, 2, + x1, y1, z1, x2, y2, z2, this.sideOverlay, this.endOverlay, "side_overlay", "end_overlay"); + return model; + } + + protected > void makePartModelElement(T model, @Nullable Direction endFace, + boolean useEndWithFullCube, + Reference2FloatMap faceEndpoints, + float offset, int sideTintIndex, int endTintIndex, + final float x1, final float y1, final float z1, + final float x2, final float y2, final float z2, + @Nullable ResourceLocation sideTexture, + @Nullable ResourceLocation endTexture, + String sideKey, String endKey) { + if (sideTexture == null && endTexture == null) { + return; + } + if (sideTexture != null) model.texture(sideKey, sideTexture); + if (endTexture != null) model.texture(endKey, endTexture); + + boolean fullCube = !useEndWithFullCube && + (x1 == y1 && x1 == z1 && x1 <= 0.0f) && + (x2 == y2 && x2 == z2 && x2 >= 16.0f); + + ModelBuilder.ElementBuilder element = model.element() + .from(x1 - offset, y1 - offset, z1 - offset) + .to(x2 + offset, y2 + offset, z2 + offset); + + for (Direction dir : GTUtil.DIRECTIONS) { + ModelBuilder.ElementBuilder.FaceBuilder face = null; + boolean isEnd = (endFace == dir || endFace == dir.getOpposite()) && !fullCube; + if (isEnd && endTexture != null) { + face = element.face(dir).texture("#" + endKey).tintindex(endTintIndex); + } else if (!isEnd && sideTexture != null) { + face = element.face(dir).texture("#" + sideKey).tintindex(sideTintIndex); + } + + float faceEnd = faceEndpoints.getFloat(dir); + if (face != null && (faceEnd >= 16.0f || faceEnd <= 0.0f)) { + face.cullface(dir); + } + } + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof PipeModel pipeModel)) return false; + return block == pipeModel.block && + Objects.equals(side, pipeModel.side) && + Objects.equals(end, pipeModel.end) && + Objects.equals(sideSecondary, pipeModel.sideSecondary) && + Objects.equals(endSecondary, pipeModel.endSecondary) && + Objects.equals(sideOverlay, pipeModel.sideOverlay) && + Objects.equals(endOverlay, pipeModel.endOverlay); + } + + @Override + public int hashCode() { + return Objects.hash(block, side, end, sideSecondary, endSecondary, sideOverlay, endOverlay); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/client/model/pipe/PipeModelLoader.java b/src/main/java/com/gregtechceu/gtceu/client/model/pipe/PipeModelLoader.java new file mode 100644 index 00000000000..9465b8f8471 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/client/model/pipe/PipeModelLoader.java @@ -0,0 +1,62 @@ +package com.gregtechceu.gtceu.client.model.pipe; + +import com.gregtechceu.gtceu.GTCEu; +import com.gregtechceu.gtceu.client.model.machine.MachineModelLoader; +import com.gregtechceu.gtceu.client.model.machine.variant.MultiVariantModel; + +import net.minecraft.client.resources.model.UnbakedModel; +import net.minecraft.core.Direction; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.GsonHelper; +import net.minecraftforge.client.model.geometry.IGeometryLoader; + +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import org.jetbrains.annotations.Nullable; + +import java.util.*; + +public class PipeModelLoader implements IGeometryLoader { + + public static final PipeModelLoader INSTANCE = new PipeModelLoader(); + public static final ResourceLocation ID = GTCEu.id("pipe"); + public static final String PRIMARY_CENTER_KEY = "center"; + public static final Set CENTER_KEYS = Set.of(PRIMARY_CENTER_KEY, "core", "null", "none"); + + @Override + public @Nullable UnbakedPipeModel read(JsonObject json, + JsonDeserializationContext context) throws JsonParseException { + // load the inner models + final Map parts = new HashMap<>(); + if (json.has("parts")) { + JsonObject variantsJson = GsonHelper.getAsJsonObject(json, "parts"); + for (Map.Entry entry : variantsJson.entrySet()) { + Direction direction = Direction.byName(entry.getKey()); + if (direction == null && !CENTER_KEYS.contains(entry.getKey().toLowerCase(Locale.ROOT))) { + throw new JsonParseException("Invalid pipe model part specifier " + entry.getKey()); + } + if (direction == null && parts.get(null) != null) { + throw new JsonParseException("Cannot specify more than one 'center' model for a pipe model"); + } + + parts.put(direction, MachineModelLoader.GSON.fromJson(entry.getValue(), MultiVariantModel.class)); + } + } + // and the restrictors + final Map restrictors = new HashMap<>(); + if (json.has("restrictors")) { + JsonObject variantsJson = GsonHelper.getAsJsonObject(json, "restrictors"); + for (Map.Entry entry : variantsJson.entrySet()) { + Direction direction = Direction.byName(entry.getKey()); + if (direction == null) { + throw new JsonParseException("Invalid pipe model part specifier " + entry.getKey()); + } + restrictors.put(direction, MachineModelLoader.GSON.fromJson(entry.getValue(), MultiVariantModel.class)); + } + } + + return new UnbakedPipeModel(parts, restrictors); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/client/model/pipe/UnbakedPipeModel.java b/src/main/java/com/gregtechceu/gtceu/client/model/pipe/UnbakedPipeModel.java new file mode 100644 index 00000000000..5ea5e68ac76 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/client/model/pipe/UnbakedPipeModel.java @@ -0,0 +1,71 @@ +package com.gregtechceu.gtceu.client.model.pipe; + +import net.minecraft.client.renderer.block.model.ItemOverrides; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.resources.model.*; +import net.minecraft.core.Direction; +import net.minecraft.resources.ResourceLocation; +import net.minecraftforge.client.model.geometry.IGeometryBakingContext; +import net.minecraftforge.client.model.geometry.IUnbakedGeometry; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.IdentityHashMap; +import java.util.Map; +import java.util.function.Function; + +import static com.gregtechceu.gtceu.client.model.machine.MachineModelLoader.MISSING_MARKER; + +public class UnbakedPipeModel implements IUnbakedGeometry { + + private final Map<@Nullable Direction, UnbakedModel> parts; + private final Map<@NotNull Direction, UnbakedModel> restrictors; + + public UnbakedPipeModel(Map<@Nullable Direction, UnbakedModel> parts, + Map<@NotNull Direction, UnbakedModel> restrictors) { + this.parts = parts; + this.restrictors = restrictors; + } + + @Override + public BakedModel bake(IGeometryBakingContext context, ModelBaker baker, + Function spriteGetter, ModelState modelState, + ItemOverrides overrides, ResourceLocation modelLocation) { + Map bakedParts = new IdentityHashMap<>(); + this.parts.forEach((direction, unbaked) -> { + bakedParts.put(direction, unbaked.bake(baker, spriteGetter, modelState, modelLocation)); + }); + Map bakedRestrictors = new IdentityHashMap<>(); + this.restrictors.forEach((direction, unbaked) -> { + bakedRestrictors.put(direction, unbaked.bake(baker, spriteGetter, modelState, modelLocation)); + }); + return new BakedPipeModel(bakedParts, bakedRestrictors); + } + + @Override + public void resolveParents(Function resolver, IGeometryBakingContext context) { + UnbakedModel missingModel = resolver.apply(ModelBakery.MISSING_MODEL_LOCATION); + + Map copy = new IdentityHashMap<>(this.parts); + copy.forEach((side, variant) -> { + if (variant == null || variant == MISSING_MARKER) { + // replace null & markers with the actual missing model + this.parts.put(side, missingModel); + } else { + variant.resolveParents(resolver); + this.parts.put(side, variant); + } + }); + copy = new IdentityHashMap<>(this.restrictors); + copy.forEach((side, variant) -> { + if (variant == null || variant == MISSING_MARKER) { + // replace null & markers with the actual missing model + this.restrictors.put(side, missingModel); + } else { + variant.resolveParents(resolver); + this.restrictors.put(side, variant); + } + }); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/client/model/pipe/package-info.java b/src/main/java/com/gregtechceu/gtceu/client/model/pipe/package-info.java new file mode 100644 index 00000000000..481c46780dc --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/client/model/pipe/package-info.java @@ -0,0 +1,7 @@ +@ParametersAreNonnullByDefault +@MethodsReturnNonnullByDefault +package com.gregtechceu.gtceu.client.model.pipe; + +import net.minecraft.MethodsReturnNonnullByDefault; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/src/main/java/com/gregtechceu/gtceu/client/renderer/BlockEntityWithBERModelRenderer.java b/src/main/java/com/gregtechceu/gtceu/client/renderer/BlockEntityWithBERModelRenderer.java index 3508a6e860e..511730ca9aa 100644 --- a/src/main/java/com/gregtechceu/gtceu/client/renderer/BlockEntityWithBERModelRenderer.java +++ b/src/main/java/com/gregtechceu/gtceu/client/renderer/BlockEntityWithBERModelRenderer.java @@ -45,7 +45,7 @@ public void render(T blockEntity, float partialTick, BakedModel model = blockRenderDispatcher.getBlockModel(blockState); if (model instanceof IBlockEntityRendererBakedModel berModel) { - if (berModel.getBlockEntityType() != blockEntity.getType()) return; + if (berModel.getBlockEntityType() != null && berModel.getBlockEntityType() != blockEntity.getType()) return; ((IBlockEntityRendererBakedModel) berModel).render(blockEntity, partialTick, poseStack, buffer, packedLight, packedOverlay); @@ -79,7 +79,7 @@ public boolean shouldRenderOffScreen(T blockEntity) { BakedModel model = blockRenderDispatcher.getBlockModel(blockState); if (model instanceof IBlockEntityRendererBakedModel berModel) { - if (berModel.getBlockEntityType() == blockEntity.getType()) { + if (berModel.getBlockEntityType() != null && berModel.getBlockEntityType() == blockEntity.getType()) { return ((IBlockEntityRendererBakedModel) berModel).shouldRenderOffScreen(blockEntity); } } @@ -92,7 +92,7 @@ public boolean shouldRender(T blockEntity, Vec3 cameraPos) { BakedModel model = blockRenderDispatcher.getBlockModel(blockState); if (model instanceof IBlockEntityRendererBakedModel berModel) { - if (berModel.getBlockEntityType() == blockEntity.getType()) { + if (berModel.getBlockEntityType() != null && berModel.getBlockEntityType() == blockEntity.getType()) { return ((IBlockEntityRendererBakedModel) berModel).shouldRender(blockEntity, cameraPos); } } diff --git a/src/main/java/com/gregtechceu/gtceu/client/renderer/block/LampItemRenderer.java b/src/main/java/com/gregtechceu/gtceu/client/renderer/block/LampItemRenderer.java new file mode 100644 index 00000000000..aed2072c637 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/client/renderer/block/LampItemRenderer.java @@ -0,0 +1,54 @@ +package com.gregtechceu.gtceu.client.renderer.block; + +import com.gregtechceu.gtceu.api.item.LampBlockItem; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.BlockEntityWithoutLevelRenderer; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.block.BlockRenderDispatcher; +import net.minecraft.client.renderer.entity.ItemRenderer; +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.world.item.ItemDisplayContext; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.state.BlockState; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import org.jetbrains.annotations.NotNull; + +/** + * All this renderer does is refer rendering to the correct block model based on the lamp item's NBT.
+ * Without it, all item variants would look like the default 'lit, with bloom' one. + */ +public class LampItemRenderer extends BlockEntityWithoutLevelRenderer { + + public static final LampItemRenderer INSTANCE = new LampItemRenderer(); + + protected final ItemRenderer itemRenderer; + protected final BlockRenderDispatcher blockRenderer; + + protected LampItemRenderer() { + super(Minecraft.getInstance().getBlockEntityRenderDispatcher(), + Minecraft.getInstance().getEntityModels()); + this.itemRenderer = Minecraft.getInstance().getItemRenderer(); + this.blockRenderer = Minecraft.getInstance().getBlockRenderer(); + } + + @Override + public void renderByItem(@NotNull ItemStack stack, @NotNull ItemDisplayContext displayContext, + @NotNull PoseStack poseStack, @NotNull MultiBufferSource buffer, + int packedLight, int packedOverlay) { + if (!(stack.getItem() instanceof LampBlockItem item)) { + return; + } + BlockState state = item.getStateFromStack(stack, null); + BakedModel p_model = blockRenderer.getBlockModel(state); + + for (var model : p_model.getRenderPasses(stack, true)) { + for (var rendertype : model.getRenderTypes(stack, true)) { + VertexConsumer foilBuffer = ItemRenderer.getFoilBufferDirect(buffer, rendertype, true, stack.hasFoil()); + itemRenderer.renderModelLists(model, stack, packedLight, packedOverlay, poseStack, foilBuffer); + } + } + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/client/renderer/block/LampRenderer.java b/src/main/java/com/gregtechceu/gtceu/client/renderer/block/LampRenderer.java deleted file mode 100644 index a9552b7ea83..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/client/renderer/block/LampRenderer.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.gregtechceu.gtceu.client.renderer.block; - -import com.gregtechceu.gtceu.GTCEu; -import com.gregtechceu.gtceu.common.block.LampBlock; - -import com.lowdragmc.lowdraglib.client.model.custommodel.ICTMPredicate; -import com.lowdragmc.lowdraglib.client.renderer.impl.IModelRenderer; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.level.BlockAndTintGetter; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -public class LampRenderer extends IModelRenderer implements ICTMPredicate { - - public LampRenderer(LampBlock lamp, BlockState state) { - super(GTCEu.id("block/%s%s_lamp%s%s".formatted( - lamp.color, - lamp.bordered ? "" : "_borderless", - state.getValue(LampBlock.LIGHT) ? "" : "_off", - state.getValue(LampBlock.LIGHT) && state.getValue(LampBlock.BLOOM) ? "_bloom" : ""))); - } - - @Override - public boolean isConnected(BlockAndTintGetter level, BlockState state, BlockPos pos, - BlockState sourceState, BlockPos sourcePos, Direction side) { - var stateAppearance = state.getAppearance(level, pos, side, sourceState, sourcePos); - var sourceStateAppearance = sourceState.getAppearance(level, sourcePos, side, state, pos); - return stateAppearance.getBlock() == sourceStateAppearance.getBlock(); - } - - @Override - @OnlyIn(Dist.CLIENT) - public boolean useAO() { - return true; - } - - @Override - public boolean reBakeCustomQuads() { - return true; - } - - @Override - public float reBakeCustomQuadsOffset() { - return 0.0f; - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/client/renderer/block/OreBlockRenderer.java b/src/main/java/com/gregtechceu/gtceu/client/renderer/block/OreBlockRenderer.java index 563f1bc6682..fbd6bff6240 100644 --- a/src/main/java/com/gregtechceu/gtceu/client/renderer/block/OreBlockRenderer.java +++ b/src/main/java/com/gregtechceu/gtceu/client/renderer/block/OreBlockRenderer.java @@ -75,12 +75,14 @@ public static void cloneBlockModel(ResourceLocation modelId, TagPrefix prefix, M JsonObject newJson = original.deepCopy(); JsonObject children = newJson.getAsJsonObject("children"); // add the base stone texture. - children.getAsJsonObject("base_stone").addProperty("parent", - TagPrefix.ORES.get(prefix).baseModelLocation().toString()); + children.getAsJsonObject("base_stone") + .addProperty("parent", TagPrefix.ORES.get(prefix).baseModelLocation().toString()); + + ResourceLocation layer0 = prefix.materialIconType() + .getBlockTexturePath(material.getMaterialIconSet(), true); + ResourceLocation layer1 = prefix.materialIconType() + .getBlockTexturePath(material.getMaterialIconSet(), "layer2", true); - ResourceLocation layer0 = prefix.materialIconType().getBlockTexturePath(material.getMaterialIconSet(), true); - ResourceLocation layer1 = prefix.materialIconType().getBlockTexturePath(material.getMaterialIconSet(), "layer2", - true); JsonObject oresTextures = children.getAsJsonObject("ore_texture").getAsJsonObject("textures"); oresTextures.addProperty("layer0", layer0.toString()); oresTextures.addProperty("layer1", layer1.toString()); diff --git a/src/main/java/com/gregtechceu/gtceu/client/renderer/block/PipeBlockRenderer.java b/src/main/java/com/gregtechceu/gtceu/client/renderer/block/PipeBlockRenderer.java deleted file mode 100644 index b06ac84c7ce..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/client/renderer/block/PipeBlockRenderer.java +++ /dev/null @@ -1,149 +0,0 @@ -package com.gregtechceu.gtceu.client.renderer.block; - -import com.gregtechceu.gtceu.GTCEu; -import com.gregtechceu.gtceu.api.data.tag.TagPrefix; -import com.gregtechceu.gtceu.api.pipenet.IPipeNode; -import com.gregtechceu.gtceu.client.model.PipeModel; -import com.gregtechceu.gtceu.client.renderer.cover.ICoverableRenderer; -import com.gregtechceu.gtceu.client.util.GTQuadTransformers; -import com.gregtechceu.gtceu.common.data.GTMaterialBlocks; -import com.gregtechceu.gtceu.utils.GTUtil; - -import com.lowdragmc.lowdraglib.client.renderer.IRenderer; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.color.block.BlockColors; -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.block.model.BakedQuad; -import net.minecraft.client.renderer.texture.TextureAtlas; -import net.minecraft.client.renderer.texture.TextureAtlasSprite; -import net.minecraft.client.resources.model.BakedModel; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.util.RandomSource; -import net.minecraft.world.item.ItemDisplayContext; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.BlockAndTintGetter; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.client.model.data.ModelData; - -import com.mojang.blaze3d.vertex.PoseStack; -import lombok.Getter; -import org.jetbrains.annotations.NotNull; - -import java.util.LinkedList; -import java.util.List; -import java.util.function.Consumer; - -import static com.lowdragmc.lowdraglib.client.model.forge.LDLRendererModel.RendererBakedModel.*; - -public class PipeBlockRenderer implements IRenderer, ICoverableRenderer { - - @Getter - PipeModel pipeModel; - - public PipeBlockRenderer(PipeModel pipeModel) { - this.pipeModel = pipeModel; - if (GTCEu.isClientSide()) { - registerEvent(); - } - } - - @Override - @OnlyIn(Dist.CLIENT) - public void renderItem(ItemStack stack, - ItemDisplayContext transformType, - boolean leftHand, PoseStack matrixStack, - MultiBufferSource buffer, int combinedLight, - int combinedOverlay, BakedModel model) { - pipeModel.renderItem(stack, transformType, leftHand, matrixStack, buffer, combinedLight, combinedOverlay, - model); - } - - @Override - public boolean useAO() { - return true; - } - - @Override - @OnlyIn(Dist.CLIENT) - public boolean useBlockLight(ItemStack stack) { - return true; - } - - @Override - @OnlyIn(Dist.CLIENT) - public List renderModel(BlockAndTintGetter level, BlockPos pos, BlockState state, Direction side, - RandomSource rand) { - if (level == null) { - return pipeModel.bakeQuads(side, PipeModel.ITEM_CONNECTIONS, 0); - } - if (!(level.getBlockEntity(pos) instanceof IPipeNode pipeNode)) { - return pipeModel.bakeQuads(side, 0, 0); - } - RenderType renderType = CURRENT_RENDER_TYPE.get(); - ModelData modelData = CURRENT_MODEL_DATA.get().get(MODEL_DATA); - if (modelData == null) modelData = ModelData.EMPTY; - - List quads = new LinkedList<>(); - - if (renderType == null || renderType == RenderType.cutoutMipped()) { - quads.addAll(pipeModel.bakeQuads(side, pipeNode.getVisualConnections(), pipeNode.getBlockedConnections())); - } - ICoverableRenderer.super.renderCovers(quads, pipeNode.getCoverContainer(), pos, level, side, rand, - modelData, renderType); - - if (pipeNode.getFrameMaterial().isNull() || (renderType != null && renderType != RenderType.translucent())) { - return quads; - } - - BlockState frameState = GTMaterialBlocks.MATERIAL_BLOCKS.get(TagPrefix.frameGt, pipeNode.getFrameMaterial()) - .getDefaultState(); - BakedModel frameModel = Minecraft.getInstance().getBlockRenderer().getBlockModel(frameState); - - modelData = frameModel.getModelData(level, pos, frameState, modelData); - - List frameQuads = new LinkedList<>(); - if (side == null || pipeNode.getCoverContainer().getCoverAtSide(side) == null) { - frameQuads.addAll(frameModel.getQuads(state, side, rand, modelData, renderType)); - } - if (side == null) { - for (Direction face : GTUtil.DIRECTIONS) { - if (pipeNode.getCoverContainer().getCoverAtSide(face) != null) { - continue; - } - frameQuads.addAll(frameModel.getQuads(state, face, rand, modelData, renderType)); - } - } - - // bake all the quads' tint colors into the vertices - BlockColors blockColors = Minecraft.getInstance().getBlockColors(); - for (BakedQuad frameQuad : frameQuads) { - if (frameQuad.isTinted()) { - int color = blockColors.getColor(frameState, level, pos, frameQuad.getTintIndex()); - frameQuad = GTQuadTransformers.setColor(frameQuad, color, true); - } - quads.add(frameQuad); - } - return quads; - } - - @NotNull - @Override - @OnlyIn(Dist.CLIENT) - public TextureAtlasSprite getParticleTexture() { - return pipeModel.getParticleTexture(); - } - - @Override - @OnlyIn(Dist.CLIENT) - public void onPrepareTextureAtlas(ResourceLocation atlasName, Consumer register) { - if (atlasName.equals(TextureAtlas.LOCATION_BLOCKS)) { - pipeModel.registerTextureAtlas(register); - } - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/common/block/CableBlock.java b/src/main/java/com/gregtechceu/gtceu/common/block/CableBlock.java index e1542d349f3..1abacd672cb 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/block/CableBlock.java +++ b/src/main/java/com/gregtechceu/gtceu/common/block/CableBlock.java @@ -11,7 +11,8 @@ import com.gregtechceu.gtceu.api.data.tag.TagPrefix; import com.gregtechceu.gtceu.api.item.tool.GTToolType; import com.gregtechceu.gtceu.api.pipenet.IPipeNode; -import com.gregtechceu.gtceu.client.model.PipeModel; +import com.gregtechceu.gtceu.api.registry.registrate.provider.GTBlockstateProvider; +import com.gregtechceu.gtceu.client.model.pipe.PipeModel; import com.gregtechceu.gtceu.common.blockentity.CableBlockEntity; import com.gregtechceu.gtceu.common.data.GTBlockEntities; import com.gregtechceu.gtceu.common.data.GTDamageTypes; @@ -54,7 +55,7 @@ public CableBlock(Properties properties, Insulation insulation, Material materia @Override public int tinted(BlockState state, @Nullable BlockAndTintGetter level, @Nullable BlockPos pos, int index) { - if (pipeType.isCable && index == 0) { + if (pipeType.isCable && (index == 0 || index == 2)) { return 0x404040; } return super.tinted(state, level, pos, index); @@ -94,8 +95,8 @@ public boolean canPipeConnectToBlock(IPipeNode selfT } @Override - protected PipeModel createPipeModel() { - return pipeType.createPipeModel(material); + public PipeModel createPipeModel(GTBlockstateProvider provider) { + return pipeType.createPipeModel(this, material, provider); } @Override diff --git a/src/main/java/com/gregtechceu/gtceu/common/block/DuctPipeBlock.java b/src/main/java/com/gregtechceu/gtceu/common/block/DuctPipeBlock.java index f08d13c97f9..69306723f59 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/block/DuctPipeBlock.java +++ b/src/main/java/com/gregtechceu/gtceu/common/block/DuctPipeBlock.java @@ -1,5 +1,6 @@ package com.gregtechceu.gtceu.common.block; +import com.gregtechceu.gtceu.GTCEu; import com.gregtechceu.gtceu.api.block.PipeBlock; import com.gregtechceu.gtceu.api.blockentity.MetaMachineBlockEntity; import com.gregtechceu.gtceu.api.blockentity.PipeBlockEntity; @@ -7,8 +8,8 @@ import com.gregtechceu.gtceu.api.machine.feature.IEnvironmentalHazardCleaner; import com.gregtechceu.gtceu.api.machine.feature.IEnvironmentalHazardEmitter; import com.gregtechceu.gtceu.api.pipenet.IPipeNode; -import com.gregtechceu.gtceu.client.model.PipeModel; -import com.gregtechceu.gtceu.client.renderer.block.PipeBlockRenderer; +import com.gregtechceu.gtceu.api.registry.registrate.provider.GTBlockstateProvider; +import com.gregtechceu.gtceu.client.model.pipe.PipeModel; import com.gregtechceu.gtceu.common.blockentity.DuctPipeBlockEntity; import com.gregtechceu.gtceu.common.data.GTBlockEntities; import com.gregtechceu.gtceu.common.pipelike.duct.DuctPipeProperties; @@ -36,15 +37,11 @@ @MethodsReturnNonnullByDefault public class DuctPipeBlock extends PipeBlock { - public final PipeBlockRenderer renderer; - public final PipeModel model; private final DuctPipeProperties properties; public DuctPipeBlock(Properties properties, DuctPipeType type) { super(properties, type); this.properties = new DuctPipeProperties(type.getRateMultiplier()); - this.model = type.createPipeModel(); - this.renderer = new PipeBlockRenderer(this.model); } @Override @@ -75,13 +72,9 @@ public DuctPipeProperties getFallbackType() { } @Override - public @Nullable PipeBlockRenderer getRenderer(BlockState state) { - return renderer; - } - - @Override - protected PipeModel getPipeModel() { - return model; + public PipeModel createPipeModel(GTBlockstateProvider provider) { + return new PipeModel(this, provider, this.pipeType.getThickness(), + GTCEu.id("block/pipe/pipe_duct_side"), GTCEu.id("block/pipe/pipe_duct_in")); } @Override diff --git a/src/main/java/com/gregtechceu/gtceu/common/block/FluidPipeBlock.java b/src/main/java/com/gregtechceu/gtceu/common/block/FluidPipeBlock.java index 3b0173a574b..1af49f770c2 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/block/FluidPipeBlock.java +++ b/src/main/java/com/gregtechceu/gtceu/common/block/FluidPipeBlock.java @@ -8,7 +8,8 @@ import com.gregtechceu.gtceu.api.data.chemical.material.properties.PropertyKey; import com.gregtechceu.gtceu.api.data.tag.TagPrefix; import com.gregtechceu.gtceu.api.pipenet.IPipeNode; -import com.gregtechceu.gtceu.client.model.PipeModel; +import com.gregtechceu.gtceu.api.registry.registrate.provider.GTBlockstateProvider; +import com.gregtechceu.gtceu.client.model.pipe.PipeModel; import com.gregtechceu.gtceu.common.blockentity.FluidPipeBlockEntity; import com.gregtechceu.gtceu.common.data.GTBlockEntities; import com.gregtechceu.gtceu.common.data.GTMaterialBlocks; @@ -82,8 +83,8 @@ public boolean canPipeConnectToBlock(IPipeNode renderers = new IdentityHashMap<>(); public LampBlock(Properties properties, DyeColor color, boolean bordered) { super(properties); @@ -65,9 +60,6 @@ public LampBlock(Properties properties, DyeColor color, boolean bordered) { .setValue(LIGHT, true) .setValue(INVERTED, false) .setValue(POWERED, false)); - for (BlockState state : getStateDefinition().getPossibleStates()) { - renderers.put(state, new LampRenderer(this, state)); - } } public static boolean isLightActive(BlockState state) { @@ -126,6 +118,12 @@ public int getLightEmission(BlockState state, BlockGetter level, BlockPos pos) { return state.getValue(LIGHT) && isLightActive(state) ? 15 : 0; } + @Override + public BlockState getAppearance(BlockState state, BlockAndTintGetter level, BlockPos pos, Direction side, + @Nullable BlockState queryState, @Nullable BlockPos queryPos) { + return state.getBlock().defaultBlockState(); + } + @Override @SuppressWarnings("deprecation") public void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean movedByPiston) { @@ -192,10 +190,4 @@ public List getDrops(BlockState state, LootParams.Builder params) { } return returnValue; } - - @Nullable - @Override - public IRenderer getRenderer(BlockState state) { - return renderers.get(state); - } } diff --git a/src/main/java/com/gregtechceu/gtceu/common/block/LaserPipeBlock.java b/src/main/java/com/gregtechceu/gtceu/common/block/LaserPipeBlock.java index 4b99ed7cdeb..311338b6a1f 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/block/LaserPipeBlock.java +++ b/src/main/java/com/gregtechceu/gtceu/common/block/LaserPipeBlock.java @@ -2,12 +2,14 @@ import com.gregtechceu.gtceu.GTCEu; import com.gregtechceu.gtceu.api.block.PipeBlock; +import com.gregtechceu.gtceu.api.block.property.GTBlockStateProperties; import com.gregtechceu.gtceu.api.blockentity.PipeBlockEntity; import com.gregtechceu.gtceu.api.capability.forge.GTCapability; import com.gregtechceu.gtceu.api.item.tool.GTToolType; import com.gregtechceu.gtceu.api.pipenet.IPipeNode; -import com.gregtechceu.gtceu.client.model.PipeModel; -import com.gregtechceu.gtceu.client.renderer.block.PipeBlockRenderer; +import com.gregtechceu.gtceu.api.registry.registrate.provider.GTBlockstateProvider; +import com.gregtechceu.gtceu.client.model.pipe.ActivablePipeModel; +import com.gregtechceu.gtceu.client.model.pipe.PipeModel; import com.gregtechceu.gtceu.common.blockentity.LaserPipeBlockEntity; import com.gregtechceu.gtceu.common.data.GTBlockEntities; import com.gregtechceu.gtceu.common.pipelike.laser.LaserPipeProperties; @@ -19,9 +21,11 @@ import net.minecraft.core.Direction; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; @@ -33,23 +37,20 @@ @MethodsReturnNonnullByDefault public class LaserPipeBlock extends PipeBlock { - public final PipeBlockRenderer renderer; - public final PipeModel model; private final LaserPipeProperties properties; public LaserPipeBlock(Properties properties, LaserPipeType type) { super(properties, type); this.properties = LaserPipeProperties.INSTANCE; - this.model = new PipeModel(LaserPipeType.NORMAL.getThickness(), () -> GTCEu.id("block/pipe/pipe_laser_side"), - () -> GTCEu.id("block/pipe/pipe_laser_in"), null, null); - this.renderer = new PipeBlockRenderer(this.model); + + registerDefaultState(defaultBlockState().setValue(GTBlockStateProperties.ACTIVE, false)); } @OnlyIn(Dist.CLIENT) public static BlockColor tintedColor() { - return (blockState, level, blockPos, index) -> { - if (blockPos != null && level != null && - level.getBlockEntity(blockPos) instanceof PipeBlockEntity pipe) { + return (state, level, pos, index) -> { + if (pos != null && level != null && + level.getBlockEntity(pos) instanceof PipeBlockEntity pipe) { if (!pipe.getFrameMaterial().isNull()) { if (index == 3) { return pipe.getFrameMaterial().getMaterialRGB(); @@ -65,6 +66,12 @@ public static BlockColor tintedColor() { }; } + @Override + protected void createBlockStateDefinition(StateDefinition.Builder builder) { + super.createBlockStateDefinition(builder); + builder.add(GTBlockStateProperties.ACTIVE); + } + @Override public LevelLaserPipeNet getWorldPipeNet(ServerLevel world) { return LevelLaserPipeNet.getOrCreate(world); @@ -93,12 +100,12 @@ public LaserPipeProperties getFallbackType() { } @Override - public @Nullable PipeBlockRenderer getRenderer(BlockState state) { - return renderer; - } - - @Override - protected PipeModel getPipeModel() { + public PipeModel createPipeModel(GTBlockstateProvider provider) { + ActivablePipeModel model = new ActivablePipeModel(this, LaserPipeType.NORMAL.getThickness(), + GTCEu.id("block/pipe/pipe_laser_side"), GTCEu.id("block/pipe/pipe_laser_in"), + provider); + model.setSideOverlay(GTCEu.id("block/pipe/pipe_laser_side_overlay")); + model.setSideOverlayActive(GTCEu.id("block/pipe/pipe_laser_side_overlay_emissive")); return model; } diff --git a/src/main/java/com/gregtechceu/gtceu/common/block/OpticalPipeBlock.java b/src/main/java/com/gregtechceu/gtceu/common/block/OpticalPipeBlock.java index 07d7e22be23..c710e296547 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/block/OpticalPipeBlock.java +++ b/src/main/java/com/gregtechceu/gtceu/common/block/OpticalPipeBlock.java @@ -2,12 +2,14 @@ import com.gregtechceu.gtceu.GTCEu; import com.gregtechceu.gtceu.api.block.PipeBlock; +import com.gregtechceu.gtceu.api.block.property.GTBlockStateProperties; import com.gregtechceu.gtceu.api.blockentity.PipeBlockEntity; import com.gregtechceu.gtceu.api.capability.forge.GTCapability; import com.gregtechceu.gtceu.api.item.tool.GTToolType; import com.gregtechceu.gtceu.api.pipenet.IPipeNode; -import com.gregtechceu.gtceu.client.model.PipeModel; -import com.gregtechceu.gtceu.client.renderer.block.PipeBlockRenderer; +import com.gregtechceu.gtceu.api.registry.registrate.provider.GTBlockstateProvider; +import com.gregtechceu.gtceu.client.model.pipe.ActivablePipeModel; +import com.gregtechceu.gtceu.client.model.pipe.PipeModel; import com.gregtechceu.gtceu.common.blockentity.OpticalPipeBlockEntity; import com.gregtechceu.gtceu.common.data.GTBlockEntities; import com.gregtechceu.gtceu.common.pipelike.optical.LevelOpticalPipeNet; @@ -18,14 +20,15 @@ import net.minecraft.core.Direction; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockBehaviour; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; -import lombok.Getter; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -34,20 +37,29 @@ @ParametersAreNonnullByDefault public class OpticalPipeBlock extends PipeBlock { - public final PipeBlockRenderer renderer; - @Getter - public final PipeModel pipeModel; - - private final OpticalPipeType pipeType; private final OpticalPipeProperties properties; - public OpticalPipeBlock(BlockBehaviour.Properties properties, @NotNull OpticalPipeType pipeType) { + public OpticalPipeBlock(BlockBehaviour.Properties properties, OpticalPipeType pipeType) { super(properties, pipeType); - this.pipeType = pipeType; this.properties = OpticalPipeProperties.INSTANCE; - this.pipeModel = new PipeModel(pipeType.getThickness(), () -> GTCEu.id("block/pipe/pipe_optical_side"), - () -> GTCEu.id("block/pipe/pipe_optical_in"), null, null); - this.renderer = new PipeBlockRenderer(this.pipeModel); + + registerDefaultState(defaultBlockState().setValue(GTBlockStateProperties.ACTIVE, false)); + } + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder builder) { + super.createBlockStateDefinition(builder); + builder.add(GTBlockStateProperties.ACTIVE); + } + + @Override + public @NotNull PipeModel createPipeModel(GTBlockstateProvider provider) { + ActivablePipeModel pipeModel = new ActivablePipeModel(this, pipeType.getThickness(), + GTCEu.id("block/pipe/pipe_optical_side"), GTCEu.id("block/pipe/pipe_optical_in"), + provider); + pipeModel.setSideOverlay(GTCEu.id("block/pipe/pipe_optical_side_overlay")); + pipeModel.setSideOverlayActive(GTCEu.id("block/pipe/pipe_optical_side_overlay_active")); + return pipeModel; } @Override @@ -77,11 +89,6 @@ public OpticalPipeProperties getFallbackType() { return OpticalPipeProperties.INSTANCE; } - @Override - public @Nullable PipeBlockRenderer getRenderer(BlockState state) { - return renderer; - } - @OnlyIn(Dist.CLIENT) public static BlockColor tintedColor() { return (blockState, level, blockPos, index) -> { diff --git a/src/main/java/com/gregtechceu/gtceu/common/blockentity/CableBlockEntity.java b/src/main/java/com/gregtechceu/gtceu/common/blockentity/CableBlockEntity.java index bdad968b985..9845dd66447 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/blockentity/CableBlockEntity.java +++ b/src/main/java/com/gregtechceu/gtceu/common/blockentity/CableBlockEntity.java @@ -74,10 +74,6 @@ public CableBlockEntity(BlockEntityType type, BlockPos pos, BlockState blockS super(type, pos, blockState); } - public static CableBlockEntity create(BlockEntityType type, BlockPos pos, BlockState blockState) { - return new CableBlockEntity(type, pos, blockState); - } - @Override public @NotNull LazyOptional getCapability(@NotNull Capability cap, @Nullable Direction side) { if (cap == GTCapability.CAPABILITY_ENERGY_CONTAINER) { diff --git a/src/main/java/com/gregtechceu/gtceu/common/blockentity/DuctPipeBlockEntity.java b/src/main/java/com/gregtechceu/gtceu/common/blockentity/DuctPipeBlockEntity.java index d2e27a69840..075cc58e284 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/blockentity/DuctPipeBlockEntity.java +++ b/src/main/java/com/gregtechceu/gtceu/common/blockentity/DuctPipeBlockEntity.java @@ -36,14 +36,10 @@ public class DuctPipeBlockEntity extends PipeBlockEntity type, BlockPos pos, BlockState blockState) { + public DuctPipeBlockEntity(BlockEntityType type, BlockPos pos, BlockState blockState) { super(type, pos, blockState); } - public static DuctPipeBlockEntity create(BlockEntityType type, BlockPos pos, BlockState blockState) { - return new DuctPipeBlockEntity(type, pos, blockState); - } - public static void onBlockEntityRegister(BlockEntityType ductBlockEntityBlockEntityType) {} @Override diff --git a/src/main/java/com/gregtechceu/gtceu/common/blockentity/ItemPipeBlockEntity.java b/src/main/java/com/gregtechceu/gtceu/common/blockentity/ItemPipeBlockEntity.java index 5fa341fd83e..f222c06da11 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/blockentity/ItemPipeBlockEntity.java +++ b/src/main/java/com/gregtechceu/gtceu/common/blockentity/ItemPipeBlockEntity.java @@ -50,10 +50,6 @@ public ItemPipeBlockEntity(BlockEntityType type, BlockPos pos, BlockState blo super(type, pos, blockState); } - public static ItemPipeBlockEntity create(BlockEntityType type, BlockPos pos, BlockState blockState) { - return new ItemPipeBlockEntity(type, pos, blockState); - } - public long getLevelTime() { return hasLevel() ? Objects.requireNonNull(getLevel()).getGameTime() : 0L; } diff --git a/src/main/java/com/gregtechceu/gtceu/common/blockentity/LaserPipeBlockEntity.java b/src/main/java/com/gregtechceu/gtceu/common/blockentity/LaserPipeBlockEntity.java index e16ffb9b549..3d8784ca767 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/blockentity/LaserPipeBlockEntity.java +++ b/src/main/java/com/gregtechceu/gtceu/common/blockentity/LaserPipeBlockEntity.java @@ -1,5 +1,6 @@ package com.gregtechceu.gtceu.common.blockentity; +import com.gregtechceu.gtceu.api.block.property.GTBlockStateProperties; import com.gregtechceu.gtceu.api.blockentity.PipeBlockEntity; import com.gregtechceu.gtceu.api.capability.GTCapabilityHelper; import com.gregtechceu.gtceu.api.capability.ILaserContainer; @@ -10,13 +11,11 @@ import com.gregtechceu.gtceu.utils.GTUtil; import com.gregtechceu.gtceu.utils.TaskHandler; -import com.lowdragmc.lowdraglib.syncdata.annotation.DescSynced; -import com.lowdragmc.lowdraglib.syncdata.annotation.Persisted; -import com.lowdragmc.lowdraglib.syncdata.field.ManagedFieldHolder; - import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; @@ -32,9 +31,6 @@ public class LaserPipeBlockEntity extends PipeBlockEntity { - public static final ManagedFieldHolder MANAGED_FIELD_HOLDER = new ManagedFieldHolder(LaserPipeBlockEntity.class, - PipeBlockEntity.MANAGED_FIELD_HOLDER); - @Getter protected final EnumMap handlers = new EnumMap<>(Direction.class); // the LaserNetHandler can only be created on the server, so we have an empty placeholder for the client @@ -43,21 +39,10 @@ public class LaserPipeBlockEntity extends PipeBlockEntity type, BlockPos pos, BlockState blockState) { + public LaserPipeBlockEntity(BlockEntityType type, BlockPos pos, BlockState blockState) { super(type, pos, blockState); } - public static LaserPipeBlockEntity create(BlockEntityType type, BlockPos pos, BlockState blockState) { - return new LaserPipeBlockEntity(type, pos, blockState); - } - public static void onBlockEntityRegister(BlockEntityType cableBlockEntityBlockEntityType) {} @Override @@ -127,28 +112,11 @@ public LaserPipeNet getLaserPipeNet() { * @param duration how long the pipe should be active for */ public void setActive(boolean active, int duration) { - if (this.active != active) { - this.active = active; - notifyBlockUpdate(); - setChanged(); - if (active && duration != this.activeDuration) { - TaskHandler.enqueueServerTask((ServerLevel) getLevel(), this::queueDisconnect, 0); - } - } - - this.activeDuration = duration; - if (duration > 0 && active) { - this.ticksActive = 0; - } + setPipeActive(this, this.getBlockState(), active, duration); } - public boolean queueDisconnect() { - if (++this.ticksActive % activeDuration == 0) { - this.ticksActive = 0; - setActive(false, -1); - return false; - } - return true; + public boolean isActive() { + return this.getBlockState().getValue(GTBlockStateProperties.ACTIVE); } @Override @@ -189,9 +157,26 @@ public GTToolType getPipeTuneTool() { return GTToolType.WIRE_CUTTER; } - @Override - public ManagedFieldHolder getFieldHolder() { - return MANAGED_FIELD_HOLDER; + public static BlockState setPipeActive(PipeBlockEntity blockEntity, + BlockState state, boolean newActive, int duration) { + if (!state.hasProperty(GTBlockStateProperties.ACTIVE) || + state.getValue(GTBlockStateProperties.ACTIVE) == newActive) { + return state; + } + BlockState newState = state.setValue(GTBlockStateProperties.ACTIVE, newActive); + if (blockEntity == null || blockEntity.getLevel() == null || blockEntity.isRemoved()) { + return newState; + } + Level level = blockEntity.getLevel(); + + level.setBlock(blockEntity.getBlockPos(), newState, Block.UPDATE_CLIENTS | Block.UPDATE_KNOWN_SHAPE); + blockEntity.notifyBlockUpdate(); + blockEntity.setChanged(); + + if (newActive && level instanceof ServerLevel serverLevel) { + TaskHandler.enqueueServerTask(serverLevel, () -> setPipeActive(blockEntity, newState, false, -1), duration); + } + return newState; } private static class DefaultLaserContainer implements ILaserContainer { diff --git a/src/main/java/com/gregtechceu/gtceu/common/blockentity/OpticalPipeBlockEntity.java b/src/main/java/com/gregtechceu/gtceu/common/blockentity/OpticalPipeBlockEntity.java index 684ed5d3c93..edd25dcc1fa 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/blockentity/OpticalPipeBlockEntity.java +++ b/src/main/java/com/gregtechceu/gtceu/common/blockentity/OpticalPipeBlockEntity.java @@ -1,5 +1,6 @@ package com.gregtechceu.gtceu.common.blockentity; +import com.gregtechceu.gtceu.api.block.property.GTBlockStateProperties; import com.gregtechceu.gtceu.api.blockentity.PipeBlockEntity; import com.gregtechceu.gtceu.api.capability.IDataAccessHatch; import com.gregtechceu.gtceu.api.capability.IOpticalComputationProvider; @@ -9,12 +10,6 @@ import com.gregtechceu.gtceu.api.recipe.GTRecipe; import com.gregtechceu.gtceu.common.pipelike.optical.*; import com.gregtechceu.gtceu.utils.GTUtil; -import com.gregtechceu.gtceu.utils.TaskHandler; - -import com.lowdragmc.lowdraglib.syncdata.annotation.DescSynced; -import com.lowdragmc.lowdraglib.syncdata.annotation.Persisted; -import com.lowdragmc.lowdraglib.syncdata.annotation.RequireRerender; -import com.lowdragmc.lowdraglib.syncdata.field.ManagedFieldHolder; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -25,7 +20,6 @@ import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.util.LazyOptional; -import lombok.Getter; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -35,9 +29,6 @@ public class OpticalPipeBlockEntity extends PipeBlockEntity { - public static final ManagedFieldHolder MANAGED_FIELD_HOLDER = new ManagedFieldHolder(OpticalPipeBlockEntity.class, - PipeBlockEntity.MANAGED_FIELD_HOLDER); - private final EnumMap handlers = new EnumMap<>(Direction.class); // the OpticalNetHandler can only be created on the server, so we have an empty placeholder for the client private final IDataAccessHatch clientDataHandler = new DefaultDataHandler(); @@ -45,12 +36,6 @@ public class OpticalPipeBlockEntity extends PipeBlockEntity currentPipeNet = new WeakReference<>(null); private OpticalNetHandler defaultHandler; - @Getter - @Persisted - @DescSynced - @RequireRerender - private boolean isActive; - public OpticalPipeBlockEntity(BlockEntityType type, BlockPos pos, BlockState blockState) { super(type, pos, blockState); } @@ -157,20 +142,11 @@ public void setConnection(Direction side, boolean connected, boolean fromNeighbo * @param duration how long the pipe should be active for */ public void setActive(boolean active, int duration) { - boolean stateChanged = false; - if (this.isActive && !active) { - this.isActive = false; - stateChanged = true; - } else if (!this.isActive && active) { - this.isActive = true; - stateChanged = true; - TaskHandler.enqueueServerTask((ServerLevel) getLevel(), () -> setActive(false, -1), duration); - } + LaserPipeBlockEntity.setPipeActive(this, this.getBlockState(), active, duration); + } - if (stateChanged) { - notifyBlockUpdate(); - setChanged(); - } + public boolean isActive() { + return this.getBlockState().getValue(GTBlockStateProperties.ACTIVE); } @Override @@ -184,11 +160,6 @@ public GTToolType getPipeTuneTool() { return GTToolType.WIRE_CUTTER; } - @Override - public ManagedFieldHolder getFieldHolder() { - return MANAGED_FIELD_HOLDER; - } - private static class DefaultDataHandler implements IDataAccessHatch { @Override diff --git a/src/main/java/com/gregtechceu/gtceu/common/commands/GTCommands.java b/src/main/java/com/gregtechceu/gtceu/common/commands/GTCommands.java index 14e31f25adb..3b9463eb764 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/commands/GTCommands.java +++ b/src/main/java/com/gregtechceu/gtceu/common/commands/GTCommands.java @@ -293,7 +293,7 @@ private static int setActiveCape(CommandSourceStack source, ServerPlayer player, private static int dumpDataRegistry(CommandContext context, GTRegistry registry, Codec codec, String folder) { - Path parent = GTCEu.getGameDir().resolve("gtceu/dumped/data"); + Path parent = GTCEu.GTCEU_FOLDER.resolve("dumped/data"); var ops = RegistryOps.create(JsonOps.INSTANCE, context.getSource().registryAccess()); int dumpedCount = 0; for (ResourceLocation id : registry.keys()) { diff --git a/src/main/java/com/gregtechceu/gtceu/common/data/GTBlockEntities.java b/src/main/java/com/gregtechceu/gtceu/common/data/GTBlockEntities.java index 4355206d72f..c4330ecb17b 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/data/GTBlockEntities.java +++ b/src/main/java/com/gregtechceu/gtceu/common/data/GTBlockEntities.java @@ -13,7 +13,7 @@ public class GTBlockEntities { @SuppressWarnings("unchecked") public static final BlockEntityEntry CABLE = REGISTRATE - .blockEntity("cable", CableBlockEntity::create) + .blockEntity("cable", CableBlockEntity::new) .onRegister(CableBlockEntity::onBlockEntityRegister) .validBlocks(GTMaterialBlocks.CABLE_BLOCKS.values().toArray(BlockEntry[]::new)) .register(); @@ -27,13 +27,13 @@ public class GTBlockEntities { @SuppressWarnings("unchecked") public static final BlockEntityEntry ITEM_PIPE = REGISTRATE - .blockEntity("item_pipe", ItemPipeBlockEntity::create) + .blockEntity("item_pipe", ItemPipeBlockEntity::new) .onRegister(ItemPipeBlockEntity::onBlockEntityRegister) .validBlocks(GTMaterialBlocks.ITEM_PIPE_BLOCKS.values().toArray(BlockEntry[]::new)) .register(); public static final BlockEntityEntry LASER_PIPE = REGISTRATE - .blockEntity("laser_pipe", LaserPipeBlockEntity::create) + .blockEntity("laser_pipe", LaserPipeBlockEntity::new) .onRegister(LaserPipeBlockEntity::onBlockEntityRegister) .validBlocks(GTBlocks.LASER_PIPES) .register(); @@ -44,7 +44,7 @@ public class GTBlockEntities { .register(); public static final BlockEntityEntry DUCT_PIPE = REGISTRATE - .blockEntity("duct_pipe", DuctPipeBlockEntity::create) + .blockEntity("duct_pipe", DuctPipeBlockEntity::new) .onRegister(DuctPipeBlockEntity::onBlockEntityRegister) .validBlocks(GTBlocks.DUCT_PIPES) .register(); diff --git a/src/main/java/com/gregtechceu/gtceu/common/data/GTBlocks.java b/src/main/java/com/gregtechceu/gtceu/common/data/GTBlocks.java index a91932797f8..241aa9101ff 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/data/GTBlocks.java +++ b/src/main/java/com/gregtechceu/gtceu/common/data/GTBlocks.java @@ -115,7 +115,7 @@ private static void registerLaserPipeBlock(int index) { .block("%s_laser_pipe".formatted(type.getSerializedName()), (p) -> new LaserPipeBlock(p, type)) .initialProperties(() -> Blocks.IRON_BLOCK) .properties(p -> p.dynamicShape().noOcclusion().forceSolidOn()) - .blockstate(NonNullBiConsumer.noop()) + .gtBlockstate(GTModels::createPipeBlockModel) .defaultLoot() .tag(CustomTags.MINEABLE_WITH_CONFIG_VALID_PICKAXE_WIRE_CUTTER) .addLayer(() -> RenderType::cutoutMipped) @@ -145,13 +145,13 @@ private static void registerOpticalPipeBlock(int index) { .lang("Optical Fiber Cable") .initialProperties(() -> Blocks.IRON_BLOCK) .properties(p -> p.dynamicShape().noOcclusion().forceSolidOn()) - .blockstate(NonNullBiConsumer.noop()) + .gtBlockstate(GTModels::createPipeBlockModel) .defaultLoot() .tag(CustomTags.MINEABLE_WITH_CONFIG_VALID_PICKAXE_WIRE_CUTTER) .addLayer(() -> RenderType::cutoutMipped) .addLayer(() -> RenderType::translucent) .color(() -> OpticalPipeBlock::tintedColor) - .item(OpticalPipeBlockItem::new) + .item(PipeBlockItem::new) .model(NonNullBiConsumer.noop()) .build() .register(); @@ -173,12 +173,12 @@ private static void registerDuctPipeBlock(int index) { .block("%s_duct_pipe".formatted(type.getSerializedName()), (p) -> new DuctPipeBlock(p, type)) .initialProperties(() -> Blocks.IRON_BLOCK) .properties(p -> p.dynamicShape().noOcclusion().forceSolidOn()) - .blockstate(NonNullBiConsumer.noop()) + .gtBlockstate(GTModels::createPipeBlockModel) .defaultLoot() .tag(CustomTags.MINEABLE_WITH_CONFIG_VALID_PICKAXE_WRENCH) .addLayer(() -> RenderType::cutoutMipped) .addLayer(() -> RenderType::translucent) - .item(DuctPipeBlockItem::new) + .item(PipeBlockItem::new) .model(NonNullBiConsumer.noop()) .build() .register(); diff --git a/src/main/java/com/gregtechceu/gtceu/common/data/models/GTModels.java b/src/main/java/com/gregtechceu/gtceu/common/data/models/GTModels.java index c33890e76d7..6065874b12c 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/data/models/GTModels.java +++ b/src/main/java/com/gregtechceu/gtceu/common/data/models/GTModels.java @@ -39,6 +39,8 @@ public class GTModels { public static final ResourceLocation BLANK_TEXTURE = GTCEu.id("block/void"); + public static final String ACTIVE_SUFFIX = "_active"; + // region BLOCK MODELS public static NonNullBiConsumer, GTBlockstateProvider> createModelBlockState(ResourceLocation modelLocation) { @@ -273,6 +275,12 @@ public static NonNullBiConsumer, RegistrateBl }; } + public static void createPipeBlockModel(DataGenContext> ctx, + GTBlockstateProvider prov) { + // the pipe model generator handles adding its models to the provider by itself + ctx.getEntry().createPipeModel(prov).initModels(); + } + // endregion // region RUNTIME GEN diff --git a/src/main/java/com/gregtechceu/gtceu/common/pipelike/cable/Insulation.java b/src/main/java/com/gregtechceu/gtceu/common/pipelike/cable/Insulation.java index b149d5df98c..fc543f04ff4 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/pipelike/cable/Insulation.java +++ b/src/main/java/com/gregtechceu/gtceu/common/pipelike/cable/Insulation.java @@ -1,19 +1,19 @@ package com.gregtechceu.gtceu.common.pipelike.cable; import com.gregtechceu.gtceu.GTCEu; +import com.gregtechceu.gtceu.api.block.PipeBlock; import com.gregtechceu.gtceu.api.data.chemical.material.Material; import com.gregtechceu.gtceu.api.data.chemical.material.info.MaterialIconType; import com.gregtechceu.gtceu.api.data.chemical.material.properties.WireProperties; import com.gregtechceu.gtceu.api.data.tag.TagPrefix; import com.gregtechceu.gtceu.api.pipenet.IMaterialPipeType; -import com.gregtechceu.gtceu.client.model.PipeModel; +import com.gregtechceu.gtceu.api.registry.registrate.provider.GTBlockstateProvider; +import com.gregtechceu.gtceu.client.model.pipe.PipeModel; +import com.gregtechceu.gtceu.common.data.models.GTModels; import net.minecraft.resources.ResourceLocation; import lombok.Getter; -import org.jetbrains.annotations.Nullable; - -import java.util.function.Supplier; import static com.gregtechceu.gtceu.api.data.tag.TagPrefix.*; @@ -83,20 +83,28 @@ public ResourceLocation type() { return TYPE_ID; } - public PipeModel createPipeModel(Material material) { - Supplier wireSideTexturePath = () -> MaterialIconType.wire + public PipeModel createPipeModel(PipeBlock block, Material material, GTBlockstateProvider provider) { + ResourceLocation side = MaterialIconType.wire .getBlockTexturePath(material.getMaterialIconSet(), "side", true); - Supplier wireEndTexturePath = () -> MaterialIconType.wire + ResourceLocation end = MaterialIconType.wire .getBlockTexturePath(material.getMaterialIconSet(), "end", true); - Supplier<@Nullable ResourceLocation> wireSideOverlayTexturePath = () -> MaterialIconType.wire + + PipeModel model = new PipeModel(block, provider, thickness, + isCable ? GTCEu.id("block/cable/insulation_5") : side, end); + + ResourceLocation sideSecondary = MaterialIconType.wire .getBlockTexturePath(material.getMaterialIconSet(), "side_overlay", true); - Supplier<@Nullable ResourceLocation> wireEndOverlayTexturePath = () -> MaterialIconType.wire + ResourceLocation endSecondary = MaterialIconType.wire .getBlockTexturePath(material.getMaterialIconSet(), "end_overlay", true); - PipeModel model = new PipeModel(thickness, - isCable ? () -> GTCEu.id("block/cable/insulation_5") : wireSideTexturePath, wireEndTexturePath, - wireSideOverlayTexturePath, wireEndOverlayTexturePath); + + if (sideSecondary != null && !sideSecondary.equals(GTModels.BLANK_TEXTURE)) { + model.setSideSecondary(sideSecondary); + } + if (endSecondary != null && !endSecondary.equals(GTModels.BLANK_TEXTURE)) { + model.setEndSecondary(endSecondary); + } if (isCable) { - model.setEndOverlayTexture(GTCEu.id("block/cable/insulation_%s".formatted(insulationLevel))); + model.setEndOverlay(GTCEu.id("block/cable/insulation_%s".formatted(insulationLevel))); } return model; } diff --git a/src/main/java/com/gregtechceu/gtceu/common/pipelike/duct/DuctPipeType.java b/src/main/java/com/gregtechceu/gtceu/common/pipelike/duct/DuctPipeType.java index 1323fa297f1..feebae0b7ca 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/pipelike/duct/DuctPipeType.java +++ b/src/main/java/com/gregtechceu/gtceu/common/pipelike/duct/DuctPipeType.java @@ -2,7 +2,6 @@ import com.gregtechceu.gtceu.GTCEu; import com.gregtechceu.gtceu.api.pipenet.IPipeType; -import com.gregtechceu.gtceu.client.model.PipeModel; import net.minecraft.resources.ResourceLocation; import net.minecraft.util.StringRepresentable; @@ -54,10 +53,4 @@ public ResourceLocation type() { public String getSerializedName() { return name().toLowerCase(Locale.ROOT); } - - public PipeModel createPipeModel() { - return new PipeModel(thickness, () -> GTCEu.id("block/pipe/pipe_duct_side"), - () -> GTCEu.id("block/pipe/pipe_duct_in"), - null, null); - } } diff --git a/src/main/java/com/gregtechceu/gtceu/common/pipelike/fluidpipe/FluidPipeType.java b/src/main/java/com/gregtechceu/gtceu/common/pipelike/fluidpipe/FluidPipeType.java index 8ad5940e500..f068dd69236 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/pipelike/fluidpipe/FluidPipeType.java +++ b/src/main/java/com/gregtechceu/gtceu/common/pipelike/fluidpipe/FluidPipeType.java @@ -1,12 +1,14 @@ package com.gregtechceu.gtceu.common.pipelike.fluidpipe; import com.gregtechceu.gtceu.GTCEu; +import com.gregtechceu.gtceu.api.block.PipeBlock; import com.gregtechceu.gtceu.api.data.chemical.material.Material; import com.gregtechceu.gtceu.api.data.chemical.material.properties.FluidPipeProperties; import com.gregtechceu.gtceu.api.data.chemical.material.properties.PropertyKey; import com.gregtechceu.gtceu.api.data.tag.TagPrefix; import com.gregtechceu.gtceu.api.pipenet.IMaterialPipeType; -import com.gregtechceu.gtceu.client.model.PipeModel; +import com.gregtechceu.gtceu.api.registry.registrate.provider.GTBlockstateProvider; +import com.gregtechceu.gtceu.client.model.pipe.PipeModel; import net.minecraft.resources.ResourceLocation; @@ -72,26 +74,20 @@ public ResourceLocation type() { return TYPE_ID; } - public PipeModel createPipeModel(Material material) { + public PipeModel createPipeModel(PipeBlock block, Material material, GTBlockstateProvider provider) { + String side = "block/pipe/pipe%s_side"; + String end = "block/pipe/pipe_%s_in".formatted(name); if (material.hasProperty(PropertyKey.WOOD)) { - return new PipeModel(thickness, () -> GTCEu.id("block/pipe/pipe_side_wood"), - () -> GTCEu.id("block/pipe/pipe_%s_in_wood".formatted(name)), null, null); + side += "_wood"; + end += "_wood"; } if (channels == 9) { - return new PipeModel(thickness, () -> GTCEu.id("block/pipe/pipe_non_side"), - () -> GTCEu.id("block/pipe/pipe_%s_in".formatted(name)), - null, null); + side = side.formatted("_non"); } else if (channels == 4) { - return new PipeModel(thickness, () -> GTCEu.id("block/pipe/pipe_quad_side"), - () -> GTCEu.id("block/pipe/pipe_%s_in".formatted(name)), - null, null); + side = side.formatted("_quad"); + } else { + side = side.formatted(""); } - return new PipeModel(thickness, () -> GTCEu.id("block/pipe/pipe_side"), - () -> GTCEu.id("block/pipe/pipe_%s_in".formatted(name)), - null, null/* - * () -> GTCEu.id("block/pipe/pipe_side_secondary"), () -> - * GTCEu.id("block/pipe/pipe_%s_in_secondary".formatted(name)) TODO enable once the textures - * are added - */); + return new PipeModel(block, provider, thickness, GTCEu.id(side), GTCEu.id(end)); } } diff --git a/src/main/java/com/gregtechceu/gtceu/common/pipelike/item/ItemPipeType.java b/src/main/java/com/gregtechceu/gtceu/common/pipelike/item/ItemPipeType.java index 68e5c37d016..8c6a4f78083 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/pipelike/item/ItemPipeType.java +++ b/src/main/java/com/gregtechceu/gtceu/common/pipelike/item/ItemPipeType.java @@ -1,12 +1,14 @@ package com.gregtechceu.gtceu.common.pipelike.item; import com.gregtechceu.gtceu.GTCEu; +import com.gregtechceu.gtceu.api.block.PipeBlock; import com.gregtechceu.gtceu.api.data.chemical.material.Material; import com.gregtechceu.gtceu.api.data.chemical.material.properties.ItemPipeProperties; import com.gregtechceu.gtceu.api.data.chemical.material.properties.PropertyKey; import com.gregtechceu.gtceu.api.data.tag.TagPrefix; import com.gregtechceu.gtceu.api.pipenet.IMaterialPipeType; -import com.gregtechceu.gtceu.client.model.PipeModel; +import com.gregtechceu.gtceu.api.registry.registrate.provider.GTBlockstateProvider; +import com.gregtechceu.gtceu.client.model.pipe.PipeModel; import net.minecraft.resources.ResourceLocation; @@ -72,25 +74,18 @@ public ResourceLocation type() { return TYPE_ID; } - public PipeModel createPipeModel(Material material) { - PipeModel model; + public PipeModel createPipeModel(PipeBlock block, Material material, GTBlockstateProvider provider) { + ResourceLocation sideTexture = GTCEu.id("block/pipe/pipe_side"); + ResourceLocation endTexture = GTCEu.id("block/pipe/pipe_%s_in" + .formatted(this.isRestrictive() ? values()[this.ordinal() - 4].name : name)); if (material.hasProperty(PropertyKey.WOOD)) { - model = new PipeModel(thickness, () -> GTCEu.id("block/pipe/pipe_side_wood"), - () -> GTCEu.id("block/pipe/pipe_%s_in_wood" - .formatted(this.isRestrictive() ? values()[this.ordinal() - 4].name : name)), - null, null); - } else { - model = new PipeModel(thickness, () -> GTCEu.id("block/pipe/pipe_side"), - () -> GTCEu.id("block/pipe/pipe_%s_in" - .formatted(this.isRestrictive() ? values()[this.ordinal() - 4].name : name)), - null, null/* - * () -> GTCEu.id("block/pipe/pipe_side_secondary"), () -> - * GTCEu.id("block/pipe/pipe_%s_in_secondary".formatted(this.isRestrictive() ? - * values()[this.ordinal() - 4].name : name)) TODO enable once the textures are added - */); + sideTexture = sideTexture.withSuffix("_wood"); + endTexture = endTexture.withSuffix("_wood"); } + + PipeModel model = new PipeModel(block, provider, thickness, sideTexture, endTexture); if (isRestrictive()) { - model.setSideOverlayTexture(GTCEu.id("block/pipe/pipe_restrictive")); + model.setSideOverlay(GTCEu.id("block/pipe/pipe_restrictive")); } return model; } diff --git a/src/main/java/com/gregtechceu/gtceu/core/mixins/client/ModelManagerMixin.java b/src/main/java/com/gregtechceu/gtceu/core/mixins/client/ModelManagerMixin.java index 24605160b28..9c8a8ec19f1 100644 --- a/src/main/java/com/gregtechceu/gtceu/core/mixins/client/ModelManagerMixin.java +++ b/src/main/java/com/gregtechceu/gtceu/core/mixins/client/ModelManagerMixin.java @@ -1,14 +1,7 @@ package com.gregtechceu.gtceu.core.mixins.client; import com.gregtechceu.gtceu.GTCEu; -import com.gregtechceu.gtceu.client.renderer.block.MaterialBlockRenderer; -import com.gregtechceu.gtceu.client.renderer.block.OreBlockRenderer; -import com.gregtechceu.gtceu.client.renderer.block.SurfaceRockRenderer; -import com.gregtechceu.gtceu.client.renderer.item.ArmorItemRenderer; -import com.gregtechceu.gtceu.client.renderer.item.TagPrefixItemRenderer; -import com.gregtechceu.gtceu.client.renderer.item.ToolItemRenderer; -import com.gregtechceu.gtceu.common.data.models.GTModels; -import com.gregtechceu.gtceu.integration.kjs.GregTechKubeJSPlugin; +import com.gregtechceu.gtceu.data.pack.event.RegisterDynamicResourcesEvent; import com.gregtechceu.gtceu.integration.modernfix.GTModernFixIntegration; import net.minecraft.client.resources.model.ModelManager; @@ -37,17 +30,8 @@ public abstract class ModelManagerMixin { long startTime = System.currentTimeMillis(); // turns out these do have to be init in here after all, as they check for asset existence. whoops. - MaterialBlockRenderer.reinitModels(); - TagPrefixItemRenderer.reinitModels(); - OreBlockRenderer.reinitModels(); - ToolItemRenderer.reinitModels(); - ArmorItemRenderer.reinitModels(); - SurfaceRockRenderer.reinitModels(); - GTModels.registerMaterialFluidModels(); - - if (GTCEu.Mods.isKubeJSLoaded()) { - GregTechKubeJSPlugin.generateMachineBlockModels(); - } + ModLoader.get().postEventWrapContainerInModOrder(new RegisterDynamicResourcesEvent()); + if (GTCEu.Mods.isModernFixLoaded()) { GTModernFixIntegration.setAsLast(); } diff --git a/src/main/java/com/gregtechceu/gtceu/data/model/builder/PipeModelBuilder.java b/src/main/java/com/gregtechceu/gtceu/data/model/builder/PipeModelBuilder.java new file mode 100644 index 00000000000..917e3996be2 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/data/model/builder/PipeModelBuilder.java @@ -0,0 +1,477 @@ +package com.gregtechceu.gtceu.data.model.builder; + +import com.gregtechceu.gtceu.GTCEu; +import com.gregtechceu.gtceu.api.blockentity.PipeBlockEntity; +import com.gregtechceu.gtceu.api.registry.registrate.provider.GTBlockstateProvider; +import com.gregtechceu.gtceu.client.model.pipe.PipeModelLoader; +import com.gregtechceu.gtceu.core.mixins.forge.ConfiguredModelBuilderAccessor; +import com.gregtechceu.gtceu.utils.GTMath; +import com.gregtechceu.gtceu.utils.GTUtil; +import com.gregtechceu.gtceu.utils.memoization.GTMemoizer; +import com.gregtechceu.gtceu.utils.memoization.function.MemoizedBiFunction; + +import net.minecraft.Util; +import net.minecraft.core.Direction; +import net.minecraft.resources.ResourceLocation; +import net.minecraftforge.client.model.generators.*; +import net.minecraftforge.client.model.generators.BlockStateProvider.ConfiguredModelList; +import net.minecraftforge.common.data.ExistingFileHelper; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; +import com.google.gson.JsonObject; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.Range; +import org.joml.Vector3f; + +import java.util.*; + +import static com.gregtechceu.gtceu.data.model.builder.MachineModelBuilder.configuredModelListToJSON; +import static com.gregtechceu.gtceu.data.model.builder.MachineModelBuilder.configuredModelToJSON; + +@Accessors(fluent = true, chain = true) +@SuppressWarnings("UnusedReturnValue") +public class PipeModelBuilder> extends CustomLoaderBuilder { + + public static > PipeModelBuilder begin(T parent, + ExistingFileHelper existingFileHelper) { + return new PipeModelBuilder<>(parent, existingFileHelper); + } + + @Accessors(fluent = false) + @Getter + private final Map parts = new IdentityHashMap<>(); + @Setter + @Range(from = 0, to = 16) + private float thickness = Float.MIN_VALUE; + @Setter + private @NotNull GTBlockstateProvider provider; + private BlockModelBuilder[] restrictors = null; + + protected PipeModelBuilder(T parent, ExistingFileHelper existingFileHelper) { + super(PipeModelLoader.ID, parent, existingFileHelper); + } + + /** + * Set the models for all pipe elements at the same time + * + * @param centerModel The model to use for the center part of the pipe + * @param connectionModels The models to use for all the connection elements + * @return {@code this} + * @see #allModels(ModelFile, ModelFile...) + * @see #allModels(ResourceLocation, ResourceLocation...) + */ + public PipeModelBuilder allModels(ConfiguredModel centerModel, ConfiguredModel... connectionModels) { + centerModels(centerModel); + connectionModels(connectionModels); + return this; + } + + /** + * Set the models for all pipe elements at the same time + * + * @param centerModel The model to use for the center part of the pipe + * @param connectionModels The models to use for all the connection elements + * @return {@code this} + * @see #allModels(ModelFile, ModelFile...) + * @see #allModels(ResourceLocation, ResourceLocation...) + */ + public PipeModelBuilder allModels(ModelFile centerModel, ModelFile... connectionModels) { + centerModels(centerModel); + connectionModels(connectionModels); + return this; + } + + /** + * Set the models for all pipe elements at the same time + * + * @param centerModel The model to use for the center part of the pipe + * @param connectionModels The models to use for all the connection elements + * @return {@code this} + * @see #allModels(ConfiguredModel, ConfiguredModel...) + * @see #allModels(ModelFile, ModelFile...) + */ + public PipeModelBuilder allModels(ResourceLocation centerModel, ResourceLocation... connectionModels) { + centerModels(centerModel); + connectionModels(connectionModels); + return this; + } + + /** + * Set the models for all connection elements + * + * @param connectionModels The models to use for all the connection elements + * @return {@code this} + * @see #connectionModels(ModelFile...) + * @see #connectionModels(ResourceLocation...) + */ + public PipeModelBuilder connectionModels(ConfiguredModel... connectionModels) { + for (Direction dir : GTUtil.DIRECTIONS) { + ConfiguredModel[] rotatedModels = Arrays.stream(connectionModels) + .map(model -> ConfiguredModel.builder() + .modelFile(model.model).uvLock(model.uvLock).weight(model.weight) + .rotationX(dir == Direction.DOWN ? 90 : dir == Direction.UP ? 270 : 0) + .rotationY(dir.getAxis().isVertical() ? 0 : ((int) dir.toYRot() + 180) % 360) + .buildLast()) + .toArray(ConfiguredModel[]::new); + modelsForDirection(dir, rotatedModels); + } + return this; + } + + /** + * Set the models for all connection elements + * + * @param connectionModels The models to use for all the connection elements + * @return {@code this} + * @see #connectionModels(ConfiguredModel...) + * @see #connectionModels(ResourceLocation...) + */ + public PipeModelBuilder connectionModels(ModelFile... connectionModels) { + for (Direction dir : GTUtil.DIRECTIONS) { + ConfiguredModel[] rotatedModels = Arrays.stream(connectionModels) + .map(model -> ConfiguredModel.builder() + .modelFile(model) + .rotationX(dir == Direction.DOWN ? 0 : dir == Direction.UP ? 180 : 90) + .rotationY(dir.getAxis().isVertical() ? 0 : (int) dir.toYRot()) + .buildLast()) + .toArray(ConfiguredModel[]::new); + modelsForDirection(dir, rotatedModels); + } + return this; + } + + /** + * Set the models for all connection elements + * + * @param connectionModels The models to use for all the connection elements + * @return {@code this} + * @see #connectionModels(ConfiguredModel...) + * @see #connectionModels(ModelFile...) + */ + public PipeModelBuilder connectionModels(ResourceLocation... connectionModels) { + return connectionModels(Arrays.stream(connectionModels) + .map(loc -> new ModelFile.ExistingModelFile(loc, this.existingFileHelper)) + .toArray(ModelFile[]::new)); + } + + /** + * Set the models for all connection elements with a builder + * + * @return A model builder + * @see #connectionModels(ConfiguredModel...) + * @see #connectionModels(ModelFile...) + * @see #connectionModels(ResourceLocation...) + */ + public ConfiguredModel.Builder> connectionModels() { + return ConfiguredModelBuilderAccessor.builder(this::connectionModels, ImmutableList.of()); + } + + /** + * Set the models for the center element + * + * @param centerModels The model to use for the center part of the pipe + * @return {@code this} + * @see #centerModels(ModelFile...) + * @see #centerModels(ResourceLocation...) + */ + public PipeModelBuilder centerModels(ConfiguredModel... centerModels) { + return modelsForDirection(null, centerModels); + } + + /** + * Set the models for the center element + * + * @param centerModels The model to use for the center part of the pipe + * @return {@code this} + * @see #centerModels(ConfiguredModel...) + * @see #centerModels(ResourceLocation...) + */ + public PipeModelBuilder centerModels(ModelFile... centerModels) { + return modelsForDirection(null, centerModels); + } + + /** + * Set the models for the center element + * + * @param centerModels The model to use for the center part of the pipe + * @return {@code this} + * @see #centerModels(ConfiguredModel...) + * @see #centerModels(ModelFile...) + */ + public PipeModelBuilder centerModels(ResourceLocation... centerModels) { + return modelsForDirection(null, centerModels); + } + + /** + * Set the models for the center element with a builder + * + * @return A model builder + * @see #centerModels(ConfiguredModel...) + * @see #centerModels(ModelFile...) + * @see #centerModels(ResourceLocation...) + */ + public ConfiguredModel.Builder> centerModel() { + return ConfiguredModelBuilderAccessor.builder(this::centerModels, ImmutableList.of()); + } + + /** + * Set the models for the given direction + * + * @param direction The direction that'll use the model(s) + * @param models The models to set for the direction. + * @return {@code this} + * @see #modelsForDirection(Direction, ModelFile...) + * @see #modelsForDirection(Direction, ResourceLocation...) + */ + public PipeModelBuilder modelsForDirection(@Nullable Direction direction, ConfiguredModel... models) { + parts.put(direction, new ConfiguredModelList(models)); + return this; + } + + /** + * Set the models for the given direction + * + * @param direction The direction that'll use the model(s) + * @param models The models to set for the direction. + * @return {@code this} + * @see #modelsForDirection(Direction, ConfiguredModel...) + * @see #modelsForDirection(Direction, ResourceLocation...) + */ + public PipeModelBuilder modelsForDirection(@Nullable Direction direction, ModelFile... models) { + return modelsForDirection(direction, Arrays.stream(models) + .map(model -> ConfiguredModel.builder().modelFile(model).buildLast()) + .toArray(ConfiguredModel[]::new)); + } + + /** + * Set the models for the given direction + * + * @param direction The direction that'll use the model(s) + * @param models The models to set for the direction. + * @return {@code this} + * @see #modelsForDirection(Direction, ConfiguredModel...) + * @see #modelsForDirection(Direction, ModelFile...) + */ + public PipeModelBuilder modelsForDirection(@Nullable Direction direction, ResourceLocation... models) { + return modelsForDirection(direction, Arrays.stream(models) + .map(model -> ConfiguredModel.builder() + .modelFile(new ModelFile.ExistingModelFile(model, this.existingFileHelper)) + .buildLast()) + .toArray(ConfiguredModel[]::new)); + } + + /** + * Set the models for the given direction with a builder + * + * @return A model builder + * @see #modelsForDirection(Direction, ConfiguredModel...) + * @see #modelsForDirection(Direction, ModelFile...) + * @see #modelsForDirection(Direction, ResourceLocation...) + */ + public ConfiguredModel.Builder> modelsForDirection(@Nullable Direction direction) { + return ConfiguredModelBuilderAccessor.builder(models -> this.modelsForDirection(direction, models), + ImmutableList.of()); + } + + @Override + public T end() { + this.restrictors = getOrCreateRestrictorModels(this.provider.models(), this.thickness); + return super.end(); + } + + @Override + public JsonObject toJson(JsonObject json) { + Preconditions.checkState(thickness != Float.MIN_VALUE, "A thickness value must be set!"); + Preconditions.checkState(thickness > 0.0f || thickness <= 16.0f, + "Thickness must be between 0 (exclusive) and 16 (inclusive). is %s", thickness); + // noinspection ConstantValue + Preconditions.checkState(provider != null, "You must pass in a GTBlockStateProvider!"); + + json = super.toJson(json); + + if (!getParts().isEmpty()) { + final JsonObject parts = new JsonObject(); + getParts().entrySet().stream() + .sorted(Map.Entry.comparingByKey(Comparator.nullsFirst(Direction::compareTo))) + .forEach(entry -> { + String key = entry.getKey() != null ? entry.getKey().getName() : + PipeModelLoader.PRIMARY_CENTER_KEY; + parts.add(key, configuredModelListToJSON(entry.getValue())); + }); + + json.add("parts", parts); + } + + if (this.restrictors != null) { + final JsonObject restrictors = new JsonObject(); + for (int i = 0; i < GTUtil.DIRECTIONS.length; i++) { + Direction dir = GTUtil.DIRECTIONS[i]; + restrictors.add(dir.getName(), + configuredModelToJSON(ConfiguredModel.builder() + .modelFile(new ModelFile.UncheckedModelFile(this.restrictors[i].getLocation())) + .buildLast(), false)); + } + json.add("restrictors", restrictors); + } + + return json; + } + + private static final ResourceLocation PIPE_BLOCKED_OVERLAY = GTCEu.id("block/pipe/blocked/pipe_blocked"); + private static final ResourceLocation PIPE_BLOCKED_OVERLAY_UP = GTCEu.id("block/pipe/blocked/pipe_blocked_up"); + private static final ResourceLocation PIPE_BLOCKED_OVERLAY_DOWN = GTCEu.id("block/pipe/blocked/pipe_blocked_down"); + private static final ResourceLocation PIPE_BLOCKED_OVERLAY_LEFT = GTCEu.id("block/pipe/blocked/pipe_blocked_left"); + private static final ResourceLocation PIPE_BLOCKED_OVERLAY_RIGHT = GTCEu + .id("block/pipe/blocked/pipe_blocked_right"); + private static final ResourceLocation PIPE_BLOCKED_OVERLAY_NU = GTCEu.id("block/pipe/blocked/pipe_blocked_nu"); + private static final ResourceLocation PIPE_BLOCKED_OVERLAY_ND = GTCEu.id("block/pipe/blocked/pipe_blocked_nd"); + private static final ResourceLocation PIPE_BLOCKED_OVERLAY_NL = GTCEu.id("block/pipe/blocked/pipe_blocked_nl"); + private static final ResourceLocation PIPE_BLOCKED_OVERLAY_NR = GTCEu.id("block/pipe/blocked/pipe_blocked_nr"); + private static final ResourceLocation PIPE_BLOCKED_OVERLAY_UD = GTCEu.id("block/pipe/blocked/pipe_blocked_ud"); + private static final ResourceLocation PIPE_BLOCKED_OVERLAY_UL = GTCEu.id("block/pipe/blocked/pipe_blocked_ul"); + private static final ResourceLocation PIPE_BLOCKED_OVERLAY_UR = GTCEu.id("block/pipe/blocked/pipe_blocked_ur"); + private static final ResourceLocation PIPE_BLOCKED_OVERLAY_DL = GTCEu.id("block/pipe/blocked/pipe_blocked_dl"); + private static final ResourceLocation PIPE_BLOCKED_OVERLAY_DR = GTCEu.id("block/pipe/blocked/pipe_blocked_dr"); + private static final ResourceLocation PIPE_BLOCKED_OVERLAY_LR = GTCEu.id("block/pipe/blocked/pipe_blocked_lr"); + + private static final Int2ObjectMap RESTRICTOR_MAP = Util.make(() -> { + Int2ObjectMap map = new Int2ObjectOpenHashMap<>(); + + addRestrictor(map, PIPE_BLOCKED_OVERLAY_UP, Border.TOP); + addRestrictor(map, PIPE_BLOCKED_OVERLAY_DOWN, Border.BOTTOM); + addRestrictor(map, PIPE_BLOCKED_OVERLAY_UD, Border.TOP, Border.BOTTOM); + addRestrictor(map, PIPE_BLOCKED_OVERLAY_LEFT, Border.LEFT); + addRestrictor(map, PIPE_BLOCKED_OVERLAY_UL, Border.TOP, Border.LEFT); + addRestrictor(map, PIPE_BLOCKED_OVERLAY_DL, Border.BOTTOM, Border.LEFT); + addRestrictor(map, PIPE_BLOCKED_OVERLAY_NR, Border.TOP, Border.BOTTOM, Border.LEFT); + addRestrictor(map, PIPE_BLOCKED_OVERLAY_RIGHT, Border.RIGHT); + addRestrictor(map, PIPE_BLOCKED_OVERLAY_UR, Border.TOP, Border.RIGHT); + addRestrictor(map, PIPE_BLOCKED_OVERLAY_DR, Border.BOTTOM, Border.RIGHT); + addRestrictor(map, PIPE_BLOCKED_OVERLAY_NL, Border.TOP, Border.BOTTOM, Border.RIGHT); + addRestrictor(map, PIPE_BLOCKED_OVERLAY_LR, Border.LEFT, Border.RIGHT); + addRestrictor(map, PIPE_BLOCKED_OVERLAY_ND, Border.TOP, Border.LEFT, Border.RIGHT); + addRestrictor(map, PIPE_BLOCKED_OVERLAY_NU, Border.BOTTOM, Border.LEFT, Border.RIGHT); + addRestrictor(map, PIPE_BLOCKED_OVERLAY, Border.TOP, Border.BOTTOM, Border.LEFT, Border.RIGHT); + + return map; + }); + + private static BlockModelBuilder[] getOrCreateRestrictorModels(BlockModelProvider provider, float thickness) { + return RESTRICTOR_MODEL_CACHE.apply(provider, thickness); + } + + private static final MemoizedBiFunction RESTRICTOR_MODEL_CACHE = GTMemoizer + .memoizeFunctionWeakIdent(PipeModelBuilder::makeRestrictorModels); + + private static BlockModelBuilder[] makeRestrictorModels(BlockModelProvider provider, float thickness) { + BlockModelBuilder[] models = new BlockModelBuilder[GTUtil.DIRECTIONS.length]; + + float min = (16.0f - thickness) / 2.0f - 0.003f; + float max = min + thickness + 0.006f; // offset by 0.003 * 2 + for (Direction dir : GTUtil.DIRECTIONS) { + String modelPath = "block/pipe/restrictor/" + dir.getName() + "/thickness_" + thickness; + ResourceLocation modelName = GTCEu.id(modelPath); + if (provider.generatedModels.containsKey(modelName)) { + models[dir.ordinal()] = provider.generatedModels.get(modelName); + continue; + } + + var coords = GTMath.getCoordinates(dir, min, max); + Vector3f minPos = coords.getLeft(); + Vector3f maxPos = coords.getRight(); + BlockModelBuilder model = provider.getBuilder(modelPath); + model.texture("restrictor", PIPE_BLOCKED_OVERLAY) + .element() + .from(minPos.x, minPos.y, minPos.z) + .to(maxPos.x, maxPos.y, maxPos.z) + .face(getSideAtBorder(dir, Border.BOTTOM)).end() + .face(getSideAtBorder(dir, Border.TOP)).end() + .face(getSideAtBorder(dir, Border.LEFT)).end() + .face(getSideAtBorder(dir, Border.RIGHT)).end() + .faces((face, builder) -> builder.texture("#restrictor")) + .end(); + models[dir.ordinal()] = model; + } + return models; + } + + @ApiStatus.Internal + public static void clearRestrictorModelCache() { + RESTRICTOR_MODEL_CACHE.getCache().clear(); + } + + private static final EnumMap> FACE_BORDER_MAP = Util.make(() -> { + EnumMap> map = new EnumMap<>(Direction.class); + + map.put(Direction.DOWN, borderMap(Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)); + map.put(Direction.UP, borderMap(Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)); + map.put(Direction.NORTH, borderMap(Direction.DOWN, Direction.UP, Direction.WEST, Direction.EAST)); + map.put(Direction.SOUTH, borderMap(Direction.DOWN, Direction.UP, Direction.WEST, Direction.EAST)); + map.put(Direction.WEST, borderMap(Direction.DOWN, Direction.UP, Direction.NORTH, Direction.SOUTH)); + map.put(Direction.EAST, borderMap(Direction.DOWN, Direction.UP, Direction.NORTH, Direction.SOUTH)); + + return map; + }); + + private static EnumMap borderMap(Direction topSide, Direction bottomSide, + Direction leftSide, Direction rightSide) { + EnumMap sideMap = new EnumMap<>(Border.class); + sideMap.put(Border.TOP, topSide); + sideMap.put(Border.BOTTOM, bottomSide); + sideMap.put(Border.LEFT, leftSide); + sideMap.put(Border.RIGHT, rightSide); + return sideMap; + } + + private static void addRestrictor(Int2ObjectMap map, ResourceLocation texture, + Border... borders) { + int mask = 0; + for (Border border : borders) { + mask |= border.mask; + } + map.put(mask, texture); + } + + private static Direction getSideAtBorder(Direction side, Border border) { + return FACE_BORDER_MAP.get(side).get(border); + } + + private static int computeBorderMask(int blockedConnections, int connections, Direction side) { + int borderMask = 0; + if (blockedConnections != 0) { + for (Border border : Border.VALUES) { + Direction borderSide = getSideAtBorder(side, border); + if (PipeBlockEntity.isFaceBlocked(blockedConnections, borderSide) && + PipeBlockEntity.isConnected(connections, borderSide)) { + // only render when the side is blocked *and* connected + borderMask |= border.mask; + } + } + } + return borderMask; + } + + private enum Border { + + TOP, + BOTTOM, + LEFT, + RIGHT; + + public static final Border[] VALUES = values(); + + public final int mask; + + Border() { + mask = 1 << this.ordinal(); + } + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/data/pack/GTDynamicDataPack.java b/src/main/java/com/gregtechceu/gtceu/data/pack/GTDynamicDataPack.java index cbf7560b4f3..103ffba6b4d 100644 --- a/src/main/java/com/gregtechceu/gtceu/data/pack/GTDynamicDataPack.java +++ b/src/main/java/com/gregtechceu/gtceu/data/pack/GTDynamicDataPack.java @@ -68,7 +68,7 @@ private static void addToData(ResourceLocation location, byte[] bytes) { public static void addRecipe(FinishedRecipe recipe) { JsonObject recipeJson = recipe.serializeRecipe(); byte[] recipeBytes = recipeJson.toString().getBytes(StandardCharsets.UTF_8); - Path parent = GTCEu.getGameDir().resolve("gtceu/dumped/data"); + Path parent = GTCEu.GTCEU_FOLDER.resolve("dumped/data"); ResourceLocation recipeId = recipe.getId(); if (ConfigHolder.INSTANCE.dev.dumpRecipes) { writeJson(recipeId, "recipes", parent, recipeBytes); diff --git a/src/main/java/com/gregtechceu/gtceu/data/pack/GTDynamicResourcePack.java b/src/main/java/com/gregtechceu/gtceu/data/pack/GTDynamicResourcePack.java index bb5522a00f3..a33acec7fff 100644 --- a/src/main/java/com/gregtechceu/gtceu/data/pack/GTDynamicResourcePack.java +++ b/src/main/java/com/gregtechceu/gtceu/data/pack/GTDynamicResourcePack.java @@ -9,6 +9,8 @@ import net.minecraft.SharedConstants; import net.minecraft.client.renderer.texture.atlas.SpriteSource; import net.minecraft.client.renderer.texture.atlas.SpriteSources; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.data.models.blockstates.BlockStateGenerator; import net.minecraft.network.chat.Component; import net.minecraft.resources.FileToIdConverter; import net.minecraft.resources.ResourceLocation; @@ -17,6 +19,9 @@ import net.minecraft.server.packs.metadata.MetadataSectionSerializer; import net.minecraft.server.packs.metadata.pack.PackMetadataSection; import net.minecraft.server.packs.resources.IoSupplier; +import net.minecraftforge.client.model.generators.BlockModelBuilder; +import net.minecraftforge.client.model.generators.ItemModelBuilder; +import net.minecraftforge.client.model.generators.ModelBuilder; import com.google.common.collect.Sets; import com.google.gson.JsonElement; @@ -52,9 +57,8 @@ public class GTDynamicResourcePack implements PackResources { private static final FileToIdConverter ATLAS_ID_CONVERTER = FileToIdConverter.json("atlases"); private static final FileToIdConverter TEXTURE_ID_CONVERTER = SpriteSource.TEXTURE_ID_CONVERTER; - private static final FileToIdConverter BLOCKSTATE_ID_CONVERTER = FileToIdConverter.json("blockstates"); - private static final FileToIdConverter BLOCK_MODEL_ID_CONVERTER = FileToIdConverter.json("models/block"); - private static final FileToIdConverter ITEM_MODEL_ID_CONVERTER = FileToIdConverter.json("models/item"); + public static final FileToIdConverter BLOCKSTATE_ID_CONVERTER = FileToIdConverter.json("blockstates"); + private static final FileToIdConverter MODEL_ID_CONVERTER = FileToIdConverter.json("models"); private final String name; @@ -81,89 +85,83 @@ public static void addResource(ResourceLocation location, JsonElement obj) { public static void addResource(ResourceLocation location, byte[] data) { if (ConfigHolder.INSTANCE.dev.dumpAssets) { - Path parent = GTCEu.getGameDir().resolve("gtceu/dumped/assets"); + Path parent = GTCEu.GTCEU_FOLDER.resolve("dumped/assets"); writeJson(location, null, parent, data); } CONTENTS.addToData(location, data); } public static void addBlockModel(ResourceLocation loc, JsonElement obj) { - ResourceLocation l = getBlockModelLocation(loc); - byte[] modelBytes = obj.toString().getBytes(StandardCharsets.UTF_8); - - if (ConfigHolder.INSTANCE.dev.dumpAssets) { - Path parent = GTCEu.getGameDir().resolve("gtceu/dumped/assets"); - writeJson(l, null, parent, modelBytes); + if (!loc.getPath().startsWith("block/")) { + loc = loc.withPrefix("block/"); } - CONTENTS.addToData(l, modelBytes); + addModel(loc, obj); } public static void addBlockModel(ResourceLocation loc, Supplier obj) { addBlockModel(loc, obj.get()); } - public static void addItemModel(ResourceLocation loc, JsonElement obj) { - ResourceLocation l = getItemModelLocation(loc); - byte[] modelBytes = obj.toString().getBytes(StandardCharsets.UTF_8); + public static void addBlockModel(BlockModelBuilder builder) { + addBlockModel(builder.getLocation(), builder.toJson()); + } - if (ConfigHolder.INSTANCE.dev.dumpAssets) { - Path parent = GTCEu.getGameDir().resolve("gtceu/dumped/assets"); - writeJson(l, null, parent, modelBytes); + public static void addItemModel(ResourceLocation loc, JsonElement obj) { + if (!loc.getPath().startsWith("item/")) { + loc = loc.withPrefix("item/"); } - CONTENTS.addToData(l, modelBytes); + addModel(loc, obj); + } + + public static void addItemModel(ItemModelBuilder builder) { + addItemModel(builder.getLocation(), builder.toJson()); } public static void addItemModel(ResourceLocation loc, Supplier obj) { addItemModel(loc, obj.get()); } - public static void addBlockState(ResourceLocation loc, JsonElement stateJson) { - ResourceLocation l = getBlockStateLocation(loc); - byte[] stateBytes = stateJson.toString().getBytes(StandardCharsets.UTF_8); + public static void addModel(ResourceLocation loc, JsonElement obj) { + loc = MODEL_ID_CONVERTER.idToFile(loc); + addResource(loc, obj); + } - if (ConfigHolder.INSTANCE.dev.dumpAssets) { - Path parent = GTCEu.getGameDir().resolve("gtceu/dumped/assets"); - writeJson(l, null, parent, stateBytes); - } - CONTENTS.addToData(l, stateBytes); + public static void addModel(ResourceLocation loc, Supplier obj) { + addModel(loc, obj.get()); + } + + public static > void addModel(T builder) { + addModel(builder.getLocation(), builder.toJson()); + } + + public static void addBlockState(ResourceLocation loc, JsonElement stateJson) { + loc = BLOCKSTATE_ID_CONVERTER.idToFile(loc); + addResource(loc, stateJson); } public static void addBlockState(ResourceLocation loc, Supplier generator) { addBlockState(loc, generator.get()); } - public static void addAtlasSpriteSource(ResourceLocation atlasLoc, SpriteSource source) { - ResourceLocation l = getAtlasLocation(atlasLoc); - JsonElement sourceJson = SpriteSources.FILE_CODEC - .encodeStart(JsonOps.INSTANCE, Collections.singletonList(source)) - .getOrThrow(false, - error -> GTCEu.LOGGER.error("Failed to encode atlas sprite source. {}", error)); - byte[] sourceBytes = sourceJson.toString().getBytes(StandardCharsets.UTF_8); - - if (ConfigHolder.INSTANCE.dev.dumpAssets) { - Path parent = GTCEu.getGameDir().resolve("gtceu/dumped/assets"); - writeJson(l, null, parent, sourceBytes); - } - CONTENTS.addToData(l, sourceBytes); + public static void addBlockState(BlockStateGenerator generator) { + addBlockState(BuiltInRegistries.BLOCK.getKey(generator.getBlock()), generator.get()); } - public static void addAtlasSpriteSourceList(ResourceLocation atlasLoc, List sources) { - ResourceLocation l = getAtlasLocation(atlasLoc); - JsonElement sourceJson = SpriteSources.FILE_CODEC.encodeStart(JsonOps.INSTANCE, sources).getOrThrow(false, - error -> GTCEu.LOGGER.error("Failed to encode atlas sprite source. {}", error)); - byte[] sourceBytes = sourceJson.toString().getBytes(StandardCharsets.UTF_8); + public static void addAtlasSpriteSource(ResourceLocation atlasLoc, SpriteSource source) { + addAtlasSpriteSourceList(atlasLoc, Collections.singletonList(source)); + } - if (ConfigHolder.INSTANCE.dev.dumpAssets) { - Path parent = GTCEu.getGameDir().resolve("gtceu/dumped/assets"); - writeJson(l, null, parent, sourceBytes); - } - CONTENTS.addToData(l, sourceBytes); + public static void addAtlasSpriteSourceList(ResourceLocation loc, List sources) { + loc = ATLAS_ID_CONVERTER.idToFile(loc); + JsonElement sourceJson = SpriteSources.FILE_CODEC.encodeStart(JsonOps.INSTANCE, sources) + .getOrThrow(false, error -> GTCEu.LOGGER.error("Failed to encode atlas sprite source. {}", error)); + addResource(loc, sourceJson); } public static void addBlockTexture(ResourceLocation loc, byte[] data) { ResourceLocation l = getTextureLocation("block", loc); if (ConfigHolder.INSTANCE.dev.dumpAssets) { - Path parent = GTCEu.getGameDir().resolve("gtceu/dumped/assets"); + Path parent = GTCEu.GTCEU_FOLDER.resolve("dumped/assets"); writeByteArray(l, null, parent, data); } CONTENTS.addToData(l, data); @@ -172,7 +170,7 @@ public static void addBlockTexture(ResourceLocation loc, byte[] data) { public static void addItemTexture(ResourceLocation loc, byte[] data) { ResourceLocation l = getTextureLocation("item", loc); if (ConfigHolder.INSTANCE.dev.dumpAssets) { - Path parent = GTCEu.getGameDir().resolve("gtceu/dumped/assets"); + Path parent = GTCEu.GTCEU_FOLDER.resolve("dumped/assets"); writeByteArray(l, null, parent, data); } CONTENTS.addToData(l, data); @@ -252,26 +250,10 @@ public void close() { // NOOP } - public static ResourceLocation getBlockStateLocation(ResourceLocation blockId) { - return BLOCKSTATE_ID_CONVERTER.idToFile(blockId); - } - - public static ResourceLocation getBlockModelLocation(ResourceLocation blockId) { - return BLOCK_MODEL_ID_CONVERTER.idToFile(blockId); - } - - public static ResourceLocation getItemModelLocation(ResourceLocation itemId) { - return ITEM_MODEL_ID_CONVERTER.idToFile(itemId); - } - public static ResourceLocation getTextureLocation(@Nullable String path, ResourceLocation textureId) { if (path == null) { return TEXTURE_ID_CONVERTER.idToFile(textureId); } return TEXTURE_ID_CONVERTER.idToFile(textureId.withPrefix(path + "/")); } - - public static ResourceLocation getAtlasLocation(ResourceLocation atlasId) { - return ATLAS_ID_CONVERTER.idToFile(atlasId); - } } diff --git a/src/main/java/com/gregtechceu/gtceu/data/pack/event/RegisterDynamicResourcesEvent.java b/src/main/java/com/gregtechceu/gtceu/data/pack/event/RegisterDynamicResourcesEvent.java new file mode 100644 index 00000000000..92f9eaa1d9a --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/data/pack/event/RegisterDynamicResourcesEvent.java @@ -0,0 +1,12 @@ +package com.gregtechceu.gtceu.data.pack.event; + +import net.minecraftforge.eventbus.api.Event; +import net.minecraftforge.fml.event.IModBusEvent; + +import org.jetbrains.annotations.ApiStatus; + +public class RegisterDynamicResourcesEvent extends Event implements IModBusEvent { + + @ApiStatus.Internal + public RegisterDynamicResourcesEvent() {} +} diff --git a/src/main/java/com/gregtechceu/gtceu/integration/kjs/GregTechKubeJSPlugin.java b/src/main/java/com/gregtechceu/gtceu/integration/kjs/GregTechKubeJSPlugin.java index 6300ac47d81..282112a3928 100644 --- a/src/main/java/com/gregtechceu/gtceu/integration/kjs/GregTechKubeJSPlugin.java +++ b/src/main/java/com/gregtechceu/gtceu/integration/kjs/GregTechKubeJSPlugin.java @@ -70,10 +70,8 @@ import com.gregtechceu.gtceu.common.data.models.GTModels; import com.gregtechceu.gtceu.common.item.armor.PowerlessJetpack; import com.gregtechceu.gtceu.common.machine.multiblock.primitive.PrimitiveFancyUIWorkableMachine; -import com.gregtechceu.gtceu.common.registry.GTRegistration; import com.gregtechceu.gtceu.common.unification.material.MaterialRegistryManager; import com.gregtechceu.gtceu.core.mixins.IngredientAccessor; -import com.gregtechceu.gtceu.data.pack.GTDynamicResourcePack; import com.gregtechceu.gtceu.data.recipe.CraftingComponent; import com.gregtechceu.gtceu.data.recipe.GTCraftingComponents; import com.gregtechceu.gtceu.data.recipe.builder.GTRecipeBuilder; @@ -93,9 +91,7 @@ import com.gregtechceu.gtceu.integration.kjs.recipe.WrappingRecipeSchemaType; import com.gregtechceu.gtceu.integration.kjs.recipe.components.ExtendedOutputItem; import com.gregtechceu.gtceu.integration.kjs.recipe.components.GTRecipeComponents; -import com.gregtechceu.gtceu.utils.data.RuntimeBlockStateProvider; -import net.minecraft.data.PackOutput; import net.minecraft.nbt.NbtOps; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.inventory.CraftingContainer; @@ -109,7 +105,6 @@ import net.minecraftforge.registries.ForgeRegistries; import com.mojang.serialization.DataResult; -import dev.latvian.mods.kubejs.KubeJSPaths; import dev.latvian.mods.kubejs.KubeJSPlugin; import dev.latvian.mods.kubejs.block.state.BlockStatePredicate; import dev.latvian.mods.kubejs.client.LangEventJS; @@ -212,23 +207,12 @@ public void generateDataJsons(DataJsonGenerator generator) { GTRegistryInfo.ALL_BUILDERS.forEach(builderBase -> builderBase.generateDataJsons(generator)); } - // Fake a data provider for the GT model builders so we don't need to handle this ourselves in any way :3 - public static RuntimeBlockStateProvider RUNTIME_BLOCKSTATE_PROVIDER = new RuntimeBlockStateProvider( - GTRegistration.REGISTRATE, new PackOutput(KubeJSPaths.DIRECTORY), - (loc, json) -> { - if (!loc.getPath().endsWith(".json")) { - loc = loc.withSuffix(".json"); - } - GTDynamicResourcePack.addResource(loc, json); - }); - public static void generateMachineBlockModels() { GTRegistryInfo.ALL_BUILDERS.forEach(builderBase -> { try { builderBase.generateAssetJsons(null); } catch (IllegalStateException ignored) {} }); - GregTechKubeJSPlugin.RUNTIME_BLOCKSTATE_PROVIDER.run(); } @Override diff --git a/src/main/java/com/gregtechceu/gtceu/utils/GTMath.java b/src/main/java/com/gregtechceu/gtceu/utils/GTMath.java index 2877a711f97..ce8ec066a59 100644 --- a/src/main/java/com/gregtechceu/gtceu/utils/GTMath.java +++ b/src/main/java/com/gregtechceu/gtceu/utils/GTMath.java @@ -1,12 +1,18 @@ package com.gregtechceu.gtceu.utils; import net.minecraft.MethodsReturnNonnullByDefault; +import net.minecraft.core.Direction; import net.minecraft.util.Mth; import net.minecraft.world.item.ItemStack; import net.minecraftforge.fluids.FluidStack; import it.unimi.dsi.fastutil.ints.IntArrayList; import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.joml.Vector3f; import java.math.BigDecimal; import java.math.BigInteger; @@ -93,4 +99,65 @@ public static int ceilDiv(int x, int y) { } return q; } + + public static float min(float @NotNull... values) { + // noinspection ConstantValue + if (values == null || values.length == 0) throw new IllegalArgumentException(); + if (values.length == 1) return values[0]; + if (values.length == 2) return Math.min(values[0], values[1]); + float min = Float.MAX_VALUE; + for (float i : values) { + if (i < min) { + min = i; + } + } + return min; + } + + public static float max(float @NotNull... values) { + // noinspection ConstantValue + if (values == null || values.length == 0) throw new IllegalArgumentException(); + if (values.length == 1) return values[0]; + if (values.length == 2) return Math.max(values[0], values[1]); + float max = Float.MIN_VALUE; + for (float i : values) { + if (i > max) { + max = i; + } + } + return max; + } + + public static Pair getCoordinates(@Nullable Direction dir, float min, float max) { + float x1 = min, y1 = min, z1 = min, x2 = max, y2 = max, z2 = max; + if (dir != null) { + switch (dir) { + case DOWN -> { + y1 = 0; + y2 = min; + } + case UP -> { + y1 = max; + y2 = 16; + } + case NORTH -> { + z1 = 0; + z2 = min; + } + case SOUTH -> { + z1 = max; + z2 = 16; + } + case WEST -> { + x1 = 0; + x2 = min; + } + case EAST -> { + x1 = max; + x2 = 16; + } + } + } + return ImmutablePair.of(new Vector3f(x1, y1, z1), new Vector3f(x2, y2, z2)); + } } diff --git a/src/main/java/com/gregtechceu/gtceu/utils/GTUtil.java b/src/main/java/com/gregtechceu/gtceu/utils/GTUtil.java index 3b42d4f2b80..d699f5223e0 100644 --- a/src/main/java/com/gregtechceu/gtceu/utils/GTUtil.java +++ b/src/main/java/com/gregtechceu/gtceu/utils/GTUtil.java @@ -52,6 +52,7 @@ import com.mojang.datafixers.util.Pair; import it.unimi.dsi.fastutil.objects.Object2IntArrayMap; import it.unimi.dsi.fastutil.objects.Object2IntMap; +import org.apache.commons.lang3.ArrayUtils; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.lwjgl.glfw.GLFW; @@ -67,6 +68,7 @@ public class GTUtil { public static final Direction[] DIRECTIONS = Direction.values(); + public static final @Nullable Direction @NotNull [] DIRECTIONS_WITH_NULL = ArrayUtils.add(DIRECTIONS, null); @SuppressWarnings("UnstableApiUsage") public static final ImmutableList NON_CORNER_NEIGHBOURS = Util.make(() -> { diff --git a/src/main/java/com/gregtechceu/gtceu/utils/data/RuntimeBlockStateProvider.java b/src/main/java/com/gregtechceu/gtceu/utils/data/RuntimeBlockstateProvider.java similarity index 64% rename from src/main/java/com/gregtechceu/gtceu/utils/data/RuntimeBlockStateProvider.java rename to src/main/java/com/gregtechceu/gtceu/utils/data/RuntimeBlockstateProvider.java index b18f2bcd41d..8d69125eeb2 100644 --- a/src/main/java/com/gregtechceu/gtceu/utils/data/RuntimeBlockStateProvider.java +++ b/src/main/java/com/gregtechceu/gtceu/utils/data/RuntimeBlockstateProvider.java @@ -1,6 +1,9 @@ package com.gregtechceu.gtceu.utils.data; +import com.gregtechceu.gtceu.GTCEu; import com.gregtechceu.gtceu.api.registry.registrate.provider.GTBlockstateProvider; +import com.gregtechceu.gtceu.common.registry.GTRegistration; +import com.gregtechceu.gtceu.data.pack.GTDynamicResourcePack; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.data.PackOutput; @@ -14,11 +17,21 @@ import java.util.Map; import java.util.function.BiConsumer; -public class RuntimeBlockStateProvider extends GTBlockstateProvider { +public class RuntimeBlockstateProvider extends GTBlockstateProvider { + + // Fake a data provider for the GT model builders so we don't need to handle this ourselves in any way :3 + public static final RuntimeBlockstateProvider INSTANCE = new RuntimeBlockstateProvider( + GTRegistration.REGISTRATE, new PackOutput(GTCEu.GTCEU_FOLDER), + (loc, json) -> { + if (!loc.getPath().endsWith(".json")) { + loc = loc.withSuffix(".json"); + } + GTDynamicResourcePack.addResource(loc, json); + }); protected final BiConsumer consumer; - public RuntimeBlockStateProvider(AbstractRegistrate parent, PackOutput packOutput, + public RuntimeBlockstateProvider(AbstractRegistrate parent, PackOutput packOutput, BiConsumer consumer) { super(parent, packOutput, RuntimeExistingFileHelper.INSTANCE); this.consumer = consumer; @@ -33,7 +46,8 @@ public void run() { processModelProvider(itemModels()); for (Map.Entry entry : registeredBlocks.entrySet()) { - ResourceLocation loc = BuiltInRegistries.BLOCK.getKey(entry.getKey()).withPrefix("blockstates/"); + ResourceLocation loc = GTDynamicResourcePack.BLOCKSTATE_ID_CONVERTER + .idToFile(BuiltInRegistries.BLOCK.getKey(entry.getKey())); this.consumer.accept(loc, entry.getValue().toJson()); } // only clear the data *after* saving so we can keep track of it during the KJS event diff --git a/src/main/java/com/gregtechceu/gtceu/utils/memoization/GTMemoizer.java b/src/main/java/com/gregtechceu/gtceu/utils/memoization/GTMemoizer.java index be27b6cb231..36728327d77 100644 --- a/src/main/java/com/gregtechceu/gtceu/utils/memoization/GTMemoizer.java +++ b/src/main/java/com/gregtechceu/gtceu/utils/memoization/GTMemoizer.java @@ -1,12 +1,19 @@ package com.gregtechceu.gtceu.utils.memoization; +import com.gregtechceu.gtceu.utils.memoization.function.MemoizedBiFunction; +import com.gregtechceu.gtceu.utils.memoization.function.MemoizedFunction; +import com.gregtechceu.gtceu.utils.memoization.function.MemoizedTriFunction; + import net.minecraft.world.level.block.Block; +import lombok.Getter; import org.apache.commons.lang3.function.TriFunction; +import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Triple; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import java.util.function.BiFunction; import java.util.function.Function; import java.util.function.Supplier; @@ -27,32 +34,59 @@ public static MemoizedBlockSupplier memoizeBlockSupplier(Su return new MemoizedBlockSupplier<>(delegate); } - public static Function memoizeFunctionWeakIdent(final Function memoFunction) { - return new Function<>() { + public static MemoizedFunction memoizeFunctionWeakIdent(final Function memoFunction) { + return new MemoizedFunction<>() { + @Getter private final Map cache = new ConcurrentWeakIdentityHashMap<>(); + @Override public R apply(T key) { return this.cache.computeIfAbsent(key, memoFunction); } + @Override public String toString() { return "memoizeFunctionWeakIdent/1[function=" + memoFunction + ", size=" + this.cache.size() + "]"; } }; } - public static TriFunction memoize(final TriFunction memoTriFunction) { - return new TriFunction<>() { + public static MemoizedBiFunction memoizeFunctionWeakIdent(final BiFunction memoBiFunction) { + return new MemoizedBiFunction<>() { + + @Getter + private final Map, R> cache = new ConcurrentWeakIdentityHashMap<>(); + + @Override + public R apply(T key1, U key2) { + return this.cache.computeIfAbsent(Pair.of(key1, key2), (key) -> { + return memoBiFunction.apply(key.getLeft(), key.getRight()); + }); + } + + @Override + public String toString() { + return "memoizeFunctionWeakIdent/2[function=" + memoBiFunction + ", size=" + this.cache.size() + "]"; + } + }; + } + + public static MemoizedTriFunction memoize(final TriFunction memoTriFunction) { + return new MemoizedTriFunction<>() { + @Getter private final Map, R> cache = new ConcurrentHashMap<>(); + @Override public R apply(T key1, U key2, V key3) { return this.cache.computeIfAbsent(Triple.of(key1, key2, key3), (cacheKey) -> { return memoTriFunction.apply(cacheKey.getLeft(), cacheKey.getMiddle(), cacheKey.getRight()); }); } + @Override public String toString() { return "memoize/3[function=" + memoTriFunction + ", size=" + this.cache.size() + "]"; } diff --git a/src/main/java/com/gregtechceu/gtceu/utils/memoization/function/MemoizedBiFunction.java b/src/main/java/com/gregtechceu/gtceu/utils/memoization/function/MemoizedBiFunction.java new file mode 100644 index 00000000000..4934e7033d5 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/utils/memoization/function/MemoizedBiFunction.java @@ -0,0 +1,11 @@ +package com.gregtechceu.gtceu.utils.memoization.function; + +import org.apache.commons.lang3.tuple.Pair; + +import java.util.Map; +import java.util.function.BiFunction; + +public interface MemoizedBiFunction extends BiFunction { + + Map, R> getCache(); +} diff --git a/src/main/java/com/gregtechceu/gtceu/utils/memoization/function/MemoizedFunction.java b/src/main/java/com/gregtechceu/gtceu/utils/memoization/function/MemoizedFunction.java new file mode 100644 index 00000000000..61b79bb6b9d --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/utils/memoization/function/MemoizedFunction.java @@ -0,0 +1,9 @@ +package com.gregtechceu.gtceu.utils.memoization.function; + +import java.util.Map; +import java.util.function.Function; + +public interface MemoizedFunction extends Function { + + Map getCache(); +} diff --git a/src/main/java/com/gregtechceu/gtceu/utils/memoization/function/MemoizedTriFunction.java b/src/main/java/com/gregtechceu/gtceu/utils/memoization/function/MemoizedTriFunction.java new file mode 100644 index 00000000000..f5608e2f489 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/utils/memoization/function/MemoizedTriFunction.java @@ -0,0 +1,11 @@ +package com.gregtechceu.gtceu.utils.memoization.function; + +import org.apache.commons.lang3.function.TriFunction; +import org.apache.commons.lang3.tuple.Triple; + +import java.util.Map; + +public interface MemoizedTriFunction extends TriFunction { + + Map, R> getCache(); +} diff --git a/src/main/resources/assets/gtceu/textures/block/pipe/pipe_optical_side.png b/src/main/resources/assets/gtceu/textures/block/pipe/pipe_optical_side.png index fa5c3c037c0..695048d32a3 100644 Binary files a/src/main/resources/assets/gtceu/textures/block/pipe/pipe_optical_side.png and b/src/main/resources/assets/gtceu/textures/block/pipe/pipe_optical_side.png differ diff --git a/src/main/resources/assets/gtceu/textures/block/pipe/pipe_optical_side_overlay.png b/src/main/resources/assets/gtceu/textures/block/pipe/pipe_optical_side_overlay.png new file mode 100644 index 00000000000..57fb4be3662 Binary files /dev/null and b/src/main/resources/assets/gtceu/textures/block/pipe/pipe_optical_side_overlay.png differ diff --git a/src/main/resources/assets/gtceu/textures/block/pipe/pipe_optical_side_overlay_active.png b/src/main/resources/assets/gtceu/textures/block/pipe/pipe_optical_side_overlay_active.png new file mode 100644 index 00000000000..d0d5cdc54a5 Binary files /dev/null and b/src/main/resources/assets/gtceu/textures/block/pipe/pipe_optical_side_overlay_active.png differ diff --git a/src/main/resources/assets/gtceu/textures/block/pipe/pipe_optical_side_overlay_active.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/pipe/pipe_optical_side_overlay_active.png.mcmeta new file mode 100644 index 00000000000..21972735d33 --- /dev/null +++ b/src/main/resources/assets/gtceu/textures/block/pipe/pipe_optical_side_overlay_active.png.mcmeta @@ -0,0 +1,5 @@ +{ + "animation": { + "frametime": 25 + } +}