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 extends D> 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 extends T> 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 extends PipeBlockEntity, ?>> 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
+ }
+}