diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 34fece61126..4132c1a42cb 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -9,6 +9,9 @@ _Any implementations in this PR that should be carefully looked over, or that co _A short description of what this PR added/fixed/changed/removed._ _For correct linking of issues please use any of the Closes/Fixes/Resolves keywords. Example: When a PR is fixing a bug use "Fixes: #number-of-bug"_ +## How Was This Tested +_This section is for screenshots, code snippets or descriptions of how the PR was tested in code or in game to ensure correctness._ + ## Additional Information _This section is for screenshots to demonstrate any GUI or rendering changes, or any other additional information that reviewers should be aware of._ diff --git a/CHANGELOG.md b/CHANGELOG.md index 4421b140e5c..af884df569f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,73 @@ # ChangeLog +## Version [v7.5.2](https://github.com/GregTechCEu/GregTech-Modern/compare/v7.5.1-1.20.1...v7.5.2-1.20.1) +### Fixed + +- Turn groupColor field value into optional field codec by @jurrejelle in [#4593](https://github.com/GregTechCEu/GregTech-Modern/pull/4593) +- Fix wrong argument check for 'redstone set #' placeholder by @FyreDrakon in [#4595](https://github.com/GregTechCEu/GregTech-Modern/pull/4595) +- Fix ore vein consistency by sorting the cache by @jurrejelle in [#4602](https://github.com/GregTechCEu/GregTech-Modern/pull/4602) +- Fix CR being displayed on CM when pasting text on windows by @TarLaboratories in [#4603](https://github.com/GregTechCEu/GregTech-Modern/pull/4603) + + +## Version [v7.5.1](https://github.com/GregTechCEu/GregTech-Modern/compare/v7.5.0-1.20.1...v7.5.1-1.20.1) +### Fixed + +- Fix access protection issue in netherite tools + lamprenderer issues by @jurrejelle in [#4579](https://github.com/GregTechCEu/GregTech-Modern/pull/4579) + + +## Version [v7.5.0](https://github.com/GregTechCEu/GregTech-Modern/compare/v7.4.1-1.20.1...v7.5.0-1.20.1) +### Added + +- 7.4.x Haze small fusion ctm tweaks bc it was bothering me by @HazeVista in [#4432](https://github.com/GregTechCEu/GregTech-Modern/pull/4432) +- Add option to display temperatures in Celsius by @TarLaboratories in [#3839](https://github.com/GregTechCEu/GregTech-Modern/pull/3839) +- Spray cans with AE2 IColorableBlockEntity support by @zetrock1 in [#4264](https://github.com/GregTechCEu/GregTech-Modern/pull/4264) +- Rework machine copy/paste card to support copying pipes, covers, cover settings, and more machine settings by @gustovafing in [#4272](https://github.com/GregTechCEu/GregTech-Modern/pull/4272) +- Add Hotkey for StepAssist by @zetrock1 in [#4291](https://github.com/GregTechCEu/GregTech-Modern/pull/4291) +- Add HV, IV screwdriver and chainsaw by @zetrock1 in [#4310](https://github.com/GregTechCEu/GregTech-Modern/pull/4310) +- Jade battery provider by @zetrock1 in [#4317](https://github.com/GregTechCEu/GregTech-Modern/pull/4317) +- Add CC: Tweaked peripheral for ghost programmed circuit by @blockninja124 in [#4468](https://github.com/GregTechCEu/GregTech-Modern/pull/4468) +- Trinium spring by @zetrock1 in [#4470](https://github.com/GregTechCEu/GregTech-Modern/pull/4470) +- Output bus filtering by @zetrock1 in [#4337](https://github.com/GregTechCEu/GregTech-Modern/pull/4337) +- Allow rendering other modules from placeholders by @TarLaboratories in [#3900](https://github.com/GregTechCEu/GregTech-Modern/pull/3900) +- Add gem slurry from purified ore recipes by @SpicyNoodle5 in [#4413](https://github.com/GregTechCEu/GregTech-Modern/pull/4413) +- Recipe Fail Reason Display by @illuciaz23 in [#4487](https://github.com/GregTechCEu/GregTech-Modern/pull/4487) +- Add biomeTag recipe condition by @chloecat34 in [#4419](https://github.com/GregTechCEu/GregTech-Modern/pull/4419) + +### Fixed + +- Fix overwriting FOV when on concrete by @zetrock1 in [#4446](https://github.com/GregTechCEu/GregTech-Modern/pull/4446) +- Stop placeholder execution when an exception is encountered by @TarLaboratories in [#4455](https://github.com/GregTechCEu/GregTech-Modern/pull/4455) +- Fix tank valve info by @zetrock1 in [#4454](https://github.com/GregTechCEu/GregTech-Modern/pull/4454) +- Fix voltage display by @illuciaz23 in [#4462](https://github.com/GregTechCEu/GregTech-Modern/pull/4462) +- Fixed Multi Smelter texture again. by @Conity723 in [#4469](https://github.com/GregTechCEu/GregTech-Modern/pull/4469) +- Terminal tooltip change to ensure consistent terminology by @HazeVista in [#4458](https://github.com/GregTechCEu/GregTech-Modern/pull/4458) +- Only allow http and https by @TarLaboratories in [#4457](https://github.com/GregTechCEu/GregTech-Modern/pull/4457) +- Add check to not cache invalid recipes by @jurrejelle in [#4486](https://github.com/GregTechCEu/GregTech-Modern/pull/4486) +- Remove BlockEntity Check in MinerLogic by @lilpaladin1 in [#4488](https://github.com/GregTechCEu/GregTech-Modern/pull/4488) +- Fix autogenerating mortar recipes by @jurrejelle in [#4498](https://github.com/GregTechCEu/GregTech-Modern/pull/4498) +- Replace mandatory air with any in blast chiler structure by @jurrejelle in [#4502](https://github.com/GregTechCEu/GregTech-Modern/pull/4502) +- Fix CME with parts and partpositions when calling getParts in addedToController by @jurrejelle in [#4505](https://github.com/GregTechCEu/GregTech-Modern/pull/4505) +- Fix missing/invalid pipe model issues by @screret in [#4530](https://github.com/GregTechCEu/GregTech-Modern/pull/4530) +- Fix bug in NBTPredicateIngredient serializer by @Mqrius in [#4536](https://github.com/GregTechCEu/GregTech-Modern/pull/4536) +- Fix dust disassembly recipes by @TarLaboratories in [#4456](https://github.com/GregTechCEu/GregTech-Modern/pull/4456) +- Fix pipes missing break particle textures by @screret in [#4533](https://github.com/GregTechCEu/GregTech-Modern/pull/4533) +- Simplify material block models and fix issues they had with shaders by @screret in [#4532](https://github.com/GregTechCEu/GregTech-Modern/pull/4532) +- Fix pipes' block break animation being the wrong shape by @screret in [#4543](https://github.com/GregTechCEu/GregTech-Modern/pull/4543) +- Fixed tooltip order for Large Assembler by @HazeVista in [#4552](https://github.com/GregTechCEu/GregTech-Modern/pull/4552) +- Match Painted Output Busses to Painted Input Busses by @DilithiumThoride in [#4273](https://github.com/GregTechCEu/GregTech-Modern/pull/4273) +- Improve bedrock vein randomness by @Gaider10 in [#4574](https://github.com/GregTechCEu/GregTech-Modern/pull/4574) + +### Changed + +- Two-Phase Recipe Addition System by @TechLord22 in [#3981](https://github.com/GregTechCEu/GregTech-Modern/pull/3981) +- Correction and update of the new uk_ua by @MetenBouldry in [#4452](https://github.com/GregTechCEu/GregTech-Modern/pull/4452) +- Use Generic Builder pattern for MachineBuilder by @jurrejelle in [#4422](https://github.com/GregTechCEu/GregTech-Modern/pull/4422) +- Distribute display voltage logic to machine implementations by @toapuro in [#4459](https://github.com/GregTechCEu/GregTech-Modern/pull/4459) +- DFS stack-based recipe lookup implementation by @jurrejelle in [#3986](https://github.com/GregTechCEu/GregTech-Modern/pull/3986) +- Pipe model rework by @screret in [#4283](https://github.com/GregTechCEu/GregTech-Modern/pull/4283) +- Remove muffler hatch requirement from Large Distillery by @GirixK in [#4195](https://github.com/GregTechCEu/GregTech-Modern/pull/4195) + + ## Version [v7.4.1](https://github.com/GregTechCEu/GregTech-Modern/compare/v7.4.0-1.20.1...v7.4.1-1.20.1) ### Added diff --git a/docs/content/Gameplay/Central-Monitor.md b/docs/content/Gameplay/Central-Monitor.md new file mode 100644 index 00000000000..037ab83c6e2 --- /dev/null +++ b/docs/content/Gameplay/Central-Monitor.md @@ -0,0 +1,72 @@ +--- +title: The Central Monitor & Placeholder System +--- + +### The Central Monitor + +The Central Monitor is a multiblock that allows you to insert modules into it to render images and text.
+Images update every 120 seconds, text update rate depends on the voltage provided to the multiblock. +Guide on how to use the central monitor: + +1. Right-click the controller +2. In the UI, you will see a grid of monitors, the controller, energy hatch and (optionally) a data hatch +3. Select some of the monitors (in any configuration) by left-clicking on them +4. Click the "Create group" button +5. You should see a group appear on the left of the UI, click on it to select all monitors in that group, click again to unselect +6. Click on the gear icon next to the name of the group you want to edit +7. A UI with a single slot should open, put a module into that slot (while it is possible to put a stack of modules in, that does literally nothing) +8. If it's a text/image module a new field should appear, where you can enter some text (for image it'll be a single line for a URL) +9. Once you've entered your text, click on the green checkmark below the slot, that will save the text you entered +10. Click on the gear icon next to the group you're editing to go back to the main menu +11. You should see the text/image on the Central Monitor + +To remove a group, select it and click "Remove from group". To remove a single monitor from a group select only it and click "Remove from group". +You cannot add monitors to a group after it has been created. Image dimensions are determined by the left-up corner of the group and the right-down corner, +the blocks between them have to be in the same group. The text module will only display text on monitors of its group. + +!!! warning "The image module is a bit buggy, so the image may not appear immediately" + +### Text Module + +You may have noticed that the text module has a number input in its UI. It is the text scale, where 1 represents a line height of 1/16th of a block. +You may have also noticed that the text module has some additional slots on the left. +Those are referenced by placeholders, you can put any item in them. Most placeholders also need a target block to work. To select a target for your monitor group, +in the main UI of the controller select the group, right-click the block you want to target and click "Set target". You may want to target a block that is not in the +central monitor, to do that you have to use a Wireless Transmitter Cover. Place it on the block you want to target and right-click it with a data stick. Then put that +data stick into a data hatch in the Central Monitor multiblock. If you select the data hatch as a target, you will see a new number field appear. Enter the number of the +slot your data stick is in and click "Set target". The target will be set to the block the Wireless Transmitter Cover is on. It can work cross-dimensionally. + +!!! note "For the Computer Monitor Cover, the targeted block is always the block it's placed on." + +### Placeholders +Placeholders can be used by players in the monitor text module, or in the computer monitor cover (though a bit more limited). +For example, a player may write something like this in a text module: +``` +Hello on day {calc {tick} / 20000}! +Current energy buffer: {formatInt {energy}}/{formatInt {energyCapacity}} EU\ +{if {cmp {energy} < 5000000} {color red "\nLOW ENERGY!"}} +Here's some random stuff: +{repeat 5 {repeat {random 2 10} {block}} +``` +And something like this would be displayed: +``` +Hello on day 420! +Current energy buffer: 4.2M/6.9M EU +LOW ENERGY! +Here's some random stuff: +███████ +██ +█████ +████ +██████████ +``` +This system is turing-complete (i.e. if the player really wanted to play Doom on the Central Monitor, they could).
+All placeholders work on strings (or, more specifically, `Component`s to allow text formatting), so when you write `{calc {calc 2 + 4} * 3}`, +first `{calc 2 + 4}` will be evaluated into `6`, then it will be converted to a string and back to an int, and then it will be passed into the second placeholder +to evaluate `{calc 6 * 3}` into `18`, which will be turned into a string again. That also allows for things like `{calc 3 + 1}2`, which will evaluate into `42`, +since outside of placeholders text is simply concatenated. Placeholder arguments are separated by spaces, which may be a bit annoying, when wanting to pass a string +with a space into a placeholder, for example `{if 1 string with spaces}`, which will cause an error. In these cases, double quotes can be used: `{if 1 "string with spaces"}` +will work perfectly fine. There are placeholders that need reference items, to achieve that, there are 8 slots in the text module's UI on the left. +Items can be inserted/extracted from these slots automatically using the `ender` placeholder by interacting with Ender Item Links.
+ +!!! tip "The full list of placeholders with explanations on what they do and usage examples can be found in-game in the text module or computer monitor UI on the left." \ No newline at end of file diff --git a/docs/content/Gameplay/Logistics/Machines.md b/docs/content/Gameplay/Logistics/Machines.md index 8cfe69a4bdd..6dcc68d5d20 100644 --- a/docs/content/Gameplay/Logistics/Machines.md +++ b/docs/content/Gameplay/Logistics/Machines.md @@ -42,6 +42,37 @@ the power button in its UI or by right-clicking it with a Soft Mallet. Buses and Hatches can accept automated import or export from other sides, so long as something else is causing it. +### Distinct, Painted, and Filtered Inputs and Outputs +Under normal circumstances, **all** input Buses and Hatches and on a multiblock machine will be checked for recipe +inputs, and all output buses and hatches will be used to place recipe outputs. However, this can lead to unwanted behavior +where a user wants a single machine to do multiple recipes, but the ingredients to those recipes can conflict and be used +to run an unwanted third recipe. Additionally, when a machine is being used like this, the output bus/hatch to which +produced items/fluids are delivered is chosen somewhat arbitrarily, making it difficult or unwieldy to plan pipes to carry +specific output products away. + +GTM offers three tools for this problem: Fluid Hatch Filter Locking, Distinct Buses and Painted Buses/Hatches. + +* Fluid Hatch Filter Locking is a simple system for resolving the problem of deciding what output hatches receive what +produced fluids. Using the same interface as a Super Tank, a Fluid Output Hatch can have its current contained fluid +Locked, meaning that only that fluid will ever be placed in it; or the Hatch can be pre-emptively locked to a fluid by +dragging that fluid from JEI/EMI into the Hatch's output slot. +* Filter Locking only works with standard *single* fluid hatches, and cannot be done to the higher-tier Quadruple or +Nonuple Fluid Hatches. (However, those Hatches also cannot contain a single fluid in more than one slot, so they do +still allow for some degree of output separation when used with Quadruple or Nonuple Fluid Pipes.) +* Distinct Buses is a toggle used on Input Buses (not Hatches), which causes the machine to look at this bus as being +separate from all other Distinct Buses. (One distinct bus has no meaning, but two distinct buses on one machine will +cause the machine to search each distinct bus separately). +* Painted Buses/Hatches are hatches which have been Painted using a can of spray paint. Input Buses/Hatches which have been +Painted in the same color are looked at together by the machine searching for recipe inputs, but any items/fluids stored +in buses/hatches with a different color are not used for the search. The isolation works the same as for Distinct Buses, +but it allows for multiple buses/hatches to be searched together as a group. +* Prior to version 7.5.0, painting **Output** Buses/Hatches had no effect. Version 7.5.0 introduced machines pairing their +Painted Outputs to their Painted Inputs, such that if a recipe pulls items from a Painted Input, it can only output the +products of that recipe to a Painted Output of the same color (or an unpainted output). +* Buses and Hatches that are not painted, or not set to Distinct, are always fair game for the machine - Distinct and +Painted Inputs can always pull from other non-distinct and non-painted inputs; and recipes that used ingredients from +Painted Inputs can always send their products to non-painted outputs. + ## Passthrough Hatches and the Cleanroom The Cleanroom is a unique multiblock with unique restrictions. Because the Cleanroom must have solid walls, pipes, cables, and inventories outside cannot directly connect to machines inside. For this purpose, Passthrough Hatches exist. 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 898852884bc..a9728fe024f 100644 --- a/docs/content/Modpacks/Changes/v7.5.0.md +++ b/docs/content/Modpacks/Changes/v7.5.0.md @@ -2,11 +2,20 @@ title: "Version 7.5.0" --- - # Updating from `7.4.1` to `7.5.0` +!!! note + Because of these changes, when using GTM 7.5.0+ you can not compile your mod(pack) against addons or coremods that are compiled for 7.4.1 and touch anything related to machines. + Make sure that your dependencies have updated. + + +## 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`. + +## 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. -## 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`. +## Multiblock Structure Change +The Large Fractionating Still no longer requires a muffler hatch, allowing it to be used in cleanrooms. ## RecipeCondition Generics We have added a Generic argument to `RecipeCondition` describing the condition. @@ -20,6 +29,111 @@ You also need to adjust the generics of `getType()` and `createTemplate()` to ma - public RecipeCondition createTemplate() { + public ExampleCondition createTemplate() { ``` +## 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. -## 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. +## 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. + +## `GTRecipeBuilder#adjacentFluidTag()` and `GTRecipeBuilder#adjacentBlockTag()` +_This is only relevant to **add-on mods** with custom recipe types that use the condition(s). **KubeJS recipes are not affected.**_ + +The renames of `GTRecipeBuilder#adjacentFluid(TagKey...)` -> `#adjacentFluidTag(TagKey...)` and `GTRecipeBuilder#adjacentBlock(TagKey...)` -> `#adjacentBlockTag(TagKey...)` +have been deprecated in favor of naming every variant `adjacentFluids` and `adjacentBlocks`, respectively. +Please update your addon mods' recipes to use these new methods, as the now deprecated methods will be removed come 8.0.0. + +A full list of all deprecated methods & their replacement is as follows: +Fluids: `adjacentFluid`, `adjacentFluidTag` -> `adjacentFluids` +Blocks: `adjacentBlock`, `adjacentBlockTag` -> `adjacentBlocks` + +## Machine Recipe Failure Diagnostics +Machines now provide detailed diagnostics explaining why recipes fail to start. + +Failure reasons are displayed in: +- the sidebar of simple machines +- the UI of multiblock machines +- the Jade tooltip for all machines + +You are supposed to replace `ModifierFunction.NULL` with `ModifierFunction.cancel(reason)` to tell the machine why the recipe fails to start. +```patch +- return ModifierFunction.NULL; ++ return ModifierFunction.cancel(Component.translatable("gtceu.recipe_modifier.xxx")); +``` + +Also, if you cancel a recipe in `IRecipeLogicMachine#beforeWorking()`, you are supposed to add some custom reason info like: +``` +@Override +public boolean beforeWorking(@Nullable GTRecipe recipe) { + if(xxx){ + RecipeLogic.putFailureReason(this, recipe, Component.literal("Machine spirit is displeased")); + return false + } + return true; +} +``` + +## Painted Output Buses/Hatches +For some time, Spray Paint cans could be used to paint Input and Output Buses/Hatches on multiblock machines. +Version 7.0.0 added the feature that Painted Input Buses/Hatches of different colors would not share their ingredients with +each other when the machine ran recipes. This system is more fully explained at [Painted Inputs and Outputs](../../Gameplay/Logistics/Machines.md#distinct-painted-and-filtered-inputs-and-outputs). + +7.5.0 also applies this logic to Output Buses/Hatches as well. Input Buses/Hatches which have been painted are now only +allowed to send their outputs to Output Buses/Hatches that are of the same paint color, or unpainted. This may cause +existing setups to stop running, if they had painted Output Buses/hatches on them. + +## Change to GTRecipe constructor +GTRecipe has had one new field added to it and its constructors: `int groupColor`. For new recipes, this parameter +is set to `-1`; however for recipes that are being prepared and run, this field holds the Paint color of the +Painted Input Group that the recipe drew its inputs from. + +Addon mods which explicitly attempt to construct, copy, or apply their own ModifierFunctions to a GTRecipe +(not using the standard builder or kjs functions) will need to either add the additional `int` parameter to the end of +their constructor calls, or the additional `recipe.groupColor` to their copy calls. + +## Added BiomeTagCondition +Added a new RecipeCondition called BiomeTagCondition for needing a specific biome tag. This can be used with KubeJS using `.biomeTag("biome")`. diff --git a/docs/content/Modpacks/Materials-and-Elements/Tool-Creation.md b/docs/content/Modpacks/Materials-and-Elements/Tool-Creation.md index cd5a6dac2ab..55bc0cc865f 100644 --- a/docs/content/Modpacks/Materials-and-Elements/Tool-Creation.md +++ b/docs/content/Modpacks/Materials-and-Elements/Tool-Creation.md @@ -59,7 +59,7 @@ The builder has the same arguments as the constructor, and can have chained meth - `ignoreCraftingTools()` - Disable crafting tools being made from this Material. -- `addEnchantmentForTools(Enchantment enchantment, int level)` +- `.enchantment(Enchantment enchantment, int level)` - Enchantment is the default enchantment applied on tool creation. Level is the level of said enchantment. - `enchantability(int enchantability)` @@ -82,7 +82,7 @@ Here is an example of using the builder in a material: ] ) .unbreakable() - .addEnchantmentForTools(silk_touch, 1) + .enchantment(SILK_TOUCH, 1) .build() ) }); diff --git a/docs/content/Modpacks/Other-Topics/Central-Monitor.md b/docs/content/Modpacks/Other-Topics/Central-Monitor.md new file mode 100644 index 00000000000..c199ae1790d --- /dev/null +++ b/docs/content/Modpacks/Other-Topics/Central-Monitor.md @@ -0,0 +1,107 @@ +--- +title: Central Monitor & Placeholder System +--- + +### Custom monitor modules +If you want to add a monitor module, simply attach a component that implements `IMonitorModuleItem` to your `ComponentItem`. +Modules can have a custom UI, can be ticked (in a placeholder or not) and, most importantly, rendered. +??? example "Example of a custom module in Java" + ```java + public class ExampleModuleBehaviour implements IMonitorModuleItem { + @Override + public String getType() { + // can be any string, this is currently only used for CC: Tweaked compat + return "example"; + } + + @Override + public void tick(ItemStack stack, CentralMonitorMachine machine, MonitorGroup group) { + // this is only called on the logical server + // put all of your module's logic here instead of in getRenderer(stack) + // can also be left completely empty (like in the image module) + } + + @Override + public void tickInPlaceholder(ItemStack stack, PlaceholderContext context) { + // this is also only called on the logical server, but only when a placeholder accesses this module and wants to render it + // this *isn't* called on each tick + // you can even put the same code here as in the tick() method, like the text module does + } + + @Override + public IMonitorRenderer getRenderer(ItemStack stack) { + // this is only called on the logical client + // should return a new instance of the renderer for this module (not null) + // for examples of renderer code look in the GTCEu Modern github: + // https://github.com/GregTechCEu/GregTech-Modern/tree/1.20.1/src/main/java/com/gregtechceu/gtceu/client/renderer + return new MonitorTextRenderer(MultiLineComponent.of("this text is displayed on the monitor"), 1.0); + } + + @Override + public Widget createUIWidget(ItemStack stack, CentralMonitorMachine machine, MonitorGroup group) { + // should create the UI for your module and return it + // if the module doesn't need a UI just return new WidgetGroup() + return new WidgetGroup(); + } + } + ``` + +!!! info "For info on the placeholder system itself, see [the gameplay wiki page](../../Gameplay/Central-Monitor.md)" + +### Adding custom placeholders + +Placeholders can be added by calling `PlaceholderHandler.addPlaceholder(...)` at any point during runtime (preferably at mod init time). +They can take any number of arguments in the form of a `List`. They also take an instance of `PlaceholderContext` and +must return a `MultiLineComponent`. Placeholders can also render literally anything, not only text, using `MultiLineComponent.addRenderer()`, +`GraphicsComponent` and an `IPlaceholderRenderer` (that has to be registered separately using `PlaceholderHandler.addRenderer(...)`) + +??? example "Example of a `sum` placeholder in Java" + ```java + public class Example { + // you should call this function at mod initialization + public static void addPlaceholders() { + int priority = 1; // by default the priority of all placeholders is 0 (you don't have to specify it) + PlaceholderHandler.addPlaceholder(new Placeholder("sum", priority) { + @Override + public MultiLineComponent apply(PlaceholderContext ctx, List args) throws PlaceholderException { + PlaceholderUtils.checkArgs(args, 2); // check that there are exactly 2 arguments + double a = PlaceholderUtils.toDouble(args.get(0)); + double b = PlaceholderUtils.toDouble(args.get(1)); + return MultiLineComponent.literal(a + b); + } + }); + // you can call addPlaceholder as many times as you need + // if you want to override an existing placeholder, simply add a new one with the same name and a higher or equal priority + } + } + ``` + +!!! tip "Placeholder exceptions" + Any runtime exception that occurs while processing a placeholder will be caught and even displayed to the player. + Instead of relying on runtime exceptions though, you should throw any subclass of `PlaceholderException`, for example + `InvalidNumberException` or `MissingItemException`. All the `PlaceholderUtils` methods throw these, so you should use them + instead of calling `parseDouble` yourself, for example. + +!!! note "Placeholder data" + If your placeholder needs to save any data specific to the placeholder caller, you can use `getData(ctx)` at any point in + a placeholder. It will return a `CompoundTag` that is automatically saved, and you're free to modify it in whatever way you want. + +### Placeholder graphics + +You may have noticed, that some placeholders output graphics instead of text, for example `rect` or `quad`. +To achieve that you have to write your own class that implements `IPlaceholderRenderer`, or use an existing one. +They work similarly to normal renderers, except you can pass a `CompoundTag` into them from your placeholder. +To register one, call `PlaceholderHandler.addRenderer("put_id_here", new YourRendererClassHere())`. +After that, you can reference it from any placeholder by calling `output.addGraphics(new GraphicsComponent(x, y, "put_id_here", renderData)` +on the object that your placeholder will return. `renderData` is the same `CompoundTag` that will be passed into your renderer as an argument. +This is done to avoid calling rendering code on the server side, as all placeholders are processed server-side only. A neat side effect of that +is that all players will (almost always) see the same thing on the monitor. + +!!! warning "Graphics do not work on the Computer Monitor Cover" + +### Placeholder parsing + +You may want to add something that needs to parse a string containing placeholders. To achieve that, you can use +`PlaceholderHandler.processPlaceholders(string, context)`. You can also use `PlaceholderHandler.placeholderExists(name)` +to check if a placeholder exists, or `PlaceholderHandler.getAllPlaceholderNames()` to get all placeholders. +To get a `PlaceholderContext`, you just have to call its constructor (it takes in basic parameters like `Level`, `BlockPos`, etc., most of which can be `null`). \ No newline at end of file diff --git a/docs/content/Modpacks/Recipes/Recipe-Conditions.md b/docs/content/Modpacks/Recipes/Recipe-Conditions.md index 5bd1a33e75b..fd3753ae7b6 100644 --- a/docs/content/Modpacks/Recipes/Recipe-Conditions.md +++ b/docs/content/Modpacks/Recipes/Recipe-Conditions.md @@ -12,8 +12,8 @@ These conditions can be used in both Java and KubeJS recipes. However, custom co ### Base Conditons - Biome: `.biome("namespace:biome_id")` - - Locks a recipe behind being inside a certain biome, works with any biome a pack has loaded. - For example, you could do `.biome("minecraft:plains")`. + - Locks a recipe behind being inside a certain biome, works with any biome a pack has loaded. + For example, you could use `minecraft:plains`. We also have `biomeTag("minecraft:biome")`. - Dimension: `.dimension("namespace:dimension_id")` - Locks a recipe being behind a certain dimension, the gas collector is a good example of this. - For example, you could do `.dimension("minecraft:the_end")` diff --git a/gradle.properties b/gradle.properties index 9b9873e5704..2bb51a408ce 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,7 @@ org.gradle.caching = true # Mod Info mod_id = gtceu mod_name = GregTech -mod_version = 7.5.0 +mod_version = 8.0.0 mod_description = GregTech CE Unofficial, ported from 1.12.2 mod_license = LGPL-3.0 license mod_url = https://github.com/GregTechCEu/GregTech-Modern/ diff --git a/gradle/scripts/repositories.gradle b/gradle/scripts/repositories.gradle index 95e4a23c400..167432e271f 100644 --- a/gradle/scripts/repositories.gradle +++ b/gradle/scripts/repositories.gradle @@ -1,6 +1,14 @@ repositories { mavenLocal() mavenCentral() + // force gradle to download FastUtil & LWJGL from the central maven so we can get source artifacts + exclusiveContent { // Force + forRepository { mavenCentral() } + filter { + includeGroup("it.unimi.dsi") + includeGroup("org.lwjgl") + } + } maven { // JEI name = "Jared's Maven" 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/lang/en_ud.json b/src/generated/resources/assets/gtceu/lang/en_ud.json index 9d11dd6f334..892d9e3836c 100644 --- a/src/generated/resources/assets/gtceu/lang/en_ud.json +++ b/src/generated/resources/assets/gtceu/lang/en_ud.json @@ -67,6 +67,7 @@ "behaviour.lighter.uses": "%d :sǝsn buıuıɐɯǝᴚ", "behaviour.memory_card.client_msg.cleared": "pǝɹɐǝןɔ uoıʇɐɹnbıɟuoɔ pǝɹoʇS", "behaviour.memory_card.client_msg.copied": "uoıʇɐɹnbıɟuoɔ ǝuıɥɔɐɯ pǝıdoƆ", + "behaviour.memory_card.client_msg.missing_items": "uoıʇɐɹnbıɟuoɔ ǝʇsɐd oʇ pǝɹınbǝɹ sɯǝʇı buıssıW", "behaviour.memory_card.client_msg.pasted": "uoıʇɐɹnbıɟuoɔ ǝuıɥɔɐɯ pǝıןddⱯ", "behaviour.memory_card.copy_target": "%s :buıʎdoƆ", "behaviour.memory_card.disabled": "ɹ§pǝןqɐsıᗡɔ§", @@ -1746,6 +1747,7 @@ "config.gtceu.option.addLoot": "ʇooꞀppɐ", "config.gtceu.option.ae2": "ᄅǝɐ", "config.gtceu.option.allowDrumsInputFluidsFromOutputSide": "ǝpıSʇndʇnOɯoɹℲspınןℲʇnduIsɯnɹᗡʍoןןɐ", + "config.gtceu.option.allowedImageDomains": "suıɐɯoᗡǝbɐɯIpǝʍoןןɐ", "config.gtceu.option.animationTime": "ǝɯı⟘uoıʇɐɯıuɐ", "config.gtceu.option.arcRecyclingYield": "pןǝıʎbuıןɔʎɔǝᴚɔɹɐ", "config.gtceu.option.armorHud": "pnHɹoɯɹɐ", @@ -1759,6 +1761,7 @@ "config.gtceu.option.casingsPerCraft": "ʇɟɐɹƆɹǝԀsbuısɐɔ", "config.gtceu.option.cleanMultiblocks": "sʞɔoןqıʇןnWuɐǝןɔ", "config.gtceu.option.client": "ʇuǝıןɔ", + "config.gtceu.option.coloredMaterialBlockOutline": "ǝuıןʇnOʞɔoןᗺןɐıɹǝʇɐWpǝɹoןoɔ", "config.gtceu.option.coloredTieredMachineOutline": "ǝuıןʇnOǝuıɥɔɐWpǝɹǝı⟘pǝɹoןoɔ", "config.gtceu.option.coloredWireOutline": "ǝuıןʇnOǝɹıMpǝɹoןoɔ", "config.gtceu.option.compat": "ʇɐdɯoɔ", @@ -1893,7 +1896,7 @@ "config.gtceu.option.steelSteamMultiblocks": "sʞɔoןqıʇןnWɯɐǝʇSןǝǝʇs", "config.gtceu.option.surfaceRockProspectRange": "ǝbuɐᴚʇɔǝdsoɹԀʞɔoᴚǝɔɐɟɹns", "config.gtceu.option.tankItemFluidPreview": "ʍǝıʌǝɹԀpınןℲɯǝʇIʞuɐʇ", - "config.gtceu.option.temperaturesInKelvin": "uıʌןǝʞuIsǝɹnʇɐɹǝdɯǝʇ", + "config.gtceu.option.temperaturesInCelsius": "snısןǝƆuIsǝɹnʇɐɹǝdɯǝʇ", "config.gtceu.option.titaniumBoilerHeatSpeed": "pǝǝdSʇɐǝHɹǝןıoᗺɯnıuɐʇıʇ", "config.gtceu.option.titaniumBoilerMaxTemperature": "ǝɹnʇɐɹǝdɯǝ⟘xɐWɹǝןıoᗺɯnıuɐʇıʇ", "config.gtceu.option.toggle": "ǝןbboʇ", @@ -2617,6 +2620,7 @@ "gtceu.key.armor_mode_switch": "ɥɔʇıʍS ǝpoW ɹoɯɹⱯ", "gtceu.key.enable_boots": "dɯnſ pǝʇsooᗺ ǝןqɐuƎ", "gtceu.key.enable_jetpack": "ʞɔɐdʇǝſ ǝןqɐuƎ", + "gtceu.key.enable_step_assist": "ʇsıssⱯdǝʇS ǝןqɐuƎ", "gtceu.key.tool_aoe_change": "ɥɔʇıʍS ǝpoW ƎoⱯ ןoo⟘", "gtceu.large_boiler": "ɹǝןıoᗺ ǝbɹɐꞀ", "gtceu.large_chemical_reactor": "ɹoʇɔɐǝᴚ ןɐɔıɯǝɥƆ ǝbɹɐꞀ", @@ -3760,8 +3764,14 @@ "gtceu.recipe_logic.insufficient_out": "sʇndʇnO ʇuǝıɔıɟɟnsuI", "gtceu.recipe_logic.no_capabilities": "sǝıʇıןıqɐdɐƆ ou sɐɥ ǝuıɥɔɐW", "gtceu.recipe_logic.no_contents": "sʇuǝʇuoƆ ou sɐɥ ǝdıɔǝᴚ", + "gtceu.recipe_logic.recipe_waiting": " :buıʇıɐM ǝdıɔǝᴚ", + "gtceu.recipe_logic.setup_fail": " :ǝdıɔǝɹ dnʇǝs oʇ ןıɐℲ", "gtceu.recipe_memory_widget.tooltip.0": "pıɹb buıʇɟɐɹɔ ǝɥʇ oʇuı ǝdıɔǝɹ sıɥʇ ʇnduı ʎןןɐɔıʇɐɯoʇnɐ oʇ ʞɔıןɔ ʇɟǝꞀㄥ§", "gtceu.recipe_memory_widget.tooltip.1": "ǝdıɔǝɹ sıɥʇ ʞɔoןun/ʞɔoן oʇ ʞɔıןɔ ʇɟıɥSㄥ§", + "gtceu.recipe_modifier.coil_temperature_too_low": "ʍoꞀ oo⟘ ǝɹnʇɐɹǝdɯǝ⟘ ןıoƆ", + "gtceu.recipe_modifier.default_fail": "ןıɐℲ ɹǝıɟıpoW ǝdıɔǝᴚ", + "gtceu.recipe_modifier.insufficient_eu_to_start_fusion": "uoıʇɔɐǝᴚ uoısnℲ ǝʇɐıʇıuI oʇ ʎbɹǝuƎ ʇuǝıɔıɟɟnsuI", + "gtceu.recipe_modifier.insufficient_voltage": "ʍoꞀ oo⟘ ɹǝı⟘ ǝbɐʇןoΛ", "gtceu.recipe_type.show_recipes": "sǝdıɔǝᴚ ʍoɥS", "gtceu.rei.group.potion_fluids": "spınןℲ uoıʇoԀ", "gtceu.research_station": "uoıʇɐʇS ɥɔɹɐǝsǝᴚ", @@ -4734,7 +4744,7 @@ "item.gtceu.talc_dust": "ɔןɐ⟘", "item.gtceu.tantalum_capacitor": "ɹoʇıɔɐdɐƆ ɯnןɐʇuɐ⟘", "item.gtceu.terminal": "ןɐuıɯɹǝ⟘", - "item.gtceu.terminal.tooltip": "ʞɔoןq-ıʇןnɯ ǝɥʇ pןınq ʎןןɐɔıʇɐɯoʇnɐ oʇ ɹǝןןoɹʇuoɔ ɐ uo ʞɔıןƆ-ᴚ + ʇɟıɥS", + "item.gtceu.terminal.tooltip": "ʎɹoʇuǝʌuı ɹnoʎ ɯoɹɟ sɯǝʇı ɥʇıʍ ʞɔoןqıʇןnɯ ɐ pןınq ʎןןɐɔıʇɐɯoʇnɐ oʇ ɹǝןןoɹʇuoɔ ɐ uo ʞɔıןƆ-ᴚ + ʇɟıɥS", "item.gtceu.text_module": "ǝןnpoW ʇxǝ⟘", "item.gtceu.tiny_ash_dust": "sǝɥsⱯ ɟo ǝןıԀ ʎuı⟘", "item.gtceu.tiny_basaltic_mineral_sand_dust": "puɐS ןɐɹǝuıW ɔıʇןɐsɐᗺ ɟo ǝןıԀ ʎuı⟘", @@ -4837,7 +4847,7 @@ "item.gtceu.tool.lv_screwdriver.tooltip": "sǝuıɥɔɐW puɐ sɹǝʌoƆ sʇsnظpⱯ8§", "item.gtceu.tool.lv_wirecutter": ")ΛꞀ( ɹǝʇʇnƆ ǝɹıM %s", "item.gtceu.tool.lv_wrench": ")ΛꞀ( ɥɔuǝɹM %s", - "item.gtceu.tool.lv_wrench.tooltip": "sǝuıɥɔɐW ǝןʇuɐɯsıp oʇs ʞɔıןɔ ʇɟǝן pןoH8§", + "item.gtceu.tool.lv_wrench.tooltip": "sǝuıɥɔɐW ǝןʇuɐɯsıp oʇ ʞɔıןɔ ʇɟǝן pןoH8§", "item.gtceu.tool.mallet": "ʇǝןןɐW ʇɟoS %s", "item.gtceu.tool.mallet.tooltip.0": "˙ǝdıɔǝᴚ ʇuǝɹɹnƆ ɹǝʇɟⱯ ǝuıɥɔɐW ǝsnɐԀ oʇ ʞɐǝuS8§", "item.gtceu.tool.mallet.tooltip.1": "sǝuıɥɔɐW sʇɹɐʇS/sdoʇS8§", @@ -5699,20 +5709,24 @@ "metaarmor.message.nightvision.disabled": "ɟɟOɔ§ :uoısıΛʇɥbıNq§", "metaarmor.message.nightvision.enabled": "uOɐ§ :uoısıΛʇɥbıNq§", "metaarmor.message.nightvision.error": "¡ɹǝʍod ɥbnouǝ ʇoNɔ§", - "metaarmor.nms.boosted_jump.disabled": "pǝןqɐsıᗡ ʇsooᗺ dɯnſ :ǝʇınS ™ǝןɔsnWouɐN", - "metaarmor.nms.boosted_jump.enabled": "pǝןqɐuƎ ʇsooᗺ dɯnſ :ǝʇınS ™ǝןɔsnWouɐN", "metaarmor.nms.nightvision.disabled": "pǝןqɐsıᗡ uoısıΛʇɥbıN :ǝʇınS ™ǝןɔsnWouɐN", "metaarmor.nms.nightvision.enabled": "pǝןqɐuƎ uoısıΛʇɥbıN :ǝʇınS ™ǝןɔsnWouɐN", "metaarmor.nms.nightvision.error": "¡ɹǝʍod ɥbnouǝ ʇoNɔ§ :ǝʇınS ™ǝןɔsnWouɐN", "metaarmor.nms.share.disable": "pǝןqɐsıᗡ buıbɹɐɥƆ :ǝʇınS ™ǝןɔsnWouɐN", "metaarmor.nms.share.enable": "pǝןqɐuƎ buıbɹɐɥƆ :ǝʇınS ™ǝןɔsnWouɐN", "metaarmor.nms.share.error": "¡buıbɹɐɥɔ ɹoɟ ɹǝʍod ɥbnouǝ ʇoNɔ§ :ǝʇınS ™ǝןɔsnWouɐN", + "metaarmor.nms.step_assist.disabled": "pǝןqɐsıᗡ ʇsıssⱯdǝʇS :ǝʇınS ™ǝןɔsnWouɐN", + "metaarmor.nms.step_assist.enabled": "pǝןqɐuƎ ʇsıssⱯdǝʇS :ǝʇınS ™ǝןɔsnWouɐN", + "metaarmor.qts.boosted_jump.disabled": "pǝןqɐsıᗡ ʇsooᗺ dɯnſ :ǝʇınS ™ɥɔǝ⟘ʞɹɐnὉ", + "metaarmor.qts.boosted_jump.enabled": "pǝןqɐuƎ ʇsooᗺ dɯnſ :ǝʇınS ™ɥɔǝ⟘ʞɹɐnὉ", "metaarmor.qts.nightvision.disabled": "pǝןqɐsıᗡ uoısıΛʇɥbıN :ǝʇınS ™ɥɔǝ⟘ʞɹɐnὉ", "metaarmor.qts.nightvision.enabled": "pǝןqɐuƎ uoısıΛʇɥbıN :ǝʇınS ™ɥɔǝ⟘ʞɹɐnὉ", "metaarmor.qts.nightvision.error": "¡ɹǝʍod ɥbnouǝ ʇoNɔ§ :ǝʇınS ™ɥɔǝ⟘ʞɹɐnὉ", "metaarmor.qts.share.disable": "pǝןqɐsıᗡ buıbɹɐɥƆ :ǝʇınS ™ɥɔǝ⟘ʞɹɐnὉ", "metaarmor.qts.share.enable": "pǝןqɐuƎ buıbɹɐɥƆ :ǝʇınS ™ɥɔǝ⟘ʞɹɐnὉ", "metaarmor.qts.share.error": "¡buıbɹɐɥɔ ɹoɟ ɹǝʍod ɥbnouǝ ʇoNɔ§ :ǝʇınS ™ɥɔǝ⟘ʞɹɐnὉ", + "metaarmor.qts.step_assist.disabled": "pǝןqɐsıᗡ ʇsıssⱯdǝʇS :ǝʇınS ™ɥɔǝ⟘ʞɹɐnὉ", + "metaarmor.qts.step_assist.enabled": "pǝןqɐuƎ ʇsıssⱯdǝʇS :ǝʇınS ™ɥɔǝ⟘ʞɹɐnὉ", "metaarmor.tooltip.autoeat": "ʎɹoʇuǝʌuI ɯoɹɟ pooℲ buıs∩ ʎq ɹɐᗺ pooℲ sǝɥsıuǝןdǝᴚ", "metaarmor.tooltip.breath": "ɹɐᗺ ɥʇɐǝɹᗺ ɹǝʇɐʍɹǝpu∩ sǝɥsıuǝןdǝᴚ", "metaarmor.tooltip.burning": "buıuɹnᗺ sǝıɟıןןnN", diff --git a/src/generated/resources/assets/gtceu/lang/en_us.json b/src/generated/resources/assets/gtceu/lang/en_us.json index b8c93957f9c..35d0223ccab 100644 --- a/src/generated/resources/assets/gtceu/lang/en_us.json +++ b/src/generated/resources/assets/gtceu/lang/en_us.json @@ -67,6 +67,7 @@ "behaviour.lighter.uses": "Remaining uses: %d", "behaviour.memory_card.client_msg.cleared": "Stored configuration cleared", "behaviour.memory_card.client_msg.copied": "Copied machine configuration", + "behaviour.memory_card.client_msg.missing_items": "Missing items required to paste configuration", "behaviour.memory_card.client_msg.pasted": "Applied machine configuration", "behaviour.memory_card.copy_target": "Copying: %s", "behaviour.memory_card.disabled": "§cDisabled§r", @@ -1746,6 +1747,7 @@ "config.gtceu.option.addLoot": "addLoot", "config.gtceu.option.ae2": "ae2", "config.gtceu.option.allowDrumsInputFluidsFromOutputSide": "allowDrumsInputFluidsFromOutputSide", + "config.gtceu.option.allowedImageDomains": "allowedImageDomains", "config.gtceu.option.animationTime": "animationTime", "config.gtceu.option.arcRecyclingYield": "arcRecyclingYield", "config.gtceu.option.armorHud": "armorHud", @@ -1759,6 +1761,7 @@ "config.gtceu.option.casingsPerCraft": "casingsPerCraft", "config.gtceu.option.cleanMultiblocks": "cleanMultiblocks", "config.gtceu.option.client": "client", + "config.gtceu.option.coloredMaterialBlockOutline": "coloredMaterialBlockOutline", "config.gtceu.option.coloredTieredMachineOutline": "coloredTieredMachineOutline", "config.gtceu.option.coloredWireOutline": "coloredWireOutline", "config.gtceu.option.compat": "compat", @@ -1893,7 +1896,7 @@ "config.gtceu.option.steelSteamMultiblocks": "steelSteamMultiblocks", "config.gtceu.option.surfaceRockProspectRange": "surfaceRockProspectRange", "config.gtceu.option.tankItemFluidPreview": "tankItemFluidPreview", - "config.gtceu.option.temperaturesInKelvin": "temperaturesInKelvin", + "config.gtceu.option.temperaturesInCelsius": "temperaturesInCelsius", "config.gtceu.option.titaniumBoilerHeatSpeed": "titaniumBoilerHeatSpeed", "config.gtceu.option.titaniumBoilerMaxTemperature": "titaniumBoilerMaxTemperature", "config.gtceu.option.toggle": "toggle", @@ -2617,8 +2620,8 @@ "gtceu.key.armor_mode_switch": "Armor Mode Switch", "gtceu.key.enable_boots": "Enable Boosted Jump", "gtceu.key.enable_jetpack": "Enable Jetpack", - "gtceu.key.tool_aoe_change": "Tool AoE Mode Switch", "gtceu.key.enable_step_assist": "Enable StepAssist", + "gtceu.key.tool_aoe_change": "Tool AoE Mode Switch", "gtceu.large_boiler": "Large Boiler", "gtceu.large_chemical_reactor": "Large Chemical Reactor", "gtceu.laser_engraver": "Laser Engraver", @@ -3761,8 +3764,14 @@ "gtceu.recipe_logic.insufficient_out": "Insufficient Outputs", "gtceu.recipe_logic.no_capabilities": "Machine has no Capabilities", "gtceu.recipe_logic.no_contents": "Recipe has no Contents", + "gtceu.recipe_logic.recipe_waiting": "Recipe Waiting: ", + "gtceu.recipe_logic.setup_fail": "Fail to setup recipe: ", "gtceu.recipe_memory_widget.tooltip.0": "§7Left click to automatically input this recipe into the crafting grid", "gtceu.recipe_memory_widget.tooltip.1": "§7Shift click to lock/unlock this recipe", + "gtceu.recipe_modifier.coil_temperature_too_low": "Coil Temperature Too Low", + "gtceu.recipe_modifier.default_fail": "Recipe Modifier Fail", + "gtceu.recipe_modifier.insufficient_eu_to_start_fusion": "Insufficient Energy to Initiate Fusion Reaction", + "gtceu.recipe_modifier.insufficient_voltage": "Voltage Tier Too Low", "gtceu.recipe_type.show_recipes": "Show Recipes", "gtceu.rei.group.potion_fluids": "Potion Fluids", "gtceu.research_station": "Research Station", @@ -4735,7 +4744,7 @@ "item.gtceu.talc_dust": "Talc", "item.gtceu.tantalum_capacitor": "Tantalum Capacitor", "item.gtceu.terminal": "Terminal", - "item.gtceu.terminal.tooltip": "Shift + R-Click on a controller to automatically build the multi-block", + "item.gtceu.terminal.tooltip": "Shift + R-Click on a controller to automatically build a multiblock with items from your inventory", "item.gtceu.text_module": "Text Module", "item.gtceu.tiny_ash_dust": "Tiny Pile of Ashes", "item.gtceu.tiny_basaltic_mineral_sand_dust": "Tiny Pile of Basaltic Mineral Sand", @@ -5700,26 +5709,24 @@ "metaarmor.message.nightvision.disabled": "§bNightVision: §cOff", "metaarmor.message.nightvision.enabled": "§bNightVision: §aOn", "metaarmor.message.nightvision.error": "§cNot enough power!", - "metaarmor.message.step_assist.disabled": "StepAssist: §cOff", - "metaarmor.message.step_assist.enabled": "StepAssist: §aOn", "metaarmor.nms.nightvision.disabled": "NanoMuscle™ Suite: NightVision Disabled", "metaarmor.nms.nightvision.enabled": "NanoMuscle™ Suite: NightVision Enabled", "metaarmor.nms.nightvision.error": "NanoMuscle™ Suite: §cNot enough power!", - "metaarmor.qts.nightvision.disabled": "QuarkTech™ Suite: NightVision Disabled", - "metaarmor.qts.nightvision.enabled": "QuarkTech™ Suite: NightVision Enabled", - "metaarmor.qts.nightvision.error": "QuarkTech™ Suite: §cNot enough power!", - "metaarmor.nms.step_assist.disabled": "NanoMuscle™ Suite: StepAssist Disabled", - "metaarmor.nms.step_assist.enabled": "NanoMuscle™ Suite: StepAssist Enabled", - "metaarmor.qts.step_assist.disabled": "QuarkTech™ Suite: StepAssist Disabled", - "metaarmor.qts.step_assist.enabled": "QuarkTech™ Suite: StepAssist Enabled", "metaarmor.nms.share.disable": "NanoMuscle™ Suite: Charging Disabled", "metaarmor.nms.share.enable": "NanoMuscle™ Suite: Charging Enabled", "metaarmor.nms.share.error": "NanoMuscle™ Suite: §cNot enough power for charging!", + "metaarmor.nms.step_assist.disabled": "NanoMuscle™ Suite: StepAssist Disabled", + "metaarmor.nms.step_assist.enabled": "NanoMuscle™ Suite: StepAssist Enabled", + "metaarmor.qts.boosted_jump.disabled": "QuarkTech™ Suite: Jump Boost Disabled", + "metaarmor.qts.boosted_jump.enabled": "QuarkTech™ Suite: Jump Boost Enabled", + "metaarmor.qts.nightvision.disabled": "QuarkTech™ Suite: NightVision Disabled", + "metaarmor.qts.nightvision.enabled": "QuarkTech™ Suite: NightVision Enabled", + "metaarmor.qts.nightvision.error": "QuarkTech™ Suite: §cNot enough power!", "metaarmor.qts.share.disable": "QuarkTech™ Suite: Charging Disabled", "metaarmor.qts.share.enable": "QuarkTech™ Suite: Charging Enabled", "metaarmor.qts.share.error": "QuarkTech™ Suite: §cNot enough power for charging!", - "metaarmor.qts.boosted_jump.disabled": "QuarkTech™ Suite: Jump Boost Disabled", - "metaarmor.qts.boosted_jump.enabled": "QuarkTech™ Suite: Jump Boost Enabled", + "metaarmor.qts.step_assist.disabled": "QuarkTech™ Suite: StepAssist Disabled", + "metaarmor.qts.step_assist.enabled": "QuarkTech™ Suite: StepAssist Enabled", "metaarmor.tooltip.autoeat": "Replenishes Food Bar by Using Food from Inventory", "metaarmor.tooltip.breath": "Replenishes Underwater Breath Bar", "metaarmor.tooltip.burning": "Nullifies Burning", 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..94e63584b2c --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/pipe/huge_duct_pipe/center.json @@ -0,0 +1,48 @@ +{ + "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 + ] + } + ], + "render_type": "minecraft:cutout_mipped", + "textures": { + "particle": "#side", + "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..e76d23f3a85 --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/pipe/huge_duct_pipe/connection.json @@ -0,0 +1,50 @@ +{ + "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 + ] + } + ], + "render_type": "minecraft:cutout_mipped", + "textures": { + "end": "gtceu:block/pipe/pipe_duct_in", + "particle": "#side", + "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..a2321bea230 --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/pipe/large_duct_pipe/center.json @@ -0,0 +1,48 @@ +{ + "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 + ] + } + ], + "render_type": "minecraft:cutout_mipped", + "textures": { + "particle": "#side", + "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..3cbd0c515e5 --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/pipe/large_duct_pipe/connection.json @@ -0,0 +1,50 @@ +{ + "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 + ] + } + ], + "render_type": "minecraft:cutout_mipped", + "textures": { + "end": "gtceu:block/pipe/pipe_duct_in", + "particle": "#side", + "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..1c26580e3bf --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/pipe/normal_duct_pipe/center.json @@ -0,0 +1,48 @@ +{ + "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 + ] + } + ], + "render_type": "minecraft:cutout_mipped", + "textures": { + "particle": "#side", + "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..8dd3319f1de --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/pipe/normal_duct_pipe/connection.json @@ -0,0 +1,50 @@ +{ + "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 + ] + } + ], + "render_type": "minecraft:cutout_mipped", + "textures": { + "end": "gtceu:block/pipe/pipe_duct_in", + "particle": "#side", + "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..465a616919f --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/pipe/normal_laser_pipe/center.json @@ -0,0 +1,87 @@ +{ + "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 + ] + } + ], + "render_type": "minecraft:cutout_mipped", + "textures": { + "particle": "#side", + "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..d7ad0f481b2 --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/pipe/normal_laser_pipe/center_active.json @@ -0,0 +1,117 @@ +{ + "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": { + "forge_data": { + "ambient_occlusion": false, + "block_light": 15, + "sky_light": 15 + }, + "texture": "#side_overlay", + "tintindex": 2 + }, + "east": { + "forge_data": { + "ambient_occlusion": false, + "block_light": 15, + "sky_light": 15 + }, + "texture": "#side_overlay", + "tintindex": 2 + }, + "north": { + "forge_data": { + "ambient_occlusion": false, + "block_light": 15, + "sky_light": 15 + }, + "texture": "#side_overlay", + "tintindex": 2 + }, + "south": { + "forge_data": { + "ambient_occlusion": false, + "block_light": 15, + "sky_light": 15 + }, + "texture": "#side_overlay", + "tintindex": 2 + }, + "up": { + "forge_data": { + "ambient_occlusion": false, + "block_light": 15, + "sky_light": 15 + }, + "texture": "#side_overlay", + "tintindex": 2 + }, + "west": { + "forge_data": { + "ambient_occlusion": false, + "block_light": 15, + "sky_light": 15 + }, + "texture": "#side_overlay", + "tintindex": 2 + } + }, + "from": [ + 4.998, + 4.998, + 4.998 + ], + "to": [ + 11.002, + 11.002, + 11.002 + ] + } + ], + "render_type": "minecraft:cutout_mipped", + "textures": { + "particle": "#side", + "side": "gtceu:block/pipe/pipe_laser_side", + "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..9e2730a1c5b --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/pipe/normal_laser_pipe/connection.json @@ -0,0 +1,81 @@ +{ + "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 + ] + } + ], + "render_type": "minecraft:cutout_mipped", + "textures": { + "end": "gtceu:block/pipe/pipe_laser_in", + "particle": "#side", + "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..f45e0d010d3 --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/pipe/normal_laser_pipe/connection_active.json @@ -0,0 +1,101 @@ +{ + "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": { + "forge_data": { + "ambient_occlusion": false, + "block_light": 15, + "sky_light": 15 + }, + "texture": "#side_overlay", + "tintindex": 2 + }, + "north": { + "forge_data": { + "ambient_occlusion": false, + "block_light": 15, + "sky_light": 15 + }, + "texture": "#side_overlay", + "tintindex": 2 + }, + "south": { + "forge_data": { + "ambient_occlusion": false, + "block_light": 15, + "sky_light": 15 + }, + "texture": "#side_overlay", + "tintindex": 2 + }, + "west": { + "forge_data": { + "ambient_occlusion": false, + "block_light": 15, + "sky_light": 15 + }, + "texture": "#side_overlay", + "tintindex": 2 + } + }, + "from": [ + 4.998, + -0.002, + 4.998 + ], + "to": [ + 11.002, + 5.002, + 11.002 + ] + } + ], + "render_type": "minecraft:cutout_mipped", + "textures": { + "end": "gtceu:block/pipe/pipe_laser_in", + "particle": "#side", + "side": "gtceu:block/pipe/pipe_laser_side", + "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..ff938952e9e --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/pipe/normal_optical_pipe/center.json @@ -0,0 +1,87 @@ +{ + "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 + ] + } + ], + "render_type": "minecraft:cutout_mipped", + "textures": { + "particle": "#side", + "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..ca30b085f41 --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/pipe/normal_optical_pipe/center_active.json @@ -0,0 +1,117 @@ +{ + "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": { + "forge_data": { + "ambient_occlusion": false, + "block_light": 15, + "sky_light": 15 + }, + "texture": "#side_overlay", + "tintindex": 2 + }, + "east": { + "forge_data": { + "ambient_occlusion": false, + "block_light": 15, + "sky_light": 15 + }, + "texture": "#side_overlay", + "tintindex": 2 + }, + "north": { + "forge_data": { + "ambient_occlusion": false, + "block_light": 15, + "sky_light": 15 + }, + "texture": "#side_overlay", + "tintindex": 2 + }, + "south": { + "forge_data": { + "ambient_occlusion": false, + "block_light": 15, + "sky_light": 15 + }, + "texture": "#side_overlay", + "tintindex": 2 + }, + "up": { + "forge_data": { + "ambient_occlusion": false, + "block_light": 15, + "sky_light": 15 + }, + "texture": "#side_overlay", + "tintindex": 2 + }, + "west": { + "forge_data": { + "ambient_occlusion": false, + "block_light": 15, + "sky_light": 15 + }, + "texture": "#side_overlay", + "tintindex": 2 + } + }, + "from": [ + 4.998, + 4.998, + 4.998 + ], + "to": [ + 11.002, + 11.002, + 11.002 + ] + } + ], + "render_type": "minecraft:cutout_mipped", + "textures": { + "particle": "#side", + "side": "gtceu:block/pipe/pipe_optical_side", + "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..d01e5420817 --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/pipe/normal_optical_pipe/connection.json @@ -0,0 +1,81 @@ +{ + "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 + ] + } + ], + "render_type": "minecraft:cutout_mipped", + "textures": { + "end": "gtceu:block/pipe/pipe_optical_in", + "particle": "#side", + "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..1f89bf4bc9c --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/pipe/normal_optical_pipe/connection_active.json @@ -0,0 +1,101 @@ +{ + "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": { + "forge_data": { + "ambient_occlusion": false, + "block_light": 15, + "sky_light": 15 + }, + "texture": "#side_overlay", + "tintindex": 2 + }, + "north": { + "forge_data": { + "ambient_occlusion": false, + "block_light": 15, + "sky_light": 15 + }, + "texture": "#side_overlay", + "tintindex": 2 + }, + "south": { + "forge_data": { + "ambient_occlusion": false, + "block_light": 15, + "sky_light": 15 + }, + "texture": "#side_overlay", + "tintindex": 2 + }, + "west": { + "forge_data": { + "ambient_occlusion": false, + "block_light": 15, + "sky_light": 15 + }, + "texture": "#side_overlay", + "tintindex": 2 + } + }, + "from": [ + 4.998, + -0.002, + 4.998 + ], + "to": [ + 11.002, + 5.002, + 11.002 + ] + } + ], + "render_type": "minecraft:cutout_mipped", + "textures": { + "end": "gtceu:block/pipe/pipe_optical_in", + "particle": "#side", + "side": "gtceu:block/pipe/pipe_optical_side", + "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..1033b2f0f73 --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/pipe/small_duct_pipe/center.json @@ -0,0 +1,48 @@ +{ + "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 + ] + } + ], + "render_type": "minecraft:cutout_mipped", + "textures": { + "particle": "#side", + "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..c7eb5ea67dc --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/pipe/small_duct_pipe/connection.json @@ -0,0 +1,50 @@ +{ + "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 + ] + } + ], + "render_type": "minecraft:cutout_mipped", + "textures": { + "end": "gtceu:block/pipe/pipe_duct_in", + "particle": "#side", + "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 26a86e594c5..c16c3d6a2c3 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/block/PipeBlock.java +++ b/src/main/java/com/gregtechceu/gtceu/api/block/PipeBlock.java @@ -13,18 +13,17 @@ 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.api.registry.registrate.provider.GTBlockstateProvider; import com.gregtechceu.gtceu.api.sync_system.ManagedSyncBlockEntity; -import com.gregtechceu.gtceu.client.model.PipeModel; -import com.gregtechceu.gtceu.client.renderer.block.PipeBlockRenderer; +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; @@ -63,10 +62,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; @@ -75,19 +73,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 @@ -130,11 +141,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) { @@ -401,7 +408,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) { @@ -425,7 +432,7 @@ public VoxelShape getShape(BlockState pState, BlockGetter pLevel, BlockPos pPos, } return shape; } - return getPipeModel().getShapes(connections); + return getShapes(connections); } @Nullable @@ -479,4 +486,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/PipeBlockEntity.java b/src/main/java/com/gregtechceu/gtceu/api/blockentity/PipeBlockEntity.java index 7dfb31788f5..b4fce4cded1 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/blockentity/PipeBlockEntity.java +++ b/src/main/java/com/gregtechceu/gtceu/api/blockentity/PipeBlockEntity.java @@ -235,8 +235,8 @@ public int getVisualConnections() { @Override public void setConnection(Direction side, boolean connected, boolean fromNeighbor) { - // fix desync between two connections. Can happen if a pipe side is blocked, and a new pipe is placed next to - // it. + // fix desync between two connections. + // Can happen if a pipe side is blocked, and a new pipe is placed next to it. if (!getLevel().isClientSide) { if (isConnected(side) == connected) { return; diff --git a/src/main/java/com/gregtechceu/gtceu/api/cover/package-info.java b/src/main/java/com/gregtechceu/gtceu/api/cover/package-info.java new file mode 100644 index 00000000000..c1cda1440f4 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/api/cover/package-info.java @@ -0,0 +1,4 @@ +@NotNullByDefault +package com.gregtechceu.gtceu.api.cover; + +import org.jetbrains.annotations.NotNullByDefault; diff --git a/src/main/java/com/gregtechceu/gtceu/api/data/chemical/material/info/MaterialIconType.java b/src/main/java/com/gregtechceu/gtceu/api/data/chemical/material/info/MaterialIconType.java index c96add6eaf3..52d57bac337 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/data/chemical/material/info/MaterialIconType.java +++ b/src/main/java/com/gregtechceu/gtceu/api/data/chemical/material/info/MaterialIconType.java @@ -97,6 +97,7 @@ public record MaterialIconType(String name) { public static final MaterialIconType molten = new MaterialIconType("molten"); public static final MaterialIconType block = new MaterialIconType("block"); public static final MaterialIconType ore = new MaterialIconType("ore"); + public static final MaterialIconType oreEmissive = new MaterialIconType("oreEmissive"); public static final MaterialIconType oreSmall = new MaterialIconType("oreSmall"); public static final MaterialIconType frameGt = new MaterialIconType("frameGt"); public static final MaterialIconType wire = new MaterialIconType("wire"); diff --git a/src/main/java/com/gregtechceu/gtceu/api/data/tag/TagPrefix.java b/src/main/java/com/gregtechceu/gtceu/api/data/tag/TagPrefix.java index eab84067316..c438c7e0167 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/data/tag/TagPrefix.java +++ b/src/main/java/com/gregtechceu/gtceu/api/data/tag/TagPrefix.java @@ -10,6 +10,7 @@ import com.gregtechceu.gtceu.api.data.chemical.material.Material; import com.gregtechceu.gtceu.api.data.chemical.material.info.MaterialFlags; import com.gregtechceu.gtceu.api.data.chemical.material.info.MaterialIconType; +import com.gregtechceu.gtceu.api.data.chemical.material.properties.OreProperty; import com.gregtechceu.gtceu.api.data.chemical.material.properties.PropertyKey; import com.gregtechceu.gtceu.api.data.chemical.material.stack.MaterialStack; import com.gregtechceu.gtceu.api.item.MaterialBlockItem; @@ -1241,6 +1242,17 @@ public boolean doGenerateBlock(Material material) { hasItemTable() && this.itemTable.get() != null && getItemFromTable(material) != null; } + public MaterialIconType getMaterialIconType(Material material) { + // special case emissive ores + if (materialIconType == MaterialIconType.ore && material.hasProperty(PropertyKey.ORE)) { + OreProperty oreProp = material.getProperty(PropertyKey.ORE); + if (oreProp.isEmissive()) { + return MaterialIconType.oreEmissive; + } + } + return materialIconType; + } + public String getLowerCaseName() { return FormattingUtil.toLowerCaseUnderscore(this.name); } diff --git a/src/main/java/com/gregtechceu/gtceu/api/data/worldgen/GTOreDefinition.java b/src/main/java/com/gregtechceu/gtceu/api/data/worldgen/GTOreDefinition.java index be7c8395c80..d449ddcf3a7 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/data/worldgen/GTOreDefinition.java +++ b/src/main/java/com/gregtechceu/gtceu/api/data/worldgen/GTOreDefinition.java @@ -26,11 +26,14 @@ import com.mojang.serialization.DataResult; import com.mojang.serialization.codecs.RecordCodecBuilder; import dev.latvian.mods.rhino.util.HideFromJS; +import dev.latvian.mods.rhino.util.RemapForJS; +import dev.latvian.mods.rhino.util.RemapPrefixForJS; import it.unimi.dsi.fastutil.ints.IntIntPair; import lombok.Getter; import lombok.Setter; import lombok.experimental.Accessors; import lombok.experimental.Tolerate; +import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; import java.util.*; @@ -45,6 +48,7 @@ @SuppressWarnings("unused") @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault +@RemapPrefixForJS("kjs$") @Accessors(chain = true, fluent = true) public class GTOreDefinition { @@ -178,33 +182,54 @@ public GTOreDefinition weight(int weight) { public GTOreDefinition layer(IWorldGenLayer layer) { this.layer = layer; if (this.dimensionFilter == null || this.dimensionFilter.isEmpty()) { - dimensions(layer.getLevels().toArray(ResourceLocation[]::new)); + dimensions(layer.getLevels().stream() + .map(location -> ResourceKey.create(Registries.DIMENSION, location)) + .collect(Collectors.toSet())); } return this; } + @HideFromJS + public final GTOreDefinition dimensions(Set> dimensions) { + this.dimensionFilter = dimensions; + return this; + } + + /** + * @deprecated Use {@link #dimensions(Set) dimensions(Set<ResourceKey<Level>>)} instead. + * @param dimensions + * @return this builder. + */ + @ApiStatus.ScheduledForRemoval(inVersion = "8.0.0") + @Deprecated(since = "7.4.1", forRemoval = true) + @ApiStatus.Internal + @SuppressWarnings("unused") + // TODO(8.0.0): rename to `kjs$dimensions` public GTOreDefinition dimensions(ResourceLocation... dimensions) { - this.dimensionFilter = Arrays.stream(dimensions) + return this.dimensions(Arrays.stream(dimensions) .map(location -> ResourceKey.create(Registries.DIMENSION, location)) - .collect(Collectors.toSet()); - return this; + .collect(Collectors.toSet())); } - public GTOreDefinition biomes(String first, String... biomes) { + /// This method should only be used in KubeJS. + @SuppressWarnings("unused") + @ApiStatus.Internal + public GTOreDefinition kjs$biomes(String first, String... biomes) { // The first param is separate to avoid method confusion with the Lombok-generated fluent getter - List biomeList = Stream.of(Stream.of(first), Arrays.stream(biomes)) - .flatMap(Function.identity()) + List biomeList = Stream.concat(Stream.of(first), Arrays.stream(biomes)) .toList(); this.biomes = OreVeinUtil.resolveBiomes(biomeList); return this; } + @HideFromJS public GTOreDefinition biomes(TagKey biomes) { this.biomes = () -> GTRegistries.builtinRegistry().lookupOrThrow(Registries.BIOME).getOrThrow(biomes); return this; } + @HideFromJS public GTOreDefinition biomes(Supplier> biomes) { this.biomes = biomes; return this; @@ -303,8 +328,8 @@ public GTOreDefinition cuboidVeinGenerator(Consumer config) } @Tolerate - @Nullable - public VeinGenerator veinGenerator(ResourceLocation id) { + @RemapForJS("customVeinGenerator") + public @Nullable VeinGenerator veinGenerator(ResourceLocation id) { if (veinGenerator == null) { veinGenerator = WorldGeneratorUtils.VEIN_GENERATOR_FUNCTIONS.containsKey(id) ? WorldGeneratorUtils.VEIN_GENERATOR_FUNCTIONS.get(id).apply(this) : null; diff --git a/src/main/java/com/gregtechceu/gtceu/api/data/worldgen/WorldGeneratorUtils.java b/src/main/java/com/gregtechceu/gtceu/api/data/worldgen/WorldGeneratorUtils.java index ad87f60f1b3..9c1a65a46fc 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/data/worldgen/WorldGeneratorUtils.java +++ b/src/main/java/com/gregtechceu/gtceu/api/data/worldgen/WorldGeneratorUtils.java @@ -58,9 +58,11 @@ private static class WorldOreVeinCache { private final Map, List> biomeVeins = new Object2ObjectOpenHashMap<>(); public WorldOreVeinCache(ServerLevel level) { - this.worldVeins = GTRegistries.ORE_VEINS.values().stream() - .filter(entry -> entry.dimensionFilter().stream() + this.worldVeins = GTRegistries.ORE_VEINS.entries().stream() + .filter(entry -> entry.getValue().dimensionFilter().stream() .anyMatch(dim -> WorldGeneratorUtils.isSameDimension(dim, level.dimension()))) + .sorted(Entry.comparingByKey()) + .map(Entry::getValue) .collect(Collectors.toList()); } diff --git a/src/main/java/com/gregtechceu/gtceu/api/data/worldgen/bedrockfluid/BedrockFluidDefinition.java b/src/main/java/com/gregtechceu/gtceu/api/data/worldgen/bedrockfluid/BedrockFluidDefinition.java index a3222217d25..c16e506e3ad 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/data/worldgen/bedrockfluid/BedrockFluidDefinition.java +++ b/src/main/java/com/gregtechceu/gtceu/api/data/worldgen/bedrockfluid/BedrockFluidDefinition.java @@ -2,7 +2,6 @@ import com.gregtechceu.gtceu.api.data.worldgen.BiomeWeightModifier; import com.gregtechceu.gtceu.api.registry.GTRegistries; -import com.gregtechceu.gtceu.utils.RegistryUtil; import net.minecraft.core.Holder; import net.minecraft.core.HolderSet; @@ -20,6 +19,7 @@ import com.mojang.serialization.MapCodec; import com.mojang.serialization.codecs.RecordCodecBuilder; import dev.latvian.mods.rhino.util.HideFromJS; +import dev.latvian.mods.rhino.util.RemapPrefixForJS; import lombok.Getter; import lombok.Setter; import lombok.experimental.Accessors; @@ -27,6 +27,7 @@ import java.util.*; import java.util.function.Supplier; +import java.util.stream.Collectors; public class BedrockFluidDefinition { @@ -139,6 +140,7 @@ public static Builder builder(ResourceLocation name) { return new Builder(name); } + @RemapPrefixForJS("kjs$") @Accessors(chain = true, fluent = true) public static class Builder { @@ -178,12 +180,14 @@ public Builder yield(int min, int max) { return minimumYield(min).maximumYield(max); } + @HideFromJS public Builder biomes(int weight, TagKey biomes) { this.biomes.add(new BiomeWeightModifier(() -> GTRegistries.builtinRegistry() .registryOrThrow(Registries.BIOME).getOrCreateTag(biomes), weight)); return this; } + @HideFromJS @SafeVarargs public final Builder biomes(int weight, ResourceKey... biomes) { this.biomes.add(new BiomeWeightModifier(() -> HolderSet.direct(GTRegistries.builtinRegistry() @@ -191,6 +195,7 @@ public final Builder biomes(int weight, ResourceKey... biomes) { return this; } + @HideFromJS public Builder biomes(int weight, HolderSet biomes) { this.biomes.add(new BiomeWeightModifier(() -> biomes, weight)); return this; @@ -202,10 +207,37 @@ public Builder dimensions(Set> dimensions) { return this; } - public Builder dimensions(String... dimensions) { - return this.dimensions(new HashSet<>(RegistryUtil.resolveResourceKeys(Registries.DIMENSION, dimensions))); + // region KubeJS versions of the above methods + + /// This method should only be used in KubeJS. + @SuppressWarnings("unused") + @ApiStatus.Internal + public Builder kjs$biomeTag(int weight, ResourceLocation biomeTag) { + return this.biomes(weight, TagKey.create(Registries.BIOME, biomeTag)); } + /// This method should only be used in KubeJS. + @SuppressWarnings({ "unused", "unchecked" }) + @ApiStatus.Internal + public Builder kjs$biomes(int weight, ResourceLocation... biomes) { + ResourceKey[] resourceKeys = new ResourceKey[biomes.length]; + for (int i = 0; i < biomes.length; i++) { + resourceKeys[i] = ResourceKey.create(Registries.BIOME, biomes[i]); + } + return this.biomes(weight, resourceKeys); + } + + /// This method should only be used in KubeJS. + @SuppressWarnings("unused") + @ApiStatus.Internal + public Builder kjs$dimensions(ResourceLocation... dimensions) { + return this.dimensions(Arrays.stream(dimensions) + .map(id -> ResourceKey.create(Registries.DIMENSION, id)) + .collect(Collectors.toSet())); + } + + // endregion + @ApiStatus.Internal public BedrockFluidDefinition build() { return new BedrockFluidDefinition(weight, minimumYield, maximumYield, depletionAmount, diff --git a/src/main/java/com/gregtechceu/gtceu/api/data/worldgen/bedrockfluid/BedrockFluidVeinSavedData.java b/src/main/java/com/gregtechceu/gtceu/api/data/worldgen/bedrockfluid/BedrockFluidVeinSavedData.java index a5ceaad8e0c..235c0e93390 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/data/worldgen/bedrockfluid/BedrockFluidVeinSavedData.java +++ b/src/main/java/com/gregtechceu/gtceu/api/data/worldgen/bedrockfluid/BedrockFluidVeinSavedData.java @@ -3,7 +3,6 @@ import com.gregtechceu.gtceu.api.GTValues; import com.gregtechceu.gtceu.api.data.worldgen.WorldGeneratorUtils; import com.gregtechceu.gtceu.api.registry.GTRegistries; -import com.gregtechceu.gtceu.utils.GTMath; import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.core.BlockPos; @@ -12,9 +11,9 @@ import net.minecraft.nbt.ListTag; import net.minecraft.nbt.Tag; import net.minecraft.server.level.ServerLevel; -import net.minecraft.util.RandomSource; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.levelgen.XoroshiroRandomSource; import net.minecraft.world.level.material.Fluid; import net.minecraft.world.level.saveddata.SavedData; @@ -86,8 +85,8 @@ public FluidVeinWorldEntry getFluidVeinWorldEntry(int chunkX, int chunkZ) { ChunkPos pos = new ChunkPos(chunkX, chunkZ); if (!veinFluids.containsKey(pos)) { BedrockFluidDefinition definition = null; - int query = RandomSource - .create(GTMath.hashLongs(serverLevel.getSeed(), getVeinCoord(chunkX), getVeinCoord(chunkZ))) + int query = new XoroshiroRandomSource( + serverLevel.getSeed() ^ ChunkPos.asLong(getVeinCoord(chunkX), getVeinCoord(chunkZ))) .nextInt(); var biome = serverLevel.getBiome(new BlockPos(chunkX << 4, 64, chunkZ << 4)); int totalWeight = getTotalWeight(biome); @@ -108,7 +107,7 @@ public FluidVeinWorldEntry getFluidVeinWorldEntry(int chunkX, int chunkZ) { } } - var random = RandomSource.create(31L * 31 * chunkX + chunkZ * 31L + Long.hashCode(serverLevel.getSeed())); + var random = new XoroshiroRandomSource(serverLevel.getSeed() ^ ChunkPos.asLong(chunkX, chunkZ)); int maximumYield = 0; if (definition != null) { diff --git a/src/main/java/com/gregtechceu/gtceu/api/data/worldgen/bedrockore/BedrockOreDefinition.java b/src/main/java/com/gregtechceu/gtceu/api/data/worldgen/bedrockore/BedrockOreDefinition.java index 16953e86ea5..37fd9bd09c6 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/data/worldgen/bedrockore/BedrockOreDefinition.java +++ b/src/main/java/com/gregtechceu/gtceu/api/data/worldgen/bedrockore/BedrockOreDefinition.java @@ -3,7 +3,6 @@ import com.gregtechceu.gtceu.api.data.chemical.material.Material; import com.gregtechceu.gtceu.api.data.worldgen.BiomeWeightModifier; import com.gregtechceu.gtceu.api.registry.GTRegistries; -import com.gregtechceu.gtceu.utils.RegistryUtil; import net.minecraft.core.Holder; import net.minecraft.core.HolderSet; @@ -20,13 +19,16 @@ import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; import dev.latvian.mods.rhino.util.HideFromJS; +import dev.latvian.mods.rhino.util.RemapPrefixForJS; import it.unimi.dsi.fastutil.ints.IntArrayList; import it.unimi.dsi.fastutil.ints.IntList; import lombok.Getter; import lombok.Setter; import lombok.experimental.Accessors; +import org.jetbrains.annotations.ApiStatus; import java.util.*; +import java.util.stream.Collectors; @Accessors(fluent = true, chain = true) public class BedrockOreDefinition { @@ -146,6 +148,7 @@ public static Builder builder(ResourceLocation name) { return new Builder(name); } + @RemapPrefixForJS("kjs$") @Accessors(chain = true, fluent = true) public static class Builder { @@ -192,12 +195,14 @@ public Builder yield(int min, int max) { return this.yield(UniformInt.of(min, max)); } + @HideFromJS public Builder biomes(int weight, TagKey biomes) { this.biomes.add(new BiomeWeightModifier(() -> GTRegistries.builtinRegistry() .registryOrThrow(Registries.BIOME).getOrCreateTag(biomes), weight)); return this; } + @HideFromJS @SafeVarargs public final Builder biomes(int weight, ResourceKey... biomes) { this.biomes.add(new BiomeWeightModifier(() -> HolderSet.direct(GTRegistries.builtinRegistry() @@ -205,6 +210,7 @@ public final Builder biomes(int weight, ResourceKey... biomes) { return this; } + @HideFromJS public Builder biomes(int weight, HolderSet biomes) { this.biomes.add(new BiomeWeightModifier(() -> biomes, weight)); return this; @@ -216,10 +222,37 @@ public Builder dimensions(Set> dimensions) { return this; } - public Builder dimensions(String... dimensions) { - return this.dimensions(new HashSet<>(RegistryUtil.resolveResourceKeys(Registries.DIMENSION, dimensions))); + // region KubeJS versions of the above methods + + /// This method should only be used in KubeJS. + @SuppressWarnings("unused") + @ApiStatus.Internal + public Builder kjs$biomeTag(int weight, ResourceLocation biomeTag) { + return this.biomes(weight, TagKey.create(Registries.BIOME, biomeTag)); + } + + /// This method should only be used in KubeJS. + @SuppressWarnings({ "unused", "unchecked" }) + @ApiStatus.Internal + public Builder kjs$biomes(int weight, ResourceLocation... biomes) { + ResourceKey[] resourceKeys = new ResourceKey[biomes.length]; + for (int i = 0; i < biomes.length; i++) { + resourceKeys[i] = ResourceKey.create(Registries.BIOME, biomes[i]); + } + return this.biomes(weight, resourceKeys); } + /// This method should only be used in KubeJS. + @SuppressWarnings("unused") + @ApiStatus.Internal + public Builder kjs$dimensions(ResourceLocation... dimensions) { + return this.dimensions(Arrays.stream(dimensions) + .map(id -> ResourceKey.create(Registries.DIMENSION, id)) + .collect(Collectors.toSet())); + } + + // endregion + public BedrockOreDefinition register() { var definition = new BedrockOreDefinition(weight, size, yield, depletionAmount, depletionChance, depletedYield, materials, biomes, dimensions); diff --git a/src/main/java/com/gregtechceu/gtceu/api/data/worldgen/bedrockore/BedrockOreVeinSavedData.java b/src/main/java/com/gregtechceu/gtceu/api/data/worldgen/bedrockore/BedrockOreVeinSavedData.java index f1225a15dd0..d15f4240065 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/data/worldgen/bedrockore/BedrockOreVeinSavedData.java +++ b/src/main/java/com/gregtechceu/gtceu/api/data/worldgen/bedrockore/BedrockOreVeinSavedData.java @@ -4,7 +4,6 @@ import com.gregtechceu.gtceu.api.data.worldgen.WorldGeneratorUtils; import com.gregtechceu.gtceu.api.registry.GTRegistries; import com.gregtechceu.gtceu.config.ConfigHolder; -import com.gregtechceu.gtceu.utils.GTMath; import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.core.BlockPos; @@ -13,9 +12,9 @@ import net.minecraft.nbt.ListTag; import net.minecraft.nbt.Tag; import net.minecraft.server.level.ServerLevel; -import net.minecraft.util.RandomSource; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.levelgen.XoroshiroRandomSource; import net.minecraft.world.level.saveddata.SavedData; import it.unimi.dsi.fastutil.objects.Object2IntMap; @@ -95,8 +94,8 @@ public OreVeinWorldEntry getOreVeinWorldEntry(int chunkX, int chunkZ) { } BedrockOreDefinition definition = null; - int query = RandomSource - .create(GTMath.hashLongs(serverLevel.getSeed(), getVeinCoord(chunkX), getVeinCoord(chunkZ))) + int query = new XoroshiroRandomSource( + serverLevel.getSeed() ^ ChunkPos.asLong(getVeinCoord(chunkX), getVeinCoord(chunkZ))) .nextInt(); var biome = serverLevel.getBiome(new BlockPos(chunkX << 4, 64, chunkZ << 4)); int totalWeight = getTotalWeight(biome); @@ -138,8 +137,7 @@ public void createVein(ChunkPos pos, @Nullable BedrockOreDefinition definition) distanceFromOriginal = distanceFromOriginal == 0 ? 1 : distanceFromOriginal; distanceFromOriginal = (float) Math.pow(distanceFromOriginal, 2); - var random = RandomSource - .create(31L * 31 * pos2.x + pos2.z * 31L + Long.hashCode(serverLevel.getSeed())); + var random = new XoroshiroRandomSource(serverLevel.getSeed() ^ pos2.toLong()); int maximumYield; if ((definition.yield().getMaxValue() - definition.yield().getMinValue()) / distanceFromOriginal <= 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..edb5174a25a 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.getInstance(); + } + }); + } + + 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/item/armor/ArmorComponentItem.java b/src/main/java/com/gregtechceu/gtceu/api/item/armor/ArmorComponentItem.java index 428b2a658df..5579e039564 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/item/armor/ArmorComponentItem.java +++ b/src/main/java/com/gregtechceu/gtceu/api/item/armor/ArmorComponentItem.java @@ -28,9 +28,7 @@ import org.jetbrains.annotations.NotNullByDefault; import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; +import java.util.*; import java.util.function.Consumer; @NotNullByDefault diff --git a/src/main/java/com/gregtechceu/gtceu/api/item/armor/IArmorLogic.java b/src/main/java/com/gregtechceu/gtceu/api/item/armor/IArmorLogic.java index c67bb1ca296..3ae5f075c83 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/item/armor/IArmorLogic.java +++ b/src/main/java/com/gregtechceu/gtceu/api/item/armor/IArmorLogic.java @@ -26,13 +26,13 @@ public interface IArmorLogic { - UUID ATTACK_DAMAGE_MODIFIER = UUID.fromString("648D7064-6A60-4F59-8ABE-C2C23A6DD7A9"); - UUID ATTACK_SPEED_MODIFIER = UUID.fromString("FA233E1C-4180-4288-B05C-BCCE9785ACA3"); + UUID ATTACK_DAMAGE_MODIFIER = UUID.fromString("2adb6ae9-df4d-4a45-bb07-8553dd4b6832"); + UUID ATTACK_SPEED_MODIFIER = UUID.fromString("876a7cd1-aec0-4ae5-ae3f-e951d5f1965a"); EnumMap ARMOR_MODIFIER_UUID_PER_TYPE = Util.make(new EnumMap<>(ArmorItem.Type.class), map -> { - map.put(ArmorItem.Type.BOOTS, UUID.fromString("845DB27C-C624-495F-8C9F-6020A9A58B6B")); - map.put(ArmorItem.Type.LEGGINGS, UUID.fromString("D8499B04-0E66-4726-AB29-64469D734E0D")); - map.put(ArmorItem.Type.CHESTPLATE, UUID.fromString("9F3D476D-C118-4544-8365-64846904B48E")); - map.put(ArmorItem.Type.HELMET, UUID.fromString("2AD3F246-FEE1-4E67-B886-69FD380BB150")); + map.put(ArmorItem.Type.BOOTS, UUID.fromString("be2b5c6e-bb5d-4675-a6be-c6c488a437f5")); + map.put(ArmorItem.Type.LEGGINGS, UUID.fromString("435c34aa-0c5b-442d-abb0-d1c984c894f9")); + map.put(ArmorItem.Type.CHESTPLATE, UUID.fromString("77d81693-63cc-4593-977d-8e0391d94a77")); + map.put(ArmorItem.Type.HELMET, UUID.fromString("cc839692-3a33-4907-a114-21fa0a18184c")); }); default void addToolComponents(ArmorComponentItem item) {} diff --git a/src/main/java/com/gregtechceu/gtceu/api/item/component/IMonitorModuleItem.java b/src/main/java/com/gregtechceu/gtceu/api/item/component/IMonitorModuleItem.java index 6bfa55da341..91a12e74343 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/item/component/IMonitorModuleItem.java +++ b/src/main/java/com/gregtechceu/gtceu/api/item/component/IMonitorModuleItem.java @@ -1,5 +1,6 @@ package com.gregtechceu.gtceu.api.item.component; +import com.gregtechceu.gtceu.api.placeholder.PlaceholderContext; import com.gregtechceu.gtceu.client.renderer.monitor.IMonitorRenderer; import com.gregtechceu.gtceu.common.machine.multiblock.electric.CentralMonitorMachine; import com.gregtechceu.gtceu.common.machine.multiblock.electric.monitor.MonitorGroup; @@ -12,7 +13,9 @@ public interface IMonitorModuleItem extends IItemComponent { default void tick(ItemStack stack, CentralMonitorMachine machine, MonitorGroup group) {} - IMonitorRenderer getRenderer(ItemStack stack, CentralMonitorMachine machine, MonitorGroup group); + default void tickInPlaceholder(ItemStack stack, PlaceholderContext context) {} + + IMonitorRenderer getRenderer(ItemStack stack); Widget createUIWidget(ItemStack stack, CentralMonitorMachine machine, MonitorGroup group); diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/multiblock/MultiblockControllerMachine.java b/src/main/java/com/gregtechceu/gtceu/api/machine/multiblock/MultiblockControllerMachine.java index acd796209a5..89b0be5835f 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/multiblock/MultiblockControllerMachine.java +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/multiblock/MultiblockControllerMachine.java @@ -116,13 +116,13 @@ public void onStructureFormed() { } } this.parts.sort(getPartSorter()); + updatePartPositions(); for (var part : parts) { if (part instanceof ParallelHatchPartMachine pHatch) { parallelHatch = pHatch; } part.addedToController(this); } - updatePartPositions(); } /** diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/multiblock/MultiblockDisplayText.java b/src/main/java/com/gregtechceu/gtceu/api/machine/multiblock/MultiblockDisplayText.java index b0270cb6d9e..1b9abeb2afa 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/multiblock/MultiblockDisplayText.java +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/multiblock/MultiblockDisplayText.java @@ -372,6 +372,19 @@ public Builder addCustomProgressLine(RecipeLogic recipeLogic) { return this; } + public Builder addRecipeFailReasonLine(RecipeLogic recipeLogic) { + if (!isStructureFormed || !recipeLogic.isIdle()) + return this; + var reasons = recipeLogic.getFailureReasons(); + if (!reasons.isEmpty()) { + textList.add(Component.translatable("gtceu.recipe_logic.setup_fail").withStyle(ChatFormatting.RED)); + for (var reason : reasons) { + textList.add(Component.literal(" - ").append(reason)); + } + } + return this; + } + public Builder addBatchModeLine(boolean batchEnabled, int batchAmount) { if (batchEnabled && batchAmount > 0) { Component runs = Component.literal(FormattingUtil.formatNumbers(batchAmount)) diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/multiblock/WorkableElectricMultiblockMachine.java b/src/main/java/com/gregtechceu/gtceu/api/machine/multiblock/WorkableElectricMultiblockMachine.java index 0c36be35e70..9dc664642b9 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/multiblock/WorkableElectricMultiblockMachine.java +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/multiblock/WorkableElectricMultiblockMachine.java @@ -132,6 +132,7 @@ public void addDisplayText(List textList) { .addBatchModeLine(isBatchEnabled(), batchParallels) .addWorkingStatusLine() .addProgressLine(recipeLogic) + .addRecipeFailReasonLine(recipeLogic) .addOutputLines(recipeLogic.getLastRecipe()); getDefinition().getAdditionalDisplay().accept(this, textList); IDisplayUIMachine.super.addDisplayText(textList); diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/trait/RecipeLogic.java b/src/main/java/com/gregtechceu/gtceu/api/machine/trait/RecipeLogic.java index 33b0e870e3e..203c0ad68e8 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/trait/RecipeLogic.java +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/trait/RecipeLogic.java @@ -15,6 +15,7 @@ import com.gregtechceu.gtceu.api.recipe.ActionResult; import com.gregtechceu.gtceu.api.recipe.GTRecipe; import com.gregtechceu.gtceu.api.recipe.RecipeHelper; +import com.gregtechceu.gtceu.api.recipe.modifier.ModifierFunction; import com.gregtechceu.gtceu.api.registry.GTRegistries; import com.gregtechceu.gtceu.api.sound.AutoReleasedSound; import com.gregtechceu.gtceu.api.sync_system.annotations.ClientFieldChangeListener; @@ -88,10 +89,18 @@ public enum Status implements StringRepresentable { @RerenderOnChanged protected boolean isActive; + @Getter @Nullable @SaveField @SyncToClient private Component waitingReason = null; + + @Getter + @SyncToClient + protected final List failureReasons = new ArrayList<>(); + + @Getter + protected final Map failureReasonMap = new HashMap<>(); /** * unsafe, it may not be found from {@link RecipeManager}. Do not index it. */ @@ -162,6 +171,8 @@ public void resetRecipeLogic() { duration = 0; isActive = false; lastFailedMatches = null; + waitingReason = null; + failureReasons.clear(); if (status != Status.SUSPEND) { setStatus(Status.IDLE); } @@ -235,7 +246,10 @@ public void serverTick() { // No recipes available and the machine wants to unsubscribe until notified unsubscribe = true; } - + if (isIdle()) { + failureReasons.clear(); + failureReasons.addAll(failureReasonMap.values()); + } if (unsubscribe && subscription != null) { subscription.unsubscribe(); subscription = null; @@ -259,6 +273,8 @@ public boolean checkMatchedRecipeAvailable(GTRecipe match) { var recipeMatch = checkRecipe(modified); if (recipeMatch.isSuccess()) { setupRecipe(modified); + } else { + putFailureReason(this, match, recipeMatch.reason()); } if (lastRecipe != null && getStatus() == Status.WORKING) { lastOriginRecipe = match; @@ -331,13 +347,16 @@ protected void regressRecipe() { public void findAndHandleRecipe() { lastFailedMatches = null; + // try to execute last recipe if possible if (!recipeDirty && lastRecipe != null && checkRecipe(lastRecipe).isSuccess()) { GTRecipe recipe = lastRecipe; lastRecipe = null; lastOriginRecipe = null; setupRecipe(recipe); - } else { // try to find and handle a new recipe + } else { + // try to find and handle a new recipe + failureReasonMap.clear(); lastRecipe = null; lastOriginRecipe = null; handleSearchingRecipes(searchRecipe()); @@ -393,6 +412,7 @@ public void setupRecipe(GTRecipe recipe) { if (lastRecipe != null && !recipe.equals(lastRecipe)) { chanceCaches.clear(); } + failureReasonMap.clear(); recipeDirty = false; lastRecipe = recipe; setStatus(Status.WORKING); @@ -533,9 +553,6 @@ public void onRecipeFinish() { setupRecipe(lastRecipe); } else { setStatus(Status.IDLE); - if (recipeCheck.io() != IO.IN || recipeCheck.capability() == EURecipeCapability.CAP) { - waitingReason = recipeCheck.reason(); - } consecutiveRecipes = 0; progress = 0; duration = 0; @@ -597,7 +614,7 @@ public void updateSound() { @Override public IGuiTexture getFancyTooltipIcon() { - if (waitingReason != null) { + if (showFancyTooltip()) { return GuiTextures.INSUFFICIENT_INPUT; } return IGuiTexture.EMPTY; @@ -605,15 +622,18 @@ public IGuiTexture getFancyTooltipIcon() { @Override public List getFancyTooltip() { - if (waitingReason != null) { + if (isWaiting() && waitingReason != null) { return List.of(waitingReason); } + if (isIdle() && !failureReasons.isEmpty()) { + return failureReasons; + } return Collections.emptyList(); } @Override public boolean showFancyTooltip() { - return waitingReason != null; + return waitingReason != null || !failureReasons.isEmpty(); } protected ChanceCacheMap makeChanceCaches() { @@ -676,4 +696,21 @@ protected ChanceCacheMap makeChanceCaches() { } }); } + + public static void putFailureReason(Object machine, GTRecipe recipe, Component reason) { + if (machine instanceof IRecipeLogicMachine rlm) { + putFailureReason(rlm.getRecipeLogic(), recipe, reason); + } + } + + public static void putFailureReason(RecipeLogic logic, GTRecipe recipe, Component reason) { + var map = logic.getFailureReasonMap(); + if (map.containsKey(recipe)) { + if (reason != ModifierFunction.DEFAULT_FAILURE) { + map.put(recipe, reason); + } + } else { + map.put(recipe, reason); + } + } } diff --git a/src/main/java/com/gregtechceu/gtceu/api/pattern/Predicates.java b/src/main/java/com/gregtechceu/gtceu/api/pattern/Predicates.java index 55c816d8620..fcbab48ad80 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/pattern/Predicates.java +++ b/src/main/java/com/gregtechceu/gtceu/api/pattern/Predicates.java @@ -17,6 +17,7 @@ import com.gregtechceu.gtceu.api.recipe.GTRecipeType; import com.gregtechceu.gtceu.common.block.BatteryBlock; import com.gregtechceu.gtceu.common.block.CoilBlock; +import com.gregtechceu.gtceu.common.block.LampBlock; import com.gregtechceu.gtceu.common.data.GTMaterialBlocks; import com.gregtechceu.gtceu.common.machine.multiblock.electric.PowerSubstationMachine; import com.gregtechceu.gtceu.config.ConfigHolder; @@ -25,11 +26,13 @@ import net.minecraft.network.chat.Component; import net.minecraft.tags.TagKey; +import net.minecraft.world.item.DyeColor; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.material.Fluid; +import com.tterrag.registrate.util.entry.BlockEntry; import com.tterrag.registrate.util.entry.RegistryEntry; import org.apache.commons.lang3.ArrayUtils; @@ -38,6 +41,8 @@ import java.util.function.Supplier; import static com.gregtechceu.gtceu.api.block.property.GTBlockStateProperties.ACTIVE; +import static com.gregtechceu.gtceu.common.data.GTBlocks.BORDERLESS_LAMPS; +import static com.gregtechceu.gtceu.common.data.GTBlocks.LAMPS; import static com.gregtechceu.gtceu.common.machine.multiblock.electric.PowerSubstationMachine.PMC_BATTERY_HEADER; public class Predicates { @@ -100,6 +105,32 @@ public static TraceabilityPredicate air() { return new TraceabilityPredicate(SimplePredicate.AIR); } + @SafeVarargs + public static TraceabilityPredicate lamps(BlockEntry... lampEntries) { + return new TraceabilityPredicate(blockWorldState -> { + BlockState state = blockWorldState.getBlockState(); + for (BlockEntry entry : lampEntries) { + if (state.is(entry.get())) return true; + } + return false; + }, () -> Arrays.stream(lampEntries) + .map(entry -> new BlockInfo(entry.get().defaultBlockState(), null)) + .toArray(BlockInfo[]::new)); + } + + public static TraceabilityPredicate anyLamp() { + List> all = new ArrayList<>(); + all.addAll(LAMPS.values()); + all.addAll(BORDERLESS_LAMPS.values()); + return lamps(all.toArray(BlockEntry[]::new)); + } + + private static final Map LAMPS_BY_COLOR = new EnumMap<>(DyeColor.class); + + public static TraceabilityPredicate lampsByColor(DyeColor color) { + return LAMPS_BY_COLOR.computeIfAbsent(color, c -> lamps(LAMPS.get(c), BORDERLESS_LAMPS.get(c))); + } + public static TraceabilityPredicate abilities(PartAbility... abilities) { return blocks(Arrays.stream(abilities).map(PartAbility::getAllBlocks).flatMap(Collection::stream) .toArray(Block[]::new)); diff --git a/src/main/java/com/gregtechceu/gtceu/api/pipenet/IPipeNode.java b/src/main/java/com/gregtechceu/gtceu/api/pipenet/IPipeNode.java index 8e12e0e15ce..8358ed88f6a 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/pipenet/IPipeNode.java +++ b/src/main/java/com/gregtechceu/gtceu/api/pipenet/IPipeNode.java @@ -7,18 +7,25 @@ import com.gregtechceu.gtceu.api.blockentity.PipeBlockEntity; import com.gregtechceu.gtceu.api.capability.ICoverable; import com.gregtechceu.gtceu.api.data.chemical.material.Material; +import com.gregtechceu.gtceu.client.model.GTModelProperties; import net.minecraft.core.Direction; import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.client.model.data.ModelData; +import net.minecraftforge.client.model.data.ModelDataManager; +import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public interface IPipeNode & IPipeType, NodeDataType> extends ITickSubscription, IPaintable, IGregtechBlockEntity { + long getOffsetTimer(); + /** * Get Cover Container. */ @@ -114,6 +121,28 @@ default NodeDataType getNodeData() { return null; } + void notifyBlockUpdate(); + + @SuppressWarnings("UnstableApiUsage") + default void scheduleRenderUpdate() { + var pos = getBlockPos(); + var level = getLevel(); + if (level != null) { + var state = level.getBlockState(pos); + if (level.isClientSide) { + // simplified from requestModelDataUpdate + ModelDataManager manager = level.getModelDataManager(); + if (manager != null) { + manager.requestRefresh(self()); + } + + level.sendBlockUpdated(pos, state, state, Block.UPDATE_IMMEDIATE); + } else { + level.blockEvent(pos, state.getBlock(), 1, 0); + } + } + } + default void serverTick() {} @Override @@ -123,4 +152,15 @@ default int getDefaultPaintingColor() { @NotNull Material getFrameMaterial(); + + @ApiStatus.Internal + @Override + default @NotNull ModelData getModelData() { + return ModelData.builder() + .with(GTModelProperties.LEVEL, self().getLevel()) + .with(GTModelProperties.POS, self().getBlockPos()) + .with(GTModelProperties.PIPE_CONNECTION_MASK, this.getVisualConnections()) + .with(GTModelProperties.PIPE_BLOCKED_MASK, this.getBlockedConnections()) + .build(); + } } diff --git a/src/main/java/com/gregtechceu/gtceu/api/placeholder/GraphicsComponent.java b/src/main/java/com/gregtechceu/gtceu/api/placeholder/GraphicsComponent.java new file mode 100644 index 00000000000..650f2645202 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/api/placeholder/GraphicsComponent.java @@ -0,0 +1,60 @@ +package com.gregtechceu.gtceu.api.placeholder; + +import com.gregtechceu.gtceu.GTCEu; +import com.gregtechceu.gtceu.client.renderer.monitor.IMonitorRenderer; +import com.gregtechceu.gtceu.common.machine.multiblock.electric.CentralMonitorMachine; +import com.gregtechceu.gtceu.common.machine.multiblock.electric.monitor.MonitorGroup; + +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtOps; +import net.minecraft.nbt.Tag; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; + +import java.util.function.Supplier; + +public record GraphicsComponent(float x, float y, float x2, float y2, String rendererId, CompoundTag renderData) + implements Supplier { + + public GraphicsComponent(double x, double y, double x2, double y2, String rendererId, CompoundTag renderData) { + this((float) x, (float) y, (float) x2, (float) y2, rendererId, renderData); + } + + public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( + Codec.FLOAT.fieldOf("x").forGetter(GraphicsComponent::x), + Codec.FLOAT.fieldOf("y").forGetter(GraphicsComponent::y), + Codec.FLOAT.fieldOf("x2").forGetter(GraphicsComponent::x2), + Codec.FLOAT.fieldOf("y2").forGetter(GraphicsComponent::y2), + Codec.STRING.fieldOf("rendererId").forGetter(GraphicsComponent::rendererId), + CompoundTag.CODEC.fieldOf("renderData").forGetter(GraphicsComponent::renderData)) + .apply(instance, GraphicsComponent::new)); + + @Override + public IMonitorRenderer get() { + return new IMonitorRenderer() { + + private final IMonitorRenderer renderer = PlaceholderHandler.getRenderer(rendererId, renderData); + + @Override + public void render(CentralMonitorMachine machine, MonitorGroup group, float partialTick, + PoseStack poseStack, MultiBufferSource buffer, int packedLight, int packedOverlay) { + poseStack.pushPose(); + poseStack.translate(x, y, 0); + assert this.renderer != null; + this.renderer.render(machine, group, partialTick, poseStack, buffer, packedLight, packedOverlay); + poseStack.popPose(); + } + }; + } + + public Tag toTag() { + return CODEC.encodeStart(NbtOps.INSTANCE, this).getOrThrow(false, GTCEu.LOGGER::error); + } + + public static GraphicsComponent fromTag(Tag tag) { + return CODEC.decode(NbtOps.INSTANCE, tag).getOrThrow(false, GTCEu.LOGGER::error).getFirst(); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/api/placeholder/IPlaceholderRenderer.java b/src/main/java/com/gregtechceu/gtceu/api/placeholder/IPlaceholderRenderer.java new file mode 100644 index 00000000000..5d55415ee85 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/api/placeholder/IPlaceholderRenderer.java @@ -0,0 +1,15 @@ +package com.gregtechceu.gtceu.api.placeholder; + +import com.gregtechceu.gtceu.common.machine.multiblock.electric.CentralMonitorMachine; +import com.gregtechceu.gtceu.common.machine.multiblock.electric.monitor.MonitorGroup; + +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.nbt.CompoundTag; + +import com.mojang.blaze3d.vertex.PoseStack; + +public interface IPlaceholderRenderer { + + void render(CentralMonitorMachine machine, MonitorGroup group, float partialTick, PoseStack poseStack, + MultiBufferSource buffer, int packedLight, int packedOverlay, CompoundTag tag); +} diff --git a/src/main/java/com/gregtechceu/gtceu/api/placeholder/MultiLineComponent.java b/src/main/java/com/gregtechceu/gtceu/api/placeholder/MultiLineComponent.java index 0889644579b..ac19946fe1b 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/placeholder/MultiLineComponent.java +++ b/src/main/java/com/gregtechceu/gtceu/api/placeholder/MultiLineComponent.java @@ -3,23 +3,32 @@ import com.gregtechceu.gtceu.utils.GTUtil; import net.minecraft.ChatFormatting; +import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.StringTag; import net.minecraft.nbt.Tag; import net.minecraft.network.chat.*; import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.Objects; +@Accessors(chain = true) public class MultiLineComponent extends ArrayList { @Getter + @Setter private boolean ignoreSpaces = false; + @Getter + private final List graphics = new ArrayList<>(); + public MultiLineComponent(List components) { super(); this.addAll(components); @@ -79,7 +88,10 @@ public double toDouble() { public int toInt() { if (this.isEmpty()) return 0; if (this.size() > 1) throw new NumberFormatException(this.toString()); - return Integer.parseInt(this.get(0).getString()); + String s = this.get(0).getString(); + if (s.startsWith("0x")) return Integer.parseInt(s.substring(2), 16); + if (s.startsWith("0b")) return Integer.parseInt(s.substring(2), 2); + return Integer.parseInt(s); } public void append(@Nullable String s) { @@ -102,6 +114,12 @@ public MultiLineComponent append(@Nullable List lines) { return this; } + public MultiLineComponent append(MultiLineComponent multiLineComponent) { + if (multiLineComponent == null) return this; + this.graphics.addAll(multiLineComponent.getGraphics()); + return this.append(multiLineComponent.toImmutable()); + } + public void appendNewline() { this.add(MutableComponent.create(ComponentContents.EMPTY)); } @@ -131,18 +149,33 @@ public List toImmutable() { } public Tag toTag() { + CompoundTag compoundTag = new CompoundTag(); ListTag tag = new ListTag(); for (MutableComponent component : this) { tag.add(StringTag.valueOf(Component.Serializer.toJson(component))); } - return tag; + compoundTag.put("text", tag); + ListTag graphicsTag = new ListTag(); + for (GraphicsComponent component : this.getGraphics()) { + graphicsTag.add(component.toTag()); + } + compoundTag.put("graphics", graphicsTag); + return compoundTag; } - public static MultiLineComponent fromTag(ListTag tag) { + public static MultiLineComponent fromTag(@Nullable Tag tag) { MultiLineComponent out = MultiLineComponent.empty(); out.clear(); - for (Tag i : tag) { - out.add(Component.Serializer.fromJson(i.getAsString())); + if (tag == null) return out; + if (tag instanceof ListTag listTag) { + for (Tag i : listTag) { + out.add(Component.Serializer.fromJson(i.getAsString())); + } + } else if (tag instanceof CompoundTag compoundTag) { + ListTag textTag = compoundTag.getList("text", Tag.TAG_STRING); + for (Tag i : textTag) out.add(Component.Serializer.fromJson(i.getAsString())); + ListTag graphicsTag = compoundTag.getList("graphics", Tag.TAG_COMPOUND); + for (Tag i : graphicsTag) out.addGraphics(GraphicsComponent.fromTag(i)); } return out; } @@ -150,11 +183,18 @@ public static MultiLineComponent fromTag(ListTag tag) { public long toLong() { if (this.isEmpty()) return 0; if (this.size() > 1) throw new NumberFormatException(this.toString()); - return Long.parseLong(this.get(0).getString()); + String s = this.get(0).getString(); + if (s.startsWith("0b")) return Long.parseLong(s.substring(2), 2); + if (s.startsWith("0x")) return Long.parseLong(s.substring(2), 16); + return Long.parseLong(s); + } + + public MultiLineComponent addGraphics(GraphicsComponent... graphicsComponents) { + return this.addGraphics(List.of(graphicsComponents)); } - public MultiLineComponent setIgnoreSpaces(boolean ignoreSpaces) { - this.ignoreSpaces = ignoreSpaces; + public MultiLineComponent addGraphics(Collection graphicsComponents) { + this.graphics.addAll(graphicsComponents); return this; } } diff --git a/src/main/java/com/gregtechceu/gtceu/api/placeholder/PlaceholderContext.java b/src/main/java/com/gregtechceu/gtceu/api/placeholder/PlaceholderContext.java index 9e55e356f85..223692a7b6d 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/placeholder/PlaceholderContext.java +++ b/src/main/java/com/gregtechceu/gtceu/api/placeholder/PlaceholderContext.java @@ -7,6 +7,7 @@ import net.minecraft.world.level.Level; import net.minecraftforge.items.ItemStackHandler; +import lombok.With; import org.jetbrains.annotations.Nullable; import java.util.UUID; @@ -17,4 +18,16 @@ public record PlaceholderContext(Level level, @Nullable ItemStackHandler itemStackHandler, @Nullable CoverBehavior cover, @Nullable MultiLineComponent previousText, - UUID uuid) {} + UUID uuid, + @With int index) { + + public PlaceholderContext(Level level, + BlockPos pos, + Direction side, + @Nullable ItemStackHandler itemStackHandler, + @Nullable CoverBehavior cover, + @Nullable MultiLineComponent previousText, + UUID uuid) { + this(level, pos, side, itemStackHandler, cover, previousText, uuid, 0); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/api/placeholder/PlaceholderHandler.java b/src/main/java/com/gregtechceu/gtceu/api/placeholder/PlaceholderHandler.java index 86edbd0bd77..00a80df2825 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/placeholder/PlaceholderHandler.java +++ b/src/main/java/com/gregtechceu/gtceu/api/placeholder/PlaceholderHandler.java @@ -5,6 +5,7 @@ import com.gregtechceu.gtceu.api.placeholder.exceptions.UnclosedBracketException; import com.gregtechceu.gtceu.api.placeholder.exceptions.UnexpectedBracketException; import com.gregtechceu.gtceu.api.placeholder.exceptions.UnknownPlaceholderException; +import com.gregtechceu.gtceu.client.renderer.monitor.IMonitorRenderer; import com.gregtechceu.gtceu.data.lang.LangHandler; import com.gregtechceu.gtceu.utils.GTStringUtils; import com.gregtechceu.gtceu.utils.GTUtil; @@ -14,16 +15,20 @@ import com.lowdragmc.lowdraglib.gui.widget.TextTextureWidget; import com.lowdragmc.lowdraglib.gui.widget.Widget; import com.lowdragmc.lowdraglib.gui.widget.WidgetGroup; -import com.lowdragmc.lowdraglib.gui.widget.codeeditor.language.LanguageDefinition; -import com.lowdragmc.lowdraglib.gui.widget.codeeditor.language.TokenTypes; import net.minecraft.ChatFormatting; import net.minecraft.MethodsReturnNonnullByDefault; +import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.MutableComponent; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import java.util.*; import java.util.function.Consumer; +import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; @ParametersAreNonnullByDefault @@ -40,18 +45,11 @@ public class PlaceholderHandler { private static final Map placeholders = new HashMap<>(); - public static final LanguageDefinition LANG_DEFINITION = new LanguageDefinition( - "Placeholders", - List.of( - TokenTypes.KEYWORD.createTokenType(PlaceholderHandler.getAllPlaceholderNames().stream().toList()), - TokenTypes.IDENTIFIER, - TokenTypes.STRING, - TokenTypes.COMMENT, - TokenTypes.NUMBER, - TokenTypes.OPERATOR, - TokenTypes.WHITESPACE, - TokenTypes.OTHER), - Set.of()); + @OnlyIn(Dist.CLIENT) + private static final class RendererHolder { + + public static final Map renderers = new HashMap<>(); + } public static void addPlaceholder(Placeholder placeholder) { if (placeholders.containsKey(placeholder.getName())) { @@ -65,11 +63,35 @@ public static boolean placeholderExists(MultiLineComponent placeholder) { return placeholders.containsKey(placeholder.toString()); } + @OnlyIn(Dist.CLIENT) + public static void addRenderer(String id, IPlaceholderRenderer renderer) { + RendererHolder.renderers.put(id, renderer); + } + + @OnlyIn(Dist.CLIENT) + public static @Nullable IMonitorRenderer getRenderer(String id, CompoundTag renderData) { + if (!RendererHolder.renderers.containsKey(id)) { + GTCEu.LOGGER.warn("Attempt to access a placeholder renderer that doesn't exist ({})", id); + return null; + } + IPlaceholderRenderer renderer = RendererHolder.renderers.get(id); + CompoundTag tag = renderData.copy(); + return (machine, group, + partialTick, poseStack, buffer, + packedLight, packedOverlay) -> renderer.render( + machine, group, + partialTick, poseStack, buffer, + packedLight, packedOverlay, tag); + } + public static MultiLineComponent processPlaceholder(List placeholder, - PlaceholderContext context) throws PlaceholderException { + PlaceholderContext context, + Object2IntOpenHashMap indices) throws PlaceholderException { if (!placeholderExists(placeholder.get(0))) throw new UnknownPlaceholderException(placeholder.get(0).toString()); - return placeholders.get(placeholder.get(0).toString()).apply(context, + String name = placeholder.get(0).toString(); + indices.addTo(name, 1); + return placeholders.get(name).apply(context.withIndex(indices.getInt(name)), placeholder.subList(1, placeholder.size())); } @@ -77,6 +99,7 @@ public static MultiLineComponent processPlaceholders(String s, PlaceholderContex if (ctx.level().isClientSide) GTCEu.LOGGER.warn("Placeholder processing is running on client instead of server!"); List exceptions = new ArrayList<>(); + Object2IntOpenHashMap indices = new Object2IntOpenHashMap<>(); boolean escape = false; boolean escapeNext = false; boolean literalEscape = false; @@ -110,7 +133,7 @@ public static MultiLineComponent processPlaceholders(String s, PlaceholderContex case PLACEHOLDER_END -> { List placeholder = stack.pop(); if (stack.isEmpty()) throw new UnexpectedBracketException(); - MultiLineComponent result = processPlaceholder(placeholder, ctx); + MultiLineComponent result = processPlaceholder(placeholder, ctx, indices); if (result.isIgnoreSpaces() || stack.size() == 1) { GTUtil.getLast(stack.peek()).append(result); } else { @@ -155,7 +178,8 @@ public static MultiLineComponent processPlaceholders(String s, PlaceholderContex } if (exceptions.isEmpty()) return stack.peek().stream().reduce(MultiLineComponent.empty(), MultiLineComponent::append); - MultiLineComponent out = MultiLineComponent.empty(); + MultiLineComponent out = MultiLineComponent.literal("Exceptions:"); + out.appendNewline(); exceptions.forEach(exception -> { out.append(exception.getMessage()); out.appendNewline(); diff --git a/src/main/java/com/gregtechceu/gtceu/api/placeholder/PlaceholderUtils.java b/src/main/java/com/gregtechceu/gtceu/api/placeholder/PlaceholderUtils.java index eeb8f00cff3..31cb62f1881 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/placeholder/PlaceholderUtils.java +++ b/src/main/java/com/gregtechceu/gtceu/api/placeholder/PlaceholderUtils.java @@ -29,6 +29,10 @@ public static double toDouble(MultiLineComponent component) throws InvalidNumber } } + public static float toFloat(MultiLineComponent component) throws InvalidNumberException { + return (float) toDouble(component); + } + public static void checkArgs(List args, int args_num) throws WrongNumberOfArgsException { if (args.size() != args_num) throw new WrongNumberOfArgsException(args_num, args.size()); } diff --git a/src/main/java/com/gregtechceu/gtceu/api/recipe/GTRecipe.java b/src/main/java/com/gregtechceu/gtceu/api/recipe/GTRecipe.java index f66e4f1e55f..66cdfb58639 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/recipe/GTRecipe.java +++ b/src/main/java/com/gregtechceu/gtceu/api/recipe/GTRecipe.java @@ -60,6 +60,7 @@ public class GTRecipe implements net.minecraft.world.item.crafting.Recipe, List> inputs, @@ -74,10 +75,11 @@ public GTRecipe(GTRecipeType recipeType, List ingredientActions, @NotNull CompoundTag data, int duration, - @NotNull GTRecipeCategory recipeCategory) { + @NotNull GTRecipeCategory recipeCategory, + int groupColor) { this(recipeType, null, inputs, outputs, tickInputs, tickOutputs, inputChanceLogics, outputChanceLogics, tickInputChanceLogics, tickOutputChanceLogics, - conditions, ingredientActions, data, duration, recipeCategory); + conditions, ingredientActions, data, duration, recipeCategory, groupColor); } public GTRecipe(GTRecipeType recipeType, @@ -94,7 +96,7 @@ public GTRecipe(GTRecipeType recipeType, List ingredientActions, @NotNull CompoundTag data, int duration, - @NotNull GTRecipeCategory recipeCategory) { + @NotNull GTRecipeCategory recipeCategory, int groupColor) { this.recipeType = recipeType; this.id = id; @@ -113,6 +115,7 @@ public GTRecipe(GTRecipeType recipeType, this.data = data; this.duration = duration; this.recipeCategory = (recipeCategory != GTRecipeCategory.DEFAULT) ? recipeCategory : recipeType.getCategory(); + this.groupColor = groupColor; } public GTRecipe copy() { @@ -130,7 +133,7 @@ public GTRecipe copy(ContentModifier modifier, boolean modifyDuration) { new HashMap<>(inputChanceLogics), new HashMap<>(outputChanceLogics), new HashMap<>(tickInputChanceLogics), new HashMap<>(tickOutputChanceLogics), new ArrayList<>(conditions), - new ArrayList<>(ingredientActions), data, duration, recipeCategory); + new ArrayList<>(ingredientActions), data, duration, recipeCategory, groupColor); if (modifyDuration) { copied.duration = modifier.apply(this.duration); } diff --git a/src/main/java/com/gregtechceu/gtceu/api/recipe/GTRecipeSerializer.java b/src/main/java/com/gregtechceu/gtceu/api/recipe/GTRecipeSerializer.java index 9730dd12684..a1ca70f39fe 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/recipe/GTRecipeSerializer.java +++ b/src/main/java/com/gregtechceu/gtceu/api/recipe/GTRecipeSerializer.java @@ -131,6 +131,7 @@ public GTRecipe fromNetwork(@NotNull ResourceLocation id, @NotNull FriendlyByteB if (data == null) { data = new CompoundTag(); } + int groupColor = buf.readInt(); ResourceLocation categoryLoc = buf.readResourceLocation(); GTRecipeType type = (GTRecipeType) BuiltInRegistries.RECIPE_TYPE.get(recipeType); @@ -139,7 +140,7 @@ public GTRecipe fromNetwork(@NotNull ResourceLocation id, @NotNull FriendlyByteB GTRecipe recipe = new GTRecipe(type, id, inputs, outputs, tickInputs, tickOutputs, inputChanceLogics, outputChanceLogics, tickInputChanceLogics, tickOutputChanceLogics, - conditions, ingredientActions, data, duration, category); + conditions, ingredientActions, data, duration, category, groupColor); recipe.recipeCategory.addRecipe(recipe); @@ -182,6 +183,7 @@ public void toNetwork(FriendlyByteBuf buf, GTRecipe recipe) { KJSCallWrapper.writeIngredientActions(recipe.ingredientActions, buf); } buf.writeNbt(recipe.data); + buf.writeInt(recipe.groupColor); buf.writeResourceLocation(recipe.recipeCategory.registryKey); } @@ -205,14 +207,15 @@ private static Codec makeCodec(boolean isKubeLoaded) { RecipeCondition.CODEC.listOf().optionalFieldOf("recipeConditions", List.of()).forGetter(val -> val.conditions), CompoundTag.CODEC.optionalFieldOf("data", new CompoundTag()).forGetter(val -> val.data), ExtraCodecs.NON_NEGATIVE_INT.fieldOf("duration").forGetter(val -> val.duration), - GTRegistries.RECIPE_CATEGORIES.codec().optionalFieldOf("category", GTRecipeCategory.DEFAULT).forGetter(val -> val.recipeCategory)) + GTRegistries.RECIPE_CATEGORIES.codec().optionalFieldOf("category", GTRecipeCategory.DEFAULT).forGetter(val -> val.recipeCategory), + Codec.INT.fieldOf("groupColor").forGetter(val -> val.groupColor)) .apply(instance, (type, inputs, outputs, tickInputs, tickOutputs, inputChanceLogics, outputChanceLogics, tickInputChanceLogics, tickOutputChanceLogics, - conditions, data, duration, recipeCategory) -> + conditions, data, duration, recipeCategory, groupColor) -> new GTRecipe(type, inputs, outputs, tickInputs, tickOutputs, inputChanceLogics, outputChanceLogics, tickInputChanceLogics, tickOutputChanceLogics, - conditions, List.of(), data, duration, recipeCategory))); + conditions, List.of(), data, duration, recipeCategory, groupColor))); } else { return RecordCodecBuilder.create(instance -> instance.group( GTRegistries.RECIPE_TYPES.codec().fieldOf("type").forGetter(val -> val.recipeType), @@ -232,7 +235,8 @@ private static Codec makeCodec(boolean isKubeLoaded) { KJSCallWrapper.INGREDIENT_ACTION_CODEC.optionalFieldOf("kubejs:actions", List.of()).forGetter(val -> (List) val.ingredientActions), CompoundTag.CODEC.optionalFieldOf("data", new CompoundTag()).forGetter(val -> val.data), ExtraCodecs.NON_NEGATIVE_INT.fieldOf("duration").forGetter(val -> val.duration), - GTRegistries.RECIPE_CATEGORIES.codec().optionalFieldOf("category", GTRecipeCategory.DEFAULT).forGetter(val -> val.recipeCategory)) + GTRegistries.RECIPE_CATEGORIES.codec().optionalFieldOf("category", GTRecipeCategory.DEFAULT).forGetter(val -> val.recipeCategory), + Codec.INT.optionalFieldOf("groupColor", -1).forGetter(val -> val.groupColor)) .apply(instance, GTRecipe::new)); } // spotless:on diff --git a/src/main/java/com/gregtechceu/gtceu/api/recipe/RecipeHelper.java b/src/main/java/com/gregtechceu/gtceu/api/recipe/RecipeHelper.java index 110305d2ecd..fb84163e48e 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/recipe/RecipeHelper.java +++ b/src/main/java/com/gregtechceu/gtceu/api/recipe/RecipeHelper.java @@ -222,7 +222,10 @@ public static ActionResult handleRecipe(IRecipeCapabilityHolder holder, GTRecipe RecipeRunner runner = new RecipeRunner(recipe, io, isTick, holder, chanceCaches, simulated); var result = runner.handle(contents); - if (result.isSuccess() || result.capability() == null) return result; + if (result.isSuccess() || result.capability() == null) { + recipe.groupColor = runner.getGroupColor(); + return result; + } if (!simulated && ConfigHolder.INSTANCE.dev.debug) { GTCEu.LOGGER.warn("IO {} Error while handling recipe {} outputs for {}", diff --git a/src/main/java/com/gregtechceu/gtceu/api/recipe/RecipeRunner.java b/src/main/java/com/gregtechceu/gtceu/api/recipe/RecipeRunner.java index 806378f1b06..d23fc3b5501 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/recipe/RecipeRunner.java +++ b/src/main/java/com/gregtechceu/gtceu/api/recipe/RecipeRunner.java @@ -5,13 +5,17 @@ import com.gregtechceu.gtceu.api.capability.recipe.RecipeCapability; import com.gregtechceu.gtceu.api.machine.feature.IVoidable; import com.gregtechceu.gtceu.api.machine.trait.RecipeHandlerGroup; +import com.gregtechceu.gtceu.api.machine.trait.RecipeHandlerGroupColor; import com.gregtechceu.gtceu.api.machine.trait.RecipeHandlerList; import com.gregtechceu.gtceu.api.recipe.chance.boost.ChanceBoostFunction; import com.gregtechceu.gtceu.api.recipe.chance.logic.ChanceLogic; import com.gregtechceu.gtceu.api.recipe.content.Content; +import net.minecraft.network.chat.Component; + import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap; +import lombok.Getter; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; @@ -36,6 +40,8 @@ public class RecipeRunner { private Map, List> recipeContents; private final Map, List> searchRecipeContents; private final Predicate> outputVoid; + @Getter + private int groupColor; public RecipeRunner(GTRecipe recipe, IO io, boolean isTick, IRecipeCapabilityHolder holder, Map, Object2IntMap> chanceCaches, @@ -49,6 +55,7 @@ public RecipeRunner(GTRecipe recipe, IO io, boolean isTick, this.searchRecipeContents = simulated ? recipeContents : new Reference2ObjectOpenHashMap<>(); this.simulated = simulated; this.outputVoid = cap -> holder instanceof IVoidable voidable && voidable.canVoidRecipeOutputs(cap); + this.groupColor = recipe.groupColor; } @NotNull @@ -114,7 +121,11 @@ private void fillContentMatchList(Map, List> entrie private ActionResult handleContents() { if (recipeContents.isEmpty()) return ActionResult.SUCCESS; if (!capabilityProxies.containsKey(io)) { - return ActionResult.FAIL_NO_CAPABILITIES; + return ActionResult.fail( + Component.translatable("gtceu.recipe_logic.no_capabilities") + .append(Component.literal(": ")) + .append(Component.translatable(io.tooltip)), + null, io); } List handlers = capabilityProxies.getOrDefault(io, Collections.emptyList()); @@ -163,6 +174,13 @@ private ActionResult handleContents() { for (Map.Entry> handlerListEntry : handlerGroups.entrySet()) { if (handlerListEntry.getKey().equals(BUS_DISTINCT)) continue; + if (handlerListEntry.getKey() instanceof RecipeHandlerGroupColor coloredGroup) { + if (io == IO.IN && simulated && !isTick) { + groupColor = coloredGroup.color(); + } else if (coloredGroup.color() != -1 && coloredGroup.color() != groupColor) { + continue; + } + } // List to keep track of the remaining items for this RecipeHandlerGroup Map, List> copiedRecipeContents = searchRecipeContents; diff --git a/src/main/java/com/gregtechceu/gtceu/api/recipe/StrictShapedRecipe.java b/src/main/java/com/gregtechceu/gtceu/api/recipe/StrictShapedRecipe.java index 529e54e4fce..e8501709ab2 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/recipe/StrictShapedRecipe.java +++ b/src/main/java/com/gregtechceu/gtceu/api/recipe/StrictShapedRecipe.java @@ -16,6 +16,7 @@ import net.minecraft.world.level.Level; import com.google.gson.JsonObject; +import lombok.Getter; import org.jetbrains.annotations.NotNull; import java.util.Map; @@ -28,13 +29,18 @@ public class StrictShapedRecipe extends ShapedRecipe { public static final RecipeSerializer SERIALIZER = new Serializer(); + @Getter + private final boolean matchSize; + public StrictShapedRecipe(ResourceLocation id, String group, CraftingBookCategory category, int width, int height, - NonNullList recipeItems, ItemStack result) { + NonNullList recipeItems, ItemStack result, boolean matchSize) { super(id, group, category, width, height, recipeItems, result); + this.matchSize = matchSize; } @Override public boolean matches(CraftingContainer inv, Level level) { + if (matchSize && (inv.getWidth() != this.getWidth() || inv.getHeight() != this.getHeight())) return false; for (int i = 0; i <= inv.getWidth() - this.getWidth(); ++i) { for (int j = 0; j <= inv.getHeight() - this.getHeight(); ++j) { if (this.matches(inv, i, j)) { @@ -82,7 +88,9 @@ public StrictShapedRecipe fromJson(ResourceLocation recipeId, JsonObject json) { int j = strings.length; NonNullList nonNullList = ShapedRecipeAccessor.callDissolvePattern(strings, map, i, j); ItemStack itemStack = StrictShapedRecipe.itemStackFromJson(GsonHelper.getAsJsonObject(json, "result")); - return new StrictShapedRecipe(recipeId, string, craftingBookCategory, i, j, nonNullList, itemStack); + boolean matchSize = json.get("matchSize").getAsBoolean(); + return new StrictShapedRecipe(recipeId, string, craftingBookCategory, i, j, nonNullList, itemStack, + matchSize); } @Override @@ -94,7 +102,9 @@ public StrictShapedRecipe fromNetwork(ResourceLocation recipeId, FriendlyByteBuf NonNullList nonNullList = NonNullList.withSize(i * j, Ingredient.EMPTY); nonNullList.replaceAll(ignored -> Ingredient.fromNetwork(buffer)); ItemStack itemStack = buffer.readItem(); - return new StrictShapedRecipe(recipeId, string, craftingBookCategory, i, j, nonNullList, itemStack); + boolean matchSize = buffer.readBoolean(); + return new StrictShapedRecipe(recipeId, string, craftingBookCategory, i, j, nonNullList, itemStack, + matchSize); } @Override @@ -107,6 +117,7 @@ public void toNetwork(FriendlyByteBuf buffer, StrictShapedRecipe recipe) { ingredient.toNetwork(buffer); } buffer.writeItem(((ShapedRecipeAccessor) recipe).getResult()); + buffer.writeBoolean(recipe.matchSize); } } } diff --git a/src/main/java/com/gregtechceu/gtceu/api/recipe/ingredient/NBTPredicateIngredient.java b/src/main/java/com/gregtechceu/gtceu/api/recipe/ingredient/NBTPredicateIngredient.java index 2fde075f7b6..b0cd45576d8 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/recipe/ingredient/NBTPredicateIngredient.java +++ b/src/main/java/com/gregtechceu/gtceu/api/recipe/ingredient/NBTPredicateIngredient.java @@ -96,7 +96,7 @@ public static class Serializer implements IIngredientSerializer recipe; + ModifierFunction IDENTITY = ModifierFunction.builder().build(); + + static ModifierFunction cancel(Component reason) { + return new ModifierFunction() { + + @Override + public @Nullable GTRecipe apply(@NotNull GTRecipe recipe) { + return null; + } + + @Override + public Component getFailReason() { + return reason; + } + }; + } /** * Applies this modifier to the passed recipe @@ -79,6 +97,12 @@ private GTRecipe applySafe(@Nullable GTRecipe recipe) { return apply(recipe); } + static final Component DEFAULT_FAILURE = Component.translatable("gtceu.recipe_modifier.default_fail"); + + default Component getFailReason() { + return DEFAULT_FAILURE; + } + /** * Creates a FunctionBuilder to easily build a ModifierFunction that modifies parts of a recipe. *

@@ -159,7 +183,7 @@ public ModifierFunction build() { new HashMap<>(recipe.inputChanceLogics), new HashMap<>(recipe.outputChanceLogics), new HashMap<>(recipe.tickInputChanceLogics), new HashMap<>(recipe.tickOutputChanceLogics), newConditions, new ArrayList<>(recipe.ingredientActions), - recipe.data, recipe.duration, recipe.recipeCategory); + recipe.data, recipe.duration, recipe.recipeCategory, recipe.groupColor); copied.parallels = recipe.parallels * parallels; copied.subtickParallels = recipe.subtickParallels * subtickParallels; copied.ocLevel = recipe.ocLevel + addOCs; diff --git a/src/main/java/com/gregtechceu/gtceu/api/recipe/modifier/ParallelLogic.java b/src/main/java/com/gregtechceu/gtceu/api/recipe/modifier/ParallelLogic.java index b8a65588451..a1e903a2883 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/recipe/modifier/ParallelLogic.java +++ b/src/main/java/com/gregtechceu/gtceu/api/recipe/modifier/ParallelLogic.java @@ -3,11 +3,13 @@ import com.gregtechceu.gtceu.api.capability.recipe.*; import com.gregtechceu.gtceu.api.machine.MetaMachine; import com.gregtechceu.gtceu.api.machine.feature.IRecipeLogicMachine; +import com.gregtechceu.gtceu.api.machine.trait.RecipeLogic; import com.gregtechceu.gtceu.api.recipe.GTRecipe; import com.gregtechceu.gtceu.api.recipe.RecipeHelper; import com.gregtechceu.gtceu.api.recipe.content.ContentModifier; import net.minecraft.MethodsReturnNonnullByDefault; +import net.minecraft.network.chat.Component; import org.jetbrains.annotations.NotNull; @@ -57,7 +59,15 @@ public static int getMaxByInput(IRecipeCapabilityHolder holder, GTRecipe recipe, for (RecipeCapability cap : recipe.inputs.keySet()) { if (cap.doMatchInRecipe() && !capsToSkip.contains(cap)) { // Find the maximum number of recipes that can be performed from the contents of the input inventories - minimum = Math.min(minimum, cap.getMaxParallelByInput(holder, recipe, parallelLimit, false)); + var capParallel = cap.getMaxParallelByInput(holder, recipe, parallelLimit, false); + if (capParallel == 0) { + Component reason = Component.translatable("gtceu.recipe_logic.insufficient_in") + .append(": ") + .append(cap.getName()); + RecipeLogic.putFailureReason(holder, recipe, reason); + return 0; + } + minimum = Math.min(minimum, capParallel); } } @@ -65,10 +75,24 @@ public static int getMaxByInput(IRecipeCapabilityHolder holder, GTRecipe recipe, for (RecipeCapability cap : recipe.tickInputs.keySet()) { if (cap.doMatchInRecipe() && !capsToSkip.contains(cap)) { // Find the maximum number of recipes that can be performed from the contents of the input inventories - minimum = Math.min(minimum, cap.getMaxParallelByInput(holder, recipe, parallelLimit, true)); + var capParallel = cap.getMaxParallelByInput(holder, recipe, parallelLimit, true); + if (capParallel == 0) { + Component reason = Component.translatable("gtceu.recipe_logic.insufficient_in") + .append(": ") + .append(cap.getName()); + RecipeLogic.putFailureReason(holder, recipe, reason); + return 0; + } + minimum = Math.min(minimum, capParallel); } } - if (minimum == Integer.MAX_VALUE) return 0; + if (minimum == Integer.MAX_VALUE) { + Component reason = Component.translatable("gtceu.recipe_logic.no_capabilities") + .append(Component.literal(": ")) + .append(Component.translatable(IO.IN.tooltip)); + RecipeLogic.putFailureReason(holder, recipe, reason); + return 0; + } return minimum; } @@ -93,6 +117,10 @@ public static int limitByOutputMerging(IRecipeCapabilityHolder holder, GTRecipe int limit = cap.limitMaxParallelByOutput(holder, recipe, parallelLimit, false); // If we are not voiding, and cannot fit any items, return 0 if (limit == 0) { + Component reason = Component.translatable("gtceu.recipe_logic.insufficient_out") + .append(": ") + .append(cap.getName()); + RecipeLogic.putFailureReason(holder, recipe, reason); return 0; } max = Math.min(max, limit); @@ -107,6 +135,10 @@ public static int limitByOutputMerging(IRecipeCapabilityHolder holder, GTRecipe int limit = cap.limitMaxParallelByOutput(holder, recipe, parallelLimit, true); // If we are not voiding, and cannot fit any items, return 0 if (limit == 0) { + Component reason = Component.translatable("gtceu.recipe_logic.insufficient_out") + .append(": ") + .append(cap.getName()); + RecipeLogic.putFailureReason(holder, recipe, reason); return 0; } max = Math.min(max, limit); diff --git a/src/main/java/com/gregtechceu/gtceu/api/recipe/modifier/RecipeModifierList.java b/src/main/java/com/gregtechceu/gtceu/api/recipe/modifier/RecipeModifierList.java index 020ce9e4f10..533b131e481 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/recipe/modifier/RecipeModifierList.java +++ b/src/main/java/com/gregtechceu/gtceu/api/recipe/modifier/RecipeModifierList.java @@ -1,6 +1,7 @@ package com.gregtechceu.gtceu.api.recipe.modifier; import com.gregtechceu.gtceu.api.machine.MetaMachine; +import com.gregtechceu.gtceu.api.machine.trait.RecipeLogic; import com.gregtechceu.gtceu.api.recipe.GTRecipe; import lombok.Getter; @@ -37,7 +38,10 @@ public RecipeModifierList(RecipeModifier... modifiers) { for (RecipeModifier modifier : modifiers) { var func = modifier.getModifier(machine, runningRecipe); runningRecipe = func.apply(runningRecipe); - if (runningRecipe == null) return ModifierFunction.NULL; + if (runningRecipe == null) { + RecipeLogic.putFailureReason(machine, recipe, func.getFailReason()); + return ModifierFunction.NULL; + } result = func.compose(result); } return result; diff --git a/src/main/java/com/gregtechceu/gtceu/api/registry/registrate/GTBlockBuilder.java b/src/main/java/com/gregtechceu/gtceu/api/registry/registrate/GTBlockBuilder.java index c1ba8744fb0..17dfee8d336 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/registry/registrate/GTBlockBuilder.java +++ b/src/main/java/com/gregtechceu/gtceu/api/registry/registrate/GTBlockBuilder.java @@ -38,6 +38,10 @@ public GTBlockBuilder exBlockstate(NonNullBiConsumer cons.accept(ctx, (GTBlockstateProvider) prov)); } + public GTBlockBuilder gtBlockstate(NonNullBiConsumer, GTBlockstateProvider> cons) { + return setData(ProviderType.BLOCKSTATE, (ctx, prov) -> cons.accept(ctx, (GTBlockstateProvider) prov)); + } + // region default overrides @Override @@ -122,6 +126,11 @@ public GTBlockBuilder setDataGeneric(Provid return this; } + @Override + public GTBlockBuilder setData(ProviderType type, NonNullBiConsumer, D> cons) { + return (GTBlockBuilder) super.setData(type, cons); + } + // spotless:on // endregion } diff --git a/src/main/java/com/gregtechceu/gtceu/api/registry/registrate/MachineBuilder.java b/src/main/java/com/gregtechceu/gtceu/api/registry/registrate/MachineBuilder.java index e4c212484d6..c1b59704aa3 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; @@ -74,7 +75,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 @@ -804,9 +804,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/api/sync_system/data_transformers/gtceu/MonitorGroupTransformer.java b/src/main/java/com/gregtechceu/gtceu/api/sync_system/data_transformers/gtceu/MonitorGroupTransformer.java index 57e1e770937..0f49c89c9ab 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/sync_system/data_transformers/gtceu/MonitorGroupTransformer.java +++ b/src/main/java/com/gregtechceu/gtceu/api/sync_system/data_transformers/gtceu/MonitorGroupTransformer.java @@ -16,7 +16,7 @@ public CompoundTag serializeNBT(MonitorGroup value, ValueTransformer.Transformer CompoundTag tag = new CompoundTag(); tag.putString("name", value.getName()); ListTag list = new ListTag(); - value.getRelativePositions().forEach(pos -> list.add(NbtUtils.writeBlockPos(pos))); + value.getMonitorPositions().forEach(pos -> list.add(NbtUtils.writeBlockPos(pos))); if (value.getTargetRaw() != null) { tag.put("targetPos", NbtUtils.writeBlockPos(value.getTargetRaw())); if (value.getTargetCoverSide() != null) { 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..547af6d647e --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/client/model/GTModelProperties.java @@ -0,0 +1,14 @@ +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<>(); +} diff --git a/src/main/java/com/gregtechceu/gtceu/client/model/IBlockEntityRendererBakedModel.java b/src/main/java/com/gregtechceu/gtceu/client/model/IBlockEntityRendererBakedModel.java index 6a59d976574..001442720cc 100644 --- a/src/main/java/com/gregtechceu/gtceu/client/model/IBlockEntityRendererBakedModel.java +++ b/src/main/java/com/gregtechceu/gtceu/client/model/IBlockEntityRendererBakedModel.java @@ -12,21 +12,21 @@ import net.minecraftforge.client.model.IDynamicBakedModel; import com.mojang.blaze3d.vertex.PoseStack; -import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public interface IBlockEntityRendererBakedModel extends IDynamicBakedModel, BlockEntityRenderer { + @Nullable BlockEntityType getBlockEntityType(); - void render(@NotNull T blockEntity, float partialTick, - @NotNull PoseStack poseStack, @NotNull MultiBufferSource buffer, + void render(T blockEntity, float partialTick, PoseStack poseStack, MultiBufferSource buffer, int packedLight, int packedOverlay); default void renderByItem(ItemStack stack, ItemDisplayContext displayContext, PoseStack poseStack, MultiBufferSource buffer, int packedLight, int packedOverlay) {} - default boolean shouldRender(T blockEntity, @NotNull Vec3 cameraPos) { + default boolean shouldRender(T blockEntity, Vec3 cameraPos) { return Vec3.atCenterOf(blockEntity.getBlockPos()).closerThan(cameraPos, this.getViewDistance()); } diff --git a/src/main/java/com/gregtechceu/gtceu/client/model/PipeModel.java b/src/main/java/com/gregtechceu/gtceu/client/model/PipeModel.java deleted file mode 100644 index efdff6bb28b..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/client/model/PipeModel.java +++ /dev/null @@ -1,357 +0,0 @@ -package com.gregtechceu.gtceu.client.model; - -import com.gregtechceu.gtceu.GTCEu; -import com.gregtechceu.gtceu.api.blockentity.PipeBlockEntity; -import com.gregtechceu.gtceu.client.util.ModelUtils; -import com.gregtechceu.gtceu.common.data.models.GTModels; -import com.gregtechceu.gtceu.utils.GTUtil; -import com.gregtechceu.gtceu.utils.memoization.GTMemoizer; -import com.gregtechceu.gtceu.utils.memoization.MemoizedSupplier; - -import com.lowdragmc.lowdraglib.client.bakedpipeline.FaceQuad; -import com.lowdragmc.lowdraglib.client.renderer.IItemRendererProvider; - -import net.minecraft.Util; -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.block.model.BakedQuad; -import net.minecraft.client.renderer.texture.TextureAtlas; -import net.minecraft.client.renderer.texture.TextureAtlasSprite; -import net.minecraft.client.resources.model.BakedModel; -import net.minecraft.core.Direction; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.inventory.InventoryMenu; -import net.minecraft.world.item.ItemDisplayContext; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.phys.AABB; -import net.minecraft.world.phys.shapes.Shapes; -import net.minecraft.world.phys.shapes.VoxelShape; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -import com.mojang.blaze3d.vertex.PoseStack; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; -import lombok.Setter; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Supplier; - -public class PipeModel { - - public static final ResourceLocation PIPE_BLOCKED_OVERLAY = GTCEu.id("block/pipe/blocked/pipe_blocked"); - public static final ResourceLocation PIPE_BLOCKED_OVERLAY_UP = GTCEu.id("block/pipe/blocked/pipe_blocked_up"); - public static final ResourceLocation PIPE_BLOCKED_OVERLAY_DOWN = GTCEu.id("block/pipe/blocked/pipe_blocked_down"); - public static final ResourceLocation PIPE_BLOCKED_OVERLAY_LEFT = GTCEu.id("block/pipe/blocked/pipe_blocked_left"); - public static final ResourceLocation PIPE_BLOCKED_OVERLAY_RIGHT = GTCEu.id("block/pipe/blocked/pipe_blocked_right"); - public static final ResourceLocation PIPE_BLOCKED_OVERLAY_NU = GTCEu.id("block/pipe/blocked/pipe_blocked_nu"); - public static final ResourceLocation PIPE_BLOCKED_OVERLAY_ND = GTCEu.id("block/pipe/blocked/pipe_blocked_nd"); - public static final ResourceLocation PIPE_BLOCKED_OVERLAY_NL = GTCEu.id("block/pipe/blocked/pipe_blocked_nl"); - public static final ResourceLocation PIPE_BLOCKED_OVERLAY_NR = GTCEu.id("block/pipe/blocked/pipe_blocked_nr"); - public static final ResourceLocation PIPE_BLOCKED_OVERLAY_UD = GTCEu.id("block/pipe/blocked/pipe_blocked_ud"); - public static final ResourceLocation PIPE_BLOCKED_OVERLAY_UL = GTCEu.id("block/pipe/blocked/pipe_blocked_ul"); - public static final ResourceLocation PIPE_BLOCKED_OVERLAY_UR = GTCEu.id("block/pipe/blocked/pipe_blocked_ur"); - public static final ResourceLocation PIPE_BLOCKED_OVERLAY_DL = GTCEu.id("block/pipe/blocked/pipe_blocked_dl"); - public static final ResourceLocation PIPE_BLOCKED_OVERLAY_DR = GTCEu.id("block/pipe/blocked/pipe_blocked_dr"); - public static final ResourceLocation PIPE_BLOCKED_OVERLAY_LR = GTCEu.id("block/pipe/blocked/pipe_blocked_lr"); - private static final Int2ObjectMap RESTRICTOR_MAP = new Int2ObjectOpenHashMap<>(); - private static boolean isRestrictorInitialized; - - protected static void initializeRestrictor(Function atlas) { - addRestrictor(atlas.apply(PIPE_BLOCKED_OVERLAY_UP), Border.TOP); - addRestrictor(atlas.apply(PIPE_BLOCKED_OVERLAY_DOWN), Border.BOTTOM); - addRestrictor(atlas.apply(PIPE_BLOCKED_OVERLAY_UD), Border.TOP, Border.BOTTOM); - addRestrictor(atlas.apply(PIPE_BLOCKED_OVERLAY_LEFT), Border.LEFT); - addRestrictor(atlas.apply(PIPE_BLOCKED_OVERLAY_UL), Border.TOP, Border.LEFT); - addRestrictor(atlas.apply(PIPE_BLOCKED_OVERLAY_DL), Border.BOTTOM, Border.LEFT); - addRestrictor(atlas.apply(PIPE_BLOCKED_OVERLAY_NR), Border.TOP, Border.BOTTOM, Border.LEFT); - addRestrictor(atlas.apply(PIPE_BLOCKED_OVERLAY_RIGHT), Border.RIGHT); - addRestrictor(atlas.apply(PIPE_BLOCKED_OVERLAY_UR), Border.TOP, Border.RIGHT); - addRestrictor(atlas.apply(PIPE_BLOCKED_OVERLAY_DR), Border.BOTTOM, Border.RIGHT); - addRestrictor(atlas.apply(PIPE_BLOCKED_OVERLAY_NL), Border.TOP, Border.BOTTOM, Border.RIGHT); - addRestrictor(atlas.apply(PIPE_BLOCKED_OVERLAY_LR), Border.LEFT, Border.RIGHT); - addRestrictor(atlas.apply(PIPE_BLOCKED_OVERLAY_ND), Border.TOP, Border.LEFT, Border.RIGHT); - addRestrictor(atlas.apply(PIPE_BLOCKED_OVERLAY_NU), Border.BOTTOM, Border.LEFT, Border.RIGHT); - addRestrictor(atlas.apply(PIPE_BLOCKED_OVERLAY), Border.TOP, Border.BOTTOM, Border.LEFT, Border.RIGHT); - } - - private static final EnumMap> FACE_BORDER_MAP = Util.make(() -> { - EnumMap> map = new EnumMap<>(Direction.class); - - map.put(Direction.DOWN, borderMap(Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)); - map.put(Direction.UP, borderMap(Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)); - map.put(Direction.NORTH, borderMap(Direction.DOWN, Direction.UP, Direction.WEST, Direction.EAST)); - map.put(Direction.SOUTH, borderMap(Direction.DOWN, Direction.UP, Direction.WEST, Direction.EAST)); - map.put(Direction.WEST, borderMap(Direction.DOWN, Direction.UP, Direction.NORTH, Direction.SOUTH)); - map.put(Direction.EAST, borderMap(Direction.DOWN, Direction.UP, Direction.NORTH, Direction.SOUTH)); - - return map; - }); - - public final static int ITEM_CONNECTIONS = 0b001100; - public final float thickness; - public final AABB coreCube; - public final Map sideCubes; - - public MemoizedSupplier sideTexture, endTexture; - @Nullable - public MemoizedSupplier secondarySideTexture, secondaryEndTexture; - @Setter - public @Nullable ResourceLocation sideOverlayTexture, endOverlayTexture; - - @OnlyIn(Dist.CLIENT) - private @Nullable TextureAtlasSprite sideSprite, endSprite; - @OnlyIn(Dist.CLIENT) - private @Nullable TextureAtlasSprite secondarySideSprite, secondaryEndSprite; - @OnlyIn(Dist.CLIENT) - private @Nullable TextureAtlasSprite sideOverlaySprite, endOverlaySprite; - - public PipeModel(float thickness, Supplier sideTexture, Supplier endTexture, - @Nullable Supplier secondarySideTexture, - @Nullable Supplier secondaryEndTexture) { - this.sideTexture = GTMemoizer.memoize(sideTexture); - this.endTexture = GTMemoizer.memoize(endTexture); - this.secondarySideTexture = secondarySideTexture != null ? GTMemoizer.memoize(secondarySideTexture) : - null; - this.secondaryEndTexture = secondaryEndTexture != null ? GTMemoizer.memoize(secondaryEndTexture) : null; - this.thickness = thickness; - double min = (1d - thickness) / 2; - double max = min + thickness; - this.coreCube = new AABB(min, min, min, max, max, max); - this.sideCubes = new EnumMap<>(Direction.class); - for (Direction side : GTUtil.DIRECTIONS) { - var normal = side.getNormal(); - sideCubes.put(side, new AABB( - normal.getX() == 0 ? min : normal.getX() > 0 ? max : 0, - normal.getY() == 0 ? min : normal.getY() > 0 ? max : 0, - normal.getZ() == 0 ? min : normal.getZ() > 0 ? max : 0, - normal.getX() == 0 ? max : normal.getX() > 0 ? 1 : min, - normal.getY() == 0 ? max : normal.getY() > 0 ? 1 : min, - normal.getZ() == 0 ? max : normal.getZ() > 0 ? 1 : min)); - } - - if (!isRestrictorInitialized) { - ModelUtils.registerAtlasStitchedEventListener(false, InventoryMenu.BLOCK_ATLAS, event -> { - initializeRestrictor(event.getAtlas()::getSprite); - }); - - isRestrictorInitialized = true; - } - ModelUtils.registerAtlasStitchedEventListener(false, InventoryMenu.BLOCK_ATLAS, event -> { - TextureAtlas atlas = event.getAtlas(); - - sideSprite = atlas.getSprite(sideTexture.get()); - endSprite = atlas.getSprite(endTexture.get()); - if (secondarySideTexture != null) { - secondarySideSprite = atlas.getSprite(secondarySideTexture.get()); - } - if (secondaryEndTexture != null) { - secondaryEndSprite = atlas.getSprite(secondaryEndTexture.get()); - } - if (sideOverlayTexture != null) { - sideOverlaySprite = atlas.getSprite(sideOverlayTexture); - } - if (endOverlayTexture != null) { - endOverlaySprite = atlas.getSprite(endOverlayTexture); - } - }); - } - - public VoxelShape getShapes(int connections) { - var shapes = new ArrayList(7); - shapes.add(Shapes.create(coreCube)); - for (Direction side : GTUtil.DIRECTIONS) { - if (PipeBlockEntity.isConnected(connections, side)) { - shapes.add(Shapes.create(sideCubes.get(side))); - } - } - return shapes.stream().reduce(Shapes.empty(), Shapes::or); - } - - @OnlyIn(Dist.CLIENT) - public List bakeQuads(@Nullable Direction side, int connections, int blockedConnections) { - if (side != null) { - if (thickness == 1) { // full block - List quads = new LinkedList<>(); - quads.add(FaceQuad.builder(side, sideSprite).cube(coreCube).cubeUV().tintIndex(0).bake()); - if (secondarySideSprite != null) { - quads.add(FaceQuad.builder(side, secondarySideSprite).cube(coreCube).cubeUV().tintIndex(0).bake()); - } - return quads; - } - - if (PipeBlockEntity.isConnected(connections, side)) { // side connected - List quads = new LinkedList<>(); - quads.add(FaceQuad.builder(side, endSprite).cube(sideCubes.get(side).inflate(-0.001)).cubeUV() - .tintIndex(1).bake()); - if (secondaryEndSprite != null) { - quads.add(FaceQuad.builder(side, secondaryEndSprite).cube(sideCubes.get(side)).cubeUV().tintIndex(1) - .bake()); - } - if (endOverlaySprite != null) { - quads.add(FaceQuad.builder(side, endOverlaySprite).cube(sideCubes.get(side)).cubeUV().tintIndex(0) - .bake()); - } - if (sideOverlaySprite != null) { - for (Direction face : GTUtil.DIRECTIONS) { - if (face.getAxis() != side.getAxis()) { - quads.add(FaceQuad.builder(face, sideOverlaySprite).cube(sideCubes.get(side)).cubeUV() - .tintIndex(2).bake()); - } - } - } - int borderMask = computeBorderMask(blockedConnections, connections, side); - if (borderMask != 0) { - quads.add(FaceQuad.builder(side, RESTRICTOR_MAP.get(borderMask)).cube(sideCubes.get(side)).cubeUV() - .bake()); - } - return quads; - } - - return Collections.emptyList(); - } - - List quads = new LinkedList<>(); - if (thickness < 1) { // non full block - // render core cube - for (Direction face : GTUtil.DIRECTIONS) { - if (!PipeBlockEntity.isConnected(connections, face)) { - quads.add(FaceQuad.builder(face, sideSprite).cube(coreCube).cubeUV().tintIndex(0).bake()); - if (secondarySideSprite != null) { - quads.add(FaceQuad.builder(face, secondarySideSprite).cube(coreCube).cubeUV().tintIndex(0) - .bake()); - } - } - // render each connected side - for (Direction facing : GTUtil.DIRECTIONS) { - if (facing.getAxis() != face.getAxis()) { - if (PipeBlockEntity.isConnected(connections, facing)) { - quads.add(FaceQuad.builder(face, sideSprite).cube(sideCubes.get(facing)).cubeUV() - .tintIndex(0).bake()); - if (secondarySideSprite != null) { - quads.add(FaceQuad.builder(face, secondarySideSprite).cube(sideCubes.get(facing)) - .cubeUV().tintIndex(0).bake()); - } - if (sideOverlaySprite != null) { - quads.add(FaceQuad.builder(face, sideOverlaySprite) - .cube(sideCubes.get(facing).inflate(0.001)).cubeUV().tintIndex(2).bake()); - } - int borderMask = computeBorderMask(blockedConnections, connections, face); - if (borderMask != 0) { - quads.add(FaceQuad.builder(face, RESTRICTOR_MAP.get(borderMask)) - .cube(coreCube).cubeUV().bake()); - quads.add(FaceQuad.builder(face, RESTRICTOR_MAP.get(borderMask)) - .cube(sideCubes.get(facing)).cubeUV().bake()); - } - } - } - } - } - } - return quads; - } - - @SuppressWarnings("DataFlowIssue") - @OnlyIn(Dist.CLIENT) - public @NotNull TextureAtlasSprite getParticleTexture() { - return sideSprite; - } - - private final Map, List> itemModelCache = new ConcurrentHashMap<>(); - - @OnlyIn(Dist.CLIENT) - public void renderItem(ItemStack stack, ItemDisplayContext transformType, boolean leftHand, PoseStack matrixStack, - MultiBufferSource buffer, int combinedLight, int combinedOverlay, BakedModel model) { - IItemRendererProvider.disabled.set(true); - Minecraft.getInstance().getItemRenderer().render(stack, transformType, leftHand, matrixStack, buffer, - combinedLight, combinedOverlay, - (ItemBakedModel) (state, direction, random) -> itemModelCache.computeIfAbsent( - Optional.ofNullable(direction), - direction1 -> bakeQuads(direction1.orElse(null), ITEM_CONNECTIONS, 0))); - IItemRendererProvider.disabled.set(false); - } - - @OnlyIn(Dist.CLIENT) - public void registerTextureAtlas(Consumer register) { - itemModelCache.clear(); - sideTexture.invalidate(); - register.accept(sideTexture.get()); - endTexture.invalidate(); - register.accept(endTexture.get()); - if (secondarySideTexture != null) { - secondarySideTexture.invalidate(); - if (secondarySideTexture.get() != GTModels.BLANK_TEXTURE) { - register.accept(secondarySideTexture.get()); - } - } - if (secondaryEndTexture != null) { - secondaryEndTexture.invalidate(); - if (secondaryEndTexture.get() != GTModels.BLANK_TEXTURE) { - register.accept(secondaryEndTexture.get()); - } - } - if (sideOverlayTexture != null) register.accept(sideOverlayTexture); - if (endOverlayTexture != null) register.accept(endOverlayTexture); - sideSprite = null; - endSprite = null; - endOverlaySprite = null; - } - - private static EnumMap borderMap(Direction topSide, Direction bottomSide, Direction leftSide, - Direction rightSide) { - EnumMap sideMap = new EnumMap<>(Border.class); - sideMap.put(Border.TOP, topSide); - sideMap.put(Border.BOTTOM, bottomSide); - sideMap.put(Border.LEFT, leftSide); - sideMap.put(Border.RIGHT, rightSide); - return sideMap; - } - - private static void addRestrictor(TextureAtlasSprite sprite, Border... borders) { - int mask = 0; - for (Border border : borders) { - mask |= border.mask; - } - RESTRICTOR_MAP.put(mask, sprite); - } - - protected static Direction getSideAtBorder(Direction side, Border border) { - return FACE_BORDER_MAP.get(side).get(border); - } - - protected static int computeBorderMask(int blockedConnections, int connections, Direction side) { - int borderMask = 0; - if (blockedConnections != 0) { - for (Border border : Border.VALUES) { - Direction borderSide = getSideAtBorder(side, border); - if (PipeBlockEntity.isFaceBlocked(blockedConnections, borderSide) && - PipeBlockEntity.isConnected(connections, borderSide)) { - // only render when the side is blocked *and* connected - borderMask |= border.mask; - } - } - } - return borderMask; - } - - public enum Border { - - TOP, - BOTTOM, - LEFT, - RIGHT; - - public static final Border[] VALUES = values(); - - public final int mask; - - Border() { - mask = 1 << this.ordinal(); - } - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/client/model/machine/MachineModel.java b/src/main/java/com/gregtechceu/gtceu/client/model/machine/MachineModel.java index c09820be6fe..701a0fd1130 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 @@ -7,6 +7,7 @@ import com.gregtechceu.gtceu.api.machine.multiblock.MultiblockControllerMachine; import com.gregtechceu.gtceu.api.machine.trait.AutoOutputTrait; 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; @@ -50,7 +51,6 @@ import lombok.Getter; import lombok.Setter; import lombok.experimental.Accessors; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.*; @@ -136,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) { @@ -150,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() : @@ -169,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(); @@ -191,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, @@ -204,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. @@ -215,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 @@ -260,7 +260,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(); @@ -282,9 +282,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)); @@ -299,7 +299,7 @@ public List replacePartBaseModel(List originalQuads, IMult ModelData modelData, @Nullable RenderType renderType) { var controllers = part.getControllers(); for (MultiblockControllerMachine controller : controllers) { - var state = controller.self().getBlockState(); + var state = controller.getBlockState(); BakedModel model = Minecraft.getInstance().getBlockRenderer().getBlockModel(state); List newQuads = null; @@ -386,8 +386,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 MetaMachine machine)) return; if (machine.getDefinition() != getDefinition()) return; @@ -445,7 +445,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 MetaMachine machine)) return false; if (machine.getDefinition() != getDefinition()) return false; if (machine.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 07d643cfa62..90b49b40e5e 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; @@ -115,8 +116,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 +138,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 +184,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/overlays/HPCAOverlay.java b/src/main/java/com/gregtechceu/gtceu/client/model/machine/overlays/HPCAOverlay.java index 3ea09f9003c..ed8de15bb92 100644 --- a/src/main/java/com/gregtechceu/gtceu/client/model/machine/overlays/HPCAOverlay.java +++ b/src/main/java/com/gregtechceu/gtceu/client/model/machine/overlays/HPCAOverlay.java @@ -3,6 +3,7 @@ import com.gregtechceu.gtceu.api.machine.trait.RecipeLogic.Status; import com.gregtechceu.gtceu.api.registry.registrate.provider.GTBlockstateProvider; import com.gregtechceu.gtceu.common.data.models.GTModels; +import com.gregtechceu.gtceu.utils.data.RuntimeExistingFileHelper; import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.resources.ResourceLocation; @@ -23,31 +24,47 @@ public class HPCAOverlay { // spotless:off public static HPCAOverlay get(ResourceLocation normalSprite, ResourceLocation damagedSprite, ExistingFileHelper fileHelper) { - // normal - if (!fileHelper.exists(normalSprite, GTBlockstateProvider.TEXTURE)) { - return HPCAOverlay.EMPTY; + if (fileHelper instanceof RuntimeExistingFileHelper runtimeFileHelper) { + // if fileHelper is an instance of RuntimeExistingFileHelper, we have to enable its existence checking. + // the AutoCloseable warning is suppressed here because there's no clean way to + // use a try-with-resources statement in this. + //noinspection resource + fileHelper = runtimeFileHelper.activeHelper(); } - ResourceLocation activeSprite = normalSprite.withSuffix("_active"); - if (!fileHelper.exists(activeSprite, GTBlockstateProvider.TEXTURE)) activeSprite = normalSprite; - ResourceLocation damagedActiveSprite = damagedSprite.withSuffix("_active"); - if (!fileHelper.exists(damagedActiveSprite, GTBlockstateProvider.TEXTURE)) damagedActiveSprite = damagedSprite; - - // emissive - ResourceLocation normalSpriteEmissive = normalSprite.withSuffix("_emissive"); - if (!fileHelper.exists(normalSpriteEmissive, GTBlockstateProvider.TEXTURE)) normalSpriteEmissive = null; - - ResourceLocation activeSpriteEmissive = activeSprite.withSuffix("_emissive"); - if (!fileHelper.exists(activeSpriteEmissive, GTBlockstateProvider.TEXTURE)) activeSpriteEmissive = null; - - ResourceLocation damagedSpriteEmissive = damagedSprite.withSuffix("_emissive"); - if (!fileHelper.exists(damagedSpriteEmissive, GTBlockstateProvider.TEXTURE)) damagedSpriteEmissive = null; - - ResourceLocation damagedActiveSpriteEmissive = damagedActiveSprite.withSuffix("_emissive"); - if (!fileHelper.exists(damagedActiveSpriteEmissive, GTBlockstateProvider.TEXTURE)) damagedActiveSpriteEmissive = null; - - return new HPCAOverlay(normalSprite, activeSprite, damagedSprite, damagedActiveSprite, - normalSpriteEmissive, activeSpriteEmissive, damagedSpriteEmissive, damagedActiveSpriteEmissive); + try { + // normal + if (!fileHelper.exists(normalSprite, GTBlockstateProvider.TEXTURE)) { + return HPCAOverlay.EMPTY; + } + ResourceLocation activeSprite = normalSprite.withSuffix("_active"); + if (!fileHelper.exists(activeSprite, GTBlockstateProvider.TEXTURE)) activeSprite = normalSprite; + + ResourceLocation damagedActiveSprite = damagedSprite.withSuffix("_active"); + if (!fileHelper.exists(damagedActiveSprite, GTBlockstateProvider.TEXTURE)) damagedActiveSprite = damagedSprite; + + // emissive + ResourceLocation normalSpriteEmissive = normalSprite.withSuffix("_emissive"); + if (!fileHelper.exists(normalSpriteEmissive, GTBlockstateProvider.TEXTURE)) normalSpriteEmissive = null; + + ResourceLocation activeSpriteEmissive = activeSprite.withSuffix("_emissive"); + if (!fileHelper.exists(activeSpriteEmissive, GTBlockstateProvider.TEXTURE)) activeSpriteEmissive = null; + + ResourceLocation damagedSpriteEmissive = damagedSprite.withSuffix("_emissive"); + if (!fileHelper.exists(damagedSpriteEmissive, GTBlockstateProvider.TEXTURE)) damagedSpriteEmissive = null; + + ResourceLocation damagedActiveSpriteEmissive = damagedActiveSprite.withSuffix("_emissive"); + if (!fileHelper.exists(damagedActiveSpriteEmissive, GTBlockstateProvider.TEXTURE)) damagedActiveSpriteEmissive = null; + + return new HPCAOverlay(normalSprite, activeSprite, damagedSprite, damagedActiveSprite, + normalSpriteEmissive, activeSpriteEmissive, damagedSpriteEmissive, damagedActiveSpriteEmissive); + } finally { + if (fileHelper instanceof RuntimeExistingFileHelper.Active activeHelper) { + // close the active helper, just for good measure. + // Also in case we ever make it do anything, this won't be forgotten. + activeHelper.close(); + } + } } // spotless:on diff --git a/src/main/java/com/gregtechceu/gtceu/client/model/machine/overlays/WorkableOverlays.java b/src/main/java/com/gregtechceu/gtceu/client/model/machine/overlays/WorkableOverlays.java index bf09a89f026..373ab7b33c6 100644 --- a/src/main/java/com/gregtechceu/gtceu/client/model/machine/overlays/WorkableOverlays.java +++ b/src/main/java/com/gregtechceu/gtceu/client/model/machine/overlays/WorkableOverlays.java @@ -4,6 +4,7 @@ import com.gregtechceu.gtceu.api.registry.registrate.provider.GTBlockstateProvider; import com.gregtechceu.gtceu.common.data.models.GTMachineModels; import com.gregtechceu.gtceu.common.data.models.GTModels; +import com.gregtechceu.gtceu.utils.data.RuntimeExistingFileHelper; import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.core.Direction; @@ -25,6 +26,14 @@ public class WorkableOverlays { public static WorkableOverlays get(ResourceLocation textureDir, ExistingFileHelper fileHelper) { + if (fileHelper instanceof RuntimeExistingFileHelper runtimeFileHelper) { + // if fileHelper is an instance of RuntimeExistingFileHelper, we have to enable its existence checking. + // the AutoCloseable warning is suppressed here because there's no clean way to + // use a try-with-resources statement in this. + // noinspection resource + fileHelper = runtimeFileHelper.activeHelper(); + } + WorkableOverlays model = new WorkableOverlays(textureDir); for (OverlayFace overlayFace : OverlayFace.VALUES) { @@ -55,6 +64,13 @@ public static WorkableOverlays get(ResourceLocation textureDir, ExistingFileHelp model.textures.put(overlayFace, new StatusTextures(normalSprite, activeSprite, pausedSprite, normalSpriteEmissive, activeSpriteEmissive, pausedSpriteEmissive)); } + + if (fileHelper instanceof RuntimeExistingFileHelper.Active activeHelper) { + // close the active helper, just for good measure. + // Also in case we ever make it do anything, this won't be forgotten. + activeHelper.close(); + } + return model; } 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..46331b3fb90 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/client/model/pipe/ActivablePipeModel.java @@ -0,0 +1,236 @@ +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.core.Direction; +import net.minecraft.resources.ResourceLocation; +import net.minecraftforge.client.model.generators.BlockModelBuilder; +import net.minecraftforge.client.model.generators.IGeneratedBlockState; +import net.minecraftforge.client.model.generators.ModelBuilder; +import net.minecraftforge.client.model.generators.ModelFile; + +import it.unimi.dsi.fastutil.objects.Reference2FloatMap; +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; + @Setter + public int activeEmissivity = 15; + + /// 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 active 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(this.thickness, 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 = makeActiveElementModel( + this.blockId.withPath(path -> "block/pipe/" + path + "/center_active"), + null, minCoord, minCoord, minCoord, maxCoord, maxCoord, maxCoord); + } + + /** + * 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 = makeActiveElementModel( + this.blockId.withPath(path -> "block/pipe/" + path + "/connection_active"), + Direction.DOWN, minCoord, 0, minCoord, maxCoord, minCoord, maxCoord); + } + + /** + * Fills out a model builder with applicable pipe model elements and returns it for further use + *


+ * This method is a copy of {@linkplain #makeElementModel} with the texture references changed for active variants. + * + * @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! + * @see #makeElementModel + */ + protected BlockModelBuilder makeActiveElementModel(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 = makeFaceEndpointMap(x1, y1, z1, x2, y2, z2); + + BlockModelBuilder model = this.provider.models().getBuilder(name.toString()) + .parent(new ModelFile.UncheckedModelFile("block/block")) + .texture("particle", "#" + (this.side != null ? SIDE_KEY : END_KEY)) + .renderType(RENDERTYPE_CUTOUT_MIPPED); + + ResourceLocation side = this.sideActive != null ? this.sideActive : this.side; + ResourceLocation end = this.endActive != null ? this.endActive : this.end; + ResourceLocation sideSecondary = this.sideSecondaryActive != null ? this.sideSecondaryActive : + this.sideSecondary; + ResourceLocation endSecondary = this.endSecondaryActive != null ? this.endSecondaryActive : this.endSecondary; + ResourceLocation sideOverlay = this.sideOverlayActive != null ? this.sideOverlayActive : this.sideOverlay; + ResourceLocation endOverlay = this.endOverlayActive != null ? this.endOverlayActive : this.endOverlay; + + makePartModelElement(model, endFace, false, faceEndpoints, 0.0f, 0, 1, + x1, y1, z1, x2, y2, z2, side, end, SIDE_KEY, END_KEY, + this.sideActive != null, this.endActive != null); + + makePartModelElement(model, endFace, true, faceEndpoints, 0.001f, 0, 1, + x1, y1, z1, x2, y2, z2, sideSecondary, endSecondary, SIDE_SECONDARY_KEY, END_SECONDARY_KEY, + this.sideSecondaryActive != null, this.endSecondaryActive != null); + + makePartModelElement(model, endFace, true, faceEndpoints, 0.002f, 2, 2, + x1, y1, z1, x2, y2, z2, sideOverlay, endOverlay, SIDE_OVERLAY_KEY, END_OVERLAY_KEY, + this.sideOverlayActive != null, this.endOverlayActive != null); + + 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, + boolean sideEmissive, boolean endEmissive) { + this.makePartModelElement(model, endFace, useEndWithFullCube, faceEndpoints, offset, + sideTintIndex, endTintIndex, x1, y1, z1, x2, y2, z2, sideTexture, endTexture, sideKey, endKey, + (face, textureKey, builder) -> { + if (activeEmissivity == 0) { + return; + } + if (sideEmissive && textureKey.equals(sideKey)) { + builder.emissivity(activeEmissivity, activeEmissivity).ao(false); + } else if (endEmissive && textureKey.equals(endKey)) { + builder.emissivity(activeEmissivity, activeEmissivity).ao(false); + } + }); + } + + @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..3553bd37510 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/client/model/pipe/BakedPipeModel.java @@ -0,0 +1,161 @@ +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 (state == null) { + connectionMask = ITEM_CONNECTIONS; + blockedMask = Node.ALL_CLOSED; + } + if (connectionMask == null || connectionMask != Node.ALL_OPENED) { + BakedModel centerModel = parts.get(null); + if (renderType == null || + state != null && centerModel.getRenderTypes(state, rand, modelData).contains(renderType)) { + quads.addAll(centerModel.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)) { + BakedModel model = parts.get(dir); + if (renderType == null || + (state != null && model.getRenderTypes(state, rand, modelData).contains(renderType))) { + quads.addAll(model.getQuads(state, side, rand, modelData, renderType)); + } + if (blockedMask != null && PipeBlockEntity.isFaceBlocked(blockedMask, dir)) { + model = restrictors.get(dir); + if (renderType == null || + (state != null && model.getRenderTypes(state, rand, modelData).contains(renderType))) { + quads.addAll(model.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()) { + 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) { + for (BakedModel part : this.parts.values()) { + modelData = part.getModelData(level, pos, state, modelData); + } + for (BakedModel restrictor : this.restrictors.values()) { + modelData = restrictor.getModelData(level, pos, state, modelData); + } + return modelData; + } + + @SuppressWarnings("deprecation") + @Override + public TextureAtlasSprite getParticleIcon() { + return parts.get(null).getParticleIcon(); + } + + @Override + public @Nullable BlockEntityType> getBlockEntityType() { + return null; + } + + @Override + public void render(PipeBlockEntity blockEntity, float partialTick, PoseStack poseStack, + MultiBufferSource buffer, int packedLight, int packedOverlay) {} +} diff --git a/src/main/java/com/gregtechceu/gtceu/client/model/pipe/PipeModel.java b/src/main/java/com/gregtechceu/gtceu/client/model/pipe/PipeModel.java new file mode 100644 index 00000000000..5f440b0214f --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/client/model/pipe/PipeModel.java @@ -0,0 +1,436 @@ +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.MustBeInvokedByOverriders; +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 { + + // spotless:off + public static final String + SIDE_KEY = "side", + END_KEY = "end", + SIDE_SECONDARY_KEY = "side_secondary", + END_SECONDARY_KEY = "end_secondary", + SIDE_OVERLAY_KEY = "side_overlay", + END_OVERLAY_KEY = "end_overlay"; + // spotless:on + protected static final ResourceLocation RENDERTYPE_CUTOUT_MIPPED = new ResourceLocation("cutout_mipped"); + + public static final Set DYNAMIC_MODELS = new HashSet<>(); + + public static void initDynamicModels() { + for (PipeModel generator : DYNAMIC_MODELS) { + generator.initModels(); + } + } + + @Getter + protected 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() + */ + @MustBeInvokedByOverriders + 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(this.thickness, 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() { + if (this.itemModel != null) { + return this.itemModel; + } + return this.itemModel = 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_KEY, END_KEY); + makePartModelElement(model, Direction.NORTH, true, faceEndpoints, 0.001f, 0, 1, + min, min, 0, max, max, 16, this.sideSecondary, this.endSecondary, SIDE_SECONDARY_KEY, + END_SECONDARY_KEY); + makePartModelElement(model, Direction.NORTH, true, faceEndpoints, 0.002f, 2, 2, + min, min, 0, max, max, 16, this.sideOverlay, this.endOverlay, SIDE_OVERLAY_KEY, END_OVERLAY_KEY); + 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 = makeFaceEndpointMap(x1, y1, z1, x2, y2, z2); + + BlockModelBuilder model = this.provider.models().getBuilder(name.toString()) + .parent(new ModelFile.UncheckedModelFile("block/block")) + .texture("particle", "#" + (this.side != null ? SIDE_KEY : END_KEY)) + .renderType(RENDERTYPE_CUTOUT_MIPPED); + makePartModelElement(model, endFace, false, faceEndpoints, 0.0f, 0, 1, + x1, y1, z1, x2, y2, z2, this.side, this.end, SIDE_KEY, END_KEY); + 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) { + makePartModelElement(model, endFace, useEndWithFullCube, faceEndpoints, + offset, sideTintIndex, endTintIndex, x1, y1, z1, x2, y2, z2, + sideTexture, endTexture, sideKey, endKey, (face, texture, builder) -> {}); + } + + 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, + FaceConfigurator faceConfigurator) { + if (sideTexture == null && (endFace == null || endTexture == null)) { + return; + } + if (sideTexture != null) model.texture(sideKey, sideTexture); + if (endFace != null && 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 = !fullCube && endFace != null && (endFace == dir || endFace == dir.getOpposite()); + if (isEnd && endTexture != null) { + face = element.face(dir).texture("#" + endKey).tintindex(endTintIndex); + faceConfigurator.accept(dir, endKey, face); + } else if (!isEnd && sideTexture != null) { + face = element.face(dir).texture("#" + sideKey).tintindex(sideTintIndex); + faceConfigurator.accept(dir, sideKey, face); + } + + float faceEnd = faceEndpoints.getFloat(dir); + if (face != null && (faceEnd >= 16.0f || faceEnd <= 0.0f)) { + face.cullface(dir); + } + } + } + + protected final Reference2FloatMap makeFaceEndpointMap(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); + }); + } + return faceEndpoints; + } + + @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); + } + + @FunctionalInterface + public interface FaceConfigurator> { + + /** + * This is a callback for modifying a block element face builder in ways not supported by "basic" API.
+ * For example, you can make faces emissive, like {@link ActivablePipeModel#makePartModelElement}. + * + * @param face The normal direction of this face. + * @param texture The texture of the face, usually in {@code #reference} format. + * Note that the String does NOT begin with {@code #}. + * @param builder The face builder. + * @see ActivablePipeModel#makePartModelElement(ModelBuilder, Direction, boolean, Reference2FloatMap, float, + * int, int, float, float, float, float, float, float, ResourceLocation, ResourceLocation, String, String, + * boolean, boolean) ActivablePipeModel.makePartModelElement + */ + void accept(Direction face, String texture, ModelBuilder.ElementBuilder.FaceBuilder builder); + } +} 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/GTRenderTypes.java b/src/main/java/com/gregtechceu/gtceu/client/renderer/GTRenderTypes.java index c36a41a91e6..ce3fea89a5d 100644 --- a/src/main/java/com/gregtechceu/gtceu/client/renderer/GTRenderTypes.java +++ b/src/main/java/com/gregtechceu/gtceu/client/renderer/GTRenderTypes.java @@ -22,6 +22,13 @@ public class GTRenderTypes extends RenderType { .setShaderState(RenderStateShard.POSITION_COLOR_SHADER) .setTransparencyState(RenderStateShard.TRANSLUCENT_TRANSPARENCY) .createCompositeState(false)); + private static final RenderType MONITOR = RenderType.create("central_monitor", + DefaultVertexFormat.POSITION_COLOR, VertexFormat.Mode.QUADS, 256, false, false, + RenderType.CompositeState.builder() + .setCullState(NO_CULL) + .setShaderState(POSITION_COLOR_SHADER) + .setTransparencyState(TRANSLUCENT_TRANSPARENCY) + .createCompositeState(false)); private static final Function GUI_TEXTURE = Util.memoize((texture) -> { return create("gui_texture", DefaultVertexFormat.POSITION_COLOR_TEX_LIGHTMAP, VertexFormat.Mode.QUADS, RenderType.TRANSIENT_BUFFER_SIZE, false, true, @@ -42,6 +49,10 @@ public static RenderType getLightRing() { return LIGHT_RING; } + public static RenderType getMonitor() { + return MONITOR; + } + public static RenderType guiTexture(ResourceLocation texture) { return GUI_TEXTURE.apply(texture); } 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..853f9a3e361 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/client/renderer/block/LampItemRenderer.java @@ -0,0 +1,61 @@ +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 { + + private static LampItemRenderer INSTANCE = null; + + public static LampItemRenderer getInstance() { + if (INSTANCE == null) { + INSTANCE = new LampItemRenderer(); + } + return INSTANCE; + } + + 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/MaterialBlockRenderer.java b/src/main/java/com/gregtechceu/gtceu/client/renderer/block/MaterialBlockRenderer.java index 193c889179f..f6559abfce2 100644 --- a/src/main/java/com/gregtechceu/gtceu/client/renderer/block/MaterialBlockRenderer.java +++ b/src/main/java/com/gregtechceu/gtceu/client/renderer/block/MaterialBlockRenderer.java @@ -15,7 +15,6 @@ public class MaterialBlockRenderer { - public static final String LAYER_2_SUFFIX = "_layer2"; private static final Set MODELS = new HashSet<>(); public static void create(Block block, MaterialIconType type, MaterialIconSet iconSet) { @@ -25,12 +24,11 @@ public static void create(Block block, MaterialIconType type, MaterialIconSet ic public static void reinitModels() { for (MaterialBlockRenderer model : MODELS) { ResourceLocation blockId = BuiltInRegistries.BLOCK.getKey(model.block); - ResourceLocation modelId = blockId.withPrefix("block/"); - GTDynamicResourcePack.addBlockModel(blockId, - new DelegatedModel(model.type.getBlockModelPath(model.iconSet, true))); + ResourceLocation modelId = model.type.getBlockModelPath(model.iconSet, true); + GTDynamicResourcePack.addBlockState(blockId, BlockModelGenerators.createSimpleBlock(model.block, modelId)); GTDynamicResourcePack.addItemModel(BuiltInRegistries.ITEM.getKey(model.block.asItem()), - new DelegatedModel(ModelLocationUtils.getModelLocation(model.block))); + new DelegatedModel(modelId)); } } 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..8453f93fbce 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 @@ -3,10 +3,12 @@ import com.gregtechceu.gtceu.GTCEu; import com.gregtechceu.gtceu.api.block.MaterialBlock; import com.gregtechceu.gtceu.api.data.chemical.material.Material; -import com.gregtechceu.gtceu.api.data.chemical.material.properties.OreProperty; -import com.gregtechceu.gtceu.api.data.chemical.material.properties.PropertyKey; +import com.gregtechceu.gtceu.api.data.chemical.material.info.MaterialIconSet; +import com.gregtechceu.gtceu.api.data.chemical.material.info.MaterialIconType; import com.gregtechceu.gtceu.api.data.tag.TagPrefix; import com.gregtechceu.gtceu.data.pack.GTDynamicResourcePack; +import com.gregtechceu.gtceu.utils.memoization.GTMemoizer; +import com.gregtechceu.gtceu.utils.memoization.function.MemoizedBiFunction; import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.client.Minecraft; @@ -14,22 +16,32 @@ import net.minecraft.data.models.BlockModelGenerators; import net.minecraft.data.models.model.*; import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.packs.resources.Resource; +import net.minecraft.server.packs.resources.ResourceManager; import net.minecraft.util.GsonHelper; -import com.google.common.base.Preconditions; import com.google.gson.JsonObject; +import org.jetbrains.annotations.ApiStatus; import java.io.BufferedReader; import java.io.IOException; import java.util.HashSet; +import java.util.Optional; import java.util.Set; @MethodsReturnNonnullByDefault public class OreBlockRenderer { - private static final Set MODELS = new HashSet<>(); + protected static final Set MODELS = new HashSet<>(); - private final MaterialBlock block; + protected static final JsonObject NULL_ELEMENT_MARKER = new JsonObject(); + protected static final MemoizedBiFunction TEMPLATE_MODEL_CACHE = GTMemoizer + .memoizeFunctionWeakIdent(OreBlockRenderer::loadTemplateOreModel); + + // First format key is material set name, 2nd is stone type prefix's name, 3rd is icon type's name + public static final String ORE_MODEL_NAME_FORMAT = "block/material_sets/%s/ores/%s/%s"; + + protected final MaterialBlock block; public static void create(MaterialBlock block) { MODELS.add(new OreBlockRenderer(block)); @@ -39,54 +51,81 @@ public OreBlockRenderer(MaterialBlock block) { this.block = block; } + @ApiStatus.Internal public static void reinitModels() { + // first set up all the stone types for all tag prefixes + for (MaterialIconSet iconSet : MaterialIconSet.ICON_SETS.values()) { + for (var entry : TagPrefix.ORES.entrySet()) { + copyOreModelWithBaseStone(entry.getKey(), entry.getValue(), MaterialIconType.ore, iconSet); + copyOreModelWithBaseStone(entry.getKey(), entry.getValue(), MaterialIconType.oreEmissive, iconSet); + // TODO uncomment if/when small ores are added + // copyOreModelWithBaseStone(entry.getKey(), entry.getValue(), MaterialIconType.oreSmall, iconSet); + } + } + + // then create block state JSONs for all ore blocks with those models for (OreBlockRenderer model : MODELS) { + Material material = model.block.material; + TagPrefix tagPrefix = model.block.tagPrefix; + MaterialIconSet iconSet = material.getMaterialIconSet(); + MaterialIconType iconType = tagPrefix.getMaterialIconType(material); + ResourceLocation blockId = BuiltInRegistries.BLOCK.getKey(model.block); - ResourceLocation modelId = blockId.withPrefix("block/"); - OreBlockRenderer.cloneBlockModel(blockId, model.block.tagPrefix, model.block.material); + ResourceLocation modelId = GTCEu.id(ORE_MODEL_NAME_FORMAT + .formatted(iconSet.name, tagPrefix.name, iconType.name())); + GTDynamicResourcePack.addBlockState(blockId, BlockModelGenerators.createSimpleBlock(model.block, modelId)); GTDynamicResourcePack.addItemModel(BuiltInRegistries.ITEM.getKey(model.block.asItem()), - new DelegatedModel(ModelLocationUtils.getModelLocation(model.block))); + new DelegatedModel(modelId)); } - } - /** - * Clones & modifies the base JSON for a single ore block. - * - * @param modelId the model id (usually {@code gtceu:block/}) - * @param prefix the TagPrefix of the block being added. - * @param material the material of the block being added. must have an ore property. - */ - public static void cloneBlockModel(ResourceLocation modelId, TagPrefix prefix, Material material) { - OreProperty prop = material.getProperty(PropertyKey.ORE); - Preconditions.checkNotNull(prop, - "material %s has no ore property, but needs one for an ore model!".formatted(material.getName())); + TEMPLATE_MODEL_CACHE.getCache().clear(); + } + /// This is called for every combination of tag prefix + icon type + icon set + protected static void copyOreModelWithBaseStone(TagPrefix tagPrefix, TagPrefix.OreType oreType, + MaterialIconType iconType, MaterialIconSet iconSet) { // read the base ore model JSON JsonObject original; - try (BufferedReader reader = Minecraft.getInstance().getResourceManager() - .openAsReader(GTCEu.id("models/block/ore%s.json".formatted(prop.isEmissive() ? "_emissive" : "")))) { - original = GsonHelper.parse(reader, true); - } catch (IOException e) { - throw new RuntimeException(e); + try { + original = TEMPLATE_MODEL_CACHE.apply(iconType, iconSet); + } catch (RuntimeException e) { + GTCEu.LOGGER.error("Could not load template block model for ore type {}, icon type '{}', icon set '{}'", + tagPrefix.name, iconType.name(), iconSet.name, e); + return; + } + if (original == NULL_ELEMENT_MARKER) { + // if the icon set doesn't have an ore model (somehow...), skip it + return; } - // clone it + // copy it 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()); + // add the base stone model. + newJson.getAsJsonObject("children") + .getAsJsonObject("base_stone") + .addProperty("parent", oreType.baseModelLocation().toString()); + + GTDynamicResourcePack.addBlockModel( + GTCEu.id(ORE_MODEL_NAME_FORMAT.formatted(iconSet.name, tagPrefix.name, iconType.name())), newJson); + } - 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()); + private static JsonObject loadTemplateOreModel(MaterialIconType iconType, MaterialIconSet iconSet) { + ResourceLocation baseModelPath = iconType.getBlockModelPath(iconSet, true); + baseModelPath = GTDynamicResourcePack.MODEL_ID_CONVERTER.idToFile(baseModelPath); - newJson.getAsJsonObject("textures").addProperty("particle", layer0.toString()); + ResourceManager resourceManager = Minecraft.getInstance().getResourceManager(); + Optional modelResource = resourceManager.getResource(baseModelPath); - GTDynamicResourcePack.addBlockModel(modelId, newJson); + if (modelResource.isEmpty()) { + // if the icon set doesn't have an ore model (somehow...), skip it gracefully + return NULL_ELEMENT_MARKER; + } + // read & cache the base ore model JSON + try (BufferedReader reader = modelResource.get().openAsReader()) { + return GsonHelper.parse(reader, true); + } catch (IOException e) { + throw new RuntimeException(e); + } } } 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/client/renderer/machine/impl/CentralMonitorRender.java b/src/main/java/com/gregtechceu/gtceu/client/renderer/machine/impl/CentralMonitorRender.java index 6e04229890f..68719e58cba 100644 --- a/src/main/java/com/gregtechceu/gtceu/client/renderer/machine/impl/CentralMonitorRender.java +++ b/src/main/java/com/gregtechceu/gtceu/client/renderer/machine/impl/CentralMonitorRender.java @@ -54,7 +54,7 @@ public void render(CentralMonitorMachine machine, float partialTick, PoseStack p continue; } poseStack.pushPose(); - module.getRenderer(group.getItemStackHandler().getStackInSlot(0), machine, group) + module.getRenderer(group.getItemStackHandler().getStackInSlot(0)) .render(machine, group, partialTick, poseStack, buffer, packedLight, packedOverlay); poseStack.popPose(); } diff --git a/src/main/java/com/gregtechceu/gtceu/client/renderer/monitor/MonitorTextRenderer.java b/src/main/java/com/gregtechceu/gtceu/client/renderer/monitor/MonitorTextRenderer.java index 029a85b5223..01865761749 100644 --- a/src/main/java/com/gregtechceu/gtceu/client/renderer/monitor/MonitorTextRenderer.java +++ b/src/main/java/com/gregtechceu/gtceu/client/renderer/monitor/MonitorTextRenderer.java @@ -1,5 +1,7 @@ package com.gregtechceu.gtceu.client.renderer.monitor; +import com.gregtechceu.gtceu.api.placeholder.GraphicsComponent; +import com.gregtechceu.gtceu.api.placeholder.MultiLineComponent; import com.gregtechceu.gtceu.common.machine.multiblock.electric.CentralMonitorMachine; import com.gregtechceu.gtceu.common.machine.multiblock.electric.monitor.MonitorGroup; @@ -10,18 +12,17 @@ import net.minecraft.core.BlockPos; import net.minecraft.network.chat.Component; import net.minecraft.util.FormattedCharSequence; +import net.minecraft.util.Mth; import com.mojang.blaze3d.vertex.PoseStack; -import java.util.List; - public class MonitorTextRenderer implements IMonitorRenderer { private static final float TEXT_SCALE = 1 / 144f; - private final List text; + private final MultiLineComponent text; private final float scale; - public MonitorTextRenderer(List text, double scale) { + public MonitorTextRenderer(MultiLineComponent text, double scale) { this.text = text; this.scale = (float) scale; } @@ -34,6 +35,23 @@ public void render(CentralMonitorMachine machine, MonitorGroup group, float part int row = 0; int columns = group.getRow(0, machine::toRelative).size(); poseStack.translate(rel.getX(), rel.getY(), rel.getZ()); + int layer = 0; + for (GraphicsComponent graphics : text.getGraphics()) { + if (graphics.x() < 0 || graphics.y() < 0) continue; + float maxX = graphics.x2(); + float maxY = graphics.y2(); + if (maxX == Math.floor(maxX)) maxX--; + if (maxY == Math.floor(maxY)) maxY--; + BlockPos relativePos = rel.offset(Mth.floor(maxX), -Mth.floor(maxY), 0); + if (!group.getMonitorPositions().stream().map(machine::toRelative).toList().contains(relativePos)) + continue; + poseStack.pushPose(); + poseStack.translate(graphics.x(), graphics.y(), layer * .001f); + graphics.get().render(machine, group, partialTick, poseStack, buffer, packedLight, packedOverlay); + poseStack.popPose(); + layer++; + } + poseStack.translate(0, 0, layer * .001f); poseStack.scale(TEXT_SCALE * scale, TEXT_SCALE * scale, TEXT_SCALE * scale); float y = 9; for (Component s : text) { diff --git a/src/main/java/com/gregtechceu/gtceu/client/renderer/placeholder/ModulePlaceholderRenderer.java b/src/main/java/com/gregtechceu/gtceu/client/renderer/placeholder/ModulePlaceholderRenderer.java new file mode 100644 index 00000000000..1df2c9ef08f --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/client/renderer/placeholder/ModulePlaceholderRenderer.java @@ -0,0 +1,31 @@ +package com.gregtechceu.gtceu.client.renderer.placeholder; + +import com.gregtechceu.gtceu.api.item.IComponentItem; +import com.gregtechceu.gtceu.api.item.component.IItemComponent; +import com.gregtechceu.gtceu.api.item.component.IMonitorModuleItem; +import com.gregtechceu.gtceu.api.placeholder.IPlaceholderRenderer; +import com.gregtechceu.gtceu.common.machine.multiblock.electric.CentralMonitorMachine; +import com.gregtechceu.gtceu.common.machine.multiblock.electric.monitor.MonitorGroup; + +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.item.ItemStack; + +import com.mojang.blaze3d.vertex.PoseStack; + +public class ModulePlaceholderRenderer implements IPlaceholderRenderer { + + @Override + public void render(CentralMonitorMachine machine, MonitorGroup group, float partialTick, PoseStack poseStack, + MultiBufferSource buffer, int packedLight, int packedOverlay, CompoundTag tag) { + ItemStack stack = ItemStack.of(tag); + if (stack.getItem() instanceof IComponentItem componentItem) { + for (IItemComponent component : componentItem.getComponents()) { + if (component instanceof IMonitorModuleItem module) { + module.getRenderer(stack).render(machine, group, partialTick, poseStack, buffer, packedLight, + packedOverlay); + } + } + } + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/client/renderer/placeholder/QuadPlaceholderRenderer.java b/src/main/java/com/gregtechceu/gtceu/client/renderer/placeholder/QuadPlaceholderRenderer.java new file mode 100644 index 00000000000..2d347e1d960 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/client/renderer/placeholder/QuadPlaceholderRenderer.java @@ -0,0 +1,35 @@ +package com.gregtechceu.gtceu.client.renderer.placeholder; + +import com.gregtechceu.gtceu.api.placeholder.IPlaceholderRenderer; +import com.gregtechceu.gtceu.client.renderer.GTRenderTypes; +import com.gregtechceu.gtceu.common.machine.multiblock.electric.CentralMonitorMachine; +import com.gregtechceu.gtceu.common.machine.multiblock.electric.monitor.MonitorGroup; + +import net.minecraft.client.renderer.LightTexture; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.nbt.CompoundTag; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import org.joml.Matrix4f; + +public class QuadPlaceholderRenderer implements IPlaceholderRenderer { + + @Override + public void render(CentralMonitorMachine machine, MonitorGroup group, float partialTick, PoseStack poseStack, + MultiBufferSource buffer, int packedLight, int packedOverlay, CompoundTag tag) { + poseStack.pushPose(); + VertexConsumer consumer = buffer.getBuffer(GTRenderTypes.getMonitor()); + Matrix4f pose = poseStack.last().pose(); + + consumer.vertex(pose, tag.getFloat("x1"), tag.getFloat("y1"), 0).color(tag.getInt("color1")) + .uv2(LightTexture.FULL_BRIGHT).endVertex(); + consumer.vertex(pose, tag.getFloat("x2"), tag.getFloat("y2"), 0).color(tag.getInt("color2")) + .uv2(LightTexture.FULL_BRIGHT).endVertex(); + consumer.vertex(pose, tag.getFloat("x3"), tag.getFloat("y3"), 0).color(tag.getInt("color3")) + .uv2(LightTexture.FULL_BRIGHT).endVertex(); + consumer.vertex(pose, tag.getFloat("x4"), tag.getFloat("y4"), 0).color(tag.getInt("color4")) + .uv2(LightTexture.FULL_BRIGHT).endVertex(); + poseStack.popPose(); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/client/renderer/placeholder/RectPlaceholderRenderer.java b/src/main/java/com/gregtechceu/gtceu/client/renderer/placeholder/RectPlaceholderRenderer.java new file mode 100644 index 00000000000..1e2c5dbff8b --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/client/renderer/placeholder/RectPlaceholderRenderer.java @@ -0,0 +1,34 @@ +package com.gregtechceu.gtceu.client.renderer.placeholder; + +import com.gregtechceu.gtceu.api.placeholder.IPlaceholderRenderer; +import com.gregtechceu.gtceu.client.renderer.GTRenderTypes; +import com.gregtechceu.gtceu.common.machine.multiblock.electric.CentralMonitorMachine; +import com.gregtechceu.gtceu.common.machine.multiblock.electric.monitor.MonitorGroup; + +import net.minecraft.client.renderer.LightTexture; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.nbt.CompoundTag; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import org.joml.Matrix4f; + +public class RectPlaceholderRenderer implements IPlaceholderRenderer { + + @Override + public void render(CentralMonitorMachine machine, MonitorGroup group, float partialTick, PoseStack poseStack, + MultiBufferSource buffer, int packedLight, int packedOverlay, CompoundTag tag) { + poseStack.pushPose(); + VertexConsumer consumer = buffer.getBuffer(GTRenderTypes.getMonitor()); + Matrix4f pose = poseStack.last().pose(); + float minX = 0, maxX = tag.getFloat("width"); + float minY = 0, maxY = tag.getFloat("height"); + int color = tag.getInt("color"); + + consumer.vertex(pose, minX, maxY, 0).color(color).uv2(LightTexture.FULL_BRIGHT).endVertex(); + consumer.vertex(pose, maxX, maxY, 0).color(color).uv2(LightTexture.FULL_BRIGHT).endVertex(); + consumer.vertex(pose, maxX, minY, 0).color(color).uv2(LightTexture.FULL_BRIGHT).endVertex(); + consumer.vertex(pose, minX, minY, 0).color(color).uv2(LightTexture.FULL_BRIGHT).endVertex(); + poseStack.popPose(); + } +} 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 c7e7fd5b683..95cffc6ee83 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.PipeBlockEntity; import com.gregtechceu.gtceu.api.capability.forge.GTCapability; @@ -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 b6787e54fa0..8d33f3c08f4 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/blockentity/CableBlockEntity.java +++ b/src/main/java/com/gregtechceu/gtceu/common/blockentity/CableBlockEntity.java @@ -70,10 +70,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 1136349e1bb..6a4a060339f 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/blockentity/DuctPipeBlockEntity.java +++ b/src/main/java/com/gregtechceu/gtceu/common/blockentity/DuctPipeBlockEntity.java @@ -35,14 +35,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 d3dde82340b..4e66ec19415 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/blockentity/LaserPipeBlockEntity.java +++ b/src/main/java/com/gregtechceu/gtceu/common/blockentity/LaserPipeBlockEntity.java @@ -1,13 +1,12 @@ 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; 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.api.sync_system.annotations.SaveField; -import com.gregtechceu.gtceu.api.sync_system.annotations.SyncToClient; import com.gregtechceu.gtceu.common.pipelike.laser.*; import com.gregtechceu.gtceu.utils.GTUtil; import com.gregtechceu.gtceu.utils.TaskHandler; @@ -15,6 +14,8 @@ 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; @@ -38,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 @@ -122,29 +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; - syncDataHolder.markClientSyncFieldDirty("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 @@ -185,6 +157,28 @@ public GTToolType getPipeTuneTool() { return GTToolType.WIRE_CUTTER; } + 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 { @Override 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 142301b164c..f6d28f19418 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; @@ -7,12 +8,8 @@ import com.gregtechceu.gtceu.api.item.tool.GTToolType; import com.gregtechceu.gtceu.api.pipenet.IPipeNode; import com.gregtechceu.gtceu.api.recipe.GTRecipe; -import com.gregtechceu.gtceu.api.sync_system.annotations.RerenderOnChanged; -import com.gregtechceu.gtceu.api.sync_system.annotations.SaveField; -import com.gregtechceu.gtceu.api.sync_system.annotations.SyncToClient; import com.gregtechceu.gtceu.common.pipelike.optical.*; import com.gregtechceu.gtceu.utils.GTUtil; -import com.gregtechceu.gtceu.utils.TaskHandler; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -23,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; @@ -40,12 +36,6 @@ public class OpticalPipeBlockEntity extends PipeBlockEntity currentPipeNet = new WeakReference<>(null); private OpticalNetHandler defaultHandler; - @Getter - @SaveField - @SyncToClient - @RerenderOnChanged - private boolean isActive; - public OpticalPipeBlockEntity(BlockEntityType type, BlockPos pos, BlockState blockState) { super(type, pos, blockState); } @@ -152,22 +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; - syncDataHolder.markClientSyncFieldDirty("isActive"); - stateChanged = true; - } else if (!this.isActive && active) { - this.isActive = true; - syncDataHolder.markClientSyncFieldDirty("isActive"); - 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 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/cover/package-info.java b/src/main/java/com/gregtechceu/gtceu/common/cover/package-info.java new file mode 100644 index 00000000000..c4a7187c0ac --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/common/cover/package-info.java @@ -0,0 +1,4 @@ +@NotNullByDefault +package com.gregtechceu.gtceu.common.cover; + +import org.jetbrains.annotations.NotNullByDefault; 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/GTPlaceholders.java b/src/main/java/com/gregtechceu/gtceu/common/data/GTPlaceholders.java index b27505a4854..45fccd4f5de 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/data/GTPlaceholders.java +++ b/src/main/java/com/gregtechceu/gtceu/common/data/GTPlaceholders.java @@ -7,16 +7,23 @@ import com.gregtechceu.gtceu.api.capability.IWorkable; import com.gregtechceu.gtceu.api.cover.filter.ItemFilter; import com.gregtechceu.gtceu.api.item.ComponentItem; +import com.gregtechceu.gtceu.api.item.IComponentItem; import com.gregtechceu.gtceu.api.item.component.IDataItem; import com.gregtechceu.gtceu.api.item.component.IItemComponent; +import com.gregtechceu.gtceu.api.item.component.IMonitorModuleItem; import com.gregtechceu.gtceu.api.machine.MetaMachine; import com.gregtechceu.gtceu.api.machine.feature.multiblock.IMaintenanceMachine; import com.gregtechceu.gtceu.api.misc.virtualregistry.EntryTypes; import com.gregtechceu.gtceu.api.misc.virtualregistry.VirtualEnderRegistry; import com.gregtechceu.gtceu.api.placeholder.*; import com.gregtechceu.gtceu.api.placeholder.exceptions.*; +import com.gregtechceu.gtceu.client.renderer.placeholder.ModulePlaceholderRenderer; +import com.gregtechceu.gtceu.client.renderer.placeholder.QuadPlaceholderRenderer; +import com.gregtechceu.gtceu.client.renderer.placeholder.RectPlaceholderRenderer; import com.gregtechceu.gtceu.common.blockentity.CableBlockEntity; +import com.gregtechceu.gtceu.common.item.modules.ImageModuleBehaviour; import com.gregtechceu.gtceu.common.machine.multiblock.part.monitor.AdvancedMonitorPartMachine; +import com.gregtechceu.gtceu.utils.GTMath; import com.gregtechceu.gtceu.utils.GTStringUtils; import com.gregtechceu.gtceu.utils.GTTransferUtils; @@ -37,8 +44,11 @@ import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.phys.Vec2; import net.minecraft.world.phys.Vec3; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.capability.IFluidHandler; +import net.minecraftforge.fml.DistExecutor; import net.minecraftforge.items.IItemHandler; import net.minecraftforge.registries.ForgeRegistries; @@ -84,6 +94,7 @@ public static int countItems(@Nullable ItemFilter filter, @Nullable IItemHandler } public static void initPlaceholders() { + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> GTPlaceholders::initRenderers); PlaceholderHandler.addPlaceholder(new Placeholder("energy") { @Override @@ -130,10 +141,10 @@ public MultiLineComponent apply(PlaceholderContext ctx, .literal(countItems(GTStringUtils.componentsToString(args.get(0)), itemHandler)); if (GTStringUtils.equals(args.get(0), "filter")) { int slot = PlaceholderUtils.toInt(args.get(1)); - PlaceholderUtils.checkRange("slot index", 1, 8, slot); + if (ctx.itemStackHandler() == null) + throw new NotSupportedException(); + PlaceholderUtils.checkRange("slot index", 1, ctx.itemStackHandler().getSlots(), slot); try { - if (ctx.itemStackHandler() == null) - throw new NotSupportedException(); return MultiLineComponent.literal(countItems( ItemFilter.loadFilter(ctx.itemStackHandler().getStackInSlot(slot - 1)), itemHandler)); } catch (NullPointerException e) { @@ -253,9 +264,7 @@ public MultiLineComponent apply(PlaceholderContext ctx, public MultiLineComponent apply(PlaceholderContext ctx, List args) throws PlaceholderException { PlaceholderUtils.checkArgs(args, 0); - if (ctx.cover() instanceof IPlaceholderInfoProviderCover cover) - return MultiLineComponent.literal(cover.getTicksSincePlaced()); - throw new NotSupportedException(); + return MultiLineComponent.literal(ctx.level().getGameTime()); } }); PlaceholderHandler.addPlaceholder(new Placeholder("select") { @@ -281,7 +290,7 @@ public MultiLineComponent apply(PlaceholderContext ctx, throw new InvalidArgsException(); return MultiLineComponent.literal(ctx.level() .getSignal(ctx.pos().relative(direction), direction)); - } else if (GTStringUtils.equals(args.get(1), "set")) { + } else if (GTStringUtils.equals(args.get(0), "set")) { int power = PlaceholderUtils.toInt(args.get(1)); PlaceholderUtils.checkRange("redstone power", 0, 15, power); if (ctx.cover() == null) throw new NotSupportedException(); @@ -397,8 +406,8 @@ public MultiLineComponent apply(PlaceholderContext ctx, PlaceholderUtils.checkArgs(args, 2, true); try { int slot = PlaceholderUtils.toInt(args.get(1)); - PlaceholderUtils.checkRange("slot index", 1, 8, slot); if (ctx.itemStackHandler() == null) throw new NotSupportedException(); + PlaceholderUtils.checkRange("slot index", 1, ctx.itemStackHandler().getSlots(), slot); ItemStack stack = ctx.itemStackHandler().getStackInSlot(slot - 1); int capacity = -1; if (stack.getItem() instanceof ComponentItem componentItem) { @@ -459,8 +468,8 @@ public MultiLineComponent apply(PlaceholderContext ctx, List args) throws PlaceholderException { PlaceholderUtils.checkArgs(args, 1, true); int slot = GTStringUtils.toInt(args.get(0)); - PlaceholderUtils.checkRange("slot index", 1, 8, slot); if (ctx.itemStackHandler() == null) throw new NotSupportedException(); + PlaceholderUtils.checkRange("slot index", 1, ctx.itemStackHandler().getSlots(), slot); Tag tag = ctx.itemStackHandler().getStackInSlot(slot - 1).getOrCreateTag(); for (int i = 1; i < args.size() - 1; i++) { if (!(tag instanceof CompoundTag compoundTag)) return MultiLineComponent.empty(); @@ -544,8 +553,8 @@ public MultiLineComponent apply(PlaceholderContext ctx, List args) throws PlaceholderException { PlaceholderUtils.checkArgs(args, 2); int slot = PlaceholderUtils.toInt(args.get(0)); - PlaceholderUtils.checkRange("slot index", 1, 8, slot); if (ctx.itemStackHandler() == null) throw new NotSupportedException(); + PlaceholderUtils.checkRange("slot index", 1, ctx.itemStackHandler().getSlots(), slot); ItemStack stack = ctx.itemStackHandler().getStackInSlot(slot - 1); int capacity = -1; if (stack.getItem() instanceof ComponentItem componentItem) { @@ -557,6 +566,9 @@ public MultiLineComponent apply(PlaceholderContext ctx, } } if (capacity == -1) throw new MissingItemException("any data item", slot); + if (!stack.getOrCreateTag().contains("computer_monitor_cover_data")) { + stack.getOrCreateTag().put("computer_monitor_cover_data", new ListTag()); + } ListTag tag = stack.getOrCreateTag().getList("computer_monitor_cover_data", Tag.TAG_STRING); int operationsLeft = 5000; int p = 0, start = 0, cnt = 0; @@ -584,19 +596,27 @@ public MultiLineComponent apply(PlaceholderContext ctx, if (cur != null) codeBuilder.append(cnt).append(cur); String code = codeBuilder.toString(); Stack loops = new Stack<>(); - if (!getData(ctx).getBoolean("completed")) { - p = getData(ctx).getInt("pointer"); - start = getData(ctx).getInt("index"); + if (!getData(ctx).contains(String.valueOf(ctx.index()))) { + getData(ctx).put(String.valueOf(ctx.index()), new CompoundTag()); } - getData(ctx).putBoolean("completed", true); + CompoundTag data = getData(ctx).getCompound(String.valueOf(ctx.index())); int num = 0; + if (!data.getBoolean("completed")) { + p = data.getInt("pointer"); + start = data.getInt("index"); + num = data.getInt("num"); + } + data.putBoolean("completed", true); for (int i = start; i < code.length(); i++) { if (operationsLeft <= 0) { - getData(ctx).putBoolean("completed", false); - getData(ctx).putInt("pointer", p); - getData(ctx).putInt("index", i); + data.putBoolean("completed", false); + data.putInt("pointer", p); + data.putInt("index", i); + data.putInt("num", num); break; } + if (p > capacity) p = p % capacity; + if (p < 0) p = (capacity - ((-p) % capacity)) % capacity; while (tag.size() <= p) tag.add(StringTag.valueOf("0")); if (tag.getString(p).isEmpty()) tag.set(i, StringTag.valueOf("0")); switch (code.charAt(i)) { @@ -612,7 +632,7 @@ public MultiLineComponent apply(PlaceholderContext ctx, case '[' -> loops.push(i); case ']' -> { if (Integer.parseInt(tag.getString(p)) == 0) loops.pop(); - else i = loops.peek(); + else i = loops.peek() + 1; } } if (Character.isDigit(code.charAt(i))) { @@ -631,7 +651,7 @@ public MultiLineComponent apply(PlaceholderContext ctx, PlaceholderUtils.checkArgs(args, 2); if (ctx.itemStackHandler() == null) throw new NotSupportedException(); int slot = PlaceholderUtils.toInt(args.get(0)); - PlaceholderUtils.checkRange("slot index", 1, 8, slot); + PlaceholderUtils.checkRange("slot index", 1, ctx.itemStackHandler().getSlots(), slot); ItemStack stack = ctx.itemStackHandler().getStackInSlot(slot - 1); if (!stack.getOrCreateTag().contains("boundPlayerPermLevel")) throw new MissingItemException("any data item bound to player", slot); @@ -706,10 +726,11 @@ public MultiLineComponent apply(PlaceholderContext ctx, 1000000000L, "B", 1000000000000L, "T"); long max = 1; - for (Long i : suffixes.keySet()) { + for (long i : suffixes.keySet()) { if (n >= i && max < i) max = i; } - return MultiLineComponent.literal("%.2f%s".formatted(((double) n) / max, suffixes.get(max))); + return MultiLineComponent.literal(String.format(Locale.ROOT, "%.2f%s", + ((double) n) / max, suffixes.get(max))); } }); PlaceholderHandler.addPlaceholder(new Placeholder("click") { @@ -739,7 +760,7 @@ public MultiLineComponent apply(PlaceholderContext ctx, if (args.size() > 2 && !args.get(2).toString().isEmpty()) { if (ctx.itemStackHandler() == null) throw new NotSupportedException(); int slot = PlaceholderUtils.toInt(args.get(2)); - PlaceholderUtils.checkRange("slot index", 1, 8, slot); + PlaceholderUtils.checkRange("slot index", 1, ctx.itemStackHandler().getSlots(), slot); ItemStack stack = ctx.itemStackHandler().getStackInSlot(slot - 1); if (stack.getOrCreateTag().contains("boundPlayerUUID")) owner = UUID.fromString(stack.getOrCreateTag().getString("boundPlayerUUID")); @@ -753,7 +774,7 @@ public MultiLineComponent apply(PlaceholderContext ctx, if (args.size() > 4) { if (ctx.itemStackHandler() == null) throw new NotSupportedException(); int slot = PlaceholderUtils.toInt(args.get(3)); - PlaceholderUtils.checkRange("slot index", 1, 8, slot); + PlaceholderUtils.checkRange("slot index", 1, ctx.itemStackHandler().getSlots(), slot); ItemStack stack = ctx.itemStackHandler().getStackInSlot(slot - 1); UUID uuid; if (stack.getOrCreateTag().contains("enderRedstoneLinkTransmitterUUID")) { @@ -827,6 +848,127 @@ public MultiLineComponent apply(PlaceholderContext ctx, return PlaceholderHandler.processPlaceholders(args.get(0).toString(), ctx); } }); + PlaceholderHandler.addPlaceholder(new Placeholder("module") { + + @Override + public MultiLineComponent apply(PlaceholderContext ctx, + List args) throws PlaceholderException { + PlaceholderUtils.checkArgs(args, 3); + int slot = PlaceholderUtils.toInt(args.get(0)); + double x = PlaceholderUtils.toDouble(args.get(1)); + double y = PlaceholderUtils.toDouble(args.get(2)); + if (ctx.itemStackHandler() == null) throw new NotSupportedException(); + PlaceholderUtils.checkRange("slot index", 1, ctx.itemStackHandler().getSlots(), slot); + ItemStack stack = ctx.itemStackHandler().getStackInSlot(slot); + if (stack.getItem() instanceof IComponentItem componentItem) { + for (IItemComponent component : componentItem.getComponents()) { + if (component instanceof IMonitorModuleItem module) module.tickInPlaceholder(stack, ctx); + } + } + return MultiLineComponent.empty().addGraphics(new GraphicsComponent( + x, y, x, y, + "module", + stack.serializeNBT())); + } + }); + PlaceholderHandler.addPlaceholder(new Placeholder("setImage") { + + @Override + public MultiLineComponent apply(PlaceholderContext ctx, + List args) throws PlaceholderException { + PlaceholderUtils.checkArgs(args, 2); + int slot = PlaceholderUtils.toInt(args.get(0)); + String url = args.get(1).toString(); + if (ctx.itemStackHandler() == null) throw new NotSupportedException(); + PlaceholderUtils.checkRange("slot index", 1, ctx.itemStackHandler().getSlots(), slot); + ItemStack stack = ctx.itemStackHandler().getStackInSlot(slot); + if (stack.getItem() instanceof IComponentItem componentItem) { + for (IItemComponent component : componentItem.getComponents()) { + if (component instanceof ImageModuleBehaviour module) { + module.setUrl(stack, url); + } + } + } + return MultiLineComponent.empty(); + } + }); + PlaceholderHandler.addPlaceholder(new Placeholder("rect") { + + @Override + public MultiLineComponent apply(PlaceholderContext ctx, + List args) throws PlaceholderException { + PlaceholderUtils.checkArgs(args, 5); + double x = PlaceholderUtils.toDouble(args.get(0)); + double y = PlaceholderUtils.toDouble(args.get(1)); + double width = PlaceholderUtils.toDouble(args.get(2)); + double height = PlaceholderUtils.toDouble(args.get(3)); + if (x < 0) x = 0; + if (y < 0) y = 0; + CompoundTag renderData = new CompoundTag(); + renderData.putDouble("x", x); + renderData.putDouble("y", y); + renderData.putDouble("width", width); + renderData.putDouble("height", height); + renderData.putInt("color", 0xFF000000 | PlaceholderUtils.toInt(args.get(4))); + return MultiLineComponent.empty().addGraphics(new GraphicsComponent( + x, y, x + width, y + height, + "rect", + renderData)); + } + }); + PlaceholderHandler.addPlaceholder(new Placeholder("quad") { + + @Override + public MultiLineComponent apply(PlaceholderContext ctx, + List args) throws PlaceholderException { + PlaceholderUtils.checkArgs(args, 12); + CompoundTag renderData = new CompoundTag(); + float x1 = PlaceholderUtils.toFloat(args.get(0)); + float y1 = PlaceholderUtils.toFloat(args.get(1)); + float x2 = PlaceholderUtils.toFloat(args.get(2)); + float y2 = PlaceholderUtils.toFloat(args.get(3)); + float x3 = PlaceholderUtils.toFloat(args.get(4)); + float y3 = PlaceholderUtils.toFloat(args.get(5)); + float x4 = PlaceholderUtils.toFloat(args.get(6)); + float y4 = PlaceholderUtils.toFloat(args.get(7)); + renderData.putFloat("x1", 0); + renderData.putFloat("y1", 0); + renderData.putFloat("x2", x2 - x1); + renderData.putFloat("y2", y2 - y1); + renderData.putFloat("x3", x3 - x1); + renderData.putFloat("y3", y3 - y1); + renderData.putFloat("x4", x4 - x1); + renderData.putFloat("y4", y4 - y1); + renderData.putInt("color1", 0xFF000000 + PlaceholderUtils.toInt(args.get(8))); + renderData.putInt("color2", 0xFF000000 + PlaceholderUtils.toInt(args.get(9))); + renderData.putInt("color3", 0xFF000000 + PlaceholderUtils.toInt(args.get(10))); + renderData.putInt("color4", 0xFF000000 + PlaceholderUtils.toInt(args.get(11))); + return MultiLineComponent.empty().addGraphics(new GraphicsComponent( + GTMath.min(x1, x2, x3, x4), GTMath.min(y1, y2, y3, y4), GTMath.max(x1, x2, x3, x4), + GTMath.max(y1, y2, y3, y4), + "quad", + renderData)); + } + }); + PlaceholderHandler.addPlaceholder(new Placeholder("item") { + + @Override + public MultiLineComponent apply(PlaceholderContext ctx, + List args) throws PlaceholderException { + PlaceholderUtils.checkArgs(args, 1); + int slot = PlaceholderUtils.toInt(args.get(0)); + if (ctx.itemStackHandler() == null) throw new NotSupportedException(); + PlaceholderUtils.checkRange("slot index", 1, ctx.itemStackHandler().getSlots(), slot); + return MultiLineComponent.literal(ctx.itemStackHandler().getStackInSlot(slot - 1).toString()); + } + }); + } + + @OnlyIn(Dist.CLIENT) + public static void initRenderers() { + PlaceholderHandler.addRenderer("module", new ModulePlaceholderRenderer()); + PlaceholderHandler.addRenderer("rect", new RectPlaceholderRenderer()); + PlaceholderHandler.addRenderer("quad", new QuadPlaceholderRenderer()); PlaceholderHandler.addPlaceholder(new Placeholder("blockNbt") { @Override diff --git a/src/main/java/com/gregtechceu/gtceu/common/data/GTRecipeConditions.java b/src/main/java/com/gregtechceu/gtceu/common/data/GTRecipeConditions.java index c0576da5752..cb655156172 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/data/GTRecipeConditions.java +++ b/src/main/java/com/gregtechceu/gtceu/common/data/GTRecipeConditions.java @@ -21,6 +21,7 @@ private GTRecipeConditions() {} // spotless:off public static final RecipeConditionType BIOME = register("biome", BiomeCondition::new, BiomeCondition.CODEC); + public static final RecipeConditionType BIOME_TAG = register("biome_tag", BiomeTagCondition::new, BiomeTagCondition.CODEC); public static final RecipeConditionType DIMENSION = register("dimension", DimensionCondition::new, DimensionCondition.CODEC); public static final RecipeConditionType POSITION_Y = register("pos_y", PositionYCondition::new, PositionYCondition.CODEC); public static final RecipeConditionType RAINING = register("rain", RainingCondition::new, RainingCondition.CODEC); diff --git a/src/main/java/com/gregtechceu/gtceu/common/data/GTRecipeModifiers.java b/src/main/java/com/gregtechceu/gtceu/common/data/GTRecipeModifiers.java index 21005394fc8..cea3cf40f93 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/data/GTRecipeModifiers.java +++ b/src/main/java/com/gregtechceu/gtceu/common/data/GTRecipeModifiers.java @@ -20,6 +20,7 @@ import net.minecraft.Util; import net.minecraft.core.BlockPos; +import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; import org.jetbrains.annotations.NotNull; @@ -38,7 +39,8 @@ public class GTRecipeModifiers { .memoize(logic -> (machine, recipe) -> { if (!(machine instanceof IOverclockMachine overclockMachine)) return ModifierFunction.IDENTITY; if (RecipeHelper.getRecipeEUtTier(recipe) > overclockMachine.getMaxOverclockTier()) { - return ModifierFunction.NULL; + return ModifierFunction + .cancel(Component.translatable("gtceu.recipe_modifier.insufficient_voltage")); } return logic.getModifier(machine, recipe, overclockMachine.getOverclockVoltage()); }); @@ -175,11 +177,11 @@ public class GTRecipeModifiers { (100 * Math.max(0, coilMachine.getTier() - GTValues.MV)); int recipeTemp = recipe.data.getInt("ebf_temp"); if (!recipe.data.contains("ebf_temp") || recipeTemp > blastFurnaceTemperature) { - return ModifierFunction.NULL; + return ModifierFunction.cancel(Component.translatable("gtceu.recipe_modifier.coil_temperature_too_low")); } if (RecipeHelper.getRecipeEUtTier(recipe) > coilMachine.getTier()) { - return ModifierFunction.NULL; + return ModifierFunction.cancel(Component.translatable("gtceu.recipe_modifier.insufficient_voltage")); } var discount = ModifierFunction.builder() diff --git a/src/main/java/com/gregtechceu/gtceu/common/data/machines/GCYMMachines.java b/src/main/java/com/gregtechceu/gtceu/common/data/machines/GCYMMachines.java index f460eb19aee..b8ec948322f 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/data/machines/GCYMMachines.java +++ b/src/main/java/com/gregtechceu/gtceu/common/data/machines/GCYMMachines.java @@ -283,9 +283,9 @@ public static void init() {} .multiblock("large_assembler", WorkableElectricMultiblockMachine::new) .langValue("Large Assembling Factory") .tooltips(Component.translatable("gtceu.multiblock.parallelizable.tooltip")) - .tooltips(Component.translatable("gtceu.multiblock.exact_hatch_1.tooltip")) .tooltips(Component.translatable("gtceu.machine.available_recipe_map_1.tooltip", Component.translatable("gtceu.assembler"))) + .tooltips(Component.translatable("gtceu.multiblock.exact_hatch_1.tooltip")) .conditionalTooltip(GTMachineUtils.defaultEnvironmentRequirement(), ConfigHolder.INSTANCE.gameplay.environmentalHazards) .rotationState(RotationState.ALL) @@ -636,7 +636,7 @@ public static void init() {} .aisle("#YYY#", "YYYYY", "YYYYY", "YYYYY", "#YYY#") .aisle("#YSY#", "YAAAY", "YAAAY", "YAAAY", "#YYY#") .aisle("##X##", "#XAX#", "XAPAX", "#XAX#", "##X##").setRepeatable(1, 12) - .aisle("#####", "#ZZZ#", "#ZCZ#", "#ZZZ#", "#####") + .aisle("#####", "#ZZZ#", "#ZZZ#", "#ZZZ#", "#####") .where('S', controller(blocks(definition.get()))) .where('Y', casingPredicate.or(abilities(IMPORT_ITEMS)) .or(abilities(INPUT_ENERGY).setMinGlobalLimited(1).setMaxGlobalLimited(2)) @@ -646,7 +646,6 @@ public static void init() {} .where('X', casingPredicate.or(exportPredicate)) .where('Z', casingPredicate) .where('P', blocks(CASING_STEEL_PIPE.get())) - .where('C', abilities(MUFFLER)) .where('A', air()) .where('#', any()) .build(); @@ -656,7 +655,6 @@ public static void init() {} var builder = MultiblockShapeInfo.builder() .where('S', definition, Direction.NORTH) .where('C', CASING_WATERTIGHT.getDefaultState()) - .where('M', MUFFLER_HATCH[IV], Direction.UP) .where('X', PARALLEL_HATCH[IV], Direction.NORTH) .where('H', FLUID_IMPORT_HATCH[IV], Direction.NORTH) .where('B', ITEM_EXPORT_BUS[IV], Direction.NORTH) @@ -676,7 +674,7 @@ public static void init() {} List aisle3 = new ArrayList<>(16); aisle3.add("CCCCC"); aisle3.add("C###C"); - aisle3.add("#CMC#"); + aisle3.add("#CCC#"); List aisle4 = new ArrayList<>(16); aisle4.add("CCCCC"); aisle4.add("C###C"); @@ -923,7 +921,7 @@ public static void init() {} .pattern(definition -> FactoryBlockPattern.start() .aisle("XXXXXXX#KKK", "XXXXXXX#KVK", "XXXXXXX#KVK", "XXXXXXX#KVK", "XXXXXXX#KKK", "XXXXXXX####", "XXXXXXX####") .aisle("XXXXXXX#KVK", "XPPPPPPPPPV", "XPAPAPX#VPV", "XPPPPPPPPPV", "XPAPAPX#KVK", "XPPPPPX####", "XXXXXXX####") - .aisle("XXXXXXX#KVK", "XPAPAPXAVPV", "XAAAAAX#VPV", "XPAAAPX#VPV", "XAAAAAX#KVK", "XPAPAPX####", "XXXXXXX####") + .aisle("XXXXXXX#KVK", "XPAPAPX#VPV", "XAAAAAX#VPV", "XPAAAPX#VPV", "XAAAAAX#KVK", "XPAPAPX####", "XXXXXXX####") .aisle("XXXXXXX#KVK", "XPAPAPPPPPV", "XAAAAAX#VPV", "XPAAAPPPPPV", "XAAAAAX#KVK", "XPAPAPX####", "XXXXXXX####") .aisle("XXXXXXX#KKK", "XPPPPPX#KVK", "XPA#APX#KVK", "XPAAAPX#KVK", "XPAAAPX#KKK", "XPPPPPX####", "XXXXXXX####") .aisle("#XXXXX#####", "#XXSXX#####", "#XGGGX#####", "#XGGGX#####", "#XGGGX#####", "#XXXXX#####", "###########") diff --git a/src/main/java/com/gregtechceu/gtceu/common/data/materials/ElementMaterials.java b/src/main/java/com/gregtechceu/gtceu/common/data/materials/ElementMaterials.java index d006d0cd977..62409787155 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/data/materials/ElementMaterials.java +++ b/src/main/java/com/gregtechceu/gtceu/common/data/materials/ElementMaterials.java @@ -1026,7 +1026,7 @@ public static void register() { Trinium = new Material.Builder(GTCEu.id("trinium")) .ingot(7).fluid() .color(0x81808a).secondaryColor(0x351d4b).iconSet(SHINY) - .flags(GENERATE_FOIL, GENERATE_BOLT_SCREW, GENERATE_GEAR) + .flags(GENERATE_FOIL, GENERATE_BOLT_SCREW, GENERATE_GEAR, GENERATE_SPRING) .element(GTElements.Ke) .cableProperties(V[ZPM], 6, 4) .blast(b -> b.temp(7200, GasTier.HIGH) diff --git a/src/main/java/com/gregtechceu/gtceu/common/data/materials/OrganicChemistryMaterials.java b/src/main/java/com/gregtechceu/gtceu/common/data/materials/OrganicChemistryMaterials.java index 545e3030f6e..b581ac7cf73 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/data/materials/OrganicChemistryMaterials.java +++ b/src/main/java/com/gregtechceu/gtceu/common/data/materials/OrganicChemistryMaterials.java @@ -509,7 +509,7 @@ public static void register() { .color(0x353529).secondaryColor(0x080808) .toolStats( ToolProperty.Builder.of(1.0F, 1.0F, 256, 1, GTToolType.SOFT_MALLET, GTToolType.PLUNGER).build()) - .flags(GENERATE_GEAR, GENERATE_RING, GENERATE_FOIL, GENERATE_BOLT_SCREW) + .flags(GENERATE_RING, GENERATE_FOIL) .components(Carbon, 5, Hydrogen, 8) .buildAndRegister(); diff --git a/src/main/java/com/gregtechceu/gtceu/common/data/materials/SecondDegreeMaterials.java b/src/main/java/com/gregtechceu/gtceu/common/data/materials/SecondDegreeMaterials.java index 0bd7ea7c667..4ece776f76b 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/data/materials/SecondDegreeMaterials.java +++ b/src/main/java/com/gregtechceu/gtceu/common/data/materials/SecondDegreeMaterials.java @@ -107,7 +107,7 @@ public static void register() { Apatite = new Material.Builder(GTCEu.id("apatite")) .gem(1).ore(4, 2) .color(0x06cdf1).secondaryColor(0x701c07).iconSet(DIAMOND) - .flags(NO_SMASHING, NO_SMELTING, CRYSTALLIZABLE, GENERATE_BOLT_SCREW, DISABLE_DECOMPOSITION) + .flags(NO_SMASHING, NO_SMELTING, CRYSTALLIZABLE, DISABLE_DECOMPOSITION) .components(Calcium, 5, Phosphate, 3, Chlorine, 1) .buildAndRegister(); 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/item/modules/ImageModuleBehaviour.java b/src/main/java/com/gregtechceu/gtceu/common/item/modules/ImageModuleBehaviour.java index fd560be54a5..b21ee3a4750 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/item/modules/ImageModuleBehaviour.java +++ b/src/main/java/com/gregtechceu/gtceu/common/item/modules/ImageModuleBehaviour.java @@ -19,7 +19,7 @@ public class ImageModuleBehaviour implements IMonitorModuleItem { @Override - public IMonitorRenderer getRenderer(ItemStack stack, CentralMonitorMachine machine, MonitorGroup group) { + public IMonitorRenderer getRenderer(ItemStack stack) { return new MonitorImageRenderer(getUrl(stack)); } diff --git a/src/main/java/com/gregtechceu/gtceu/common/item/modules/TextModuleBehaviour.java b/src/main/java/com/gregtechceu/gtceu/common/item/modules/TextModuleBehaviour.java index d745051fe54..beb0f1289f3 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/item/modules/TextModuleBehaviour.java +++ b/src/main/java/com/gregtechceu/gtceu/common/item/modules/TextModuleBehaviour.java @@ -39,32 +39,42 @@ public class TextModuleBehaviour implements IMonitorModuleItem, IAddInformation { - private void updateText(ItemStack stack, CentralMonitorMachine machine, MonitorGroup group) { + private void updateText(ItemStack stack, PlaceholderContext ctx) { if (!stack.getOrCreateTag().contains("placeholderUUID")) { stack.getOrCreateTag().putUUID("placeholderUUID", UUID.randomUUID()); } MultiLineComponent text = PlaceholderHandler.processPlaceholders( getPlaceholderText(stack), - new PlaceholderContext( - group.getTargetLevel(machine.getLevel()), - group.getTarget(machine.getLevel()), - group.getTargetCoverSide(), - group.getPlaceholderSlotsHandler(), - group.getTargetCover(machine.getLevel()), - null, - stack.getOrCreateTag().getUUID("placeholderUUID"))); + ctx); stack.getOrCreateTag().put("text", text.toTag()); } + private PlaceholderContext makeContext(ItemStack stack, CentralMonitorMachine machine, MonitorGroup group) { + return new PlaceholderContext( + group.getTargetLevel(machine.getLevel()), + group.getTarget(machine.getLevel()), + group.getTargetCoverSide(), + group.getPlaceholderSlotsHandler(), + group.getTargetCover(machine.getLevel()), + null, + stack.getOrCreateTag().contains("placeholderUUID") ? stack.getOrCreateTag().getUUID("placeholderUUID") : + null); + } + @Override public void tick(ItemStack stack, CentralMonitorMachine machine, MonitorGroup group) { - this.updateText(stack, machine, group); + this.updateText(stack, makeContext(stack, machine, group)); + } + + @Override + public void tickInPlaceholder(ItemStack stack, PlaceholderContext context) { + this.updateText(stack, context); } @Override - public IMonitorRenderer getRenderer(ItemStack stack, CentralMonitorMachine machine, MonitorGroup group) { + public IMonitorRenderer getRenderer(ItemStack stack) { return new MonitorTextRenderer( - getText(stack).toImmutable(), + getText(stack), Math.max(getScale(stack), .0001)); } @@ -81,7 +91,7 @@ public Widget createUIWidget(ItemStack stack, CentralMonitorMachine machine, Mon ButtonWidget saveButton = new ButtonWidget(-40, 22, 20, 20, click -> { if (!click.isRemote) return; ListTag listTag = new ListTag(); - editor.getLines().forEach(line -> listTag.add(StringTag.valueOf(line))); + editor.getLines().forEach(line -> listTag.add(StringTag.valueOf(line.replaceAll("\r", "")))); CompoundTag tag2 = stack.getOrCreateTag(); tag2.put("formatStringLines", listTag); try { @@ -123,7 +133,7 @@ public String getType() { } public MultiLineComponent getText(ItemStack stack) { - return MultiLineComponent.fromTag(stack.getOrCreateTag().getList("text", Tag.TAG_STRING)); + return MultiLineComponent.fromTag(stack.getOrCreateTag().get("text")); } public double getScale(ItemStack stack) { @@ -136,7 +146,7 @@ public void setScale(ItemStack stack, double scale) { public void setPlaceholderText(ItemStack stack, String text) { ListTag listTag = new ListTag(); - for (String line : text.split("\n")) listTag.add(StringTag.valueOf(line)); + for (String line : text.split("\n")) listTag.add(StringTag.valueOf(line.replaceAll("\r", ""))); stack.getOrCreateTag().put("formatStringLines", listTag); } diff --git a/src/main/java/com/gregtechceu/gtceu/common/machine/multiblock/electric/CentralMonitorMachine.java b/src/main/java/com/gregtechceu/gtceu/common/machine/multiblock/electric/CentralMonitorMachine.java index 4c18fd64f73..84cf9d94b28 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/machine/multiblock/electric/CentralMonitorMachine.java +++ b/src/main/java/com/gregtechceu/gtceu/common/machine/multiblock/electric/CentralMonitorMachine.java @@ -391,7 +391,7 @@ public Widget createUIWidget() { text.setType(TextTexture.TextType.LEFT); label.setButtonTexture(text); label.setOnPressCallback(click -> { - group.getRelativePositions().forEach(pos -> { + group.getMonitorPositions().forEach(pos -> { BlockPos rel = toRelative(pos); if (imageButtons.size() - 1 < rel.getY()) return; if (imageButtons.get(rel.getY()).size() - 1 < rel.getX()) return; diff --git a/src/main/java/com/gregtechceu/gtceu/common/machine/multiblock/electric/DistillationTowerMachine.java b/src/main/java/com/gregtechceu/gtceu/common/machine/multiblock/electric/DistillationTowerMachine.java index b0ad0b7bf7c..f783a7d5d99 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/machine/multiblock/electric/DistillationTowerMachine.java +++ b/src/main/java/com/gregtechceu/gtceu/common/machine/multiblock/electric/DistillationTowerMachine.java @@ -160,7 +160,7 @@ private static GTRecipe modifyOutputs(GTRecipe recipe, ContentModifier cm) { recipe.outputChanceLogics, recipe.tickInputChanceLogics, recipe.tickOutputChanceLogics, recipe.conditions, recipe.ingredientActions, - recipe.data, recipe.duration, recipe.recipeCategory); + recipe.data, recipe.duration, recipe.recipeCategory, recipe.groupColor); } public static class DistillationTowerLogic extends RecipeLogic { diff --git a/src/main/java/com/gregtechceu/gtceu/common/machine/multiblock/electric/FusionReactorMachine.java b/src/main/java/com/gregtechceu/gtceu/common/machine/multiblock/electric/FusionReactorMachine.java index 11331b040d7..d22921206a8 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/machine/multiblock/electric/FusionReactorMachine.java +++ b/src/main/java/com/gregtechceu/gtceu/common/machine/multiblock/electric/FusionReactorMachine.java @@ -177,7 +177,8 @@ public static ModifierFunction recipeModifier(@NotNull MetaMachine machine, @Not if (RecipeHelper.getRecipeEUtTier(recipe) > fusionReactorMachine.getTier() || !recipe.data.contains("eu_to_start") || recipe.data.getLong("eu_to_start") > fusionReactorMachine.energyContainer.getEnergyCapacity()) { - return ModifierFunction.NULL; + return ModifierFunction + .cancel(Component.translatable("gtceu.recipe_modifier.insufficient_eu_to_start_fusion")); } long heatDiff = recipe.data.getLong("eu_to_start") - fusionReactorMachine.heat; @@ -187,7 +188,9 @@ public static ModifierFunction recipeModifier(@NotNull MetaMachine machine, @Not return FUSION_OC.getModifier(machine, recipe, fusionReactorMachine.getMaxVoltage(), false); } // if the remaining energy needed is more than stored, do not run - if (fusionReactorMachine.energyContainer.getEnergyStored() < heatDiff) return ModifierFunction.NULL; + if (fusionReactorMachine.energyContainer.getEnergyStored() < heatDiff) + return ModifierFunction + .cancel(Component.translatable("gtceu.recipe_modifier.insufficient_eu_to_start_fusion")); // remove the energy needed fusionReactorMachine.energyContainer.removeEnergy(heatDiff); diff --git a/src/main/java/com/gregtechceu/gtceu/common/machine/multiblock/electric/monitor/MonitorGroup.java b/src/main/java/com/gregtechceu/gtceu/common/machine/multiblock/electric/monitor/MonitorGroup.java index c2e0c35dafe..2977aca420f 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/machine/multiblock/electric/monitor/MonitorGroup.java +++ b/src/main/java/com/gregtechceu/gtceu/common/machine/multiblock/electric/monitor/MonitorGroup.java @@ -30,6 +30,7 @@ public class MonitorGroup { + @Getter private final Set monitorPositions = new HashSet<>(); @Getter private final String name; @@ -105,10 +106,6 @@ public boolean isEmpty() { return monitorPositions.isEmpty(); } - public Set getRelativePositions() { - return monitorPositions; - } - public @Nullable CoverBehavior getTargetCover(Level level) { if (getTarget(level) != null && targetCoverSide != null) { ICoverable coverable = GTCapabilityHelper.getCoverable(level, getTarget(level), targetCoverSide); diff --git a/src/main/java/com/gregtechceu/gtceu/common/machine/multiblock/part/ItemBusPartMachine.java b/src/main/java/com/gregtechceu/gtceu/common/machine/multiblock/part/ItemBusPartMachine.java index c3b0e7345c7..871f9236356 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/machine/multiblock/part/ItemBusPartMachine.java +++ b/src/main/java/com/gregtechceu/gtceu/common/machine/multiblock/part/ItemBusPartMachine.java @@ -3,6 +3,9 @@ import com.gregtechceu.gtceu.api.blockentity.BlockEntityCreationInfo; import com.gregtechceu.gtceu.api.blockentity.IPaintable; import com.gregtechceu.gtceu.api.capability.recipe.IO; +import com.gregtechceu.gtceu.api.cover.filter.FilterHandler; +import com.gregtechceu.gtceu.api.cover.filter.FilterHandlers; +import com.gregtechceu.gtceu.api.cover.filter.ItemFilter; import com.gregtechceu.gtceu.api.gui.GuiTextures; import com.gregtechceu.gtceu.api.gui.fancy.ConfiguratorPanel; import com.gregtechceu.gtceu.api.gui.widget.SlotWidget; @@ -70,12 +73,18 @@ public class ItemBusPartMachine extends TieredIOPartMachine @SaveField @SyncToClient private boolean isDistinct = false; + @SaveField + @SyncToClient + @Getter + protected final FilterHandler filterHandler; public ItemBusPartMachine(BlockEntityCreationInfo info, int tier, IO io) { super(info, tier, io); this.inventory = createInventory(); this.circuitSlotEnabled = true; this.circuitInventory = createCircuitItemHandler(io).shouldSearchContent(false); + filterHandler = FilterHandlers.item(this); + inventory.setFilter(this::matchesFilter); } ////////////////////////////////////// @@ -91,6 +100,12 @@ protected NotifiableItemStackHandler createInventory() { return new NotifiableItemStackHandler(this, getInventorySize(), io); } + protected boolean matchesFilter(ItemStack stack) { + if (filterHandler.isFilterPresent()) + return filterHandler.getFilter().test(stack); + return true; + } + protected NotifiableItemStackHandler createCircuitItemHandler(IO io) { if (io == IO.IN) { return new NotifiableItemStackHandler(this, 1, IO.IN, IO.NONE) @@ -261,7 +276,7 @@ public boolean swapIO() { getLevel().setBlockAndUpdate(blockPos, newBlockState); if (getLevel().getBlockEntity(blockPos) instanceof ItemBusPartMachine newMachine) { - // We don't set the circuit or distinct busses, since + // We don't set the circuit or distinct buses, since // that doesn't make sense on an output bus. // Furthermore, existing inventory items // and conveyors will drop to the floor on block override. @@ -298,6 +313,7 @@ public Widget createUIWidget() { var group = new WidgetGroup(0, 0, 18 * rowSize + 16, 18 * colSize + 16); var container = new WidgetGroup(4, 4, 18 * rowSize + 8, 18 * colSize + 8); int index = 0; + group.addWidget(filterHandler.createFilterSlotUI(-115 + (18 * rowSize) / 2, 35 + 11 * rowSize)); for (int y = 0; y < colSize; y++) { for (int x = 0; x < rowSize; x++) { container.addWidget( @@ -309,7 +325,6 @@ public Widget createUIWidget() { container.setBackground(GuiTextures.BACKGROUND_INVERSE); group.addWidget(container); - return group; } } 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/common/recipe/condition/AdjacentFluidCondition.java b/src/main/java/com/gregtechceu/gtceu/common/recipe/condition/AdjacentFluidCondition.java index a1c2217d086..8efbde197a2 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/recipe/condition/AdjacentFluidCondition.java +++ b/src/main/java/com/gregtechceu/gtceu/common/recipe/condition/AdjacentFluidCondition.java @@ -93,7 +93,12 @@ public RecipeConditionType getType() { @Override public Component getTooltips() { - return Component.translatable("recipe.condition.adjacent_fluid.tooltip"); + var tooltips = Component.translatable("recipe.condition.adjacent_fluid.tooltip"); + fluids.forEach(set -> { + var id = set.get().get(0).get().getFluidType().getDescription(); + tooltips.append(" ").append(id); + }); + return tooltips; } @Override diff --git a/src/main/java/com/gregtechceu/gtceu/common/recipe/condition/BiomeTagCondition.java b/src/main/java/com/gregtechceu/gtceu/common/recipe/condition/BiomeTagCondition.java new file mode 100644 index 00000000000..8e78c454778 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/common/recipe/condition/BiomeTagCondition.java @@ -0,0 +1,73 @@ +package com.gregtechceu.gtceu.common.recipe.condition; + +import com.gregtechceu.gtceu.api.machine.trait.RecipeLogic; +import com.gregtechceu.gtceu.api.recipe.GTRecipe; +import com.gregtechceu.gtceu.api.recipe.RecipeCondition; +import com.gregtechceu.gtceu.api.recipe.condition.RecipeConditionType; +import com.gregtechceu.gtceu.common.data.GTRecipeConditions; + +import net.minecraft.core.Holder; +import net.minecraft.core.registries.Registries; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.TagKey; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.biome.Biome; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.jetbrains.annotations.NotNull; + +@NoArgsConstructor +public class BiomeTagCondition extends RecipeCondition { + + public static final Codec CODEC = RecordCodecBuilder + .create(instance -> RecipeCondition.isReverse(instance) + .and(TagKey.codec(Registries.BIOME).fieldOf("biome_tag").forGetter(val -> val.biome)) + .apply(instance, BiomeTagCondition::new)); + + public final static BiomeTagCondition INSTANCE = new BiomeTagCondition(); + @Getter + private TagKey biome = TagKey.create(Registries.BIOME, new ResourceLocation("dummy")); + + public BiomeTagCondition(boolean isReverse, TagKey biome) { + super(isReverse); + this.biome = biome; + } + + public BiomeTagCondition(TagKey biome) { + this.biome = biome; + } + + @Override + public RecipeConditionType getType() { + return GTRecipeConditions.BIOME_TAG; + } + + @Override + public boolean isOr() { + return true; + } + + @Override + public Component getTooltips() { + return Component.translatable("recipe.condition.biome.tooltip", + Component.translatableWithFallback(biome.location().toLanguageKey("biome"), + biome.location().toString())); + } + + @Override + public boolean testCondition(@NotNull GTRecipe recipe, @NotNull RecipeLogic recipeLogic) { + Level level = recipeLogic.machine.self().getLevel(); + if (level == null) return false; + Holder biome = level.getBiome(recipeLogic.machine.self().getBlockPos()); + return biome.is(this.biome); + } + + @Override + public BiomeTagCondition createTemplate() { + return new BiomeTagCondition(); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/common/recipe/condition/DimensionCondition.java b/src/main/java/com/gregtechceu/gtceu/common/recipe/condition/DimensionCondition.java index 84b2f9d86c8..d046376bdd0 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/recipe/condition/DimensionCondition.java +++ b/src/main/java/com/gregtechceu/gtceu/common/recipe/condition/DimensionCondition.java @@ -82,7 +82,7 @@ public SlotWidget setupDimensionMarkers(int xOffset, int yOffset) { @Override public boolean testCondition(@NotNull GTRecipe recipe, @NotNull RecipeLogic recipeLogic) { Level level = recipeLogic.machine.self().getLevel(); - return level != null && dimension.equals(level.dimension().location()); + return level != null && dimension.location().equals(level.dimension().location()); } @Override diff --git a/src/main/java/com/gregtechceu/gtceu/config/ConfigHolder.java b/src/main/java/com/gregtechceu/gtceu/config/ConfigHolder.java index c15a4275e3f..3248f0c11be 100644 --- a/src/main/java/com/gregtechceu/gtceu/config/ConfigHolder.java +++ b/src/main/java/com/gregtechceu/gtceu/config/ConfigHolder.java @@ -846,6 +846,10 @@ public static class DeveloperConfigs { @Configurable @Configurable.Comment({ "Dump all registered GT models/blockstates/etc?", "Default: false" }) public boolean dumpAssets = false; + @Configurable + @Configurable.Comment({ "Executes ./gradlew :processResources when F3+T is pressed", + "Only works in a development environment", "Default: false" }) + public boolean autoRebuildResources = false; } public static class RendererConfigs { @@ -858,13 +862,18 @@ public static class RendererConfigs { @Configurable.Comment({ "Render growing plants in multiblocks that support them?", "Default: true" }) public boolean renderGrowingPlants = true; + @Configurable + @Configurable.Comment({ "Whether or not to color material/ore block highlights in the material color", + "Default: true" }) + public boolean coloredMaterialBlockOutline = true; + @Configurable @Configurable.Comment({ "Whether or not to color tiered machine highlights in the tier color", "Default: true" }) public boolean coloredTieredMachineOutline = true; @Configurable - @Configurable.Comment({ "Whether or not to color wire/cable highlights based on voltage tier", + @Configurable.Comment({ "Whether or not to color wire/cable highlights based on voltage tier or material color", "Default: true" }) public boolean coloredWireOutline = true; } diff --git a/src/main/java/com/gregtechceu/gtceu/core/mixins/SmithingTransformRecipeMixin.java b/src/main/java/com/gregtechceu/gtceu/core/mixins/SmithingTransformRecipeMixin.java new file mode 100644 index 00000000000..d349dc17cb2 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/core/mixins/SmithingTransformRecipeMixin.java @@ -0,0 +1,63 @@ +package com.gregtechceu.gtceu.core.mixins; + +import com.gregtechceu.gtceu.api.item.IGTTool; +import com.gregtechceu.gtceu.api.item.tool.ToolHelper; + +import net.minecraft.core.RegistryAccess; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.Tag; +import net.minecraft.world.Container; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.SmithingTransformRecipe; + +import com.llamalad7.mixinextras.sugar.Share; +import com.llamalad7.mixinextras.sugar.ref.LocalRef; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(SmithingTransformRecipe.class) +public class SmithingTransformRecipeMixin { + + @Shadow + @Final + ItemStack result; + + @Inject(method = "assemble", + at = @At(value = "INVOKE", + target = "Lnet/minecraft/world/item/ItemStack;setTag(Lnet/minecraft/nbt/CompoundTag;)V")) + private void gtceu$gtToolSmithingTransform1(Container container, RegistryAccess registryAccess, + CallbackInfoReturnable cir, + @Share("newTag") LocalRef sharedTag) { + ItemStack output = this.result.copy(); + + if (!(output.getItem() instanceof IGTTool igtTool)) return; + + CompoundTag originalTag = container.getItem(1).getTag(); + CompoundTag newTag = originalTag != null ? originalTag.copy() : null; + if (newTag == null) return; + + // Remove old tool stats + newTag.remove("GT.Tool"); + + // Copy stats from the upgraded tool + ItemStack newStack = ToolHelper.get(igtTool.getToolType(), igtTool.getMaterial()); + Tag newStats = newStack.getTag() != null ? newStack.getTag().get("GT.Tool") : null; + if (newStats != null) { + newTag.put("GT.Tool", newStats); + sharedTag.set(newTag); + } + } + + @Redirect(method = "assemble", + at = @At(value = "INVOKE", + target = "Lnet/minecraft/world/item/ItemStack;setTag(Lnet/minecraft/nbt/CompoundTag;)V")) + private void gtceu$gtToolSmithingTransform2(ItemStack itemStack, CompoundTag tag, + @Share("newTag") LocalRef sharedTag) { + itemStack.setTag(sharedTag.get()); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/core/mixins/client/LevelRendererMixin.java b/src/main/java/com/gregtechceu/gtceu/core/mixins/client/LevelRendererMixin.java index c79852c7beb..fe2adab665c 100644 --- a/src/main/java/com/gregtechceu/gtceu/core/mixins/client/LevelRendererMixin.java +++ b/src/main/java/com/gregtechceu/gtceu/core/mixins/client/LevelRendererMixin.java @@ -7,7 +7,6 @@ import com.gregtechceu.gtceu.api.data.chemical.material.stack.MaterialEntry; import com.gregtechceu.gtceu.api.item.tool.ToolHelper; import com.gregtechceu.gtceu.api.item.tool.aoe.AoESymmetrical; -import com.gregtechceu.gtceu.api.machine.MetaMachine; import com.gregtechceu.gtceu.api.machine.feature.ITieredMachine; import com.gregtechceu.gtceu.api.machine.steam.SteamMachine; import com.gregtechceu.gtceu.api.pipenet.IPipeNode; @@ -19,7 +18,6 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.renderer.*; -import net.minecraft.client.resources.model.BakedModel; import net.minecraft.client.resources.model.ModelBakery; import net.minecraft.core.BlockPos; import net.minecraft.server.level.BlockDestructionProgress; @@ -44,7 +42,6 @@ import com.mojang.blaze3d.vertex.SheetedDecalTextureGenerator; import com.mojang.blaze3d.vertex.VertexConsumer; import it.unimi.dsi.fastutil.longs.Long2ObjectMap; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.joml.Matrix4f; import org.spongepowered.asm.mixin.Final; @@ -177,26 +174,23 @@ private static void renderShape(PoseStack poseStack, VertexConsumer consumer, Vo assert level != null; var rendererCfg = ConfigHolder.INSTANCE.client.renderer; int rgb = 0; - boolean doRenderColoredOutline = false; + boolean renderColoredOutline = false; // spotless:off - // if it's translucent and a material block, always do the colored outline - MaterialEntry materialEntry = gtceu$getTranslucentBlockMaterial(state, pos); - if (!materialEntry.isEmpty()) { - doRenderColoredOutline = true; + MaterialEntry materialEntry = ChemicalHelper.getMaterialEntry(state.getBlock()); + if (rendererCfg.coloredMaterialBlockOutline && !materialEntry.isEmpty()) { + renderColoredOutline = true; rgb = materialEntry.material().getMaterialRGB(); - } else if (level.getBlockEntity(pos) instanceof MetaMachine mbe) { - if (rendererCfg.coloredTieredMachineOutline) { - if (mbe instanceof SteamMachine steam) { - doRenderColoredOutline = true; + } else if (rendererCfg.coloredTieredMachineOutline) { + if (level.getBlockEntity(pos) instanceof SteamMachine steam) { + renderColoredOutline = true; rgb = steam.isHighPressure() ? GTValues.VC_HP_STEAM : GTValues.VC_LP_STEAM; - } else if (mbe instanceof ITieredMachine tiered) { - doRenderColoredOutline = true; + } else if (level.getBlockEntity(pos) instanceof ITieredMachine tiered) { + renderColoredOutline = true; rgb = GTValues.VCM[tiered.getTier()]; } - } } else if (rendererCfg.coloredWireOutline && level.getBlockEntity(pos) instanceof IPipeNode pipe) { - doRenderColoredOutline = true; + renderColoredOutline = true; if (!pipe.getFrameMaterial().isNull()) { rgb = pipe.getFrameMaterial().getMaterialRGB(); } else if (pipe instanceof CableBlockEntity cable) { @@ -205,48 +199,18 @@ private static void renderShape(PoseStack poseStack, VertexConsumer consumer, Vo rgb = materialPipe.material.getMaterialRGB(); } } - - VoxelShape blockShape = state.getShape(level, pos, CollisionContext.of(entity)); // spotless:on - if (doRenderColoredOutline) { + VoxelShape blockShape = state.getShape(level, pos, CollisionContext.of(entity)); + + if (renderColoredOutline) { float red = FastColor.ARGB32.red(rgb) / 255f; float green = FastColor.ARGB32.green(rgb) / 255f; float blue = FastColor.ARGB32.blue(rgb) / 255f; renderShape(poseStack, consumer, blockShape, pos.getX() - camX, pos.getY() - camY, pos.getZ() - camZ, - red, green, blue, 1f); + red, green, blue, 0.4f); return; } - BlockPos.MutableBlockPos mutable = pos.mutable(); - for (BlockPos o : GTUtil.NON_CORNER_NEIGHBOURS) { - BlockPos offset = mutable.setWithOffset(pos, o); - if (!gtceu$getTranslucentBlockMaterial(level.getBlockState(offset), offset).isEmpty()) { - renderShape(poseStack, consumer, blockShape, - pos.getX() - camX, pos.getY() - camY, pos.getZ() - camZ, - 0, 0, 0, 1f); - return; - } - } original.call(instance, poseStack, consumer, entity, camX, camY, camZ, pos, state); } - - @Unique - private @NotNull MaterialEntry gtceu$getTranslucentBlockMaterial(BlockState state, BlockPos pos) { - assert level != null; - // skip non-solid blocks from other mods (like vanilla ice blocks) - if (!state.isSolidRender(level, pos) && !(state.getBlock() instanceof MaterialBlock)) { - return MaterialEntry.NULL_ENTRY; - } - - BakedModel blockModel = minecraft.getBlockRenderer().getBlockModel(state); - ModelData modelData = level.getModelDataManager().getAt(pos); - if (modelData == null) modelData = ModelData.EMPTY; - modelData = blockModel.getModelData(level, pos, state, modelData); - - gtceu$modelRandom.setSeed(state.getSeed(pos)); - if (blockModel.getRenderTypes(state, gtceu$modelRandom, modelData).contains(RenderType.translucent())) { - return ChemicalHelper.getMaterialEntry(state.getBlock()); - } - return MaterialEntry.NULL_ENTRY; - } } 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/core/mixins/dev/client/KeyboardHandlerMixin.java b/src/main/java/com/gregtechceu/gtceu/core/mixins/dev/client/KeyboardHandlerMixin.java new file mode 100644 index 00000000000..e06b0e59053 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/core/mixins/dev/client/KeyboardHandlerMixin.java @@ -0,0 +1,25 @@ +package com.gregtechceu.gtceu.core.mixins.dev.client; + +import com.gregtechceu.gtceu.utils.dev.ResourceReloadDetector; + +import net.minecraft.client.KeyboardHandler; +import net.minecraft.client.Minecraft; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import java.util.concurrent.CompletableFuture; + +@Mixin(KeyboardHandler.class) +public abstract class KeyboardHandlerMixin { + + @WrapOperation(method = "handleDebugKeys", + at = @At(value = "INVOKE", + target = "Lnet/minecraft/client/Minecraft;reloadResourcePacks()Ljava/util/concurrent/CompletableFuture;")) + private CompletableFuture gtceu$hookResourceReload(Minecraft instance, + Operation> original) { + return ResourceReloadDetector.regenerateResourcesOnReload(() -> original.call(instance)); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/data/lang/LangHandler.java b/src/main/java/com/gregtechceu/gtceu/data/lang/LangHandler.java index 7aabc341492..f36f4b91036 100644 --- a/src/main/java/com/gregtechceu/gtceu/data/lang/LangHandler.java +++ b/src/main/java/com/gregtechceu/gtceu/data/lang/LangHandler.java @@ -28,6 +28,7 @@ public static void init(RegistrateLangProvider provider) { MachineLang.init(provider); ToolLang.init(provider); ConfigurationLang.init(provider); + RecipeLogicLang.init(provider); provider.add("gtceu.gui.editor.tips.citation", "Number of citations"); provider.add("gtceu.gui.editor.group.recipe_type", "cap"); @@ -1234,6 +1235,9 @@ public static void init(RegistrateLangProvider provider) { provider.add("gtceu.key.enable_step_assist", "Enable StepAssist"); provider.add("gtceu.debug.f3_h.enabled", "GregTech has modified the debug info! For Developers: enable the misc:debug config option in the GregTech config file to see more"); + provider.add("gtceu.debug.resource_rebuild.done", "Gradle resource rebuild done in %s"); + provider.add("gtceu.debug.resource_rebuild.start", + "Invoking gradle resource rebuild (./gradlew :processResources)"); provider.add("config.jade.plugin_gtceu.controllable_provider", "[GTCEu] Controllable"); provider.add("config.jade.plugin_gtceu.workable_provider", "[GTCEu] Workable"); provider.add("config.jade.plugin_gtceu.battery_info", "[GTCEu] Battery info"); @@ -1264,12 +1268,7 @@ public static void init(RegistrateLangProvider provider) { provider.add("gtceu.button.hide_depleted", "Hide Depleted Veins"); provider.add("gtceu.button.show_depleted", "Show Depleted Veins"); provider.add("gtceu.recipe_type.show_recipes", "Show Recipes"); - provider.add("gtceu.recipe_logic.insufficient_fuel", "Insufficient Fuel"); - provider.add("gtceu.recipe_logic.insufficient_in", "Insufficient Inputs"); - provider.add("gtceu.recipe_logic.insufficient_out", "Insufficient Outputs"); - provider.add("gtceu.recipe_logic.condition_fails", "Condition Fails"); - provider.add("gtceu.recipe_logic.no_contents", "Recipe has no Contents"); - provider.add("gtceu.recipe_logic.no_capabilities", "Machine has no Capabilities"); + provider.add("gtceu.gui.cover_setting.title", "Cover Settings"); provider.add("gtceu.gui.output_setting.title", "Output Settings"); provider.add("gtceu.gui.circuit.title", "Circuit Settings"); @@ -1669,6 +1668,27 @@ public static void init(RegistrateLangProvider provider) { " {eval \"repeating a: {repeat 5 \\\"a \\\"}\" -> repeating a: a a a a a ", " {eval \\\"\"{some random text}\"\\\" -> {some random text}", " {eval \"text \"\\\"\"{something with spaces}\"\\\"\" more text\" -> text {something with spaces} more text"); + multiLang(provider, "gtceu.placeholder_info.module", + "Renders the module in the specified slot onto the central monitor (does not work in a cover)", + "Usage:", + " {module } -> empty string"); + multiLang(provider, "gtceu.placeholder_info.setImage", + "Sets the image URL in an image module in the specified slot", + "Usage:", + " {setImage } -> empty string"); + multiLang(provider, "gtceu.placeholder_info.rect", + "Draws a rectangle at the specified position with the specified coordinates and size", + "Usage:", + " {rect } -> empty string", + " {rect 0.5 0.25 2 1 0xFFFFFFFF} -> draws a white rectangle at (0.5, 0.25) with the size (2, 1)"); + multiLang(provider, "gtceu.placeholder_info.quad", + "Draws a quad (must specify parameters for all 4 vertices)", + "Usage:", + " {quad } -> empty string"); + multiLang(provider, "gtceu.placeholder_info.item", + "Returns the amount and id of the item in a specified slot", + "Usage:", + " {item } -> \"31 minecraft:diamond\" (for example)"); multiLang(provider, "gtceu.placeholder_info.bufferText", "Returns the text from a buffer accessible by ComputerCraft", "Usage:", diff --git a/src/main/java/com/gregtechceu/gtceu/data/lang/RecipeLogicLang.java b/src/main/java/com/gregtechceu/gtceu/data/lang/RecipeLogicLang.java new file mode 100644 index 00000000000..3146df4ba7b --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/data/lang/RecipeLogicLang.java @@ -0,0 +1,31 @@ +package com.gregtechceu.gtceu.data.lang; + +import com.tterrag.registrate.providers.RegistrateLangProvider; + +public class RecipeLogicLang { + + public static void init(RegistrateLangProvider provider) { + initGenericLang(provider); + initModifierLang(provider); + } + + private static void initGenericLang(RegistrateLangProvider provider) { + provider.add("gtceu.recipe_logic.setup_fail", "Fail to setup recipe: "); + provider.add("gtceu.recipe_logic.recipe_waiting", "Recipe Waiting: "); + + provider.add("gtceu.recipe_logic.insufficient_fuel", "Insufficient Fuel"); + provider.add("gtceu.recipe_logic.insufficient_in", "Insufficient Inputs"); + provider.add("gtceu.recipe_logic.insufficient_out", "Insufficient Outputs"); + provider.add("gtceu.recipe_logic.condition_fails", "Condition Fails"); + provider.add("gtceu.recipe_logic.no_contents", "Recipe has no Contents"); + provider.add("gtceu.recipe_logic.no_capabilities", "Machine has no Capabilities"); + } + + private static void initModifierLang(RegistrateLangProvider provider) { + provider.add("gtceu.recipe_modifier.default_fail", "Recipe Modifier Fail"); + provider.add("gtceu.recipe_modifier.insufficient_voltage", "Voltage Tier Too Low"); + provider.add("gtceu.recipe_modifier.insufficient_eu_to_start_fusion", + "Insufficient Energy to Initiate Fusion Reaction"); + provider.add("gtceu.recipe_modifier.coil_temperature_too_low", "Coil Temperature Too Low"); + } +} 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..57ffd1f470c --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/data/model/builder/PipeModelBuilder.java @@ -0,0 +1,475 @@ +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.experimental.Accessors; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.Range; +import org.joml.Vector3f; + +import java.util.*; +import java.util.function.BiFunction; + +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 { + + // spotless:off + public static > BiFunction> begin(@Range(from = 0, to = 16) float thickness, + GTBlockstateProvider provider) { + return (parent, existingFileHelper) -> new PipeModelBuilder<>(parent, existingFileHelper, thickness, provider); + } + // spotless:on + + @Accessors(fluent = false) + @Getter + private final Map<@Nullable Direction, ConfiguredModelList> parts = new IdentityHashMap<>(); + private final float thickness; + private final GTBlockstateProvider provider; + private BlockModelBuilder @Nullable [] restrictors = null; + + protected PipeModelBuilder(T parent, ExistingFileHelper existingFileHelper, + float thickness, GTBlockstateProvider provider) { + super(PipeModelLoader.ID, parent, existingFileHelper); + + Preconditions.checkArgument(thickness > 0.0f && thickness <= 16.0f, + "Thickness must be between 0 (exclusive) and 16 (inclusive). It is %s", thickness); + this.thickness = thickness; + this.provider = provider; + } + + /** + * 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) { + 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/model/builder/package-info.java b/src/main/java/com/gregtechceu/gtceu/data/model/builder/package-info.java new file mode 100644 index 00000000000..2f6102b3cd1 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/data/model/builder/package-info.java @@ -0,0 +1,4 @@ +@NotNullByDefault +package com.gregtechceu.gtceu.data.model.builder; + +import org.jetbrains.annotations.NotNullByDefault; 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..986d7be8744 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; @@ -51,10 +56,9 @@ public class GTDynamicResourcePack implements PackResources { protected static final GTDynamicPackContents CONTENTS = new GTDynamicPackContents(); 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 TEXTURE_ID_CONVERTER = SpriteSource.TEXTURE_ID_CONVERTER; + public static final FileToIdConverter BLOCKSTATE_ID_CONVERTER = FileToIdConverter.json("blockstates"); + public 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/data/recipe/VanillaRecipeHelper.java b/src/main/java/com/gregtechceu/gtceu/data/recipe/VanillaRecipeHelper.java index ce0db2d32f6..4b3bb603ab6 100644 --- a/src/main/java/com/gregtechceu/gtceu/data/recipe/VanillaRecipeHelper.java +++ b/src/main/java/com/gregtechceu/gtceu/data/recipe/VanillaRecipeHelper.java @@ -10,10 +10,14 @@ import com.gregtechceu.gtceu.api.data.chemical.material.stack.MaterialEntry; import com.gregtechceu.gtceu.api.data.chemical.material.stack.MaterialStack; import com.gregtechceu.gtceu.api.data.tag.TagPrefix; +import com.gregtechceu.gtceu.api.item.tool.GTToolType; import com.gregtechceu.gtceu.api.item.tool.ToolHelper; import com.gregtechceu.gtceu.data.recipe.builder.*; +import net.minecraft.advancements.critereon.InventoryChangeTrigger; import net.minecraft.data.recipes.FinishedRecipe; +import net.minecraft.data.recipes.RecipeCategory; +import net.minecraft.data.recipes.SmithingTransformRecipeBuilder; import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.TagKey; import net.minecraft.world.item.Item; @@ -22,7 +26,9 @@ import net.minecraft.world.level.ItemLike; import com.tterrag.registrate.util.entry.ItemProviderEntry; -import it.unimi.dsi.fastutil.chars.*; +import it.unimi.dsi.fastutil.chars.Char2IntOpenHashMap; +import it.unimi.dsi.fastutil.chars.CharArraySet; +import it.unimi.dsi.fastutil.chars.CharSet; import it.unimi.dsi.fastutil.objects.Reference2LongOpenHashMap; import org.jetbrains.annotations.NotNull; @@ -224,7 +230,7 @@ public static void addShapedNBTClearingRecipe(Consumer provider, } /** - * @see #addShapedRecipe(Consumer, boolean, boolean, ResourceLocation, ItemStack, Object...) + * @see #addShapedRecipe(Consumer, boolean, boolean, boolean, ResourceLocation, ItemStack, Object...) */ public static void addShapedRecipe(Consumer provider, @NotNull String regName, @NotNull ItemStack result, @NotNull Object... recipe) { @@ -232,7 +238,7 @@ public static void addShapedRecipe(Consumer provider, @NotNull S } /** - * @see #addShapedRecipe(Consumer, boolean, boolean, ResourceLocation, ItemStack, Object...) + * @see #addShapedRecipe(Consumer, boolean, boolean, boolean, ResourceLocation, ItemStack, Object...) */ public static void addShapedRecipe(Consumer provider, @NotNull ResourceLocation regName, @NotNull ItemStack result, @NotNull Object... recipe) { @@ -240,7 +246,7 @@ public static void addShapedRecipe(Consumer provider, @NotNull R } /** - * @see #addShapedRecipe(Consumer, boolean, boolean, ResourceLocation, ItemStack, Object...) + * @see #addShapedRecipe(Consumer, boolean, boolean, boolean, ResourceLocation, ItemStack, Object...) */ public static void addStrictShapedRecipe(Consumer provider, @NotNull String regName, @NotNull ItemStack result, @NotNull Object... recipe) { @@ -248,7 +254,7 @@ public static void addStrictShapedRecipe(Consumer provider, @Not } /** - * @see #addShapedRecipe(Consumer, boolean, boolean, ResourceLocation, ItemStack, Object...) + * @see #addShapedRecipe(Consumer, boolean, boolean, boolean, ResourceLocation, ItemStack, Object...) */ public static void addStrictShapedRecipe(Consumer provider, boolean setMaterialInfoData, @NotNull String regName, @@ -257,13 +263,38 @@ public static void addStrictShapedRecipe(Consumer provider, bool } /** - * @see #addShapedRecipe(Consumer, boolean, boolean, ResourceLocation, ItemStack, Object...) + * @see #addShapedRecipe(Consumer, boolean, boolean, boolean, ResourceLocation, ItemStack, Object...) */ public static void addStrictShapedRecipe(Consumer provider, @NotNull ResourceLocation regName, @NotNull ItemStack result, @NotNull Object... recipe) { addStrictShapedRecipe(provider, false, regName, result, recipe); } + /** + * @see #addShapedRecipe(Consumer, boolean, boolean, boolean, ResourceLocation, ItemStack, Object...) + */ + public static void addStrictSizeShapedRecipe(Consumer provider, @NotNull String regName, + @NotNull ItemStack result, @NotNull Object... recipe) { + addStrictSizeShapedRecipe(provider, GTCEu.id(regName), result, recipe); + } + + /** + * @see #addShapedRecipe(Consumer, boolean, boolean, boolean, ResourceLocation, ItemStack, Object...) + */ + public static void addStrictSizeShapedRecipe(Consumer provider, boolean setMaterialInfoData, + @NotNull String regName, + @NotNull ItemStack result, @NotNull Object... recipe) { + addStrictSizeShapedRecipe(provider, setMaterialInfoData, GTCEu.id(regName), result, recipe); + } + + /** + * @see #addShapedRecipe(Consumer, boolean, boolean, boolean, ResourceLocation, ItemStack, Object...) + */ + public static void addStrictSizeShapedRecipe(Consumer provider, @NotNull ResourceLocation regName, + @NotNull ItemStack result, @NotNull Object... recipe) { + addStrictSizeShapedRecipe(provider, false, regName, result, recipe); + } + /** * Adds Shaped Crafting Recipes. *

@@ -284,17 +315,20 @@ public static void addStrictShapedRecipe(Consumer provider, @Not *

  • {@code 'w'} - {@code craftingToolWrench}
  • *
  • {@code 'x'} - {@code craftingToolWireCutter}
  • * - * + * * @param setMaterialInfoData whether to add material decomposition information to the recipe output + * + * @param matchSize * @param regName the registry name for the recipe * @param result the output for the recipe * @param recipe the contents of the recipe */ public static void addShapedRecipe(Consumer provider, boolean setMaterialInfoData, boolean isStrict, - @NotNull ResourceLocation regName, @NotNull ItemStack result, + boolean matchSize, @NotNull ResourceLocation regName, @NotNull ItemStack result, @NotNull Object... recipe) { var builder = new ShapedRecipeBuilder(regName).output(result); builder.isStrict(isStrict); + builder.matchSize(matchSize); final CharSet tools = ToolHelper.getToolSymbols(); CharSet foundTools = new CharArraySet(9); for (int i = 0; i < recipe.length; i++) { @@ -355,7 +389,7 @@ public static void addShapedRecipe(Consumer provider, boolean se } /** - * @see #addShapedRecipe(Consumer, boolean, boolean, ResourceLocation, ItemStack, Object...) + * @see #addShapedRecipe(Consumer, boolean, boolean, boolean, ResourceLocation, ItemStack, Object...) */ public static void addShapedRecipe(Consumer provider, boolean setMaterialInfoData, @NotNull String regName, @NotNull ItemStack result, @NotNull Object... recipe) { @@ -363,21 +397,30 @@ public static void addShapedRecipe(Consumer provider, boolean se } /** - * @see #addShapedRecipe(Consumer, boolean, boolean, ResourceLocation, ItemStack, Object...) + * @see #addShapedRecipe(Consumer, boolean, boolean, boolean, ResourceLocation, ItemStack, Object...) */ public static void addShapedRecipe(Consumer provider, boolean setMaterialInfoData, @NotNull ResourceLocation regName, @NotNull ItemStack result, @NotNull Object... recipe) { - addShapedRecipe(provider, setMaterialInfoData, false, regName, result, recipe); + addShapedRecipe(provider, setMaterialInfoData, false, false, regName, result, recipe); } /** - * @see #addShapedRecipe(Consumer, boolean, boolean, ResourceLocation, ItemStack, Object...) + * @see #addShapedRecipe(Consumer, boolean, boolean, boolean, ResourceLocation, ItemStack, Object...) */ public static void addStrictShapedRecipe(Consumer provider, boolean setMaterialInfoData, @NotNull ResourceLocation regName, @NotNull ItemStack result, @NotNull Object... recipe) { - addShapedRecipe(provider, setMaterialInfoData, true, regName, result, recipe); + addShapedRecipe(provider, setMaterialInfoData, true, false, regName, result, recipe); + } + + /** + * @see #addShapedRecipe(Consumer, boolean, boolean, boolean, ResourceLocation, ItemStack, Object...) + */ + public static void addStrictSizeShapedRecipe(Consumer provider, boolean setMaterialInfoData, + @NotNull ResourceLocation regName, @NotNull ItemStack result, + @NotNull Object... recipe) { + addShapedRecipe(provider, setMaterialInfoData, true, true, regName, result, recipe); } public static void addShapelessRecipe(Consumer provider, @NotNull String regName, @@ -583,6 +626,38 @@ public static void addShapelessRecipe(Consumer provider, @NotNul builder.save(provider); } + public static void addSmithingTransformRecipe(Consumer provider, @NotNull ResourceLocation regName, + @NotNull Item result, @NotNull ItemLike baseInput, + @NotNull ItemLike template, @NotNull ItemLike addition, + @NotNull RecipeCategory category) { + SmithingTransformRecipeBuilder + .smithing(Ingredient.of(template), Ingredient.of(baseInput), Ingredient.of(addition), category, result) + .unlocks(String.format("has_%s", baseInput), InventoryChangeTrigger.TriggerInstance.hasItems(baseInput)) + .save(provider, regName); + } + + public static void addSmithingTransformRecipe(Consumer provider, @NotNull String regName, + @NotNull Item result, @NotNull ItemLike baseInput, + @NotNull ItemLike template, @NotNull ItemLike addition) { + addSmithingTransformRecipe(provider, GTCEu.id(regName), result, baseInput, template, addition, + RecipeCategory.MISC); + } + + public static void addToolUpgradingRecipe(@NotNull Consumer provider, @NotNull GTToolType tool, + @NotNull Material upgradeMaterial, @NotNull Material baseMaterial, + @NotNull ItemLike template, @NotNull ItemLike addition) { + ItemStack upgradeToolStack = ToolHelper.get(tool, upgradeMaterial); + ItemStack baseToolStack = ToolHelper.get(tool, baseMaterial); + + if (upgradeToolStack.isEmpty() || baseToolStack.isEmpty()) return; + + VanillaRecipeHelper.addSmithingTransformRecipe(provider, + String.format("%s_%s_smithing_transform_from_%s", upgradeMaterial.getName(), tool.name, + baseMaterial.getName()), + upgradeToolStack.getItem(), baseToolStack.getItem(), + template, addition); + } + /** * @param material the material to check * @return if the material is a wood diff --git a/src/main/java/com/gregtechceu/gtceu/data/recipe/builder/GTRecipeBuilder.java b/src/main/java/com/gregtechceu/gtceu/data/recipe/builder/GTRecipeBuilder.java index e5f5368ba2d..eb97eff4d6d 100644 --- a/src/main/java/com/gregtechceu/gtceu/data/recipe/builder/GTRecipeBuilder.java +++ b/src/main/java/com/gregtechceu/gtceu/data/recipe/builder/GTRecipeBuilder.java @@ -62,6 +62,7 @@ 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; @@ -214,7 +215,7 @@ public GTRecipeBuilder output(RecipeCapability capability, T... obj) { return this; } - public GTRecipeBuilder addCondition(RecipeCondition condition) { + public GTRecipeBuilder addCondition(RecipeCondition condition) { conditions.add(condition); recipeType.setMinRecipeConditions(conditions.size()); return this; @@ -1149,6 +1150,14 @@ public GTRecipeBuilder biome(ResourceKey biome) { return biome(biome, false); } + public GTRecipeBuilder biomeTag(TagKey biome, boolean reverse) { + return addCondition(new BiomeTagCondition(biome).setReverse(reverse)); + } + + public GTRecipeBuilder biomeTag(TagKey biome) { + return biomeTag(biome, false); + } + public GTRecipeBuilder rain(float level, boolean reverse) { return addCondition(new RainingCondition(level).setReverse(reverse)); } @@ -1187,62 +1196,112 @@ public final GTRecipeBuilder adjacentFluids(Fluid... fluids) { public final GTRecipeBuilder adjacentFluids(boolean isReverse, Fluid... fluids) { if (fluids.length > GTUtil.NON_CORNER_NEIGHBOURS.size()) { - GTCEu.LOGGER.error("Has too many fluids, not adding to recipe, id: {}", this.id); + GTCEu.LOGGER.error("Adjacent fluid condition has too many fluids, not adding to recipe. id: {}", this.id); return this; } return addCondition(AdjacentFluidCondition.fromFluids(fluids).setReverse(isReverse)); } - public final GTRecipeBuilder adjacentFluid(Fluid... fluids) { - return adjacentFluid(false, fluids); + @SafeVarargs + public final GTRecipeBuilder adjacentFluids(TagKey... tags) { + return adjacentFluids(false, tags); } - public final GTRecipeBuilder adjacentFluid(boolean isReverse, Fluid... fluids) { - if (fluids.length > GTUtil.NON_CORNER_NEIGHBOURS.size()) { - GTCEu.LOGGER.error("Has too many fluids, not adding to recipe, id: {}", this.id); + @SafeVarargs + public final GTRecipeBuilder adjacentFluids(boolean isReverse, TagKey... tags) { + if (tags.length > GTUtil.NON_CORNER_NEIGHBOURS.size()) { + GTCEu.LOGGER.error("Adjacent fluid condition has too many fluids, not adding to recipe. id: {}", this.id); return this; } - return addCondition(AdjacentFluidCondition.fromFluids(fluids).setReverse(isReverse)); + return addCondition(AdjacentFluidCondition.fromTags(tags).setReverse(isReverse)); + } + + public GTRecipeBuilder adjacentFluids(Collection> fluids) { + return adjacentFluids(fluids, false); + } + + public GTRecipeBuilder adjacentFluids(Collection> fluids, boolean isReverse) { + if (fluids.size() > GTUtil.NON_CORNER_NEIGHBOURS.size()) { + GTCEu.LOGGER.error("Adjacent fluid condition has too many fluids, not adding to recipe. id: {}", this.id); + return this; + } + return addCondition(new AdjacentFluidCondition(isReverse, List.copyOf(fluids))); + } + + /** + * @deprecated use {@link #adjacentFluids(Fluid...)} instead + */ + @ApiStatus.ScheduledForRemoval(inVersion = "8.0.0") + @Deprecated(since = "7.2.1", forRemoval = true) + public final GTRecipeBuilder adjacentFluid(Fluid... fluids) { + return adjacentFluids(fluids); } + /** + * @deprecated use {@link #adjacentFluids(boolean, Fluid...)} instead + */ + @ApiStatus.ScheduledForRemoval(inVersion = "8.0.0") + @Deprecated(since = "7.2.1", forRemoval = true) + public final GTRecipeBuilder adjacentFluid(boolean isReverse, Fluid... fluids) { + return adjacentFluids(isReverse, fluids); + } + + /** + * @deprecated use {@link #adjacentFluids(TagKey...)} instead + */ + @ApiStatus.ScheduledForRemoval(inVersion = "8.0.0") + @Deprecated(since = "7.2.1", forRemoval = true) @SafeVarargs public final GTRecipeBuilder adjacentFluidTag(TagKey... tags) { - return adjacentFluidTag(false, tags); + return adjacentFluids(tags); } + /** + * @deprecated use {@link #adjacentFluids(boolean, TagKey...)} instead + */ + @ApiStatus.ScheduledForRemoval(inVersion = "8.0.0") + @Deprecated(since = "7.2.1", forRemoval = true) @SafeVarargs public final GTRecipeBuilder adjacentFluidTag(boolean isReverse, TagKey... tags) { - if (tags.length > GTUtil.NON_CORNER_NEIGHBOURS.size()) { - GTCEu.LOGGER.error("Has too many fluids, not adding to recipe, id: {}", this.id); - return this; - } - return addCondition(AdjacentFluidCondition.fromTags(tags).setReverse(isReverse)); + return adjacentFluids(isReverse, tags); } + /** + * @deprecated use {@link #adjacentFluids(TagKey...)} instead + */ + @ApiStatus.ScheduledForRemoval(inVersion = "8.0.0") + @Deprecated(since = "7.2.1", forRemoval = true) @SafeVarargs public final GTRecipeBuilder adjacentFluid(TagKey... tags) { - return adjacentFluid(false, tags); + return adjacentFluids(tags); } + /** + * @deprecated use {@link #adjacentFluids(boolean, TagKey...)} instead + */ + @ApiStatus.ScheduledForRemoval(inVersion = "8.0.0") + @Deprecated(since = "7.2.1", forRemoval = true) @SafeVarargs public final GTRecipeBuilder adjacentFluid(boolean isReverse, TagKey... tags) { - if (tags.length > GTUtil.NON_CORNER_NEIGHBOURS.size()) { - GTCEu.LOGGER.error("Has too many fluids, not adding to recipe, id: {}", this.id); - return this; - } - return addCondition(AdjacentFluidCondition.fromTags(tags).setReverse(isReverse)); + return adjacentFluids(isReverse, tags); } + /** + * @deprecated use {@link #adjacentFluids(Collection)} instead + */ + @ApiStatus.ScheduledForRemoval(inVersion = "8.0.0") + @Deprecated(since = "7.2.1", forRemoval = true) public GTRecipeBuilder adjacentFluid(Collection> fluids) { - return adjacentFluid(fluids, false); + return adjacentFluids(fluids); } + /** + * @deprecated use {@link #adjacentFluids(Collection, boolean)} instead + */ + @ApiStatus.ScheduledForRemoval(inVersion = "8.0.0") + @Deprecated(since = "7.2.1", forRemoval = true) public GTRecipeBuilder adjacentFluid(Collection> fluids, boolean isReverse) { - if (fluids.size() > GTUtil.NON_CORNER_NEIGHBOURS.size()) { - GTCEu.LOGGER.error("Has too many fluids, not adding to recipe, id: {}", this.id); - return this; - } - return addCondition(new AdjacentFluidCondition(isReverse, new ArrayList<>(fluids))); + return adjacentFluids(fluids, isReverse); } public GTRecipeBuilder adjacentBlocks(Block... blocks) { @@ -1251,62 +1310,116 @@ public GTRecipeBuilder adjacentBlocks(Block... blocks) { public GTRecipeBuilder adjacentBlocks(boolean isReverse, Block... blocks) { if (blocks.length > GTUtil.NON_CORNER_NEIGHBOURS.size()) { - GTCEu.LOGGER.error("Has too many blocks, not adding to recipe, id: {}", this.id); + GTCEu.LOGGER.error("Adjacent block condition has too many blocks, not adding to recipe. id: {}", this.id); return this; } return addCondition(AdjacentBlockCondition.fromBlocks(blocks).setReverse(isReverse)); } + @SafeVarargs + public final GTRecipeBuilder adjacentBlocks(TagKey... tags) { + return adjacentBlocks(false, tags); + } + + @SafeVarargs + public final GTRecipeBuilder adjacentBlocks(boolean isReverse, TagKey... tags) { + if (tags.length > GTUtil.NON_CORNER_NEIGHBOURS.size()) { + GTCEu.LOGGER.error("Adjacent block condition has too many blocks, not adding to recipe. id: {}", this.id); + return this; + } + return addCondition(AdjacentBlockCondition.fromTags(tags).setReverse(isReverse)); + } + + public GTRecipeBuilder adjacentBlocks(Collection> blocks) { + return adjacentBlocks(blocks, false); + } + + public GTRecipeBuilder adjacentBlocks(Collection> blocks, boolean isReverse) { + if (blocks.size() > GTUtil.NON_CORNER_NEIGHBOURS.size()) { + GTCEu.LOGGER.error("Adjacent block condition has too many blocks, not adding to recipe. id: {}", this.id); + return this; + } + return addCondition(new AdjacentBlockCondition(isReverse, List.copyOf(blocks))); + } + + /** + * @deprecated use {@link #adjacentBlocks(Block...)} instead + */ + @ApiStatus.ScheduledForRemoval(inVersion = "8.0.0") + @Deprecated(since = "7.2.1", forRemoval = true) public GTRecipeBuilder adjacentBlock(Block... blocks) { return adjacentBlock(false, blocks); } + /** + * @deprecated use {@link #adjacentBlocks(boolean, Block...)} instead + */ + @ApiStatus.ScheduledForRemoval(inVersion = "8.0.0") + @Deprecated(since = "7.2.1", forRemoval = true) public GTRecipeBuilder adjacentBlock(boolean isReverse, Block... blocks) { if (blocks.length > GTUtil.NON_CORNER_NEIGHBOURS.size()) { - GTCEu.LOGGER.error("Has too many blocks, not adding to recipe, id: {}", this.id); + GTCEu.LOGGER.error("Adjacent block condition has too many blocks, not adding to recipe. id: {}", this.id); return this; } return addCondition(AdjacentBlockCondition.fromBlocks(blocks).setReverse(isReverse)); } + /** + * @deprecated use {@link #adjacentBlocks(TagKey...)} instead + */ + @ApiStatus.ScheduledForRemoval(inVersion = "8.0.0") + @Deprecated(since = "7.2.1", forRemoval = true) @SafeVarargs public final GTRecipeBuilder adjacentBlock(TagKey... tags) { - return adjacentBlock(false, tags); + return adjacentBlocks(tags); } + /** + * @deprecated use {@link #adjacentBlocks(boolean, TagKey...)} instead + */ + @ApiStatus.ScheduledForRemoval(inVersion = "8.0.0") + @Deprecated(since = "7.2.1", forRemoval = true) @SafeVarargs public final GTRecipeBuilder adjacentBlock(boolean isReverse, TagKey... tags) { - if (tags.length > GTUtil.NON_CORNER_NEIGHBOURS.size()) { - GTCEu.LOGGER.error("Has too many blocks, not adding to recipe, id: {}", this.id); - return this; - } - return addCondition(AdjacentBlockCondition.fromTags(tags).setReverse(isReverse)); + return adjacentBlocks(isReverse, tags); } + /** + * @deprecated use {@link #adjacentBlocks(TagKey...)} instead + */ + @ApiStatus.ScheduledForRemoval(inVersion = "8.0.0") + @Deprecated(since = "7.2.1", forRemoval = true) @SafeVarargs public final GTRecipeBuilder adjacentBlockTag(TagKey... tags) { - return adjacentBlockTag(false, tags); + return adjacentBlocks(tags); } + /** + * @deprecated use {@link #adjacentBlocks(boolean, TagKey...)} instead + */ + @ApiStatus.ScheduledForRemoval(inVersion = "8.0.0") + @Deprecated(since = "7.2.1", forRemoval = true) @SafeVarargs public final GTRecipeBuilder adjacentBlockTag(boolean isReverse, TagKey... tags) { - if (tags.length > GTUtil.NON_CORNER_NEIGHBOURS.size()) { - GTCEu.LOGGER.error("Has too many blocks, not adding to recipe, id: {}", this.id); - return this; - } - return addCondition(AdjacentBlockCondition.fromTags(tags).setReverse(isReverse)); + return adjacentBlocks(isReverse, tags); } + /** + * @deprecated use {@link #adjacentBlocks(Collection)} instead + */ + @ApiStatus.ScheduledForRemoval(inVersion = "8.0.0") + @Deprecated(since = "7.2.1", forRemoval = true) public GTRecipeBuilder adjacentBlock(Collection> blocks) { - return adjacentBlock(blocks, false); + return adjacentBlocks(blocks); } + /** + * @deprecated use {@link #adjacentBlocks(Collection, boolean)} instead + */ + @ApiStatus.ScheduledForRemoval(inVersion = "8.0.0") + @Deprecated(since = "7.2.1", forRemoval = true) public GTRecipeBuilder adjacentBlock(Collection> blocks, boolean isReverse) { - if (blocks.size() > GTUtil.NON_CORNER_NEIGHBOURS.size()) { - GTCEu.LOGGER.error("Has too many blocks, not adding to recipe, id: {}", this.id); - return this; - } - return addCondition(new AdjacentBlockCondition(isReverse, new ArrayList<>(blocks))); + return adjacentBlocks(blocks, isReverse); } public GTRecipeBuilder daytime(boolean isNight) { @@ -1692,7 +1805,7 @@ public GTRecipe buildRawRecipe() { return new GTRecipe(recipeType, id.withPrefix(recipeType.registryName.getPath() + "/"), input, output, tickInput, tickOutput, inputChanceLogic, outputChanceLogic, tickInputChanceLogic, tickOutputChanceLogic, - conditions, List.of(), data, duration, recipeCategory); + conditions, List.of(), data, duration, recipeCategory, -1); } protected void warnTooManyIngredients(RecipeCapability capability, diff --git a/src/main/java/com/gregtechceu/gtceu/data/recipe/builder/ShapedRecipeBuilder.java b/src/main/java/com/gregtechceu/gtceu/data/recipe/builder/ShapedRecipeBuilder.java index 26d6f675325..b871319e325 100644 --- a/src/main/java/com/gregtechceu/gtceu/data/recipe/builder/ShapedRecipeBuilder.java +++ b/src/main/java/com/gregtechceu/gtceu/data/recipe/builder/ShapedRecipeBuilder.java @@ -30,6 +30,7 @@ public class ShapedRecipeBuilder extends Builder provider, ItemStack smallDustStack = ChemicalHelper.get(dustSmall, material); ItemStack dustStack = ChemicalHelper.get(dust, material); - VanillaRecipeHelper.addStrictShapedRecipe(provider, + VanillaRecipeHelper.addStrictSizeShapedRecipe(provider, String.format("small_dust_disassembling_%s", material.getName()), smallDustStack.copyWithCount(4), " X", " ", 'X', new MaterialEntry(dust, material)); + VanillaRecipeHelper.addStrictSizeShapedRecipe(provider, + String.format("small_dust_disassembling_3x3_%s", material.getName()), + smallDustStack.copyWithCount(4), " X ", " ", " ", 'X', new MaterialEntry(dust, material)); VanillaRecipeHelper.addShapedRecipe(provider, String.format("small_dust_assembling_%s", material.getName()), dustStack, "XX", "XX", 'X', new MaterialEntry(dustSmall, material)); @@ -282,9 +285,12 @@ private static void processTinyDust(@NotNull Consumer provider, ItemStack tinyDustStack = ChemicalHelper.get(dustTiny, material); ItemStack dustStack = ChemicalHelper.get(dust, material); - VanillaRecipeHelper.addStrictShapedRecipe(provider, + VanillaRecipeHelper.addStrictSizeShapedRecipe(provider, String.format("tiny_dust_disassembling_%s", material.getName()), tinyDustStack.copyWithCount(9), "X ", " ", 'X', new MaterialEntry(dust, material)); + VanillaRecipeHelper.addStrictSizeShapedRecipe(provider, + String.format("tiny_dust_disassembling_3x3_%s", material.getName()), + tinyDustStack.copyWithCount(9), "X ", " ", " ", 'X', new MaterialEntry(dust, material)); VanillaRecipeHelper.addShapedRecipe(provider, String.format("tiny_dust_assembling_%s", material.getName()), dustStack, "XXX", "XXX", "XXX", 'X', new MaterialEntry(dustTiny, material)); diff --git a/src/main/java/com/gregtechceu/gtceu/data/recipe/generated/ToolRecipeHandler.java b/src/main/java/com/gregtechceu/gtceu/data/recipe/generated/ToolRecipeHandler.java index 2139209ef0b..1b809ec0bd5 100644 --- a/src/main/java/com/gregtechceu/gtceu/data/recipe/generated/ToolRecipeHandler.java +++ b/src/main/java/com/gregtechceu/gtceu/data/recipe/generated/ToolRecipeHandler.java @@ -25,6 +25,7 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.world.level.block.Blocks; import com.tterrag.registrate.util.entry.ItemEntry; import it.unimi.dsi.fastutil.ints.Int2ReferenceArrayMap; @@ -63,14 +64,19 @@ public static void run(@NotNull Consumer provider, @NotNull Mate } private static void processTool(@NotNull Consumer provider, @NotNull Material material) { + ItemStack stick = new ItemStack(Items.STICK); + MaterialEntry ingot = new MaterialEntry( + material.hasProperty(PropertyKey.GEM) ? TagPrefix.gem : TagPrefix.ingot, material); + addToolRecipe(provider, material, GTToolType.MORTAR, false, + " I ", "SIS", "SSS", + 'I', ingot, + 'S', new ItemStack(Blocks.STONE)); + if (!material.shouldGenerateRecipesFor(plate)) { return; } - ItemStack stick = new ItemStack(Items.STICK); MaterialEntry plate = new MaterialEntry(TagPrefix.plate, material); - MaterialEntry ingot = new MaterialEntry( - material.hasProperty(PropertyKey.GEM) ? TagPrefix.gem : TagPrefix.ingot, material); if (material.hasFlag(GENERATE_PLATE)) { addToolRecipe(provider, material, GTToolType.MINING_HAMMER, true, @@ -195,6 +201,8 @@ private static void processTool(@NotNull Consumer provider, @Not GTCEu.LOGGER.warn("Did not find rod for " + material.getName() + ", skipping wirecutter, butchery knife, screwdriver, crowbar recipes"); } + + GTToolType.getTypes().forEach((s, gtToolType) -> addNetheriteToolRecipe(provider, gtToolType)); } private static void processElectricTool(@NotNull Consumer provider, @NotNull ToolProperty property, @@ -350,6 +358,11 @@ public static void addToolRecipe(@NotNull Consumer provider, @No } } + public static void addNetheriteToolRecipe(@NotNull Consumer provider, @NotNull GTToolType tool) { + VanillaRecipeHelper.addToolUpgradingRecipe(provider, tool, GTMaterials.Netherite, GTMaterials.Diamond, + Items.NETHERITE_UPGRADE_SMITHING_TEMPLATE, ChemicalHelper.get(ingot, GTMaterials.Netherite).getItem()); + } + public static void addArmorRecipe(Consumer provider, @NotNull Material material, @NotNull ArmorItem.Type armor, Object... recipe) { ItemStack armorStack = ToolHelper.getArmor(armor, material); diff --git a/src/main/java/com/gregtechceu/gtceu/data/recipe/misc/CircuitRecipes.java b/src/main/java/com/gregtechceu/gtceu/data/recipe/misc/CircuitRecipes.java index ea1ca537eff..36f3b7e7a2e 100644 --- a/src/main/java/com/gregtechceu/gtceu/data/recipe/misc/CircuitRecipes.java +++ b/src/main/java/com/gregtechceu/gtceu/data/recipe/misc/CircuitRecipes.java @@ -3,6 +3,7 @@ import com.gregtechceu.gtceu.api.data.chemical.material.MarkerMaterials.Color; import com.gregtechceu.gtceu.api.data.chemical.material.stack.MaterialEntry; import com.gregtechceu.gtceu.api.machine.multiblock.CleanroomType; +import com.gregtechceu.gtceu.common.data.GTRecipeCategories; import com.gregtechceu.gtceu.config.ConfigHolder; import com.gregtechceu.gtceu.data.recipe.CustomTags; import com.gregtechceu.gtceu.data.recipe.VanillaRecipeHelper; @@ -338,6 +339,7 @@ private static void componentRecipes(Consumer provider) { .inputItems(dust, Glass) .notConsumable(SHAPE_MOLD_BALL) .outputItems(GLASS_TUBE) + .category(GTRecipeCategories.INGOT_MOLDING) .duration(160).EUt(16).save(provider); FLUID_SOLIDFICATION_RECIPES.recipeBuilder("solidify_glass_tube") diff --git a/src/main/java/com/gregtechceu/gtceu/data/recipe/misc/CustomToolRecipes.java b/src/main/java/com/gregtechceu/gtceu/data/recipe/misc/CustomToolRecipes.java index 2d94a1c84ca..a5510ac10c5 100644 --- a/src/main/java/com/gregtechceu/gtceu/data/recipe/misc/CustomToolRecipes.java +++ b/src/main/java/com/gregtechceu/gtceu/data/recipe/misc/CustomToolRecipes.java @@ -130,7 +130,6 @@ private static void registerPowerUnitRecipes(@NotNull Consumer p private static void registerCustomToolRecipes(@NotNull Consumer provider) { registerFlintToolRecipes(provider); - registerMortarRecipes(provider); registerSoftToolRecipes(provider); registerElectricRecipes(provider); @@ -178,20 +177,6 @@ private static void registerFlintToolRecipes(@NotNull Consumer p 'S', stick); } - private static void registerMortarRecipes(@NotNull Consumer provider) { - for (Material material : new Material[] { - GTMaterials.Bronze, GTMaterials.Iron, GTMaterials.Invar, GTMaterials.Steel, - GTMaterials.DamascusSteel, GTMaterials.CobaltBrass, GTMaterials.WroughtIron }) { - - addToolRecipe(provider, material, GTToolType.MORTAR, false, - " I ", "SIS", "SSS", - 'I', - new MaterialEntry(material.hasProperty(PropertyKey.GEM) ? TagPrefix.gem : TagPrefix.ingot, - material), - 'S', new ItemStack(Blocks.STONE)); - } - } - private static void registerSoftToolRecipes(@NotNull Consumer provider) { final ItemStack stick = new ItemStack(Items.STICK); diff --git a/src/main/java/com/gregtechceu/gtceu/data/recipe/misc/MiscRecipeLoader.java b/src/main/java/com/gregtechceu/gtceu/data/recipe/misc/MiscRecipeLoader.java index df745a5e92b..8ea508e563c 100644 --- a/src/main/java/com/gregtechceu/gtceu/data/recipe/misc/MiscRecipeLoader.java +++ b/src/main/java/com/gregtechceu/gtceu/data/recipe/misc/MiscRecipeLoader.java @@ -89,7 +89,7 @@ public static void init(Consumer provider) { ROCK_BREAKER_RECIPES.recipeBuilder("cobblestone") .notConsumable(Blocks.COBBLESTONE.asItem()) .outputItems(Blocks.COBBLESTONE.asItem()) - .adjacentFluidTag(FluidTags.LAVA, FluidTags.WATER) + .adjacentFluids(FluidTags.LAVA, FluidTags.WATER) .duration(16) .EUt(VA[ULV]) .save(provider); @@ -97,7 +97,7 @@ public static void init(Consumer provider) { ROCK_BREAKER_RECIPES.recipeBuilder("stone") .notConsumable(Blocks.STONE.asItem()) .outputItems(Blocks.STONE.asItem()) - .adjacentFluidTag(FluidTags.LAVA, FluidTags.WATER) + .adjacentFluids(FluidTags.LAVA, FluidTags.WATER) .duration(16) .EUt(VA[ULV]) .save(provider); @@ -105,7 +105,7 @@ public static void init(Consumer provider) { ROCK_BREAKER_RECIPES.recipeBuilder("andesite") .notConsumable(Blocks.ANDESITE.asItem()) .outputItems(Blocks.ANDESITE.asItem()) - .adjacentFluidTag(FluidTags.LAVA, FluidTags.WATER) + .adjacentFluids(FluidTags.LAVA, FluidTags.WATER) .duration(16) .EUt(VHA[MV]) .save(provider); @@ -113,7 +113,7 @@ public static void init(Consumer provider) { ROCK_BREAKER_RECIPES.recipeBuilder("granite") .notConsumable(Blocks.GRANITE.asItem()) .outputItems(Blocks.GRANITE.asItem()) - .adjacentFluidTag(FluidTags.LAVA, FluidTags.WATER) + .adjacentFluids(FluidTags.LAVA, FluidTags.WATER) .duration(16) .EUt(VHA[MV]) .save(provider); @@ -121,7 +121,7 @@ public static void init(Consumer provider) { ROCK_BREAKER_RECIPES.recipeBuilder("diorite") .notConsumable(Blocks.DIORITE.asItem()) .outputItems(Blocks.DIORITE.asItem()) - .adjacentFluidTag(FluidTags.LAVA, FluidTags.WATER) + .adjacentFluids(FluidTags.LAVA, FluidTags.WATER) .duration(16) .EUt(VHA[MV]) .save(provider); @@ -129,7 +129,7 @@ public static void init(Consumer provider) { ROCK_BREAKER_RECIPES.recipeBuilder("obsidian") .notConsumable(dust, Redstone) .outputItems(Blocks.OBSIDIAN.asItem()) - .adjacentFluidTag(FluidTags.LAVA, FluidTags.WATER) + .adjacentFluids(FluidTags.LAVA, FluidTags.WATER) .duration(16) .EUt(VHA[HV]) .save(provider); @@ -137,7 +137,7 @@ public static void init(Consumer provider) { ROCK_BREAKER_RECIPES.recipeBuilder("basalt") .notConsumable(Blocks.BASALT.asItem()) .outputItems(Blocks.BASALT.asItem()) - .adjacentFluidTag(FluidTags.LAVA, FluidTags.WATER) + .adjacentFluids(FluidTags.LAVA, FluidTags.WATER) .duration(16) .EUt(VHA[HV]) .save(provider); @@ -145,7 +145,7 @@ public static void init(Consumer provider) { ROCK_BREAKER_RECIPES.recipeBuilder("blackstone") .notConsumable(Blocks.BLACKSTONE.asItem()) .outputItems(Blocks.BLACKSTONE.asItem()) - .adjacentFluidTag(FluidTags.LAVA, FluidTags.WATER) + .adjacentFluids(FluidTags.LAVA, FluidTags.WATER) .duration(16) .EUt(VHA[HV]) .save(provider); @@ -153,7 +153,7 @@ public static void init(Consumer provider) { ROCK_BREAKER_RECIPES.recipeBuilder("deepslate") .notConsumable(Blocks.DEEPSLATE.asItem()) .outputItems(Blocks.DEEPSLATE.asItem()) - .adjacentFluidTag(FluidTags.LAVA, FluidTags.WATER) + .adjacentFluids(FluidTags.LAVA, FluidTags.WATER) .duration(16) .EUt(VHA[EV]) .save(provider); @@ -161,7 +161,7 @@ public static void init(Consumer provider) { ROCK_BREAKER_RECIPES.recipeBuilder("marble") .notConsumable(rock, Marble) .outputItems(rock, Marble) - .adjacentFluidTag(FluidTags.LAVA, FluidTags.WATER) + .adjacentFluids(FluidTags.LAVA, FluidTags.WATER) .duration(16) .EUt(VHA[HV]) .save(provider); @@ -169,7 +169,7 @@ public static void init(Consumer provider) { ROCK_BREAKER_RECIPES.recipeBuilder("basalt") .notConsumable(rock, Basalt) .outputItems(rock, Basalt) - .adjacentFluidTag(FluidTags.LAVA, FluidTags.WATER) + .adjacentFluids(FluidTags.LAVA, FluidTags.WATER) .duration(16) .EUt(VHA[HV]) .save(provider); @@ -177,7 +177,7 @@ public static void init(Consumer provider) { ROCK_BREAKER_RECIPES.recipeBuilder("red_granite") .notConsumable(rock, GraniteRed) .outputItems(rock, GraniteRed) - .adjacentFluidTag(FluidTags.LAVA, FluidTags.WATER) + .adjacentFluids(FluidTags.LAVA, FluidTags.WATER) .duration(16) .EUt(VHA[EV]) .save(provider); @@ -401,6 +401,7 @@ public static void init(Consumer provider) { .inputItems(dust, Glass, 2) .notConsumable(SHAPE_MOLD_PLATE) .outputItems(plate, Glass) + .category(GTRecipeCategories.INGOT_MOLDING) .duration(40).EUt(6).save(provider); // Dyed Lens Recipes diff --git a/src/main/java/com/gregtechceu/gtceu/data/recipe/misc/VanillaStandardRecipes.java b/src/main/java/com/gregtechceu/gtceu/data/recipe/misc/VanillaStandardRecipes.java index 7543739d90e..7d996a54f0b 100644 --- a/src/main/java/com/gregtechceu/gtceu/data/recipe/misc/VanillaStandardRecipes.java +++ b/src/main/java/com/gregtechceu/gtceu/data/recipe/misc/VanillaStandardRecipes.java @@ -225,6 +225,7 @@ private static void glassRecipes(Consumer provider) { .inputItems(dust, Glass) .notConsumable(SHAPE_MOLD_BOTTLE) .outputItems(new ItemStack(Items.GLASS_BOTTLE)) + .category(GTRecipeCategories.INGOT_MOLDING) .addMaterialInfo(true) .save(provider); @@ -250,6 +251,7 @@ private static void glassRecipes(Consumer provider) { .inputItems(dust, Glass) .notConsumable(SHAPE_MOLD_BLOCK) .outputItems(new ItemStack(Blocks.GLASS, 1)) + .category(GTRecipeCategories.INGOT_MOLDING) .save(provider); CUTTER_RECIPES.recipeBuilder("cut_glass_block_to_plate").duration(50).EUt(VA[ULV]) diff --git a/src/main/java/com/gregtechceu/gtceu/data/recipe/serialized/chemistry/GemSlurryRecipes.java b/src/main/java/com/gregtechceu/gtceu/data/recipe/serialized/chemistry/GemSlurryRecipes.java index 801caa333a5..9dd5dbfc532 100644 --- a/src/main/java/com/gregtechceu/gtceu/data/recipe/serialized/chemistry/GemSlurryRecipes.java +++ b/src/main/java/com/gregtechceu/gtceu/data/recipe/serialized/chemistry/GemSlurryRecipes.java @@ -14,12 +14,18 @@ public class GemSlurryRecipes { public static void init(Consumer provider) { // Ruby - MIXER_RECIPES.recipeBuilder("ruby_slurry").duration(280).EUt(VA[EV]) + MIXER_RECIPES.recipeBuilder("ruby_slurry_from_crushed_ruby").duration(280).EUt(VA[EV]) .inputItems(crushed, Ruby, 2) .inputFluids(AquaRegia.getFluid(3000)) .outputFluids(RubySlurry.getFluid(3000)) .save(provider); + MIXER_RECIPES.recipeBuilder("ruby_slurry_from_washed_ruby").duration(280).EUt(VA[EV]) + .inputItems(crushedPurified, Ruby, 2) + .inputFluids(AquaRegia.getFluid(3000)) + .outputFluids(RubySlurry.getFluid(3000)) + .save(provider); + CENTRIFUGE_RECIPES.recipeBuilder("ruby_slurry_centrifuging").duration(320).EUt(VA[HV]) .inputFluids(RubySlurry.getFluid(3000)) .outputItems(dust, Aluminium, 2) @@ -31,12 +37,18 @@ public static void init(Consumer provider) { .save(provider); // Sapphire - MIXER_RECIPES.recipeBuilder("sapphire_slurry").duration(280).EUt(VA[EV]) + MIXER_RECIPES.recipeBuilder("sapphire_slurry_from_crushed_sapphire").duration(280).EUt(VA[EV]) .inputItems(crushed, Sapphire, 2) .inputFluids(AquaRegia.getFluid(3000)) .outputFluids(SapphireSlurry.getFluid(3000)) .save(provider); + MIXER_RECIPES.recipeBuilder("sapphire_slurry_from_washed_sapphire").duration(280).EUt(VA[EV]) + .inputItems(crushedPurified, Sapphire, 2) + .inputFluids(AquaRegia.getFluid(3000)) + .outputFluids(SapphireSlurry.getFluid(3000)) + .save(provider); + CENTRIFUGE_RECIPES.recipeBuilder("sapphire_slurry_centrifuging").duration(320).EUt(VA[HV]) .inputFluids(SapphireSlurry.getFluid(3000)) .outputItems(dust, Aluminium, 2) @@ -47,12 +59,18 @@ public static void init(Consumer provider) { .save(provider); // Green Sapphire - MIXER_RECIPES.recipeBuilder("green_sapphire_slurry").duration(280).EUt(VA[EV]) + MIXER_RECIPES.recipeBuilder("green_sapphire_slurry_from_crushed_green_sapphire").duration(280).EUt(VA[EV]) .inputItems(crushed, GreenSapphire, 2) .inputFluids(AquaRegia.getFluid(3000)) .outputFluids(GreenSapphireSlurry.getFluid(3000)) .save(provider); + MIXER_RECIPES.recipeBuilder("green_sapphire_slurry_from_washed_green_sapphire").duration(280).EUt(VA[EV]) + .inputItems(crushedPurified, GreenSapphire, 2) + .inputFluids(AquaRegia.getFluid(3000)) + .outputFluids(GreenSapphireSlurry.getFluid(3000)) + .save(provider); + CENTRIFUGE_RECIPES.recipeBuilder("green_sapphire_slurry_centrifuging").duration(320).EUt(VA[HV]) .inputFluids(GreenSapphireSlurry.getFluid(3000)) .outputItems(dust, Aluminium, 2) 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/integration/kjs/recipe/GTRecipeSchema.java b/src/main/java/com/gregtechceu/gtceu/integration/kjs/recipe/GTRecipeSchema.java index 61ab2a31211..280c5d5aba5 100644 --- a/src/main/java/com/gregtechceu/gtceu/integration/kjs/recipe/GTRecipeSchema.java +++ b/src/main/java/com/gregtechceu/gtceu/integration/kjs/recipe/GTRecipeSchema.java @@ -974,6 +974,14 @@ public GTRecipeJS biome(ResourceKey biome) { return biome(biome, false); } + public GTRecipeJS biomeTag(ResourceLocation biome, boolean reverse) { + return addCondition(new BiomeTagCondition(TagKey.create(Registries.BIOME, biome)).setReverse(reverse)); + } + + public GTRecipeJS biomeTag(ResourceLocation biome) { + return biomeTag(biome, false); + } + public GTRecipeJS rain(float level, boolean reverse) { return addCondition(new RainingCondition(level).setReverse(reverse)); } @@ -1014,25 +1022,6 @@ public GTRecipeJS adjacentFluids(boolean isReverse, Fluid... fluids) { return addCondition(AdjacentFluidCondition.fromFluids(fluids).setReverse(isReverse)); } - public GTRecipeJS adjacentFluid(Fluid... fluids) { - return adjacentFluid(false, fluids); - } - - public GTRecipeJS adjacentFluid(boolean isReverse, Fluid... fluids) { - return addCondition(AdjacentFluidCondition.fromFluids(fluids).setReverse(isReverse)); - } - - public GTRecipeJS adjacentFluid(ResourceLocation... tagNames) { - return adjacentFluid(false, tagNames); - } - - public GTRecipeJS adjacentFluid(boolean isReverse, ResourceLocation... tagNames) { - List> tags = Arrays.stream(tagNames) - .map(id -> TagKey.create(Registries.FLUID, id)) - .toList(); - return addCondition(AdjacentFluidCondition.fromTags(tags).setReverse(isReverse)); - } - public GTRecipeJS adjacentFluidTag(ResourceLocation... tagNames) { return adjacentFluidTag(false, tagNames); } @@ -1052,14 +1041,6 @@ public GTRecipeJS adjacentBlocks(boolean isReverse, Block... blocks) { return addCondition(AdjacentBlockCondition.fromBlocks(blocks).setReverse(isReverse)); } - public GTRecipeJS adjacentBlock(Block... blocks) { - return adjacentBlock(false, blocks); - } - - public GTRecipeJS adjacentBlock(boolean isReverse, Block... blocks) { - return addCondition(AdjacentBlockCondition.fromBlocks(blocks).setReverse(isReverse)); - } - public GTRecipeJS adjacentBlockTag(ResourceLocation... tagNames) { return adjacentBlockTag(false, tagNames); } @@ -1071,17 +1052,6 @@ public GTRecipeJS adjacentBlockTag(boolean isReverse, ResourceLocation... tagNam return addCondition(AdjacentBlockCondition.fromTags(tags).setReverse(isReverse)); } - public GTRecipeJS adjacentBlock(ResourceLocation... tagNames) { - return adjacentBlock(false, tagNames); - } - - public GTRecipeJS adjacentBlock(boolean isReverse, ResourceLocation... tagNames) { - List> tags = Arrays.stream(tagNames) - .map(id -> TagKey.create(Registries.BLOCK, id)) - .toList(); - return addCondition(AdjacentBlockCondition.fromTags(tags).setReverse(isReverse)); - } - public GTRecipeJS daytime(boolean isNight) { return addCondition(new DaytimeCondition().setReverse(isNight)); } 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 81cf922611e..61a1c8e3cfd 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/RegistryUtil.java b/src/main/java/com/gregtechceu/gtceu/utils/RegistryUtil.java deleted file mode 100644 index 41d5ea6df1c..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/utils/RegistryUtil.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.gregtechceu.gtceu.utils; - -import net.minecraft.MethodsReturnNonnullByDefault; -import net.minecraft.core.Registry; -import net.minecraft.resources.ResourceKey; -import net.minecraft.resources.ResourceLocation; - -import java.util.Arrays; -import java.util.List; - -import javax.annotation.ParametersAreNonnullByDefault; - -@MethodsReturnNonnullByDefault -@ParametersAreNonnullByDefault -public class RegistryUtil { - - private RegistryUtil() {} - - public static List> resolveResourceKeys(ResourceKey> registryKey, - String... locations) { - return Arrays.stream(locations) - .map(location -> ResourceKey.create(registryKey, new ResourceLocation(location))) - .toList(); - } -} 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/data/RuntimeExistingFileHelper.java b/src/main/java/com/gregtechceu/gtceu/utils/data/RuntimeExistingFileHelper.java index e6e7c50d4c4..f2d04d3629d 100644 --- a/src/main/java/com/gregtechceu/gtceu/utils/data/RuntimeExistingFileHelper.java +++ b/src/main/java/com/gregtechceu/gtceu/utils/data/RuntimeExistingFileHelper.java @@ -12,7 +12,7 @@ import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; -import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.io.FileNotFoundException; import java.util.Collections; @@ -23,25 +23,41 @@ /** * Existing file helper that wraps the client/server resource manager instead of creating its own.
    * Useful for using data generators outside datagen. + *

    + * By default, this class assumes all resources exist and does not check any references' validity. + * To enable actual checking, you may use a try-with-resources statement like this: + * + *

    {@code
    + * try (var helper = RuntimeExistingFileHelper.INSTANCE.activeHelper()) {
    + *     // If you don't use a try-with-resources or try-finally block to
    + *     // enable checking, calling `exists` will always return true.
    + *     if (helper.exists(texture, GTBlockstateProvider.TEXTURE)) {
    + *         // do stuff
    + *     }
    + * }
    + * }
    + * */ @ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault public class RuntimeExistingFileHelper extends ExistingFileHelper { - public static final RuntimeExistingFileHelper INSTANCE = new RuntimeExistingFileHelper(); + public static final RuntimeExistingFileHelper INSTANCE = new RuntimeExistingFileHelper(HashMultimap.create()); - protected final Multimap generated = HashMultimap.create(); + protected final Multimap generated; + protected @Nullable Active activeHelper; - protected RuntimeExistingFileHelper() { + protected RuntimeExistingFileHelper(Multimap generated) { super(Collections.emptySet(), Collections.emptySet(), false, null, null); + this.generated = generated; } - public static @NotNull ResourceManager getManager(PackType packType) { + public static ResourceManager getManager(PackType packType) { if (packType == PackType.CLIENT_RESOURCES) { return Minecraft.getInstance().getResourceManager(); } else if (packType == PackType.SERVER_DATA) { if (GTCEu.getMinecraftServer() == null) { - throw new IllegalStateException("Cannot get server resources without a server or on a remote client."); + throw new IllegalStateException("Cannot get server resources without a server / on a remote client."); } return GTCEu.getMinecraftServer().getResourceManager(); } else { @@ -53,11 +69,26 @@ protected ResourceLocation getLocation(ResourceLocation base, String prefix, Str return base.withPath(path -> prefix + "/" + path + suffix); } + public RuntimeExistingFileHelper.Active activeHelper() { + if (this.activeHelper == null) { + // pass the same generated resources map into the subclass + // so any resources added/checked by it are automatically updated here + this.activeHelper = new Active(this.generated); + } + return this.activeHelper; + } + + /** + * Bypass the normal {@code exists} function so missing/invalid references etc. don't cause runtime errors.
    + * A toggle for enabling proper functionality is implemented in the form of {@link #activeHelper()}- + */ @Override public boolean exists(ResourceLocation loc, PackType packType) { - return generated.get(packType).contains(loc) || getManager(packType).getResource(loc).isPresent(); + return true; } + /// Implement a copy of the normal {@code exists} function that we can use for checking + @Override public void trackGenerated(ResourceLocation loc, IResourceType type) { trackGenerated(loc, type.getPackType(), type.getSuffix(), type.getPrefix()); @@ -83,4 +114,31 @@ public Resource getResource(ResourceLocation loc, PackType packType) throws File public List getResourceStack(ResourceLocation loc, PackType packType) { return getManager(packType).getResourceStack(loc); } + + /** + * This class implements {@link AutoCloseable} for ease of enabling actual checking when it is required. + *

    + * Note that it's safe to ignore "unclosed AutoCloseable"/{@code resource} warnings on this class, as is done in + * {@linkplain com.gregtechceu.gtceu.client.model.machine.overlays.WorkableOverlays#get WorkableOverlays#get}. + *

    + */ + public static class Active extends RuntimeExistingFileHelper implements AutoCloseable { + + protected Active(Multimap parentGenerated) { + super(parentGenerated); + } + + @Override + public Active activeHelper() { + return this; + } + + @Override + public boolean exists(ResourceLocation loc, PackType packType) { + return this.generated.get(packType).contains(loc) || getManager(packType).getResource(loc).isPresent(); + } + + @Override + public void close() {} + } } diff --git a/src/main/java/com/gregtechceu/gtceu/utils/dev/ResourceReloadDetector.java b/src/main/java/com/gregtechceu/gtceu/utils/dev/ResourceReloadDetector.java new file mode 100644 index 00000000000..64baf26b5a7 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/utils/dev/ResourceReloadDetector.java @@ -0,0 +1,68 @@ +package com.gregtechceu.gtceu.utils.dev; + +import com.gregtechceu.gtceu.GTCEu; +import com.gregtechceu.gtceu.config.ConfigHolder; + +import net.minecraft.Util; +import net.minecraft.client.Minecraft; +import net.minecraft.network.chat.Component; + +import com.sun.jna.platform.win32.*; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Nullable; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.time.Duration; +import java.time.Instant; +import java.util.concurrent.CompletableFuture; +import java.util.function.Supplier; + +@ApiStatus.Internal +public class ResourceReloadDetector { + + private static final Path gradleDir = findGradleDir(); + + @ApiStatus.Internal + public static CompletableFuture regenerateResourcesOnReload(Supplier> reloadFuture) { + if (!ConfigHolder.INSTANCE.dev.autoRebuildResources || !GTCEu.isDev() || gradleDir == null) { + return reloadFuture.get(); + } + ProcessBuilder builder = switch (Util.getPlatform()) { + case WINDOWS -> new ProcessBuilder("cmd.exe", "/c", "gradlew.bat", ":processResources"); + default -> new ProcessBuilder("./gradlew", ":processResources"); + }; + builder.directory(gradleDir.toFile()); + builder.inheritIO(); + Process process; + try { + process = builder.start(); + } catch (IOException exception) { + GTCEu.LOGGER.error("Cound not run ./gradlew :processResources", exception); + GTCEu.LOGGER.error("Message the GTCEu developers about this!"); + return reloadFuture.get(); + } + Minecraft.getInstance().player.sendSystemMessage(Component.translatable("gtceu.debug.resource_rebuild.start")); + Instant start = Instant.now(); + // wait for the resource reload to finish, then send chat message, then let MC actually reload resources + return process.toHandle().onExit() + .thenRun(() -> Minecraft.getInstance().player + .sendSystemMessage(Component.translatable("gtceu.debug.resource_rebuild.done", + Duration.between(start, Instant.now())))) + .thenCompose($ -> reloadFuture.get()); + } + + private static @Nullable Path findGradleDir() { + Path path = Path.of(".").toAbsolutePath(); + do { + if (Files.isRegularFile(path.resolve("settings.gradle")) || + Files.isRegularFile(path.resolve("settings.gradle.kts"))) { + return path; + } + path = path.getParent(); + } while (path.getParent() != null); + + return null; + } +} 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/lang/zh_cn.json b/src/main/resources/assets/gtceu/lang/zh_cn.json index ca9c93f6ff7..057f5ffa80c 100644 --- a/src/main/resources/assets/gtceu/lang/zh_cn.json +++ b/src/main/resources/assets/gtceu/lang/zh_cn.json @@ -64,8 +64,16 @@ "behaviour.lighter.tooltip.description": "可以点火", "behaviour.lighter.tooltip.usage": "潜行右击以开/关", "behaviour.lighter.uses": "剩余次数:%d", - "behaviour.meta.machine.config.copy.tooltip": "§7潜行右键单击以复制机器配置", - "behaviour.meta.machine.config.paste.tooltip": "§7右键单击以粘贴机器配置", + "behaviour.memory_card.client_msg.cleared": "已清除存储的配置", + "behaviour.memory_card.client_msg.copied": "已复制机器配置", + "behaviour.memory_card.client_msg.pasted": "已应用机器配置", + "behaviour.memory_card.copy_target": "复制源:%s", + "behaviour.memory_card.disabled": "§c已禁用§r", + "behaviour.memory_card.enabled": "§a已启用§r", + "behaviour.memory_card.tooltip.copy": "§7潜行+右键单击机器或管道复制配置,单击其他方块则会清除数据", + "behaviour.memory_card.tooltip.items_to_paste": "应用此配置需要以下物品:", + "behaviour.memory_card.tooltip.paste": "§7右键单击以粘贴机器配置", + "behaviour.memory_card.tooltip.view_stored": "§8<潜行以查看存储的配置>", "behaviour.paintspray.black.tooltip": "可以将物品染成黑色", "behaviour.paintspray.blue.tooltip": "可以将物品染成蓝色", "behaviour.paintspray.brown.tooltip": "可以将物品染成棕色", @@ -85,10 +93,15 @@ "behaviour.paintspray.white.tooltip": "可以将物品染成白色", "behaviour.paintspray.yellow.tooltip": "可以将物品染成黄色", "behaviour.prospecting": "适用于探矿", - "behaviour.setting.allow.input.from.output.tooltip": "%s-允许从输出面输入:%s", - "behaviour.setting.item_auto_output.tooltip": "%s-自动输出:%s", - "behaviour.setting.muffled.tooltip": "静音:%s", - "behaviour.setting.output.direction.tooltip": "%s-输出面方向:%s", + "behaviour.setting.tooltip.allow_input": "§2允许输入§r", + "behaviour.setting.tooltip.auto_output": "§2自动输出§r", + "behaviour.setting.tooltip.auto_output_allow_input": "§2自动输出/允许输入§r", + "behaviour.setting.tooltip.circuit_config": "编程电路:", + "behaviour.setting.tooltip.fluid_io": "流体输出:%s(%s)", + "behaviour.setting.tooltip.item_io": "物品输出:%s(%s)", + "behaviour.setting.tooltip.muffled": "静音%s", + "behaviour.setting.tooltip.pipe_blocked_connections": "管道禁入:%s", + "behaviour.setting.tooltip.pipe_connections": "管道连接:%s", "behaviour.soft_hammer": "用来开启与关闭机器", "behaviour.soft_hammer.disabled": "已暂停工作", "behaviour.soft_hammer.disabled_cycle": "本运行周期后暂停工作", @@ -1731,7 +1744,6 @@ "command.gtceu.share_prospection_data.notification": "%s向你分享了矿脉数据!", "config.gtceu.option.addLoot": "添加战利品", "config.gtceu.option.ae2": "ae2", - "config.gtceu.option.allUniqueStoneTypes": "所有独特石头类型", "config.gtceu.option.allowDrumsInputFluidsFromOutputSide": "允许桶从输出面输入流体", "config.gtceu.option.animationTime": "动画时间", "config.gtceu.option.arcRecyclingYield": "电弧炉回收率", @@ -1880,6 +1892,7 @@ "config.gtceu.option.steelSteamMultiblocks": "用钢的蒸汽多方块结构", "config.gtceu.option.surfaceRockProspectRange": "地表岩石探测半径", "config.gtceu.option.tankItemFluidPreview": "储罐流体预览", + "config.gtceu.option.temperaturesInKelvin": "开尔文温度", "config.gtceu.option.titaniumBoilerHeatSpeed": "钛锅炉-加热速度", "config.gtceu.option.titaniumBoilerMaxTemperature": "钛锅炉-最高温度", "config.gtceu.option.toggle": "切换", @@ -1906,6 +1919,7 @@ "config.gtceu.option.yOffset": "y偏移", "config.gtceu.option.zombieSpawnWithSabers": "带纳米剑的僵尸生成", "config.jade.plugin_gtceu.auto_output_info": "[GTCEu] 自动输出信息", + "config.jade.plugin_gtceu.battery_info": "[GTCEu] 电池信息", "config.jade.plugin_gtceu.cable_info": "[GTCEu] 线缆信息", "config.jade.plugin_gtceu.controllable_provider": "[GTCEu] 是否停工", "config.jade.plugin_gtceu.data_bank": "[GTCEu] 数据库信息", @@ -1913,6 +1927,7 @@ "config.jade.plugin_gtceu.energy_converter_provider": "[GTCEu] 能量转换器模式", "config.jade.plugin_gtceu.exhaust_vent_info": "[GTCEu] 排气口信息", "config.jade.plugin_gtceu.hazard_cleaner_provider": "[GTCEu] 污染清理", + "config.jade.plugin_gtceu.ldp_endpoint": "[GTCEu] 长距离管道接口信息", "config.jade.plugin_gtceu.machine_mode": "[GTCEu] 机器模式", "config.jade.plugin_gtceu.maintenance_info": "[GTCEu] 维护信息", "config.jade.plugin_gtceu.me_pattern_buffer": "[GTCEu] 样板总成信息", @@ -1961,7 +1976,7 @@ "cover.advanced_fluid_detector.invert.enabled.1": "", "cover.advanced_fluid_detector.invert.enabled.2": "切换以反转红石逻辑", "cover.advanced_fluid_detector.invert.enabled.3": "默认情况下,流体量介于所设定的最小值和最大值之间时覆盖板将发出红石信号,小于最小值时则停止发出红石信号", - "cover.advanced_fluid_detector.label": "进阶流体探测器", + "cover.advanced_fluid_detector.label": "进阶流体探测覆盖板", "cover.advanced_fluid_detector.max": "最大流体量(mB)", "cover.advanced_fluid_detector.min": "最小流体量(mB)", "cover.advanced_item_detector.invert.disabled.0": "输出:普通", @@ -1972,7 +1987,7 @@ "cover.advanced_item_detector.invert.enabled.1": "", "cover.advanced_item_detector.invert.enabled.2": "切换以反转红石逻辑", "cover.advanced_item_detector.invert.enabled.3": "默认情况下,物品数量介于所设定的最小值和最大值之间时覆盖板将发出红石信号,小于最小值时则停止发出红石信号", - "cover.advanced_item_detector.label": "进阶物品探测器", + "cover.advanced_item_detector.label": "进阶物品探测覆盖板", "cover.advanced_item_detector.max": "最大物品数量", "cover.advanced_item_detector.min": "最小物品数量", "cover.bucket.mode.bucket": "B", @@ -2293,8 +2308,10 @@ "gtceu.electrolyzer": "电解机", "gtceu.electromagnetic_separator": "电磁选矿机", "gtceu.ender_item_link_cover.title": "末影物品连接", + "gtceu.ender_item_link_cover.tooltip": "作§f覆盖板§7时利用§f无线§7§d末影§f连接§7传输§f物品§7。", "gtceu.ender_redstone_link_cover.label": "红石信号强度:%d", "gtceu.ender_redstone_link_cover.title": "末影红石连接", + "gtceu.ender_redstone_link_cover.tooltip": "作§f覆盖板§7时利用§f无线§7§d末影§f连接§7传输§f红石信号§7。", "gtceu.extractor": "提取机", "gtceu.extruder": "压模器", "gtceu.fermenter": "发酵槽", @@ -2312,7 +2329,7 @@ "gtceu.fluid.state_gas": "§a状态:气态", "gtceu.fluid.state_liquid": "§a状态:液态", "gtceu.fluid.state_plasma": "§a状态:等离子态", - "gtceu.fluid.temperature": "§c温度:%d", + "gtceu.fluid.temperature": "§c温度:%s", "gtceu.fluid.temperature.cryogenic": "§b低温流体!轻拿轻放!", "gtceu.fluid.type_acid.tooltip": "§6酸性流体!轻拿轻放!", "gtceu.fluid_heater": "流体加热器", @@ -2394,6 +2411,8 @@ "gtceu.gui.content.units.per_second": "/s", "gtceu.gui.content.units.per_tick": "/t", "gtceu.gui.cover_setting.title": "覆盖板设置", + "gtceu.gui.directional_setting.tab_tooltip": "更改方向设置", + "gtceu.gui.directional_setting.title": "方向设置", "gtceu.gui.editor.group.recipe_type": "封顶", "gtceu.gui.editor.tips.citation": "引用次数", "gtceu.gui.fisher_mode.tooltip.0": "捕捉垃圾物品", @@ -2486,12 +2505,20 @@ "gtceu.item_pipe.priority": "§9优先级:§f%d", "gtceu.jade.amperage_use": "%s A", "gtceu.jade.at": " @ ", + "gtceu.jade.changes_eu_sec": "%sEU/s", "gtceu.jade.cleaned_this_second": "污染清理速率:%s/s", + "gtceu.jade.days": "%s天", "gtceu.jade.energy_stored": "%d / %d EU", "gtceu.jade.fluid_use": "%s mB/t", + "gtceu.jade.hours": "%s小时", + "gtceu.jade.minutes": "%s分钟", "gtceu.jade.progress_computation": "%s / %s CWU", "gtceu.jade.progress_sec": "%s / %s s", "gtceu.jade.progress_tick": "%s / %s t", + "gtceu.jade.remaining_charge_time": "预计充满时间:%s", + "gtceu.jade.remaining_discharge_time": "预计耗空时间:%s", + "gtceu.jade.seconds": "%s秒", + "gtceu.jade.years": "%s年", "gtceu.jei.bedrock_fluid.heavy_oil_deposit": "重油矿藏", "gtceu.jei.bedrock_fluid.lava_deposit": "熔岩矿藏", "gtceu.jei.bedrock_fluid.light_oil_deposit": "轻油矿藏", @@ -2589,6 +2616,7 @@ "gtceu.key.armor_mode_switch": "切换盔甲模式", "gtceu.key.enable_boots": "启用跳跃提升", "gtceu.key.enable_jetpack": "启用喷气背包", + "gtceu.key.enable_step_assist": "启用步行辅助", "gtceu.key.tool_aoe_change": "切换工具范围模式", "gtceu.large_boiler": "大型锅炉", "gtceu.large_chemical_reactor": "大型化学反应釜", @@ -3541,6 +3569,10 @@ "gtceu.placeholder_info.block.0": "返回方块符号‘█’。", "gtceu.placeholder_info.block.1": "用法:", "gtceu.placeholder_info.block.2": " {block} -> '█'", + "gtceu.placeholder_info.blockNbt.0": "返回方块实体的NBT", + "gtceu.placeholder_info.blockNbt.1": "用法:", + "gtceu.placeholder_info.blockNbt.2": " {blockNbt} -> 方块实体的全部NBT", + "gtceu.placeholder_info.blockNbt.3": " {blockNbt [键1] [键2] ...} -> 部分NBT", "gtceu.placeholder_info.bufferText.0": "返回ComputerCraft可访问的缓冲区中的文本", "gtceu.placeholder_info.bufferText.1": "用法:", "gtceu.placeholder_info.bufferText.2": " {bufferText <行>} -> 缓冲区中指定行的文本(行号为1-100)", @@ -3852,6 +3884,10 @@ "gtceu.top.fuel_none": "无燃料", "gtceu.top.invalid_structure": "结构不完整", "gtceu.top.item_auto_output": "物品输出:%s", + "gtceu.top.ldp_endpoint.io_type": "IO类型:%s", + "gtceu.top.ldp_endpoint.is_formed": "§a管路已成型§r", + "gtceu.top.ldp_endpoint.not_formed": "§c管路未连接§r", + "gtceu.top.ldp_endpoint.output_direction": "输出方向:%s", "gtceu.top.link_cover.color": "颜色:", "gtceu.top.machine_mode": "机器模式:", "gtceu.top.maintenance.crowbar": "这东西不属于这儿", @@ -3943,12 +3979,12 @@ "item.glass_lens": "玻璃透镜(白色)", "item.gtceu.activity_detector_cover": "活跃探测覆盖板", "item.gtceu.activity_detector_cover.tooltip": "§7作§f覆盖板§7时依照§f机器活跃状态§7发出红石信号。", - "item.gtceu.advanced_activity_detector_cover": "进阶活跃状态探测器", + "item.gtceu.advanced_activity_detector_cover": "进阶活跃状态探测覆盖板", "item.gtceu.advanced_activity_detector_cover.tooltip": "§7作§f覆盖板§7时依照§f机器处理进度§7发出红石信号。", "item.gtceu.advanced_electric_jetpack": "进阶电力喷气背包", "item.gtceu.advanced_energy_detector_cover": "进阶能量探测覆盖板", "item.gtceu.advanced_energy_detector_cover.tooltip": "§7作§f覆盖板§7时依照由§fRS锁存器§7控制的§f能量状态§7发出红石信号。", - "item.gtceu.advanced_fluid_detector_cover": "进阶流体探测器", + "item.gtceu.advanced_fluid_detector_cover": "进阶流体探测覆盖板", "item.gtceu.advanced_fluid_detector_cover.tooltip": "作§f覆盖板§7时依照由§fRS锁存器§7控制的§f流体存储状态§7发出红石信号。", "item.gtceu.advanced_fluid_voiding_cover": "进阶流体销毁覆盖板", "item.gtceu.advanced_fluid_voiding_cover.tooltip.0": "§7作§f覆盖板§7时允许按数量销毁§f流体§7。", @@ -3956,7 +3992,7 @@ "item.gtceu.advanced_integrated_circuit": "进阶集成电路", "item.gtceu.advanced_integrated_circuit.tooltip.0": "§7更小也更强", "item.gtceu.advanced_integrated_circuit.tooltip.1": "§6HV级电路", - "item.gtceu.advanced_item_detector_cover": "进阶物品探测器", + "item.gtceu.advanced_item_detector_cover": "进阶物品探测覆盖板", "item.gtceu.advanced_item_detector_cover.tooltip": "作§f覆盖板§7时依照由§fRS锁存器§7控制的§f物品存储状态§7发出红石信号。", "item.gtceu.advanced_item_voiding_cover": "进阶物品销毁覆盖板", "item.gtceu.advanced_item_voiding_cover.tooltip.0": "§7作§f覆盖板§7时销毁物品。", @@ -4743,7 +4779,7 @@ "item.gtceu.tool.behavior.block_rotation": "§2精械师傅:§f旋转方块", "item.gtceu.tool.behavior.crop_harvesting": "§a庄稼收割:§f收获成熟的作物", "item.gtceu.tool.behavior.damage_boost": "§4伤害增益:§f对%s造成额外伤害", - "item.gtceu.tool.behavior.dowse_campfire": "§F消防战士:§f扑灭营火", + "item.gtceu.tool.behavior.dowse_campfire": "§1消防战士:§f扑灭营火", "item.gtceu.tool.behavior.grass_path": "§e园林策划:§f制造草径", "item.gtceu.tool.behavior.ground_tilling": "§e耕地农夫:§f耕耘土地", "item.gtceu.tool.behavior.plunger": "§9水管工人:§f清除流体", @@ -4781,10 +4817,15 @@ "item.gtceu.tool.hoe": "%s锄", "item.gtceu.tool.hv_chainsaw": "%s链锯(§6HV§r)", "item.gtceu.tool.hv_drill": "%s电钻(§6HV§r)", + "item.gtceu.tool.hv_screwdriver": "%s螺丝刀(§6HV§r)", + "item.gtceu.tool.hv_screwdriver.tooltip": "§8调整覆盖板和机器", "item.gtceu.tool.hv_wirecutter": "%s剪线钳(HV)", "item.gtceu.tool.hv_wrench": "%s扳手(§6HV§r)", "item.gtceu.tool.hv_wrench.tooltip": "§8按住左键以拆卸机器", + "item.gtceu.tool.iv_chainsaw": "%s链锯(§9IV§r)", "item.gtceu.tool.iv_drill": "%s电钻(§9IV§r)", + "item.gtceu.tool.iv_screwdriver": "%s螺丝刀(§9IV§r)", + "item.gtceu.tool.iv_screwdriver.tooltip": "§8调整覆盖板和机器", "item.gtceu.tool.iv_wirecutter": "%s剪线钳(IV)", "item.gtceu.tool.iv_wrench": "%s扳手(§9IV§r)", "item.gtceu.tool.iv_wrench.tooltip": "§8按住左键以拆卸机器", @@ -4965,7 +5006,6 @@ "item.gtceu.zpm_voltage_coil.tooltip": "超级线圈", "item.invalid.name": "无效物品", "item.netherrack_nether_quartz": "下界石英矿石", - "item.toggle.advanced.info.tooltip": "§8<按住Shift查阅已存储配置信息>", "itemGroup.gtceu.decoration": "格雷科技 | 装饰方块", "itemGroup.gtceu.item": "格雷科技 | 物品", "itemGroup.gtceu.machine": "格雷科技 | 机器", @@ -5592,6 +5632,7 @@ "material.gtceu.tritanium": "三钛", "material.gtceu.tritium": "氚", "material.gtceu.trona": "天然碱", + "material.gtceu.tuff": "凝灰岩", "material.gtceu.tungstate": "钨酸锂", "material.gtceu.tungsten": "钨", "material.gtceu.tungsten_carbide": "碳化钨", @@ -5658,20 +5699,26 @@ "metaarmor.message.nightvision.disabled": "§b夜视:§c关闭", "metaarmor.message.nightvision.enabled": "§b夜视:§a开启", "metaarmor.message.nightvision.error": "§c能量不足!", - "metaarmor.nms.boosted_jump.disabled": "纳米肌体™套装:跳跃提升已禁用", - "metaarmor.nms.boosted_jump.enabled": "纳米肌体™套装:跳跃提升已启用", + "metaarmor.message.step_assist.disabled": "步行辅助:§c关", + "metaarmor.message.step_assist.enabled": "步行辅助:§a开", "metaarmor.nms.nightvision.disabled": "纳米肌体™套装:夜视已禁用", "metaarmor.nms.nightvision.enabled": "纳米肌体™套装:夜视已启用", "metaarmor.nms.nightvision.error": "纳米肌体™套装:§c能量不足!", "metaarmor.nms.share.disable": "纳米肌体™套装:供能模式已禁用", "metaarmor.nms.share.enable": "纳米肌体™套装:供能模式已启用", "metaarmor.nms.share.error": "纳米肌体™套装:§c能量不足,无法供能!", + "metaarmor.nms.step_assist.disabled": "纳米肌体™套装:步行辅助已禁用", + "metaarmor.nms.step_assist.enabled": "纳米肌体™套装:步行辅助已启用", + "metaarmor.qts.boosted_jump.disabled": "夸克高科™套装:跳跃提升已禁用", + "metaarmor.qts.boosted_jump.enabled": "夸克高科™套装:跳跃提升已启用", "metaarmor.qts.nightvision.disabled": "夸克高科™套装:夜视已禁用", "metaarmor.qts.nightvision.enabled": "夸克高科™套装:夜视已启用", "metaarmor.qts.nightvision.error": "夸克高科™套装:§c能量不足!", "metaarmor.qts.share.disable": "夸克高科™套装:供能模式已禁用", "metaarmor.qts.share.enable": "夸克高科™套装:供能模式已启用", "metaarmor.qts.share.error": "夸克高科™套装:§c能量不足,无法供能!", + "metaarmor.qts.step_assist.disabled": "夸克高科™套装:步行辅助已禁用", + "metaarmor.qts.step_assist.enabled": "夸克高科™套装:步行辅助已启用", "metaarmor.tooltip.autoeat": "使用物品栏中的食物补充饱食度", "metaarmor.tooltip.breath": "补充氧气条", "metaarmor.tooltip.burning": "扑灭身上的火焰", diff --git a/src/main/resources/assets/gtceu/models/block/material_sets/diamond/ore.json b/src/main/resources/assets/gtceu/models/block/material_sets/diamond/ore.json new file mode 100644 index 00000000000..239cf811df9 --- /dev/null +++ b/src/main/resources/assets/gtceu/models/block/material_sets/diamond/ore.json @@ -0,0 +1,51 @@ +{ + "parent": "block/block", + "loader": "forge:composite", + "textures": { + "particle": "gtceu:block/material_sets/diamond/ore" + }, + "children": { + "base_stone": { + "render_type": "solid" + }, + "ore_texture": { + "parent": "block/block", + "textures": { + "layer0": "gtceu:block/material_sets/diamond/ore", + "layer1": "gtceu:block/material_sets/diamond/ore_layer2", + "particle": "#layer0" + }, + "render_type": "translucent", + "elements": [ + { + "from": [0, 0, 0 ], + "to": [16, 16, 16], + "faces": { + "down": { "texture": "#layer0", "cullface": "down", "tintindex": 0 }, + "up": { "texture": "#layer0", "cullface": "up", "tintindex": 0 }, + "north": { "texture": "#layer0", "cullface": "north", "tintindex": 0 }, + "south": { "texture": "#layer0", "cullface": "south", "tintindex": 0 }, + "west": { "texture": "#layer0", "cullface": "west", "tintindex": 0 }, + "east": { "texture": "#layer0", "cullface": "east", "tintindex": 0 } + } + }, + { + "from": [0, 0, 0 ], + "to": [16, 16, 16], + "faces": { + "down": { "texture": "#layer1", "cullface": "down", "tintindex": 1 }, + "up": { "texture": "#layer1", "cullface": "up", "tintindex": 1 }, + "north": { "texture": "#layer1", "cullface": "north", "tintindex": 1 }, + "south": { "texture": "#layer1", "cullface": "south", "tintindex": 1 }, + "west": { "texture": "#layer1", "cullface": "west", "tintindex": 1 }, + "east": { "texture": "#layer1", "cullface": "east", "tintindex": 1 } + } + } + ] + } + }, + "item_render_order": [ + "base_stone", + "ore_texture" + ] +} diff --git a/src/main/resources/assets/gtceu/models/block/material_sets/diamond/ore_emissive.json b/src/main/resources/assets/gtceu/models/block/material_sets/diamond/ore_emissive.json new file mode 100644 index 00000000000..530e76750b5 --- /dev/null +++ b/src/main/resources/assets/gtceu/models/block/material_sets/diamond/ore_emissive.json @@ -0,0 +1,53 @@ +{ + "parent": "block/block", + "loader": "forge:composite", + "textures": { + "particle": "gtceu:block/material_sets/diamond/ore_emissive" + }, + "children": { + "base_stone": { + "render_type": "solid" + }, + "ore_texture": { + "parent": "block/block", + "textures": { + "layer0": "gtceu:block/material_sets/diamond/ore_emissive", + "layer1": "gtceu:block/material_sets/diamond/ore_emissive_layer2", + "particle": "#layer0" + }, + "render_type": "translucent", + "elements": [ + { + "from": [0, 0, 0 ], + "to": [16, 16, 16], + "forge_data": { "block_light": 15, "sky_light": 15 }, + "faces": { + "down": { "texture": "#layer0", "cullface": "down", "tintindex": -101 }, + "up": { "texture": "#layer0", "cullface": "up", "tintindex": -101 }, + "north": { "texture": "#layer0", "cullface": "north", "tintindex": -101 }, + "south": { "texture": "#layer0", "cullface": "south", "tintindex": -101 }, + "west": { "texture": "#layer0", "cullface": "west", "tintindex": -101 }, + "east": { "texture": "#layer0", "cullface": "east", "tintindex": -101 } + } + }, + { + "from": [0, 0, 0 ], + "to": [16, 16, 16], + "forge_data": { "block_light": 15, "sky_light": 15 }, + "faces": { + "down": { "texture": "#layer1", "cullface": "down", "tintindex": -102 }, + "up": { "texture": "#layer1", "cullface": "up", "tintindex": -102 }, + "north": { "texture": "#layer1", "cullface": "north", "tintindex": -102 }, + "south": { "texture": "#layer1", "cullface": "south", "tintindex": -102 }, + "west": { "texture": "#layer1", "cullface": "west", "tintindex": -102 }, + "east": { "texture": "#layer1", "cullface": "east", "tintindex": -102 } + } + } + ] + } + }, + "item_render_order": [ + "base_stone", + "ore_texture" + ] +} diff --git a/src/main/resources/assets/gtceu/models/block/material_sets/dull/block.json b/src/main/resources/assets/gtceu/models/block/material_sets/dull/block.json index f3e2aec258c..9220a964136 100644 --- a/src/main/resources/assets/gtceu/models/block/material_sets/dull/block.json +++ b/src/main/resources/assets/gtceu/models/block/material_sets/dull/block.json @@ -1,7 +1,27 @@ { - "parent": "gtceu:block/cube_2_layer/tinted_both/all_translucent", + "parent": "block/block", + "loader": "forge:composite", "textures": { - "bot_all": "gtceu:block/material_sets/dull/block", - "top_all": "gtceu:block/material_sets/dull/block_secondary" - } + "particle": "gtceu:block/material_sets/dull/block" + }, + "children": { + "base": { + "parent": "gtceu:block/cube/tinted/all_0", + "render_type": "solid", + "textures": { + "all": "gtceu:block/material_sets/dull/block" + } + }, + "secondary": { + "parent": "gtceu:block/cube/tinted/all", + "render_type": "translucent", + "textures": { + "all": "gtceu:block/material_sets/dull/block_secondary" + } + } + }, + "item_render_order": [ + "base", + "secondary" + ] } diff --git a/src/main/resources/assets/gtceu/models/block/material_sets/dull/frame_gt.json b/src/main/resources/assets/gtceu/models/block/material_sets/dull/frame_gt.json index 4145d0ceb64..b74dc0fe62f 100644 --- a/src/main/resources/assets/gtceu/models/block/material_sets/dull/frame_gt.json +++ b/src/main/resources/assets/gtceu/models/block/material_sets/dull/frame_gt.json @@ -1,7 +1,27 @@ { - "parent": "gtceu:block/cube_2_layer/tinted_both/all_translucent", + "parent": "block/block", + "loader": "forge:composite", "textures": { - "bot_all": "gtceu:block/material_sets/dull/frame_gt", - "top_all": "gtceu:block/material_sets/dull/frame_gt_secondary" - } + "particle": "gtceu:block/material_sets/dull/frame_gt" + }, + "children": { + "base": { + "parent": "gtceu:block/cube/tinted/all_0", + "render_type": "cutout", + "textures": { + "all": "gtceu:block/material_sets/dull/frame_gt" + } + }, + "secondary": { + "parent": "gtceu:block/cube/tinted/all", + "render_type": "translucent", + "textures": { + "all": "gtceu:block/material_sets/dull/frame_gt_secondary" + } + } + }, + "item_render_order": [ + "base", + "secondary" + ] } diff --git a/src/main/resources/assets/gtceu/models/block/material_sets/dull/ore.json b/src/main/resources/assets/gtceu/models/block/material_sets/dull/ore.json new file mode 100644 index 00000000000..87059560e15 --- /dev/null +++ b/src/main/resources/assets/gtceu/models/block/material_sets/dull/ore.json @@ -0,0 +1,51 @@ +{ + "parent": "block/block", + "loader": "forge:composite", + "textures": { + "particle": "gtceu:block/material_sets/dull/ore" + }, + "children": { + "base_stone": { + "render_type": "solid" + }, + "ore_texture": { + "parent": "block/block", + "textures": { + "layer0": "gtceu:block/material_sets/dull/ore", + "layer1": "gtceu:block/material_sets/dull/ore_layer2", + "particle": "#layer0" + }, + "render_type": "translucent", + "elements": [ + { + "from": [0, 0, 0 ], + "to": [16, 16, 16], + "faces": { + "down": { "texture": "#layer0", "cullface": "down", "tintindex": 0 }, + "up": { "texture": "#layer0", "cullface": "up", "tintindex": 0 }, + "north": { "texture": "#layer0", "cullface": "north", "tintindex": 0 }, + "south": { "texture": "#layer0", "cullface": "south", "tintindex": 0 }, + "west": { "texture": "#layer0", "cullface": "west", "tintindex": 0 }, + "east": { "texture": "#layer0", "cullface": "east", "tintindex": 0 } + } + }, + { + "from": [0, 0, 0 ], + "to": [16, 16, 16], + "faces": { + "down": { "texture": "#layer1", "cullface": "down", "tintindex": 1 }, + "up": { "texture": "#layer1", "cullface": "up", "tintindex": 1 }, + "north": { "texture": "#layer1", "cullface": "north", "tintindex": 1 }, + "south": { "texture": "#layer1", "cullface": "south", "tintindex": 1 }, + "west": { "texture": "#layer1", "cullface": "west", "tintindex": 1 }, + "east": { "texture": "#layer1", "cullface": "east", "tintindex": 1 } + } + } + ] + } + }, + "item_render_order": [ + "base_stone", + "ore_texture" + ] +} diff --git a/src/main/resources/assets/gtceu/models/block/material_sets/dull/ore_emissive.json b/src/main/resources/assets/gtceu/models/block/material_sets/dull/ore_emissive.json new file mode 100644 index 00000000000..41b0e9971cd --- /dev/null +++ b/src/main/resources/assets/gtceu/models/block/material_sets/dull/ore_emissive.json @@ -0,0 +1,53 @@ +{ + "parent": "block/block", + "loader": "forge:composite", + "textures": { + "particle": "gtceu:block/material_sets/dull/ore_emissive" + }, + "children": { + "base_stone": { + "render_type": "solid" + }, + "ore_texture": { + "parent": "block/block", + "textures": { + "layer0": "gtceu:block/material_sets/dull/ore_emissive", + "layer1": "gtceu:block/material_sets/dull/ore_emissive_layer2", + "particle": "#layer0" + }, + "render_type": "translucent", + "elements": [ + { + "from": [0, 0, 0 ], + "to": [16, 16, 16], + "forge_data": { "block_light": 15, "sky_light": 15 }, + "faces": { + "down": { "texture": "#layer0", "cullface": "down", "tintindex": -101 }, + "up": { "texture": "#layer0", "cullface": "up", "tintindex": -101 }, + "north": { "texture": "#layer0", "cullface": "north", "tintindex": -101 }, + "south": { "texture": "#layer0", "cullface": "south", "tintindex": -101 }, + "west": { "texture": "#layer0", "cullface": "west", "tintindex": -101 }, + "east": { "texture": "#layer0", "cullface": "east", "tintindex": -101 } + } + }, + { + "from": [0, 0, 0 ], + "to": [16, 16, 16], + "forge_data": { "block_light": 15, "sky_light": 15 }, + "faces": { + "down": { "texture": "#layer1", "cullface": "down", "tintindex": -102 }, + "up": { "texture": "#layer1", "cullface": "up", "tintindex": -102 }, + "north": { "texture": "#layer1", "cullface": "north", "tintindex": -102 }, + "south": { "texture": "#layer1", "cullface": "south", "tintindex": -102 }, + "west": { "texture": "#layer1", "cullface": "west", "tintindex": -102 }, + "east": { "texture": "#layer1", "cullface": "east", "tintindex": -102 } + } + } + ] + } + }, + "item_render_order": [ + "base_stone", + "ore_texture" + ] +} diff --git a/src/main/resources/assets/gtceu/models/block/material_sets/emerald/block.json b/src/main/resources/assets/gtceu/models/block/material_sets/emerald/block.json index 4c82d064ae1..561f7ff3061 100644 --- a/src/main/resources/assets/gtceu/models/block/material_sets/emerald/block.json +++ b/src/main/resources/assets/gtceu/models/block/material_sets/emerald/block.json @@ -1,7 +1,27 @@ { - "parent": "gtceu:block/cube_2_layer/tinted_both/all_translucent", + "parent": "block/block", + "loader": "forge:composite", "textures": { - "bot_all": "gtceu:block/material_sets/emerald/block", - "top_all": "gtceu:block/material_sets/emerald/block_secondary" - } + "particle": "gtceu:block/material_sets/emerald/block" + }, + "children": { + "base": { + "parent": "gtceu:block/cube/tinted/all_0", + "render_type": "solid", + "textures": { + "all": "gtceu:block/material_sets/emerald/block" + } + }, + "secondary": { + "parent": "gtceu:block/cube/tinted/all", + "render_type": "translucent", + "textures": { + "all": "gtceu:block/material_sets/emerald/block_secondary" + } + } + }, + "item_render_order": [ + "base", + "secondary" + ] } diff --git a/src/main/resources/assets/gtceu/models/block/material_sets/fine/block.json b/src/main/resources/assets/gtceu/models/block/material_sets/fine/block.json index f0ea3273608..e67185edb1a 100644 --- a/src/main/resources/assets/gtceu/models/block/material_sets/fine/block.json +++ b/src/main/resources/assets/gtceu/models/block/material_sets/fine/block.json @@ -1,7 +1,27 @@ { - "parent": "gtceu:block/cube_2_layer/tinted_both/all_translucent", + "parent": "block/block", + "loader": "forge:composite", "textures": { - "bot_all": "gtceu:block/material_sets/fine/block", - "top_all": "gtceu:block/material_sets/fine/block_secondary" - } + "particle": "gtceu:block/material_sets/fine/block" + }, + "children": { + "base": { + "parent": "gtceu:block/cube/tinted/all_0", + "render_type": "solid", + "textures": { + "all": "gtceu:block/material_sets/fine/block" + } + }, + "secondary": { + "parent": "gtceu:block/cube/tinted/all", + "render_type": "translucent", + "textures": { + "all": "gtceu:block/material_sets/fine/block_secondary" + } + } + }, + "item_render_order": [ + "base", + "secondary" + ] } diff --git a/src/main/resources/assets/gtceu/models/block/material_sets/fine/ore.json b/src/main/resources/assets/gtceu/models/block/material_sets/fine/ore.json new file mode 100644 index 00000000000..d1a151c2ed9 --- /dev/null +++ b/src/main/resources/assets/gtceu/models/block/material_sets/fine/ore.json @@ -0,0 +1,51 @@ +{ + "parent": "block/block", + "loader": "forge:composite", + "textures": { + "particle": "gtceu:block/material_sets/fine/ore" + }, + "children": { + "base_stone": { + "render_type": "solid" + }, + "ore_texture": { + "parent": "block/block", + "textures": { + "layer0": "gtceu:block/material_sets/fine/ore", + "layer1": "gtceu:block/material_sets/fine/ore_layer2", + "particle": "#layer0" + }, + "render_type": "translucent", + "elements": [ + { + "from": [0, 0, 0 ], + "to": [16, 16, 16], + "faces": { + "down": { "texture": "#layer0", "cullface": "down", "tintindex": 0 }, + "up": { "texture": "#layer0", "cullface": "up", "tintindex": 0 }, + "north": { "texture": "#layer0", "cullface": "north", "tintindex": 0 }, + "south": { "texture": "#layer0", "cullface": "south", "tintindex": 0 }, + "west": { "texture": "#layer0", "cullface": "west", "tintindex": 0 }, + "east": { "texture": "#layer0", "cullface": "east", "tintindex": 0 } + } + }, + { + "from": [0, 0, 0 ], + "to": [16, 16, 16], + "faces": { + "down": { "texture": "#layer1", "cullface": "down", "tintindex": 1 }, + "up": { "texture": "#layer1", "cullface": "up", "tintindex": 1 }, + "north": { "texture": "#layer1", "cullface": "north", "tintindex": 1 }, + "south": { "texture": "#layer1", "cullface": "south", "tintindex": 1 }, + "west": { "texture": "#layer1", "cullface": "west", "tintindex": 1 }, + "east": { "texture": "#layer1", "cullface": "east", "tintindex": 1 } + } + } + ] + } + }, + "item_render_order": [ + "base_stone", + "ore_texture" + ] +} diff --git a/src/main/resources/assets/gtceu/models/block/material_sets/fine/ore_emissive.json b/src/main/resources/assets/gtceu/models/block/material_sets/fine/ore_emissive.json new file mode 100644 index 00000000000..1f3a55ddf91 --- /dev/null +++ b/src/main/resources/assets/gtceu/models/block/material_sets/fine/ore_emissive.json @@ -0,0 +1,53 @@ +{ + "parent": "block/block", + "loader": "forge:composite", + "textures": { + "particle": "gtceu:block/material_sets/fine/ore_emissive" + }, + "children": { + "base_stone": { + "render_type": "solid" + }, + "ore_texture": { + "parent": "block/block", + "textures": { + "layer0": "gtceu:block/material_sets/fine/ore_emissive", + "layer1": "gtceu:block/material_sets/fine/ore_emissive_layer2", + "particle": "#layer0" + }, + "render_type": "translucent", + "elements": [ + { + "from": [0, 0, 0 ], + "to": [16, 16, 16], + "forge_data": { "block_light": 15, "sky_light": 15 }, + "faces": { + "down": { "texture": "#layer0", "cullface": "down", "tintindex": -101 }, + "up": { "texture": "#layer0", "cullface": "up", "tintindex": -101 }, + "north": { "texture": "#layer0", "cullface": "north", "tintindex": -101 }, + "south": { "texture": "#layer0", "cullface": "south", "tintindex": -101 }, + "west": { "texture": "#layer0", "cullface": "west", "tintindex": -101 }, + "east": { "texture": "#layer0", "cullface": "east", "tintindex": -101 } + } + }, + { + "from": [0, 0, 0 ], + "to": [16, 16, 16], + "forge_data": { "block_light": 15, "sky_light": 15 }, + "faces": { + "down": { "texture": "#layer1", "cullface": "down", "tintindex": -102 }, + "up": { "texture": "#layer1", "cullface": "up", "tintindex": -102 }, + "north": { "texture": "#layer1", "cullface": "north", "tintindex": -102 }, + "south": { "texture": "#layer1", "cullface": "south", "tintindex": -102 }, + "west": { "texture": "#layer1", "cullface": "west", "tintindex": -102 }, + "east": { "texture": "#layer1", "cullface": "east", "tintindex": -102 } + } + } + ] + } + }, + "item_render_order": [ + "base_stone", + "ore_texture" + ] +} diff --git a/src/main/resources/assets/gtceu/models/block/material_sets/flint/ore.json b/src/main/resources/assets/gtceu/models/block/material_sets/flint/ore.json new file mode 100644 index 00000000000..db813a630ac --- /dev/null +++ b/src/main/resources/assets/gtceu/models/block/material_sets/flint/ore.json @@ -0,0 +1,51 @@ +{ + "parent": "block/block", + "loader": "forge:composite", + "textures": { + "particle": "gtceu:block/material_sets/flint/ore" + }, + "children": { + "base_stone": { + "render_type": "solid" + }, + "ore_texture": { + "parent": "block/block", + "textures": { + "layer0": "gtceu:block/material_sets/flint/ore", + "layer1": "gtceu:block/material_sets/flint/ore_layer2", + "particle": "#layer0" + }, + "render_type": "translucent", + "elements": [ + { + "from": [0, 0, 0 ], + "to": [16, 16, 16], + "faces": { + "down": { "texture": "#layer0", "cullface": "down", "tintindex": 0 }, + "up": { "texture": "#layer0", "cullface": "up", "tintindex": 0 }, + "north": { "texture": "#layer0", "cullface": "north", "tintindex": 0 }, + "south": { "texture": "#layer0", "cullface": "south", "tintindex": 0 }, + "west": { "texture": "#layer0", "cullface": "west", "tintindex": 0 }, + "east": { "texture": "#layer0", "cullface": "east", "tintindex": 0 } + } + }, + { + "from": [0, 0, 0 ], + "to": [16, 16, 16], + "faces": { + "down": { "texture": "#layer1", "cullface": "down", "tintindex": 1 }, + "up": { "texture": "#layer1", "cullface": "up", "tintindex": 1 }, + "north": { "texture": "#layer1", "cullface": "north", "tintindex": 1 }, + "south": { "texture": "#layer1", "cullface": "south", "tintindex": 1 }, + "west": { "texture": "#layer1", "cullface": "west", "tintindex": 1 }, + "east": { "texture": "#layer1", "cullface": "east", "tintindex": 1 } + } + } + ] + } + }, + "item_render_order": [ + "base_stone", + "ore_texture" + ] +} diff --git a/src/main/resources/assets/gtceu/models/block/material_sets/flint/ore_emissive.json b/src/main/resources/assets/gtceu/models/block/material_sets/flint/ore_emissive.json new file mode 100644 index 00000000000..d1dac37287d --- /dev/null +++ b/src/main/resources/assets/gtceu/models/block/material_sets/flint/ore_emissive.json @@ -0,0 +1,53 @@ +{ + "parent": "block/block", + "loader": "forge:composite", + "textures": { + "particle": "gtceu:block/material_sets/flint/ore_emissive" + }, + "children": { + "base_stone": { + "render_type": "solid" + }, + "ore_texture": { + "parent": "block/block", + "textures": { + "layer0": "gtceu:block/material_sets/flint/ore_emissive", + "layer1": "gtceu:block/material_sets/flint/ore_emissive_layer2", + "particle": "#layer0" + }, + "render_type": "translucent", + "elements": [ + { + "from": [0, 0, 0 ], + "to": [16, 16, 16], + "forge_data": { "block_light": 15, "sky_light": 15 }, + "faces": { + "down": { "texture": "#layer0", "cullface": "down", "tintindex": -101 }, + "up": { "texture": "#layer0", "cullface": "up", "tintindex": -101 }, + "north": { "texture": "#layer0", "cullface": "north", "tintindex": -101 }, + "south": { "texture": "#layer0", "cullface": "south", "tintindex": -101 }, + "west": { "texture": "#layer0", "cullface": "west", "tintindex": -101 }, + "east": { "texture": "#layer0", "cullface": "east", "tintindex": -101 } + } + }, + { + "from": [0, 0, 0 ], + "to": [16, 16, 16], + "forge_data": { "block_light": 15, "sky_light": 15 }, + "faces": { + "down": { "texture": "#layer1", "cullface": "down", "tintindex": -102 }, + "up": { "texture": "#layer1", "cullface": "up", "tintindex": -102 }, + "north": { "texture": "#layer1", "cullface": "north", "tintindex": -102 }, + "south": { "texture": "#layer1", "cullface": "south", "tintindex": -102 }, + "west": { "texture": "#layer1", "cullface": "west", "tintindex": -102 }, + "east": { "texture": "#layer1", "cullface": "east", "tintindex": -102 } + } + } + ] + } + }, + "item_render_order": [ + "base_stone", + "ore_texture" + ] +} diff --git a/src/main/resources/assets/gtceu/models/block/material_sets/lapis/block.json b/src/main/resources/assets/gtceu/models/block/material_sets/lapis/block.json index 5470aee534b..c9d66e5f5a7 100644 --- a/src/main/resources/assets/gtceu/models/block/material_sets/lapis/block.json +++ b/src/main/resources/assets/gtceu/models/block/material_sets/lapis/block.json @@ -1,7 +1,27 @@ { - "parent": "gtceu:block/cube_2_layer/tinted_both/all_translucent", + "parent": "block/block", + "loader": "forge:composite", "textures": { - "bot_all": "gtceu:block/material_sets/lapis/block", - "top_all": "gtceu:block/material_sets/lapis/block_secondary" - } + "particle": "gtceu:block/material_sets/lapis/block" + }, + "children": { + "base": { + "parent": "gtceu:block/cube/tinted/all_0", + "render_type": "solid", + "textures": { + "all": "gtceu:block/material_sets/lapis/block" + } + }, + "secondary": { + "parent": "gtceu:block/cube/tinted/all", + "render_type": "translucent", + "textures": { + "all": "gtceu:block/material_sets/lapis/block_secondary" + } + } + }, + "item_render_order": [ + "base", + "secondary" + ] } diff --git a/src/main/resources/assets/gtceu/models/block/material_sets/lapis/ore.json b/src/main/resources/assets/gtceu/models/block/material_sets/lapis/ore.json new file mode 100644 index 00000000000..df02a9b8199 --- /dev/null +++ b/src/main/resources/assets/gtceu/models/block/material_sets/lapis/ore.json @@ -0,0 +1,51 @@ +{ + "parent": "block/block", + "loader": "forge:composite", + "textures": { + "particle": "gtceu:block/material_sets/lapis/ore" + }, + "children": { + "base_stone": { + "render_type": "solid" + }, + "ore_texture": { + "parent": "block/block", + "textures": { + "layer0": "gtceu:block/material_sets/lapis/ore", + "layer1": "gtceu:block/material_sets/lapis/ore_layer2", + "particle": "#layer0" + }, + "render_type": "translucent", + "elements": [ + { + "from": [0, 0, 0 ], + "to": [16, 16, 16], + "faces": { + "down": { "texture": "#layer0", "cullface": "down", "tintindex": 0 }, + "up": { "texture": "#layer0", "cullface": "up", "tintindex": 0 }, + "north": { "texture": "#layer0", "cullface": "north", "tintindex": 0 }, + "south": { "texture": "#layer0", "cullface": "south", "tintindex": 0 }, + "west": { "texture": "#layer0", "cullface": "west", "tintindex": 0 }, + "east": { "texture": "#layer0", "cullface": "east", "tintindex": 0 } + } + }, + { + "from": [0, 0, 0 ], + "to": [16, 16, 16], + "faces": { + "down": { "texture": "#layer1", "cullface": "down", "tintindex": 1 }, + "up": { "texture": "#layer1", "cullface": "up", "tintindex": 1 }, + "north": { "texture": "#layer1", "cullface": "north", "tintindex": 1 }, + "south": { "texture": "#layer1", "cullface": "south", "tintindex": 1 }, + "west": { "texture": "#layer1", "cullface": "west", "tintindex": 1 }, + "east": { "texture": "#layer1", "cullface": "east", "tintindex": 1 } + } + } + ] + } + }, + "item_render_order": [ + "base_stone", + "ore_texture" + ] +} diff --git a/src/main/resources/assets/gtceu/models/block/material_sets/lapis/ore_emissive.json b/src/main/resources/assets/gtceu/models/block/material_sets/lapis/ore_emissive.json new file mode 100644 index 00000000000..bb285c1e3b6 --- /dev/null +++ b/src/main/resources/assets/gtceu/models/block/material_sets/lapis/ore_emissive.json @@ -0,0 +1,53 @@ +{ + "parent": "block/block", + "loader": "forge:composite", + "textures": { + "particle": "gtceu:block/material_sets/lapis/ore_emissive" + }, + "children": { + "base_stone": { + "render_type": "solid" + }, + "ore_texture": { + "parent": "block/block", + "textures": { + "layer0": "gtceu:block/material_sets/lapis/ore_emissive", + "layer1": "gtceu:block/material_sets/lapis/ore_emissive_layer2", + "particle": "#layer0" + }, + "render_type": "translucent", + "elements": [ + { + "from": [0, 0, 0 ], + "to": [16, 16, 16], + "forge_data": { "block_light": 15, "sky_light": 15 }, + "faces": { + "down": { "texture": "#layer0", "cullface": "down", "tintindex": -101 }, + "up": { "texture": "#layer0", "cullface": "up", "tintindex": -101 }, + "north": { "texture": "#layer0", "cullface": "north", "tintindex": -101 }, + "south": { "texture": "#layer0", "cullface": "south", "tintindex": -101 }, + "west": { "texture": "#layer0", "cullface": "west", "tintindex": -101 }, + "east": { "texture": "#layer0", "cullface": "east", "tintindex": -101 } + } + }, + { + "from": [0, 0, 0 ], + "to": [16, 16, 16], + "forge_data": { "block_light": 15, "sky_light": 15 }, + "faces": { + "down": { "texture": "#layer1", "cullface": "down", "tintindex": -102 }, + "up": { "texture": "#layer1", "cullface": "up", "tintindex": -102 }, + "north": { "texture": "#layer1", "cullface": "north", "tintindex": -102 }, + "south": { "texture": "#layer1", "cullface": "south", "tintindex": -102 }, + "west": { "texture": "#layer1", "cullface": "west", "tintindex": -102 }, + "east": { "texture": "#layer1", "cullface": "east", "tintindex": -102 } + } + } + ] + } + }, + "item_render_order": [ + "base_stone", + "ore_texture" + ] +} diff --git a/src/main/resources/assets/gtceu/models/block/material_sets/lignite/block.json b/src/main/resources/assets/gtceu/models/block/material_sets/lignite/block.json index 4509d7f85d4..e29ae1c608f 100644 --- a/src/main/resources/assets/gtceu/models/block/material_sets/lignite/block.json +++ b/src/main/resources/assets/gtceu/models/block/material_sets/lignite/block.json @@ -1,7 +1,27 @@ { - "parent": "gtceu:block/cube_2_layer/tinted_both/all_translucent", + "parent": "block/block", + "loader": "forge:composite", "textures": { - "bot_all": "gtceu:block/material_sets/lignite/block", - "top_all": "gtceu:block/material_sets/lignite/block_secondary" - } + "particle": "gtceu:block/material_sets/lignite/block" + }, + "children": { + "base": { + "parent": "gtceu:block/cube/tinted/all_0", + "render_type": "solid", + "textures": { + "all": "gtceu:block/material_sets/lignite/block" + } + }, + "secondary": { + "parent": "gtceu:block/cube/tinted/all", + "render_type": "translucent", + "textures": { + "all": "gtceu:block/material_sets/lignite/block_secondary" + } + } + }, + "item_render_order": [ + "base", + "secondary" + ] } diff --git a/src/main/resources/assets/gtceu/models/block/material_sets/lignite/ore.json b/src/main/resources/assets/gtceu/models/block/material_sets/lignite/ore.json new file mode 100644 index 00000000000..7bff65a2d15 --- /dev/null +++ b/src/main/resources/assets/gtceu/models/block/material_sets/lignite/ore.json @@ -0,0 +1,51 @@ +{ + "parent": "block/block", + "loader": "forge:composite", + "textures": { + "particle": "gtceu:block/material_sets/lignite/ore" + }, + "children": { + "base_stone": { + "render_type": "solid" + }, + "ore_texture": { + "parent": "block/block", + "textures": { + "layer0": "gtceu:block/material_sets/lignite/ore", + "layer1": "gtceu:block/material_sets/lignite/ore_layer2", + "particle": "#layer0" + }, + "render_type": "translucent", + "elements": [ + { + "from": [0, 0, 0 ], + "to": [16, 16, 16], + "faces": { + "down": { "texture": "#layer0", "cullface": "down", "tintindex": 0 }, + "up": { "texture": "#layer0", "cullface": "up", "tintindex": 0 }, + "north": { "texture": "#layer0", "cullface": "north", "tintindex": 0 }, + "south": { "texture": "#layer0", "cullface": "south", "tintindex": 0 }, + "west": { "texture": "#layer0", "cullface": "west", "tintindex": 0 }, + "east": { "texture": "#layer0", "cullface": "east", "tintindex": 0 } + } + }, + { + "from": [0, 0, 0 ], + "to": [16, 16, 16], + "faces": { + "down": { "texture": "#layer1", "cullface": "down", "tintindex": 1 }, + "up": { "texture": "#layer1", "cullface": "up", "tintindex": 1 }, + "north": { "texture": "#layer1", "cullface": "north", "tintindex": 1 }, + "south": { "texture": "#layer1", "cullface": "south", "tintindex": 1 }, + "west": { "texture": "#layer1", "cullface": "west", "tintindex": 1 }, + "east": { "texture": "#layer1", "cullface": "east", "tintindex": 1 } + } + } + ] + } + }, + "item_render_order": [ + "base_stone", + "ore_texture" + ] +} diff --git a/src/main/resources/assets/gtceu/models/block/material_sets/lignite/ore_emissive.json b/src/main/resources/assets/gtceu/models/block/material_sets/lignite/ore_emissive.json new file mode 100644 index 00000000000..c37c4c6f90f --- /dev/null +++ b/src/main/resources/assets/gtceu/models/block/material_sets/lignite/ore_emissive.json @@ -0,0 +1,53 @@ +{ + "parent": "block/block", + "loader": "forge:composite", + "textures": { + "particle": "gtceu:block/material_sets/lignite/ore_emissive" + }, + "children": { + "base_stone": { + "render_type": "solid" + }, + "ore_texture": { + "parent": "block/block", + "textures": { + "layer0": "gtceu:block/material_sets/lignite/ore_emissive", + "layer1": "gtceu:block/material_sets/lignite/ore_emissive_layer2", + "particle": "#layer0" + }, + "render_type": "translucent", + "elements": [ + { + "from": [0, 0, 0 ], + "to": [16, 16, 16], + "forge_data": { "block_light": 15, "sky_light": 15 }, + "faces": { + "down": { "texture": "#layer0", "cullface": "down", "tintindex": -101 }, + "up": { "texture": "#layer0", "cullface": "up", "tintindex": -101 }, + "north": { "texture": "#layer0", "cullface": "north", "tintindex": -101 }, + "south": { "texture": "#layer0", "cullface": "south", "tintindex": -101 }, + "west": { "texture": "#layer0", "cullface": "west", "tintindex": -101 }, + "east": { "texture": "#layer0", "cullface": "east", "tintindex": -101 } + } + }, + { + "from": [0, 0, 0 ], + "to": [16, 16, 16], + "forge_data": { "block_light": 15, "sky_light": 15 }, + "faces": { + "down": { "texture": "#layer1", "cullface": "down", "tintindex": -102 }, + "up": { "texture": "#layer1", "cullface": "up", "tintindex": -102 }, + "north": { "texture": "#layer1", "cullface": "north", "tintindex": -102 }, + "south": { "texture": "#layer1", "cullface": "south", "tintindex": -102 }, + "west": { "texture": "#layer1", "cullface": "west", "tintindex": -102 }, + "east": { "texture": "#layer1", "cullface": "east", "tintindex": -102 } + } + } + ] + } + }, + "item_render_order": [ + "base_stone", + "ore_texture" + ] +} diff --git a/src/main/resources/assets/gtceu/models/block/material_sets/netherstar/block.json b/src/main/resources/assets/gtceu/models/block/material_sets/netherstar/block.json index 3ec8294e7d3..78c44413ca4 100644 --- a/src/main/resources/assets/gtceu/models/block/material_sets/netherstar/block.json +++ b/src/main/resources/assets/gtceu/models/block/material_sets/netherstar/block.json @@ -1,7 +1,27 @@ { - "parent": "gtceu:block/cube_2_layer/tinted_both/all_translucent", + "parent": "block/block", + "loader": "forge:composite", "textures": { - "bot_all": "gtceu:block/material_sets/netherstar/block", - "top_all": "gtceu:block/material_sets/netherstar/block_secondary" - } + "particle": "gtceu:block/material_sets/netherstar/block" + }, + "children": { + "base": { + "parent": "gtceu:block/cube/tinted/all_0", + "render_type": "solid", + "textures": { + "all": "gtceu:block/material_sets/netherstar/block" + } + }, + "secondary": { + "parent": "gtceu:block/cube/tinted/all", + "render_type": "translucent", + "textures": { + "all": "gtceu:block/material_sets/netherstar/block_secondary" + } + } + }, + "item_render_order": [ + "base", + "secondary" + ] } diff --git a/src/main/resources/assets/gtceu/models/block/material_sets/opal/block.json b/src/main/resources/assets/gtceu/models/block/material_sets/opal/block.json index 03c9569efef..c50e7409747 100644 --- a/src/main/resources/assets/gtceu/models/block/material_sets/opal/block.json +++ b/src/main/resources/assets/gtceu/models/block/material_sets/opal/block.json @@ -1,7 +1,27 @@ { - "parent": "gtceu:block/cube_2_layer/tinted_both/all_translucent", + "parent": "block/block", + "loader": "forge:composite", "textures": { - "bot_all": "gtceu:block/material_sets/opal/block", - "top_all": "gtceu:block/material_sets/opal/block_secondary" - } + "particle": "gtceu:block/material_sets/opal/block" + }, + "children": { + "base": { + "parent": "gtceu:block/cube/tinted/all_0", + "render_type": "solid", + "textures": { + "all": "gtceu:block/material_sets/opal/block" + } + }, + "secondary": { + "parent": "gtceu:block/cube/tinted/all", + "render_type": "translucent", + "textures": { + "all": "gtceu:block/material_sets/opal/block_secondary" + } + } + }, + "item_render_order": [ + "base", + "secondary" + ] } diff --git a/src/main/resources/assets/gtceu/models/block/material_sets/paper/ore.json b/src/main/resources/assets/gtceu/models/block/material_sets/paper/ore.json new file mode 100644 index 00000000000..b49f3ceee85 --- /dev/null +++ b/src/main/resources/assets/gtceu/models/block/material_sets/paper/ore.json @@ -0,0 +1,51 @@ +{ + "parent": "block/block", + "loader": "forge:composite", + "textures": { + "particle": "gtceu:block/material_sets/paper/ore" + }, + "children": { + "base_stone": { + "render_type": "solid" + }, + "ore_texture": { + "parent": "block/block", + "textures": { + "layer0": "gtceu:block/material_sets/paper/ore", + "layer1": "gtceu:block/material_sets/paper/ore_layer2", + "particle": "#layer0" + }, + "render_type": "translucent", + "elements": [ + { + "from": [0, 0, 0 ], + "to": [16, 16, 16], + "faces": { + "down": { "texture": "#layer0", "cullface": "down", "tintindex": 0 }, + "up": { "texture": "#layer0", "cullface": "up", "tintindex": 0 }, + "north": { "texture": "#layer0", "cullface": "north", "tintindex": 0 }, + "south": { "texture": "#layer0", "cullface": "south", "tintindex": 0 }, + "west": { "texture": "#layer0", "cullface": "west", "tintindex": 0 }, + "east": { "texture": "#layer0", "cullface": "east", "tintindex": 0 } + } + }, + { + "from": [0, 0, 0 ], + "to": [16, 16, 16], + "faces": { + "down": { "texture": "#layer1", "cullface": "down", "tintindex": 1 }, + "up": { "texture": "#layer1", "cullface": "up", "tintindex": 1 }, + "north": { "texture": "#layer1", "cullface": "north", "tintindex": 1 }, + "south": { "texture": "#layer1", "cullface": "south", "tintindex": 1 }, + "west": { "texture": "#layer1", "cullface": "west", "tintindex": 1 }, + "east": { "texture": "#layer1", "cullface": "east", "tintindex": 1 } + } + } + ] + } + }, + "item_render_order": [ + "base_stone", + "ore_texture" + ] +} diff --git a/src/main/resources/assets/gtceu/models/block/material_sets/paper/ore_emissive.json b/src/main/resources/assets/gtceu/models/block/material_sets/paper/ore_emissive.json new file mode 100644 index 00000000000..d5a86695f64 --- /dev/null +++ b/src/main/resources/assets/gtceu/models/block/material_sets/paper/ore_emissive.json @@ -0,0 +1,53 @@ +{ + "parent": "block/block", + "loader": "forge:composite", + "textures": { + "particle": "gtceu:block/material_sets/paper/ore_emissive" + }, + "children": { + "base_stone": { + "render_type": "solid" + }, + "ore_texture": { + "parent": "block/block", + "textures": { + "layer0": "gtceu:block/material_sets/paper/ore_emissive", + "layer1": "gtceu:block/material_sets/paper/ore_emissive_layer2", + "particle": "#layer0" + }, + "render_type": "translucent", + "elements": [ + { + "from": [0, 0, 0 ], + "to": [16, 16, 16], + "forge_data": { "block_light": 15, "sky_light": 15 }, + "faces": { + "down": { "texture": "#layer0", "cullface": "down", "tintindex": -101 }, + "up": { "texture": "#layer0", "cullface": "up", "tintindex": -101 }, + "north": { "texture": "#layer0", "cullface": "north", "tintindex": -101 }, + "south": { "texture": "#layer0", "cullface": "south", "tintindex": -101 }, + "west": { "texture": "#layer0", "cullface": "west", "tintindex": -101 }, + "east": { "texture": "#layer0", "cullface": "east", "tintindex": -101 } + } + }, + { + "from": [0, 0, 0 ], + "to": [16, 16, 16], + "forge_data": { "block_light": 15, "sky_light": 15 }, + "faces": { + "down": { "texture": "#layer1", "cullface": "down", "tintindex": -102 }, + "up": { "texture": "#layer1", "cullface": "up", "tintindex": -102 }, + "north": { "texture": "#layer1", "cullface": "north", "tintindex": -102 }, + "south": { "texture": "#layer1", "cullface": "south", "tintindex": -102 }, + "west": { "texture": "#layer1", "cullface": "west", "tintindex": -102 }, + "east": { "texture": "#layer1", "cullface": "east", "tintindex": -102 } + } + } + ] + } + }, + "item_render_order": [ + "base_stone", + "ore_texture" + ] +} diff --git a/src/main/resources/assets/gtceu/models/block/material_sets/powder/ore.json b/src/main/resources/assets/gtceu/models/block/material_sets/powder/ore.json new file mode 100644 index 00000000000..f8cbb176f81 --- /dev/null +++ b/src/main/resources/assets/gtceu/models/block/material_sets/powder/ore.json @@ -0,0 +1,51 @@ +{ + "parent": "block/block", + "loader": "forge:composite", + "textures": { + "particle": "gtceu:block/material_sets/powder/ore" + }, + "children": { + "base_stone": { + "render_type": "solid" + }, + "ore_texture": { + "parent": "block/block", + "textures": { + "layer0": "gtceu:block/material_sets/powder/ore", + "layer1": "gtceu:block/material_sets/powder/ore_layer2", + "particle": "#layer0" + }, + "render_type": "translucent", + "elements": [ + { + "from": [0, 0, 0 ], + "to": [16, 16, 16], + "faces": { + "down": { "texture": "#layer0", "cullface": "down", "tintindex": 0 }, + "up": { "texture": "#layer0", "cullface": "up", "tintindex": 0 }, + "north": { "texture": "#layer0", "cullface": "north", "tintindex": 0 }, + "south": { "texture": "#layer0", "cullface": "south", "tintindex": 0 }, + "west": { "texture": "#layer0", "cullface": "west", "tintindex": 0 }, + "east": { "texture": "#layer0", "cullface": "east", "tintindex": 0 } + } + }, + { + "from": [0, 0, 0 ], + "to": [16, 16, 16], + "faces": { + "down": { "texture": "#layer1", "cullface": "down", "tintindex": 1 }, + "up": { "texture": "#layer1", "cullface": "up", "tintindex": 1 }, + "north": { "texture": "#layer1", "cullface": "north", "tintindex": 1 }, + "south": { "texture": "#layer1", "cullface": "south", "tintindex": 1 }, + "west": { "texture": "#layer1", "cullface": "west", "tintindex": 1 }, + "east": { "texture": "#layer1", "cullface": "east", "tintindex": 1 } + } + } + ] + } + }, + "item_render_order": [ + "base_stone", + "ore_texture" + ] +} diff --git a/src/main/resources/assets/gtceu/models/block/material_sets/powder/ore_emissive.json b/src/main/resources/assets/gtceu/models/block/material_sets/powder/ore_emissive.json new file mode 100644 index 00000000000..001449aa154 --- /dev/null +++ b/src/main/resources/assets/gtceu/models/block/material_sets/powder/ore_emissive.json @@ -0,0 +1,53 @@ +{ + "parent": "block/block", + "loader": "forge:composite", + "textures": { + "particle": "gtceu:block/material_sets/powder/ore_emissive" + }, + "children": { + "base_stone": { + "render_type": "solid" + }, + "ore_texture": { + "parent": "block/block", + "textures": { + "layer0": "gtceu:block/material_sets/powder/ore_emissive", + "layer1": "gtceu:block/material_sets/powder/ore_emissive_layer2", + "particle": "#layer0" + }, + "render_type": "translucent", + "elements": [ + { + "from": [0, 0, 0 ], + "to": [16, 16, 16], + "forge_data": { "block_light": 15, "sky_light": 15 }, + "faces": { + "down": { "texture": "#layer0", "cullface": "down", "tintindex": -101 }, + "up": { "texture": "#layer0", "cullface": "up", "tintindex": -101 }, + "north": { "texture": "#layer0", "cullface": "north", "tintindex": -101 }, + "south": { "texture": "#layer0", "cullface": "south", "tintindex": -101 }, + "west": { "texture": "#layer0", "cullface": "west", "tintindex": -101 }, + "east": { "texture": "#layer0", "cullface": "east", "tintindex": -101 } + } + }, + { + "from": [0, 0, 0 ], + "to": [16, 16, 16], + "forge_data": { "block_light": 15, "sky_light": 15 }, + "faces": { + "down": { "texture": "#layer1", "cullface": "down", "tintindex": -102 }, + "up": { "texture": "#layer1", "cullface": "up", "tintindex": -102 }, + "north": { "texture": "#layer1", "cullface": "north", "tintindex": -102 }, + "south": { "texture": "#layer1", "cullface": "south", "tintindex": -102 }, + "west": { "texture": "#layer1", "cullface": "west", "tintindex": -102 }, + "east": { "texture": "#layer1", "cullface": "east", "tintindex": -102 } + } + } + ] + } + }, + "item_render_order": [ + "base_stone", + "ore_texture" + ] +} diff --git a/src/main/resources/assets/gtceu/models/block/material_sets/quartz/block.json b/src/main/resources/assets/gtceu/models/block/material_sets/quartz/block.json index 8c4b0140993..5241a54615e 100644 --- a/src/main/resources/assets/gtceu/models/block/material_sets/quartz/block.json +++ b/src/main/resources/assets/gtceu/models/block/material_sets/quartz/block.json @@ -1,7 +1,27 @@ { - "parent": "gtceu:block/cube_2_layer/tinted_both/all_translucent", + "parent": "block/block", + "loader": "forge:composite", "textures": { - "bot_all": "gtceu:block/material_sets/quartz/block", - "top_all": "gtceu:block/material_sets/quartz/block_secondary" - } + "particle": "gtceu:block/material_sets/quartz/block" + }, + "children": { + "base": { + "parent": "gtceu:block/cube/tinted/all_0", + "render_type": "solid", + "textures": { + "all": "gtceu:block/material_sets/quartz/block" + } + }, + "secondary": { + "parent": "gtceu:block/cube/tinted/all", + "render_type": "translucent", + "textures": { + "all": "gtceu:block/material_sets/quartz/block_secondary" + } + } + }, + "item_render_order": [ + "base", + "secondary" + ] } diff --git a/src/main/resources/assets/gtceu/models/block/material_sets/quartz/ore.json b/src/main/resources/assets/gtceu/models/block/material_sets/quartz/ore.json new file mode 100644 index 00000000000..228158d1450 --- /dev/null +++ b/src/main/resources/assets/gtceu/models/block/material_sets/quartz/ore.json @@ -0,0 +1,51 @@ +{ + "parent": "block/block", + "loader": "forge:composite", + "textures": { + "particle": "gtceu:block/material_sets/quartz/ore" + }, + "children": { + "base_stone": { + "render_type": "solid" + }, + "ore_texture": { + "parent": "block/block", + "textures": { + "layer0": "gtceu:block/material_sets/quartz/ore", + "layer1": "gtceu:block/material_sets/quartz/ore_layer2", + "particle": "#layer0" + }, + "render_type": "translucent", + "elements": [ + { + "from": [0, 0, 0 ], + "to": [16, 16, 16], + "faces": { + "down": { "texture": "#layer0", "cullface": "down", "tintindex": 0 }, + "up": { "texture": "#layer0", "cullface": "up", "tintindex": 0 }, + "north": { "texture": "#layer0", "cullface": "north", "tintindex": 0 }, + "south": { "texture": "#layer0", "cullface": "south", "tintindex": 0 }, + "west": { "texture": "#layer0", "cullface": "west", "tintindex": 0 }, + "east": { "texture": "#layer0", "cullface": "east", "tintindex": 0 } + } + }, + { + "from": [0, 0, 0 ], + "to": [16, 16, 16], + "faces": { + "down": { "texture": "#layer1", "cullface": "down", "tintindex": 1 }, + "up": { "texture": "#layer1", "cullface": "up", "tintindex": 1 }, + "north": { "texture": "#layer1", "cullface": "north", "tintindex": 1 }, + "south": { "texture": "#layer1", "cullface": "south", "tintindex": 1 }, + "west": { "texture": "#layer1", "cullface": "west", "tintindex": 1 }, + "east": { "texture": "#layer1", "cullface": "east", "tintindex": 1 } + } + } + ] + } + }, + "item_render_order": [ + "base_stone", + "ore_texture" + ] +} diff --git a/src/main/resources/assets/gtceu/models/block/material_sets/quartz/ore_emissive.json b/src/main/resources/assets/gtceu/models/block/material_sets/quartz/ore_emissive.json new file mode 100644 index 00000000000..646132f17cd --- /dev/null +++ b/src/main/resources/assets/gtceu/models/block/material_sets/quartz/ore_emissive.json @@ -0,0 +1,53 @@ +{ + "parent": "block/block", + "loader": "forge:composite", + "textures": { + "particle": "gtceu:block/material_sets/quartz/ore_emissive" + }, + "children": { + "base_stone": { + "render_type": "solid" + }, + "ore_texture": { + "parent": "block/block", + "textures": { + "layer0": "gtceu:block/material_sets/quartz/ore_emissive", + "layer1": "gtceu:block/material_sets/quartz/ore_emissive_layer2", + "particle": "#layer0" + }, + "render_type": "translucent", + "elements": [ + { + "from": [0, 0, 0 ], + "to": [16, 16, 16], + "forge_data": { "block_light": 15, "sky_light": 15 }, + "faces": { + "down": { "texture": "#layer0", "cullface": "down", "tintindex": -101 }, + "up": { "texture": "#layer0", "cullface": "up", "tintindex": -101 }, + "north": { "texture": "#layer0", "cullface": "north", "tintindex": -101 }, + "south": { "texture": "#layer0", "cullface": "south", "tintindex": -101 }, + "west": { "texture": "#layer0", "cullface": "west", "tintindex": -101 }, + "east": { "texture": "#layer0", "cullface": "east", "tintindex": -101 } + } + }, + { + "from": [0, 0, 0 ], + "to": [16, 16, 16], + "forge_data": { "block_light": 15, "sky_light": 15 }, + "faces": { + "down": { "texture": "#layer1", "cullface": "down", "tintindex": -102 }, + "up": { "texture": "#layer1", "cullface": "up", "tintindex": -102 }, + "north": { "texture": "#layer1", "cullface": "north", "tintindex": -102 }, + "south": { "texture": "#layer1", "cullface": "south", "tintindex": -102 }, + "west": { "texture": "#layer1", "cullface": "west", "tintindex": -102 }, + "east": { "texture": "#layer1", "cullface": "east", "tintindex": -102 } + } + } + ] + } + }, + "item_render_order": [ + "base_stone", + "ore_texture" + ] +} diff --git a/src/main/resources/assets/gtceu/models/block/material_sets/radioactive/block.json b/src/main/resources/assets/gtceu/models/block/material_sets/radioactive/block.json index 5158d10858e..5194e406e48 100644 --- a/src/main/resources/assets/gtceu/models/block/material_sets/radioactive/block.json +++ b/src/main/resources/assets/gtceu/models/block/material_sets/radioactive/block.json @@ -1,6 +1,24 @@ { "parent": "gtceu:block/material_sets/dull/block", - "textures": { - "top_all": "gtceu:block/material_sets/radioactive/block_secondary" - } + "loader": "forge:composite", + "children": { + "base": { + "parent": "gtceu:block/cube/tinted/all_0", + "render_type": "solid", + "textures": { + "all": "gtceu:block/material_sets/dull/block" + } + }, + "secondary": { + "parent": "gtceu:block/cube/tinted/all", + "render_type": "translucent", + "textures": { + "all": "gtceu:block/material_sets/radioactive/block_secondary" + } + } + }, + "item_render_order": [ + "base", + "secondary" + ] } diff --git a/src/main/resources/assets/gtceu/models/block/material_sets/radioactive/frame_gt.json b/src/main/resources/assets/gtceu/models/block/material_sets/radioactive/frame_gt.json index 03b56173f7f..b3050276fa1 100644 --- a/src/main/resources/assets/gtceu/models/block/material_sets/radioactive/frame_gt.json +++ b/src/main/resources/assets/gtceu/models/block/material_sets/radioactive/frame_gt.json @@ -1,6 +1,24 @@ { "parent": "gtceu:block/material_sets/dull/frame_gt", - "textures": { - "top_all": "gtceu:block/material_sets/radioactive/frame_gt_secondary" - } + "loader": "forge:composite", + "children": { + "base": { + "parent": "gtceu:block/cube/tinted/all_0", + "render_type": "cutout", + "textures": { + "all": "gtceu:block/material_sets/dull/frame_gt" + } + }, + "secondary": { + "parent": "gtceu:block/cube/tinted/all", + "render_type": "translucent", + "textures": { + "all": "gtceu:block/material_sets/radioactive/frame_gt_secondary" + } + } + }, + "item_render_order": [ + "base", + "secondary" + ] } diff --git a/src/main/resources/assets/gtceu/models/block/material_sets/rough/block.json b/src/main/resources/assets/gtceu/models/block/material_sets/rough/block.json index 52fa4e18cb6..0564fbf8739 100644 --- a/src/main/resources/assets/gtceu/models/block/material_sets/rough/block.json +++ b/src/main/resources/assets/gtceu/models/block/material_sets/rough/block.json @@ -1,7 +1,27 @@ { - "parent": "gtceu:block/cube_2_layer/tinted_both/all_translucent", + "parent": "block/block", + "loader": "forge:composite", "textures": { - "bot_all": "gtceu:block/material_sets/rough/block", - "top_all": "gtceu:block/material_sets/rough/block_secondary" - } + "particle": "gtceu:block/material_sets/rough/block" + }, + "children": { + "base": { + "parent": "gtceu:block/cube/tinted/all_0", + "render_type": "solid", + "textures": { + "all": "gtceu:block/material_sets/rough/block" + } + }, + "secondary": { + "parent": "gtceu:block/cube/tinted/all", + "render_type": "translucent", + "textures": { + "all": "gtceu:block/material_sets/rough/block_secondary" + } + } + }, + "item_render_order": [ + "base", + "secondary" + ] } diff --git a/src/main/resources/assets/gtceu/models/block/material_sets/rough/ore.json b/src/main/resources/assets/gtceu/models/block/material_sets/rough/ore.json new file mode 100644 index 00000000000..5f76ff8831f --- /dev/null +++ b/src/main/resources/assets/gtceu/models/block/material_sets/rough/ore.json @@ -0,0 +1,51 @@ +{ + "parent": "block/block", + "loader": "forge:composite", + "textures": { + "particle": "gtceu:block/material_sets/rough/ore" + }, + "children": { + "base_stone": { + "render_type": "solid" + }, + "ore_texture": { + "parent": "block/block", + "textures": { + "layer0": "gtceu:block/material_sets/rough/ore", + "layer1": "gtceu:block/material_sets/rough/ore_layer2", + "particle": "#layer0" + }, + "render_type": "translucent", + "elements": [ + { + "from": [0, 0, 0 ], + "to": [16, 16, 16], + "faces": { + "down": { "texture": "#layer0", "cullface": "down", "tintindex": 0 }, + "up": { "texture": "#layer0", "cullface": "up", "tintindex": 0 }, + "north": { "texture": "#layer0", "cullface": "north", "tintindex": 0 }, + "south": { "texture": "#layer0", "cullface": "south", "tintindex": 0 }, + "west": { "texture": "#layer0", "cullface": "west", "tintindex": 0 }, + "east": { "texture": "#layer0", "cullface": "east", "tintindex": 0 } + } + }, + { + "from": [0, 0, 0 ], + "to": [16, 16, 16], + "faces": { + "down": { "texture": "#layer1", "cullface": "down", "tintindex": 1 }, + "up": { "texture": "#layer1", "cullface": "up", "tintindex": 1 }, + "north": { "texture": "#layer1", "cullface": "north", "tintindex": 1 }, + "south": { "texture": "#layer1", "cullface": "south", "tintindex": 1 }, + "west": { "texture": "#layer1", "cullface": "west", "tintindex": 1 }, + "east": { "texture": "#layer1", "cullface": "east", "tintindex": 1 } + } + } + ] + } + }, + "item_render_order": [ + "base_stone", + "ore_texture" + ] +} diff --git a/src/main/resources/assets/gtceu/models/block/material_sets/rough/ore_emissive.json b/src/main/resources/assets/gtceu/models/block/material_sets/rough/ore_emissive.json new file mode 100644 index 00000000000..cfb1d0996a4 --- /dev/null +++ b/src/main/resources/assets/gtceu/models/block/material_sets/rough/ore_emissive.json @@ -0,0 +1,53 @@ +{ + "parent": "block/block", + "loader": "forge:composite", + "textures": { + "particle": "gtceu:block/material_sets/rough/ore_emissive" + }, + "children": { + "base_stone": { + "render_type": "solid" + }, + "ore_texture": { + "parent": "block/block", + "textures": { + "layer0": "gtceu:block/material_sets/rough/ore_emissive", + "layer1": "gtceu:block/material_sets/rough/ore_emissive_layer2", + "particle": "#layer0" + }, + "render_type": "translucent", + "elements": [ + { + "from": [0, 0, 0 ], + "to": [16, 16, 16], + "forge_data": { "block_light": 15, "sky_light": 15 }, + "faces": { + "down": { "texture": "#layer0", "cullface": "down", "tintindex": -101 }, + "up": { "texture": "#layer0", "cullface": "up", "tintindex": -101 }, + "north": { "texture": "#layer0", "cullface": "north", "tintindex": -101 }, + "south": { "texture": "#layer0", "cullface": "south", "tintindex": -101 }, + "west": { "texture": "#layer0", "cullface": "west", "tintindex": -101 }, + "east": { "texture": "#layer0", "cullface": "east", "tintindex": -101 } + } + }, + { + "from": [0, 0, 0 ], + "to": [16, 16, 16], + "forge_data": { "block_light": 15, "sky_light": 15 }, + "faces": { + "down": { "texture": "#layer1", "cullface": "down", "tintindex": -102 }, + "up": { "texture": "#layer1", "cullface": "up", "tintindex": -102 }, + "north": { "texture": "#layer1", "cullface": "north", "tintindex": -102 }, + "south": { "texture": "#layer1", "cullface": "south", "tintindex": -102 }, + "west": { "texture": "#layer1", "cullface": "west", "tintindex": -102 }, + "east": { "texture": "#layer1", "cullface": "east", "tintindex": -102 } + } + } + ] + } + }, + "item_render_order": [ + "base_stone", + "ore_texture" + ] +} diff --git a/src/main/resources/assets/gtceu/models/block/material_sets/sand/block.json b/src/main/resources/assets/gtceu/models/block/material_sets/sand/block.json index 5c23ce2fa58..99feb35f9bd 100644 --- a/src/main/resources/assets/gtceu/models/block/material_sets/sand/block.json +++ b/src/main/resources/assets/gtceu/models/block/material_sets/sand/block.json @@ -1,7 +1,27 @@ { - "parent": "gtceu:block/cube_2_layer/tinted_both/all_translucent", + "parent": "block/block", + "loader": "forge:composite", "textures": { - "bot_all": "gtceu:block/material_sets/sand/block", - "top_all": "gtceu:block/material_sets/sand/block_secondary" - } + "particle": "gtceu:block/material_sets/sand/block" + }, + "children": { + "base": { + "parent": "gtceu:block/cube/tinted/all_0", + "render_type": "solid", + "textures": { + "all": "gtceu:block/material_sets/sand/block" + } + }, + "secondary": { + "parent": "gtceu:block/cube/tinted/all", + "render_type": "translucent", + "textures": { + "all": "gtceu:block/material_sets/sand/block_secondary" + } + } + }, + "item_render_order": [ + "base", + "secondary" + ] } diff --git a/src/main/resources/assets/gtceu/models/block/material_sets/shiny/block.json b/src/main/resources/assets/gtceu/models/block/material_sets/shiny/block.json index c260da6326c..2c9c91c7368 100644 --- a/src/main/resources/assets/gtceu/models/block/material_sets/shiny/block.json +++ b/src/main/resources/assets/gtceu/models/block/material_sets/shiny/block.json @@ -1,7 +1,27 @@ { - "parent": "gtceu:block/cube_2_layer/tinted_both/all_translucent", + "parent": "block/block", + "loader": "forge:composite", "textures": { - "bot_all": "gtceu:block/material_sets/shiny/block", - "top_all": "gtceu:block/material_sets/shiny/block_secondary" - } + "particle": "gtceu:block/material_sets/shiny/block" + }, + "children": { + "base": { + "parent": "gtceu:block/cube/tinted/all_0", + "render_type": "solid", + "textures": { + "all": "gtceu:block/material_sets/shiny/block" + } + }, + "secondary": { + "parent": "gtceu:block/cube/tinted/all", + "render_type": "translucent", + "textures": { + "all": "gtceu:block/material_sets/shiny/block_secondary" + } + } + }, + "item_render_order": [ + "base", + "secondary" + ] } diff --git a/src/main/resources/assets/gtceu/models/block/material_sets/wood/block.json b/src/main/resources/assets/gtceu/models/block/material_sets/wood/block.json index 847ff131455..375e29e2abf 100644 --- a/src/main/resources/assets/gtceu/models/block/material_sets/wood/block.json +++ b/src/main/resources/assets/gtceu/models/block/material_sets/wood/block.json @@ -1,7 +1,27 @@ { - "parent": "gtceu:block/cube_2_layer/tinted_both/all_translucent", + "parent": "block/block", + "loader": "forge:composite", "textures": { - "bot_all": "gtceu:block/material_sets/wood/block", - "top_all": "gtceu:block/material_sets/wood/block_secondary" - } + "particle": "gtceu:block/material_sets/wood/block" + }, + "children": { + "base": { + "parent": "gtceu:block/cube/tinted/all_0", + "render_type": "solid", + "textures": { + "all": "gtceu:block/material_sets/wood/block" + } + }, + "secondary": { + "parent": "gtceu:block/cube/tinted/all", + "render_type": "translucent", + "textures": { + "all": "gtceu:block/material_sets/wood/block_secondary" + } + } + }, + "item_render_order": [ + "base", + "secondary" + ] } diff --git a/src/main/resources/assets/gtceu/textures/block/machines/electrolyzer/overlay_front.png b/src/main/resources/assets/gtceu/textures/block/machines/electrolyzer/overlay_front.png index eb8aef6ab7d..c59c7c2c55a 100644 Binary files a/src/main/resources/assets/gtceu/textures/block/machines/electrolyzer/overlay_front.png and b/src/main/resources/assets/gtceu/textures/block/machines/electrolyzer/overlay_front.png differ diff --git a/src/main/resources/assets/gtceu/textures/block/material_sets/paper/foil.png b/src/main/resources/assets/gtceu/textures/block/material_sets/paper/foil.png deleted file mode 100644 index 2f1b92d5cdc..00000000000 Binary files a/src/main/resources/assets/gtceu/textures/block/material_sets/paper/foil.png and /dev/null differ diff --git a/src/main/resources/assets/gtceu/textures/block/material_sets/paper/wire.png b/src/main/resources/assets/gtceu/textures/block/material_sets/paper/wire_side.png similarity index 100% rename from src/main/resources/assets/gtceu/textures/block/material_sets/paper/wire.png rename to src/main/resources/assets/gtceu/textures/block/material_sets/paper/wire_side.png 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 + } +} diff --git a/src/main/resources/gtceu.mixins.json b/src/main/resources/gtceu.mixins.json index 4e26ab732db..c7352d5caf9 100644 --- a/src/main/resources/gtceu.mixins.json +++ b/src/main/resources/gtceu.mixins.json @@ -21,6 +21,7 @@ "client.MultiPlayerGameModeMixin", "client.PlayerInfoAccessor", "client.VariantDeserializerMixin", + "dev.client.KeyboardHandlerMixin", "ftbchunks.FTBChunksClientMixin", "ftbchunks.LargeMapScreenMixin", "ftbchunks.RegionMapPanelMixin", @@ -57,6 +58,7 @@ "ServerGamePacketListenerImplAccessor", "ShapedRecipeAccessor", "SidedRedstoneConnectivityMixin", + "SmithingTransformRecipeMixin", "TagLoaderMixin", "TagManagerMixin", "TagValueAccessor", diff --git a/src/test/java/com/gregtechceu/gtceu/api/recipe/ingredient/IntProviderFluidIngredientTest.java b/src/test/java/com/gregtechceu/gtceu/api/recipe/ingredient/IntProviderFluidIngredientTest.java index d8c27ffe263..c5969ab5b0d 100644 --- a/src/test/java/com/gregtechceu/gtceu/api/recipe/ingredient/IntProviderFluidIngredientTest.java +++ b/src/test/java/com/gregtechceu/gtceu/api/recipe/ingredient/IntProviderFluidIngredientTest.java @@ -595,7 +595,9 @@ public static void multiblockLCRRangedFluidOutput(GameTestHelper helper) { // test for multiblock machine with 16x Parallels with ranged fluid input @GameTest(template = "large_centrifuge_zpm_batch_parallel16", batch = "RangedFluidIngredients", - timeoutTicks = 200) + timeoutTicks = 200, + requiredSuccesses = 1, + attempts = 10) public static void multiblockLCentRangedFluidInput16Parallel(GameTestHelper helper) { BusHolderBatchParallel busHolder = getBussesAndFormLCENT(helper); @@ -667,7 +669,9 @@ public static void multiblockLCentRangedFluidInput16Parallel(GameTestHelper help // test for multiblock machine with 16x Parallels with ranged fluid output @GameTest(template = "large_centrifuge_zpm_batch_parallel16", batch = "RangedFluidIngredients", - timeoutTicks = 200) + timeoutTicks = 200, + requiredSuccesses = 1, + attempts = 10) public static void multiblockLCentRangedFluidOutput16Parallel(GameTestHelper helper) { BusHolderBatchParallel busHolder = getBussesAndFormLCENT(helper); @@ -741,7 +745,9 @@ public static void multiblockLCentRangedFluidOutput16Parallel(GameTestHelper hel // test for multiblock machine with 16x Parallels with ranged fluid input @GameTest(template = "large_centrifuge_zpm_batch_parallel16", batch = "RangedFluidIngredients", - timeoutTicks = 200) + timeoutTicks = 200, + requiredSuccesses = 1, + attempts = 10) public static void multiblockLCentRangedFluidInputBatched(GameTestHelper helper) { BusHolderBatchParallel busHolder = getBussesAndFormLCENT(helper); @@ -813,7 +819,9 @@ public static void multiblockLCentRangedFluidInputBatched(GameTestHelper helper) // test for multiblock machine with 16x Parallels with ranged fluid output @GameTest(template = "large_centrifuge_zpm_batch_parallel16", batch = "RangedFluidIngredients", - timeoutTicks = 200) + timeoutTicks = 200, + requiredSuccesses = 1, + attempts = 10) public static void multiblockLCentRangedFluidOutputBatched(GameTestHelper helper) { BusHolderBatchParallel busHolder = getBussesAndFormLCENT(helper); @@ -887,7 +895,9 @@ public static void multiblockLCentRangedFluidOutputBatched(GameTestHelper helper // test for multiblock machine with 16x Parallels with ranged fluid input @GameTest(template = "large_centrifuge_zpm_batch_parallel16", batch = "RangedFluidIngredients", - timeoutTicks = 500) + timeoutTicks = 500, + requiredSuccesses = 1, + attempts = 10) public static void multiblockLCentRangedFluidInput16ParallelBatched(GameTestHelper helper) { BusHolderBatchParallel busHolder = getBussesAndFormLCENT(helper); @@ -964,7 +974,9 @@ public static void multiblockLCentRangedFluidInput16ParallelBatched(GameTestHelp // test for multiblock machine with 16x Parallels with ranged fluid output @GameTest(template = "large_centrifuge_zpm_batch_parallel16", batch = "RangedFluidIngredients", - timeoutTicks = 500) + timeoutTicks = 500, + requiredSuccesses = 1, + attempts = 10) public static void multiblockLCentRangedFluidOutput16ParallelBatched(GameTestHelper helper) { BusHolderBatchParallel busHolder = getBussesAndFormLCENT(helper); diff --git a/src/test/java/com/gregtechceu/gtceu/api/recipe/ingredient/IntProviderIngredientTest.java b/src/test/java/com/gregtechceu/gtceu/api/recipe/ingredient/IntProviderIngredientTest.java index a492540d596..f3b7bee123a 100644 --- a/src/test/java/com/gregtechceu/gtceu/api/recipe/ingredient/IntProviderIngredientTest.java +++ b/src/test/java/com/gregtechceu/gtceu/api/recipe/ingredient/IntProviderIngredientTest.java @@ -584,7 +584,9 @@ public static void multiblockLCRRangedItemOutput(GameTestHelper helper) { // test for multiblock machine with 16x Parallels with ranged item input @GameTest(template = "large_centrifuge_zpm_batch_parallel16", batch = "RangedIngredients", - timeoutTicks = 200) + timeoutTicks = 200, + requiredSuccesses = 1, + attempts = 10) public static void multiblockLCentRangedItemInput16Parallel(GameTestHelper helper) { BusHolderBatchParallel busHolder = getBussesAndFormLCENT(helper); @@ -654,7 +656,9 @@ public static void multiblockLCentRangedItemInput16Parallel(GameTestHelper helpe // test for multiblock machine with 16x Parallels with ranged item output @GameTest(template = "large_centrifuge_zpm_batch_parallel16", batch = "RangedIngredients", - timeoutTicks = 200) + timeoutTicks = 200, + requiredSuccesses = 1, + attempts = 10) public static void multiblockLCentRangedItemOutput16Parallel(GameTestHelper helper) { BusHolderBatchParallel busHolder = getBussesAndFormLCENT(helper); @@ -728,7 +732,9 @@ public static void multiblockLCentRangedItemOutput16Parallel(GameTestHelper help // test for multiblock machine with 16x Parallels with ranged item input @GameTest(template = "large_centrifuge_zpm_batch_parallel16", batch = "RangedIngredients", - timeoutTicks = 200) + timeoutTicks = 200, + requiredSuccesses = 1, + attempts = 10) public static void multiblockLCentRangedItemInputBatched(GameTestHelper helper) { BusHolderBatchParallel busHolder = getBussesAndFormLCENT(helper); @@ -798,7 +804,9 @@ public static void multiblockLCentRangedItemInputBatched(GameTestHelper helper) // test for multiblock machine with 16x Parallels with ranged item output @GameTest(template = "large_centrifuge_zpm_batch_parallel16", batch = "RangedIngredients", - timeoutTicks = 200) + timeoutTicks = 200, + requiredSuccesses = 1, + attempts = 10) public static void multiblockLCentRangedItemOutputBatched(GameTestHelper helper) { BusHolderBatchParallel busHolder = getBussesAndFormLCENT(helper); @@ -872,7 +880,9 @@ public static void multiblockLCentRangedItemOutputBatched(GameTestHelper helper) // test for multiblock machine with 16x Parallels with ranged item input @GameTest(template = "large_centrifuge_zpm_batch_parallel16", batch = "RangedIngredients", - timeoutTicks = 500) + timeoutTicks = 500, + requiredSuccesses = 1, + attempts = 10) public static void multiblockLCentRangedItemInput16ParallelBatched(GameTestHelper helper) { BusHolderBatchParallel busHolder = getBussesAndFormLCENT(helper); @@ -954,7 +964,9 @@ public static void multiblockLCentRangedItemInput16ParallelBatched(GameTestHelpe // test for multiblock machine with 16x Parallels with ranged item output @GameTest(template = "large_centrifuge_zpm_batch_parallel16", batch = "RangedIngredients", - timeoutTicks = 500) + timeoutTicks = 500, + requiredSuccesses = 1, + attempts = 10) public static void multiblockLCentRangedItemOutput16ParallelBatched(GameTestHelper helper) { BusHolderBatchParallel busHolder = getBussesAndFormLCENT(helper); diff --git a/src/test/java/com/gregtechceu/gtceu/common/recipe/condition/AdjacentFluidConditionTest.java b/src/test/java/com/gregtechceu/gtceu/common/recipe/condition/AdjacentFluidConditionTest.java index a291a0ecb2f..cc67d2c6f7d 100644 --- a/src/test/java/com/gregtechceu/gtceu/common/recipe/condition/AdjacentFluidConditionTest.java +++ b/src/test/java/com/gregtechceu/gtceu/common/recipe/condition/AdjacentFluidConditionTest.java @@ -37,7 +37,7 @@ public static void prepare(ServerLevel level) { .recipeBuilder(GTCEu.id("test_adjacent_fluid_conditions")) .inputItems(new ItemStack(Blocks.COBBLESTONE)) .outputItems(new ItemStack(Blocks.STONE)) - .adjacentFluidTag(FluidTags.WATER) + .adjacentFluids(FluidTags.WATER) .EUt(GTValues.VA[GTValues.HV]) .duration(8) .buildRawRecipe()); @@ -46,7 +46,7 @@ public static void prepare(ServerLevel level) { .recipeBuilder(GTCEu.id("test_adjacent_fluid_conditions_multiple_fluids")) .inputItems(new ItemStack(Blocks.OAK_WOOD)) .outputItems(new ItemStack(Items.CHARCOAL)) - .adjacentFluidTag(FluidTags.WATER, FluidTags.LAVA) + .adjacentFluids(FluidTags.WATER, FluidTags.LAVA) .EUt(GTValues.VA[GTValues.HV]) .duration(8) .buildRawRecipe());