Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 44f03b2c96 | |||
| c3e0ab16b7 | |||
| d8e4153754 | |||
| 572182e9f0 | |||
| 6f394bbe6f | |||
| b05c0ebd42 | |||
| 4309310c02 | |||
| 74a290fd16 | |||
| a430a8e62b | |||
| 3afee9e501 | |||
| 319d247e4c | |||
| f1af00738e | |||
| 3048f53878 | |||
| f222e4dc24 | |||
| 5c064176b2 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -33,3 +33,4 @@ local.properties
|
||||
*-autosave.kra
|
||||
*.kra~
|
||||
/src/generated/
|
||||
/libs/
|
||||
|
||||
16
LICENSE
16
LICENSE
@@ -1,15 +1 @@
|
||||
Copyright (c) 2019 B0undarybreaker (Meredith Espinosa)
|
||||
Copyright (c) 2024 Adrien1106
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
MIT AND LGPL-3.0
|
||||
165
LICENSE.LGPL-3.0
Normal file
165
LICENSE.LGPL-3.0
Normal file
@@ -0,0 +1,165 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
||||
15
LICENSE.MIT
Normal file
15
LICENSE.MIT
Normal file
@@ -0,0 +1,15 @@
|
||||
Copyright (c) 2019 B0undarybreaker (Meredith Espinosa)\
|
||||
Copyright (c) 2024 Adrien1106
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
43
README.md
Normal file
43
README.md
Normal file
@@ -0,0 +1,43 @@
|
||||
# ReFramed
|
||||
## Overview
|
||||
This Project is an unofficial port of [FramedBlocks](https://github.com/XFactHD/FramedBlocks)
|
||||
forked from [Templates 2](https://github.com/quat1024/templates-mod).
|
||||
It aims to add the same mechanics as [FramedBlocks](https://github.com/XFactHD/FramedBlocks) into Fabric.
|
||||
|
||||
For a complete Feature list please have a look at the [Modrinth](https://modrinth.com/mod/reframed) page.
|
||||
|
||||
## Information
|
||||
### Where to get it?
|
||||
The mod can be downloaded on [Modrinth](https://modrinth.com/mod/reframed).
|
||||
|
||||
### Issues/requests
|
||||
Any issues/requests may be addressed on this repository in the [Issues](https://github.com/DriHut/ReFramed/issues) section.
|
||||
|
||||
### Out of date?
|
||||
I will be adding new shapes as time passes, but I am currently not planing on keeping up with the newer versions of the game.
|
||||
That said this mod is under permissive licenses and make it easy for anyone to create their own fork.
|
||||
If anyone in the future plans to do so, I will gladly either link it from here and the modrinth page,
|
||||
or based on preferences add the person(s) to the project
|
||||
|
||||
### What Shapes are planed to be added
|
||||
Currently, the list of shapes to be added is pretty simple as the mod is still under development:
|
||||
- Wall
|
||||
- Fence
|
||||
- Pane
|
||||
- Button
|
||||
- Pressure Plate
|
||||
- Trapdoor
|
||||
- Door
|
||||
- Carpet
|
||||
- Post
|
||||
- Half Slab (maybe redundant with Layer)
|
||||
- Slabs Stair (a stair with one end being of a second theme, might be done in multiple blocks)
|
||||
|
||||
Any Ideas feel free to make a suggestion [here](https://github.com/DriHut/ReFramed/issues).
|
||||
|
||||
## License
|
||||
This work is dual-licensed under MIT and LGPL 3.0 both applying to different part of this project:
|
||||
- The LGPL 3.0 license applies to all the textures that can be found in [`assets/reframed/textures`](src/main/resources/assets/reframed/textures)
|
||||
- The MIT license applied to everything else so including all the code present within this project
|
||||
|
||||
`SPDX-License-Identifier: MIT AND LGPL-3.0`
|
||||
@@ -110,11 +110,15 @@ dependencies {
|
||||
modCompileOnly "earth.terrarium.athena:athena-fabric-${project.minecraft_version}:${project.athena_version}"
|
||||
modRuntimeOnly "earth.terrarium.athena:athena-fabric-${project.minecraft_version}:${project.athena_version}"
|
||||
|
||||
// Continuity for connectedTextures
|
||||
modCompileOnly "maven.modrinth:continuity:${project.continuity_version}"
|
||||
modRuntimeOnly "maven.modrinth:continuity:${project.continuity_version}"
|
||||
|
||||
// Chipped to test athena implementation
|
||||
modRuntimeOnly "com.teamresourceful.resourcefullib:resourcefullib-fabric-${project.minecraft_version}:2.4.7"
|
||||
modRuntimeOnly "earth.terrarium.chipped:Chipped-fabric-${project.minecraft_version}:3.1.2"
|
||||
|
||||
// Fabric API. This is technically optional, but you probably want it anyway.
|
||||
// Fabric API.
|
||||
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
|
||||
}
|
||||
|
||||
@@ -126,6 +130,7 @@ processResources {
|
||||
inputs.property "athena_version", project.athena_version
|
||||
inputs.property "indium_version", project.indium_version
|
||||
inputs.property "sodium_version", project.sodium_version
|
||||
inputs.property "continuity_version", project.continuity_version
|
||||
filteringCharset "UTF-8"
|
||||
|
||||
filesMatching("fabric.mod.json") {
|
||||
@@ -205,6 +210,7 @@ modrinth {
|
||||
required.project "fabric-api"
|
||||
optional.version "b1ZV3DIJ", "${project.athena_version}"
|
||||
optional.version "Orvt0mRa", "${project.indium_version}+mc${project.minecraft_version}"
|
||||
optional.version "1IjD5062", "${project.continuity_version}"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ loader_version=0.15.6
|
||||
|
||||
# Mod Properties
|
||||
modrinth_id = jCpoCBpn
|
||||
mod_version = 1.5
|
||||
mod_version = 1.5.7
|
||||
maven_group = fr.adrien1106
|
||||
archives_base_name = ReFramed
|
||||
mod_id = reframed
|
||||
@@ -24,3 +24,4 @@ git_repo=ReFramed
|
||||
athena_version=3.3.0
|
||||
sodium_version=0.5.8
|
||||
indium_version=1.0.30
|
||||
continuity_version=3.0.0-beta.4+1.20.2
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
package fr.adrien1106.reframed;
|
||||
|
||||
import fr.adrien1106.reframed.block.*;
|
||||
import fr.adrien1106.reframed.item.ReFramedHammerItem;
|
||||
import fr.adrien1106.reframed.item.ReFramedBlueprintItem;
|
||||
import fr.adrien1106.reframed.item.ReFramedBlueprintWrittenItem;
|
||||
import fr.adrien1106.reframed.item.ReFramedScrewdriverItem;
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
import net.fabricmc.fabric.api.itemgroup.v1.FabricItemGroup;
|
||||
import net.fabricmc.fabric.api.object.builder.v1.block.entity.FabricBlockEntityTypeBuilder;
|
||||
@@ -8,10 +12,7 @@ import net.minecraft.block.AbstractBlock;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.block.entity.BlockEntityType;
|
||||
import net.minecraft.item.BlockItem;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemGroup;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.*;
|
||||
import net.minecraft.registry.Registries;
|
||||
import net.minecraft.registry.Registry;
|
||||
import net.minecraft.sound.BlockSoundGroup;
|
||||
@@ -22,23 +23,26 @@ import net.minecraft.world.World;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static fr.adrien1106.reframed.util.blocks.BlockProperties.LIGHT;
|
||||
|
||||
/**
|
||||
* TODO make block pairable by right click -> for v1.6
|
||||
* TODO add Hammer from framed ( removes theme ) -> for v1.5.5
|
||||
* TODO add screwdriver ( iterate over theme states ) ?
|
||||
* TODO add blueprint for survival friendly copy paste of a theme. -> for v1.5.5
|
||||
* TODO add minecraft models like wall fence etc -> for v1.6
|
||||
* TODO better connected textures -> maybe v1.6 ?
|
||||
* TODO Dynamic Ambient Occlusion -> for v1.6
|
||||
* TODO add minecraft models like wall fence etc -> for v1.6
|
||||
* TODO better connected textures -> maybe v1.6 ?
|
||||
* TODO support continuity overlays -> not scheduled
|
||||
* TODO better state caching per models (e.g. wall only has 3 max per model) -> not scheduled
|
||||
*/
|
||||
public class ReFramed implements ModInitializer {
|
||||
public static final String MODID = "reframed";
|
||||
|
||||
public static final ArrayList<Block> BLOCKS = new ArrayList<>();
|
||||
public static Block CUBE, SMALL_CUBE, SMALL_CUBES_STEP, STAIR, HALF_STAIR, STAIRS_CUBE, HALF_STAIRS_SLAB, HALF_STAIRS_STAIR, SLAB, SLABS_CUBE, STEP, STEPS_SLAB, LAYER;
|
||||
public static Block CUBE, SMALL_CUBE, SMALL_CUBES_STEP, STAIR, HALF_STAIR, STAIRS_CUBE, HALF_STAIRS_SLAB, HALF_STAIRS_STAIR, SLAB, SLABS_CUBE, STEP, STEPS_SLAB, LAYER, PILLAR, WALL;
|
||||
|
||||
public static final ArrayList<Item> ITEMS = new ArrayList<>();
|
||||
public static Item HAMMER, SCREWDRIVER, BLUEPRINT, BLUEPRINT_WRITTEN;
|
||||
|
||||
public static ItemGroup ITEM_GROUP;
|
||||
|
||||
public static BlockEntityType<ReFramedEntity> REFRAMED_BLOCK_ENTITY;
|
||||
@@ -48,19 +52,26 @@ public class ReFramed implements ModInitializer {
|
||||
|
||||
@Override
|
||||
public void onInitialize() {
|
||||
CUBE = registerReFramed("cube" , new ReFramedBlock(cp(Blocks.OAK_PLANKS)));
|
||||
SMALL_CUBE = registerReFramed("small_cube" , new ReFramedSmallCubeBlock(cp(Blocks.OAK_PLANKS)));
|
||||
SMALL_CUBES_STEP = registerReFramed("small_cubes_step" , new ReFramedSmallCubesStepBlock(cp(Blocks.OAK_PLANKS)));
|
||||
STAIR = registerReFramed("stair" , new ReFramedStairBlock(cp(Blocks.OAK_STAIRS)));
|
||||
STAIRS_CUBE = registerReFramed("stairs_cube" , new ReFramedStairsCubeBlock(cp(Blocks.OAK_STAIRS)));
|
||||
HALF_STAIR = registerReFramed("half_stair" , new ReFramedHalfStairBlock(cp(Blocks.OAK_STAIRS)));
|
||||
HALF_STAIRS_SLAB = registerReFramed("half_stairs_slab" , new ReFramedHalfStairsSlabBlock(cp(Blocks.OAK_STAIRS)));
|
||||
HALF_STAIRS_STAIR = registerReFramed("half_stairs_stair" , new ReFramedHalfStairsStairBlock(cp(Blocks.OAK_STAIRS)));
|
||||
LAYER = registerReFramed("layer" , new ReFramedLayerBlock(cp(Blocks.OAK_SLAB)));
|
||||
SLAB = registerReFramed("slab" , new ReFramedSlabBlock(cp(Blocks.OAK_SLAB)));
|
||||
SLABS_CUBE = registerReFramed("slabs_cube" , new ReFramedSlabsCubeBlock(cp(Blocks.OAK_SLAB)));
|
||||
STEP = registerReFramed("step" , new ReFramedStepBlock(cp(Blocks.OAK_SLAB)));
|
||||
STEPS_SLAB = registerReFramed("steps_slab" , new ReFramedStepsSlabBlock(cp(Blocks.OAK_SLAB)));
|
||||
CUBE = registerBlock("cube" , new ReFramedBlock(cp(Blocks.OAK_PLANKS)));
|
||||
SMALL_CUBE = registerBlock("small_cube" , new ReFramedSmallCubeBlock(cp(Blocks.OAK_PLANKS)));
|
||||
SMALL_CUBES_STEP = registerBlock("small_cubes_step" , new ReFramedSmallCubesStepBlock(cp(Blocks.OAK_PLANKS)));
|
||||
STAIR = registerBlock("stair" , new ReFramedStairBlock(cp(Blocks.OAK_STAIRS)));
|
||||
STAIRS_CUBE = registerBlock("stairs_cube" , new ReFramedStairsCubeBlock(cp(Blocks.OAK_STAIRS)));
|
||||
HALF_STAIR = registerBlock("half_stair" , new ReFramedHalfStairBlock(cp(Blocks.OAK_STAIRS)));
|
||||
HALF_STAIRS_SLAB = registerBlock("half_stairs_slab" , new ReFramedHalfStairsSlabBlock(cp(Blocks.OAK_STAIRS)));
|
||||
HALF_STAIRS_STAIR = registerBlock("half_stairs_stair" , new ReFramedHalfStairsStairBlock(cp(Blocks.OAK_STAIRS)));
|
||||
LAYER = registerBlock("layer" , new ReFramedLayerBlock(cp(Blocks.OAK_SLAB)));
|
||||
SLAB = registerBlock("slab" , new ReFramedSlabBlock(cp(Blocks.OAK_SLAB)));
|
||||
SLABS_CUBE = registerBlock("slabs_cube" , new ReFramedSlabsCubeBlock(cp(Blocks.OAK_SLAB)));
|
||||
STEP = registerBlock("step" , new ReFramedStepBlock(cp(Blocks.OAK_SLAB)));
|
||||
STEPS_SLAB = registerBlock("steps_slab" , new ReFramedStepsSlabBlock(cp(Blocks.OAK_SLAB)));
|
||||
PILLAR = registerBlock("pillar" , new ReFramedPillarBlock(cp(Blocks.OAK_FENCE)));
|
||||
WALL = registerBlock("wall" , new ReframedWallBlock(cp(Blocks.OAK_FENCE)));
|
||||
|
||||
HAMMER = registerItem("hammer" , new ReFramedHammerItem(new Item.Settings().maxCount(1)));
|
||||
SCREWDRIVER = registerItem("screwdriver" , new ReFramedScrewdriverItem(new Item.Settings().maxCount(1)));
|
||||
BLUEPRINT = registerItem("blueprint" , new ReFramedBlueprintItem(new Item.Settings()));
|
||||
BLUEPRINT_WRITTEN = registerItem("blueprint_written" , new ReFramedBlueprintWrittenItem(new Item.Settings().maxCount(1)));
|
||||
|
||||
REFRAMED_BLOCK_ENTITY = Registry.register(Registries.BLOCK_ENTITY_TYPE, id("camo"),
|
||||
FabricBlockEntityTypeBuilder.create(
|
||||
@@ -81,7 +92,12 @@ public class ReFramed implements ModInitializer {
|
||||
ITEM_GROUP = Registry.register(Registries.ITEM_GROUP, id("tab"), FabricItemGroup.builder()
|
||||
.displayName(Text.translatable("itemGroup.reframed.tab"))
|
||||
.icon(() -> new ItemStack(SLAB))
|
||||
.entries((ctx, e) -> e.addAll(BLOCKS.stream().map(ItemStack::new).collect(Collectors.toList()))).build()
|
||||
.entries((ctx, e) -> e.addAll(
|
||||
Stream.concat(
|
||||
ITEMS.stream().filter(item -> item != BLUEPRINT_WRITTEN),
|
||||
BLOCKS.stream().map(Block::asItem)
|
||||
).map(Item::getDefaultStack).toList())
|
||||
).build()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -94,8 +110,15 @@ public class ReFramed implements ModInitializer {
|
||||
.suffocates((a,b,c) -> false)
|
||||
.blockVision((a,b,c) -> false);
|
||||
}
|
||||
|
||||
private static <I extends Item> I registerItem(String path, I item) {
|
||||
Identifier id = id(path);
|
||||
Registry.register(Registries.ITEM, id, item);
|
||||
ITEMS.add(item);
|
||||
return item;
|
||||
}
|
||||
|
||||
private static <B extends Block> B registerReFramed(String path, B block) {
|
||||
private static <B extends Block> B registerBlock(String path, B block) {
|
||||
Identifier id = id(path);
|
||||
|
||||
Registry.register(Registries.BLOCK, id, block);
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
package fr.adrien1106.reframed.block;
|
||||
|
||||
import fr.adrien1106.reframed.ReFramed;
|
||||
import fr.adrien1106.reframed.generator.RecipeSetter;
|
||||
import fr.adrien1106.reframed.util.blocks.BlockHelper;
|
||||
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
|
||||
import net.minecraft.block.*;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.data.server.recipe.RecipeExporter;
|
||||
import net.minecraft.data.server.recipe.ShapedRecipeJsonBuilder;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.BlockItem;
|
||||
@@ -15,7 +11,8 @@ import net.minecraft.item.ItemPlacementContext;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.recipe.book.RecipeCategory;
|
||||
import net.minecraft.nbt.NbtHelper;
|
||||
import net.minecraft.registry.Registries;
|
||||
import net.minecraft.state.StateManager;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.Hand;
|
||||
@@ -31,11 +28,15 @@ import net.minecraft.world.GameRules;
|
||||
import net.minecraft.world.World;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import static fr.adrien1106.reframed.block.ReFramedEntity.BLOCKSTATE_KEY;
|
||||
import static fr.adrien1106.reframed.util.blocks.BlockProperties.LIGHT;
|
||||
|
||||
public class ReFramedBlock extends Block implements BlockEntityProvider, RecipeSetter {
|
||||
public class ReFramedBlock extends Block implements BlockEntityProvider {
|
||||
|
||||
public ReFramedBlock(Settings settings) {
|
||||
super(settings);
|
||||
@@ -97,7 +98,7 @@ public class ReFramedBlock extends Block implements BlockEntityProvider, RecipeS
|
||||
|
||||
@Override
|
||||
public void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) {
|
||||
if(!state.isOf(newState.getBlock()) &&
|
||||
if(!(newState.getBlock() instanceof ReFramedBlock) &&
|
||||
world.getBlockEntity(pos) instanceof ReFramedEntity frame_entity &&
|
||||
world.getGameRules().getBoolean(GameRules.DO_TILE_DROPS)
|
||||
) {
|
||||
@@ -122,14 +123,52 @@ public class ReFramedBlock extends Block implements BlockEntityProvider, RecipeS
|
||||
}
|
||||
super.onStateReplaced(state, world, pos, newState, moved);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlaced(World world, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack stack) {
|
||||
if(world.isClient && world.getBlockEntity(pos) instanceof ReFramedEntity be) {
|
||||
NbtCompound tag = BlockItem.getBlockEntityNbt(stack);
|
||||
if(tag != null) be.readNbt(tag);
|
||||
|
||||
public void onPlaced(World world, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack stack, BlockState old_state, BlockEntity old_entity) {
|
||||
if (!(world.getBlockEntity(pos) instanceof ReFramedEntity frame_entity)) {
|
||||
onPlaced(world, pos, state, placer, stack);
|
||||
return;
|
||||
}
|
||||
super.onPlaced(world, pos, state, placer, stack);
|
||||
|
||||
// apply state change keeping the old information
|
||||
if (old_state.getBlock() instanceof ReFramedBlock old_frame_block
|
||||
&& old_entity instanceof ReFramedEntity old_frame_entity) {
|
||||
Map<Integer, Integer> theme_map = old_frame_block.getThemeMap(old_state, state);
|
||||
theme_map.forEach((self, other) ->
|
||||
frame_entity.setTheme(old_frame_entity.getTheme(self), other)
|
||||
);
|
||||
|
||||
// apply any changes needed to keep previous properties
|
||||
if (old_frame_entity.emitsLight() && !frame_entity.emitsLight()) {
|
||||
frame_entity.toggleLight();
|
||||
world.setBlockState(pos, state.with(LIGHT, true));
|
||||
}
|
||||
if (old_frame_entity.emitsRedstone() && !frame_entity.emitsRedstone()) {
|
||||
frame_entity.toggleRedstone();
|
||||
world.updateNeighbors(pos, this);
|
||||
}
|
||||
if (old_frame_entity.isSolid() && !frame_entity.isSolid()) frame_entity.toggleSolidity();
|
||||
|
||||
// apply themes from item
|
||||
NbtCompound tag = BlockItem.getBlockEntityNbt(stack);
|
||||
if(tag != null) {
|
||||
// determine a list of themes than can be used
|
||||
Iterator<Integer> free_themes = IntStream
|
||||
.rangeClosed(1, frame_entity.getThemes().size())
|
||||
.filter(value -> !theme_map.containsValue(value))
|
||||
.iterator();
|
||||
// apply all the themes possible from item
|
||||
for (int i = 1; tag.contains(BLOCKSTATE_KEY + i) && free_themes.hasNext(); i++) {
|
||||
BlockState theme = NbtHelper.toBlockState(Registries.BLOCK.getReadOnlyWrapper(), tag.getCompound(BLOCKSTATE_KEY + i));
|
||||
if (theme == null || theme.getBlock() == Blocks.AIR) continue;
|
||||
frame_entity.setTheme(theme, free_themes.next());
|
||||
}
|
||||
}
|
||||
} else if(world.isClient) { // prevents flashing with default texture before server sends the update
|
||||
NbtCompound tag = BlockItem.getBlockEntityNbt(stack);
|
||||
if(tag != null) frame_entity.readNbt(tag);
|
||||
}
|
||||
onPlaced(world, pos, state, placer, stack);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -165,21 +204,20 @@ public class ReFramedBlock extends Block implements BlockEntityProvider, RecipeS
|
||||
return getWeakRedstonePower(state, view, pos, dir);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param state - the block state to get the top theme index from
|
||||
* @return the index of the top theme to use for the block
|
||||
*/
|
||||
public int getTopThemeIndex(BlockState state) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRecipe(RecipeExporter exporter) {
|
||||
ShapedRecipeJsonBuilder
|
||||
.create(RecipeCategory.BUILDING_BLOCKS, this)
|
||||
.pattern("III")
|
||||
.pattern("I~I")
|
||||
.pattern("III")
|
||||
.input('I', Items.BAMBOO)
|
||||
.input('~', Items.STRING)
|
||||
.criterion(FabricRecipeProvider.hasItem(Items.BAMBOO), FabricRecipeProvider.conditionsFromItem(Items.BAMBOO))
|
||||
.criterion(FabricRecipeProvider.hasItem(this), FabricRecipeProvider.conditionsFromItem(this))
|
||||
.offerTo(exporter);
|
||||
/**
|
||||
* @param state - the block state of the block that is being replaced
|
||||
* @param new_state - the block state of the block that is replacing the block
|
||||
* @return a map of the theme indexes to map when changing state so that the themes are preserved
|
||||
*/
|
||||
public Map<Integer, Integer> getThemeMap(BlockState state, BlockState new_state) {
|
||||
return Map.of();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,8 +31,11 @@ public abstract class ReFramedDoubleBlock extends ReFramedBlock {
|
||||
return ReFramed.REFRAMED_DOUBLE_BLOCK_ENTITY.instantiate(pos, state);
|
||||
}
|
||||
|
||||
protected int getHitShape(BlockState state, BlockHitResult hit) {
|
||||
Direction side = hit.getSide();
|
||||
public int getHitShape(BlockState state, BlockHitResult hit) {
|
||||
return getHitShape(state, hit.getPos(), hit.getBlockPos(), hit.getSide());
|
||||
}
|
||||
|
||||
public int getHitShape(BlockState state, Vec3d hit, BlockPos pos, Direction side) {
|
||||
VoxelShape first_shape = getShape(state, 1);
|
||||
VoxelShape second_shape = getShape(state, 2);
|
||||
|
||||
@@ -40,13 +43,20 @@ public abstract class ReFramedDoubleBlock extends ReFramedBlock {
|
||||
if (isFaceFullSquare(first_shape, side)) return 1;
|
||||
if (isFaceFullSquare(second_shape, side)) return 2;
|
||||
|
||||
Vec3d pos = BlockHelper.getRelativePos(hit.getPos(), hit.getBlockPos());
|
||||
// System.out.println(side.getAxis().choose(hit.getPos().x, hit.getPos().y, hit.getPos().z));
|
||||
if (BlockHelper.cursorMatchesFace(first_shape, pos)) return 1;
|
||||
if (BlockHelper.cursorMatchesFace(second_shape, pos)) return 2;
|
||||
Vec3d rel = BlockHelper.getRelativePos(hit, pos);
|
||||
if (BlockHelper.cursorMatchesFace(first_shape, rel)) return 1;
|
||||
if (BlockHelper.cursorMatchesFace(second_shape, rel)) return 2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
public boolean matchesShape(Vec3d hit, BlockPos pos, BlockState state, int i) {
|
||||
Vec3d rel = BlockHelper.getRelativePos(hit, pos);
|
||||
return BlockHelper.cursorMatchesFace(
|
||||
getShape(state, i),
|
||||
rel
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTransparent(BlockState state, BlockView world, BlockPos pos) {
|
||||
return world.getBlockEntity(pos) instanceof ThemeableBlockEntity framed_entity
|
||||
|
||||
@@ -1,38 +1,31 @@
|
||||
package fr.adrien1106.reframed.block;
|
||||
|
||||
import fr.adrien1106.reframed.ReFramed;
|
||||
import fr.adrien1106.reframed.generator.BlockStateProvider;
|
||||
import fr.adrien1106.reframed.generator.GBlockstate;
|
||||
import fr.adrien1106.reframed.util.VoxelHelper;
|
||||
import fr.adrien1106.reframed.util.blocks.BlockHelper;
|
||||
import fr.adrien1106.reframed.util.blocks.Corner;
|
||||
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.ShapeContext;
|
||||
import net.minecraft.data.client.BlockStateSupplier;
|
||||
import net.minecraft.data.client.MultipartBlockStateSupplier;
|
||||
import net.minecraft.data.server.recipe.RecipeExporter;
|
||||
import net.minecraft.data.server.recipe.RecipeProvider;
|
||||
import net.minecraft.data.server.recipe.ShapedRecipeJsonBuilder;
|
||||
import net.minecraft.item.BlockItem;
|
||||
import net.minecraft.item.ItemPlacementContext;
|
||||
import net.minecraft.recipe.book.RecipeCategory;
|
||||
import net.minecraft.state.StateManager;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.function.BooleanBiFunction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.shape.VoxelShape;
|
||||
import net.minecraft.util.shape.VoxelShapes;
|
||||
import net.minecraft.world.BlockView;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import static fr.adrien1106.reframed.util.VoxelHelper.VoxelListBuilder;
|
||||
import static fr.adrien1106.reframed.util.blocks.BlockProperties.CORNER;
|
||||
import static fr.adrien1106.reframed.util.blocks.BlockProperties.CORNER_FACE;
|
||||
import static fr.adrien1106.reframed.util.blocks.Corner.*;
|
||||
import static net.minecraft.data.client.VariantSettings.Rotation.*;
|
||||
import java.util.Map;
|
||||
|
||||
public class ReFramedHalfStairBlock extends WaterloggableReFramedBlock implements BlockStateProvider {
|
||||
import static fr.adrien1106.reframed.util.VoxelHelper.VoxelListBuilder;
|
||||
import static fr.adrien1106.reframed.util.blocks.BlockProperties.*;
|
||||
import static fr.adrien1106.reframed.util.blocks.Corner.*;
|
||||
import static net.minecraft.state.property.Properties.WATERLOGGED;
|
||||
|
||||
public class ReFramedHalfStairBlock extends WaterloggableReFramedBlock {
|
||||
|
||||
public static final VoxelShape[] HALF_STAIR_VOXELS;
|
||||
|
||||
@@ -58,8 +51,57 @@ public class ReFramedHalfStairBlock extends WaterloggableReFramedBlock implement
|
||||
super.appendProperties(builder.add(CORNER,CORNER_FACE));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canReplace(BlockState state, ItemPlacementContext context) {
|
||||
Direction dir = state.get(CORNER).getDirection(state.get(CORNER_FACE));
|
||||
return !(
|
||||
context.getPlayer().isSneaking()
|
||||
|| !(context.getStack().getItem() instanceof BlockItem block_item)
|
||||
|| (
|
||||
!(
|
||||
block_item.getBlock() == this
|
||||
&& ((ReFramedHalfStairsStairBlock) ReFramed.HALF_STAIRS_STAIR)
|
||||
.matchesShape(
|
||||
context.getHitPos(),
|
||||
context.getBlockPos(),
|
||||
ReFramed.HALF_STAIRS_STAIR.getDefaultState()
|
||||
.with(EDGE, state.get(CORNER).getEdge(dir)),
|
||||
dir.getDirection() == Direction.AxisDirection.POSITIVE ? 1 : 2
|
||||
)
|
||||
)
|
||||
&& !(
|
||||
block_item.getBlock() == ReFramed.SMALL_CUBE
|
||||
&& BlockHelper.cursorMatchesFace(
|
||||
ReFramed.SMALL_CUBE.getOutlineShape(
|
||||
ReFramed.SMALL_CUBE.getDefaultState()
|
||||
.with(CORNER, state.get(CORNER).getOpposite(state.get(CORNER_FACE))),
|
||||
context.getWorld(),
|
||||
context.getBlockPos(),
|
||||
ShapeContext.absent()
|
||||
),
|
||||
BlockHelper.getRelativePos(context.getHitPos(), context.getBlockPos())
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable BlockState getPlacementState(ItemPlacementContext ctx) {
|
||||
BlockState current_state = ctx.getWorld().getBlockState(ctx.getBlockPos());
|
||||
if (current_state.isOf(ReFramed.SMALL_CUBE)) {
|
||||
Corner corner = current_state.get(CORNER).getOpposite(ctx.getSide().getOpposite());
|
||||
return ReFramed.HALF_STAIRS_SLAB.getDefaultState()
|
||||
.with(CORNER, corner)
|
||||
.with(CORNER_FACE, corner.getDirectionIndex(ctx.getSide().getOpposite()))
|
||||
.with(WATERLOGGED, current_state.get(WATERLOGGED));
|
||||
}
|
||||
|
||||
if (current_state.isOf(this))
|
||||
return ReFramed.HALF_STAIRS_STAIR.getDefaultState()
|
||||
.with(EDGE, current_state.get(CORNER).getEdge(current_state.get(CORNER).getDirection(current_state.get(CORNER_FACE))))
|
||||
.with(WATERLOGGED, current_state.get(WATERLOGGED));
|
||||
|
||||
Corner corner = BlockHelper.getPlacementCorner(ctx);
|
||||
return super.getPlacementState(ctx)
|
||||
.with(CORNER, corner)
|
||||
@@ -72,84 +114,16 @@ public class ReFramedHalfStairBlock extends WaterloggableReFramedBlock implement
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockStateSupplier getMultipart() {
|
||||
return getHalfStairMultipart(
|
||||
this,
|
||||
ReFramed.id("half_stair_down_special"),
|
||||
ReFramed.id("half_stair_side_special")
|
||||
);
|
||||
}
|
||||
|
||||
public static BlockStateSupplier getHalfStairMultipart(Block block, Identifier model_down, Identifier model_side) {
|
||||
return MultipartBlockStateSupplier.create(block)
|
||||
.with(GBlockstate.when(CORNER, NORTH_EAST_DOWN, CORNER_FACE, 1),
|
||||
GBlockstate.variant(model_side, true, R0, R0))
|
||||
.with(GBlockstate.when(CORNER, NORTH_EAST_DOWN, CORNER_FACE, 0),
|
||||
GBlockstate.variant(model_side, true, R90, R270))
|
||||
.with(GBlockstate.when(CORNER, NORTH_EAST_DOWN, CORNER_FACE, 2),
|
||||
GBlockstate.variant(model_down, true, R0, R0))
|
||||
|
||||
.with(GBlockstate.when(CORNER, EAST_SOUTH_DOWN, CORNER_FACE, 1),
|
||||
GBlockstate.variant(model_side, true, R0, R90))
|
||||
.with(GBlockstate.when(CORNER, EAST_SOUTH_DOWN, CORNER_FACE, 0),
|
||||
GBlockstate.variant(model_side, true, R90, R0))
|
||||
.with(GBlockstate.when(CORNER, EAST_SOUTH_DOWN, CORNER_FACE, 2),
|
||||
GBlockstate.variant(model_down, true, R0, R90))
|
||||
|
||||
.with(GBlockstate.when(CORNER, SOUTH_WEST_DOWN, CORNER_FACE, 1),
|
||||
GBlockstate.variant(model_side, true, R0, R180))
|
||||
.with(GBlockstate.when(CORNER, SOUTH_WEST_DOWN, CORNER_FACE, 0),
|
||||
GBlockstate.variant(model_side, true, R90, R90))
|
||||
.with(GBlockstate.when(CORNER, SOUTH_WEST_DOWN, CORNER_FACE, 2),
|
||||
GBlockstate.variant(model_down, true, R0, R180))
|
||||
|
||||
.with(GBlockstate.when(CORNER, WEST_NORTH_DOWN, CORNER_FACE, 1),
|
||||
GBlockstate.variant(model_side, true, R0, R270))
|
||||
.with(GBlockstate.when(CORNER, WEST_NORTH_DOWN, CORNER_FACE, 0),
|
||||
GBlockstate.variant(model_side, true, R90, R180))
|
||||
.with(GBlockstate.when(CORNER, WEST_NORTH_DOWN, CORNER_FACE, 2),
|
||||
GBlockstate.variant(model_down, true, R0, R270))
|
||||
|
||||
.with(GBlockstate.when(CORNER, EAST_SOUTH_UP, CORNER_FACE, 0),
|
||||
GBlockstate.variant(model_side, true, R180, R0))
|
||||
.with(GBlockstate.when(CORNER, EAST_SOUTH_UP, CORNER_FACE, 1),
|
||||
GBlockstate.variant(model_side, true, R270, R90))
|
||||
.with(GBlockstate.when(CORNER, EAST_SOUTH_UP, CORNER_FACE, 2),
|
||||
GBlockstate.variant(model_down, true, R180, R0))
|
||||
|
||||
.with(GBlockstate.when(CORNER, SOUTH_WEST_UP, CORNER_FACE, 0),
|
||||
GBlockstate.variant(model_side, true, R180, R90))
|
||||
.with(GBlockstate.when(CORNER, SOUTH_WEST_UP, CORNER_FACE, 1),
|
||||
GBlockstate.variant(model_side, true, R270, R180))
|
||||
.with(GBlockstate.when(CORNER, SOUTH_WEST_UP, CORNER_FACE, 2),
|
||||
GBlockstate.variant(model_down, true, R180, R90))
|
||||
|
||||
.with(GBlockstate.when(CORNER, WEST_NORTH_UP, CORNER_FACE, 0),
|
||||
GBlockstate.variant(model_side, true, R180, R180))
|
||||
.with(GBlockstate.when(CORNER, WEST_NORTH_UP, CORNER_FACE, 1),
|
||||
GBlockstate.variant(model_side, true, R270, R270))
|
||||
.with(GBlockstate.when(CORNER, WEST_NORTH_UP, CORNER_FACE, 2),
|
||||
GBlockstate.variant(model_down, true, R180, R180))
|
||||
|
||||
.with(GBlockstate.when(CORNER, NORTH_EAST_UP, CORNER_FACE, 0),
|
||||
GBlockstate.variant(model_side, true, R180, R270))
|
||||
.with(GBlockstate.when(CORNER, NORTH_EAST_UP, CORNER_FACE, 1),
|
||||
GBlockstate.variant(model_side, true, R270, R0))
|
||||
.with(GBlockstate.when(CORNER, NORTH_EAST_UP, CORNER_FACE, 2),
|
||||
GBlockstate.variant(model_down, true, R180, R270));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRecipe(RecipeExporter exporter) {
|
||||
RecipeProvider.offerStonecuttingRecipe(exporter, RecipeCategory.BUILDING_BLOCKS, this, ReFramed.CUBE, 2);
|
||||
ShapedRecipeJsonBuilder
|
||||
.create(RecipeCategory.BUILDING_BLOCKS, this, 4)
|
||||
.pattern("I ")
|
||||
.pattern("II ")
|
||||
.input('I', ReFramed.CUBE)
|
||||
.criterion(FabricRecipeProvider.hasItem(ReFramed.CUBE), FabricRecipeProvider.conditionsFromItem(ReFramed.CUBE))
|
||||
.criterion(FabricRecipeProvider.hasItem(this), FabricRecipeProvider.conditionsFromItem(this))
|
||||
.offerTo(exporter);
|
||||
public Map<Integer, Integer> getThemeMap(BlockState state, BlockState new_state) {
|
||||
if (new_state.isOf(ReFramed.HALF_STAIRS_SLAB)) return Map.of(1, 1);
|
||||
if (new_state.isOf(ReFramed.HALF_STAIRS_STAIR))
|
||||
return Map.of(
|
||||
1,
|
||||
state.get(CORNER)
|
||||
.getDirection(state.get(CORNER_FACE))
|
||||
.getDirection() == Direction.AxisDirection.POSITIVE ? 2 : 1
|
||||
);
|
||||
return super.getThemeMap(state, new_state);
|
||||
}
|
||||
|
||||
static {
|
||||
|
||||
@@ -1,19 +1,11 @@
|
||||
package fr.adrien1106.reframed.block;
|
||||
|
||||
import fr.adrien1106.reframed.ReFramed;
|
||||
import fr.adrien1106.reframed.generator.BlockStateProvider;
|
||||
import fr.adrien1106.reframed.util.blocks.BlockHelper;
|
||||
import fr.adrien1106.reframed.util.blocks.Corner;
|
||||
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.ShapeContext;
|
||||
import net.minecraft.data.client.BlockStateSupplier;
|
||||
import net.minecraft.data.server.recipe.RecipeExporter;
|
||||
import net.minecraft.data.server.recipe.RecipeProvider;
|
||||
import net.minecraft.data.server.recipe.ShapelessRecipeJsonBuilder;
|
||||
import net.minecraft.item.ItemPlacementContext;
|
||||
import net.minecraft.recipe.book.RecipeCategory;
|
||||
import net.minecraft.state.StateManager;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.shape.VoxelShape;
|
||||
@@ -21,7 +13,6 @@ import net.minecraft.world.BlockView;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import static fr.adrien1106.reframed.block.ReFramedHalfStairBlock.HALF_STAIR_VOXELS;
|
||||
import static fr.adrien1106.reframed.block.ReFramedHalfStairBlock.getHalfStairMultipart;
|
||||
import static fr.adrien1106.reframed.block.ReFramedSlabBlock.getSlabShape;
|
||||
import static fr.adrien1106.reframed.block.ReFramedSmallCubeBlock.SMALL_CUBE_VOXELS;
|
||||
import static fr.adrien1106.reframed.util.blocks.BlockProperties.CORNER;
|
||||
@@ -29,7 +20,7 @@ import static fr.adrien1106.reframed.util.blocks.BlockProperties.CORNER_FACE;
|
||||
import static fr.adrien1106.reframed.util.blocks.Corner.NORTH_EAST_DOWN;
|
||||
import static net.minecraft.util.shape.VoxelShapes.empty;
|
||||
|
||||
public class ReFramedHalfStairsSlabBlock extends WaterloggableReFramedDoubleBlock implements BlockStateProvider {
|
||||
public class ReFramedHalfStairsSlabBlock extends WaterloggableReFramedDoubleBlock {
|
||||
|
||||
private record ModelCacheKey(Corner corner, int face) {}
|
||||
|
||||
@@ -79,25 +70,4 @@ public class ReFramedHalfStairsSlabBlock extends WaterloggableReFramedDoubleBloc
|
||||
? SMALL_CUBE_VOXELS[corner.getOpposite(face).getID()]
|
||||
: HALF_STAIR_VOXELS[face + corner.getID() * 3];
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockStateSupplier getMultipart() {
|
||||
return getHalfStairMultipart(
|
||||
this,
|
||||
ReFramed.id("half_stairs_slab_down_special"),
|
||||
ReFramed.id("half_stairs_slab_side_special")
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRecipe(RecipeExporter exporter) {
|
||||
RecipeProvider.offerStonecuttingRecipe(exporter, RecipeCategory.BUILDING_BLOCKS, this, ReFramed.CUBE, 2);
|
||||
ShapelessRecipeJsonBuilder
|
||||
.create(RecipeCategory.BUILDING_BLOCKS, this)
|
||||
.input(ReFramed.HALF_STAIR)
|
||||
.input(ReFramed.SMALL_CUBE)
|
||||
.criterion(FabricRecipeProvider.hasItem(ReFramed.CUBE), FabricRecipeProvider.conditionsFromItem(ReFramed.CUBE))
|
||||
.criterion(FabricRecipeProvider.hasItem(this), FabricRecipeProvider.conditionsFromItem(this))
|
||||
.offerTo(exporter);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,25 +1,14 @@
|
||||
package fr.adrien1106.reframed.block;
|
||||
|
||||
import fr.adrien1106.reframed.ReFramed;
|
||||
import fr.adrien1106.reframed.generator.BlockStateProvider;
|
||||
import fr.adrien1106.reframed.generator.GBlockstate;
|
||||
import fr.adrien1106.reframed.util.blocks.BlockHelper;
|
||||
import fr.adrien1106.reframed.util.blocks.Corner;
|
||||
import fr.adrien1106.reframed.util.blocks.Edge;
|
||||
import fr.adrien1106.reframed.util.blocks.StairShape;
|
||||
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.ShapeContext;
|
||||
import net.minecraft.data.client.BlockStateSupplier;
|
||||
import net.minecraft.data.client.MultipartBlockStateSupplier;
|
||||
import net.minecraft.data.server.recipe.RecipeExporter;
|
||||
import net.minecraft.data.server.recipe.RecipeProvider;
|
||||
import net.minecraft.data.server.recipe.ShapelessRecipeJsonBuilder;
|
||||
import net.minecraft.item.ItemPlacementContext;
|
||||
import net.minecraft.recipe.book.RecipeCategory;
|
||||
import net.minecraft.state.StateManager;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.shape.VoxelShape;
|
||||
@@ -30,10 +19,9 @@ import static fr.adrien1106.reframed.block.ReFramedHalfStairBlock.HALF_STAIR_VOX
|
||||
import static fr.adrien1106.reframed.block.ReFramedStairBlock.getStairShape;
|
||||
import static fr.adrien1106.reframed.util.blocks.BlockProperties.EDGE;
|
||||
import static fr.adrien1106.reframed.util.blocks.Edge.*;
|
||||
import static net.minecraft.data.client.VariantSettings.Rotation.*;
|
||||
import static net.minecraft.util.shape.VoxelShapes.empty;
|
||||
|
||||
public class ReFramedHalfStairsStairBlock extends WaterloggableReFramedDoubleBlock implements BlockStateProvider {
|
||||
public class ReFramedHalfStairsStairBlock extends WaterloggableReFramedDoubleBlock {
|
||||
public ReFramedHalfStairsStairBlock(Settings settings) {
|
||||
super(settings);
|
||||
setDefaultState(getDefaultState().with(EDGE, NORTH_DOWN));
|
||||
@@ -89,50 +77,4 @@ public class ReFramedHalfStairsStairBlock extends WaterloggableReFramedDoubleBlo
|
||||
public int getTopThemeIndex(BlockState state) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockStateSupplier getMultipart() {
|
||||
Identifier model_id = ReFramed.id("half_stairs_stair_down_special");
|
||||
Identifier side_model_id = ReFramed.id("half_stairs_stair_side_special");
|
||||
Identifier reverse_model_id = ReFramed.id("half_stairs_stair_reverse_special");
|
||||
return MultipartBlockStateSupplier.create(this)
|
||||
/* X AXIS */
|
||||
.with(GBlockstate.when(EDGE, NORTH_DOWN),
|
||||
GBlockstate.variant(side_model_id, true, R90, R180))
|
||||
.with(GBlockstate.when(EDGE, DOWN_SOUTH),
|
||||
GBlockstate.variant(side_model_id, true, R0, R180))
|
||||
.with(GBlockstate.when(EDGE, SOUTH_UP),
|
||||
GBlockstate.variant(side_model_id, true, R270, R180))
|
||||
.with(GBlockstate.when(EDGE, UP_NORTH),
|
||||
GBlockstate.variant(side_model_id, true, R180, R180))
|
||||
/* Y AXIS */
|
||||
.with(GBlockstate.when(EDGE, NORTH_EAST),
|
||||
GBlockstate.variant(model_id, true, R0, R0))
|
||||
.with(GBlockstate.when(EDGE, EAST_SOUTH),
|
||||
GBlockstate.variant(model_id, true, R0, R90))
|
||||
.with(GBlockstate.when(EDGE, SOUTH_WEST),
|
||||
GBlockstate.variant(model_id, true, R0, R180))
|
||||
.with(GBlockstate.when(EDGE, WEST_NORTH),
|
||||
GBlockstate.variant(model_id, true, R0, R270))
|
||||
/* Z AXIS */
|
||||
.with(GBlockstate.when(EDGE, DOWN_EAST),
|
||||
GBlockstate.variant(side_model_id, true, R0, R90))
|
||||
.with(GBlockstate.when(EDGE, EAST_UP),
|
||||
GBlockstate.variant(reverse_model_id, true, R180, R270))
|
||||
.with(GBlockstate.when(EDGE, UP_WEST),
|
||||
GBlockstate.variant(side_model_id, true, R180, R90))
|
||||
.with(GBlockstate.when(EDGE, WEST_DOWN),
|
||||
GBlockstate.variant(reverse_model_id, true, R0, R270));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRecipe(RecipeExporter exporter) {
|
||||
RecipeProvider.offerStonecuttingRecipe(exporter, RecipeCategory.BUILDING_BLOCKS, this, ReFramed.CUBE, 2);
|
||||
ShapelessRecipeJsonBuilder
|
||||
.create(RecipeCategory.BUILDING_BLOCKS, this)
|
||||
.input(ReFramed.HALF_STAIR, 2)
|
||||
.criterion(FabricRecipeProvider.hasItem(ReFramed.CUBE), FabricRecipeProvider.conditionsFromItem(ReFramed.CUBE))
|
||||
.criterion(FabricRecipeProvider.hasItem(this), FabricRecipeProvider.conditionsFromItem(this))
|
||||
.offerTo(exporter);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
package fr.adrien1106.reframed.block;
|
||||
|
||||
import fr.adrien1106.reframed.ReFramed;
|
||||
import fr.adrien1106.reframed.generator.GBlockstate;
|
||||
import fr.adrien1106.reframed.util.VoxelHelper;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.ShapeContext;
|
||||
import net.minecraft.data.client.MultipartBlockStateSupplier;
|
||||
import net.minecraft.item.BlockItem;
|
||||
import net.minecraft.item.ItemPlacementContext;
|
||||
import net.minecraft.state.StateManager;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.shape.VoxelShape;
|
||||
@@ -17,7 +14,6 @@ import net.minecraft.world.BlockView;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import static fr.adrien1106.reframed.util.VoxelHelper.VoxelListBuilder;
|
||||
import static net.minecraft.data.client.VariantSettings.Rotation.*;
|
||||
import static net.minecraft.state.property.Properties.FACING;
|
||||
import static net.minecraft.state.property.Properties.LAYERS;
|
||||
|
||||
@@ -52,8 +48,12 @@ public class ReFramedLayerBlock extends ReFramedSlabBlock {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canReplace(BlockState state, ItemPlacementContext ctx) {
|
||||
return !(!state.isOf(this) || ctx.getPlayer().isSneaking() || state.get(LAYERS) == 8);
|
||||
public boolean canReplace(BlockState state, ItemPlacementContext context) {
|
||||
return !(
|
||||
context.getPlayer().isSneaking()
|
||||
|| !(context.getStack().getItem() instanceof BlockItem block_item)
|
||||
|| !(block_item.getBlock() == this && state.get(LAYERS) < 8)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -63,29 +63,6 @@ public class ReFramedLayerBlock extends ReFramedSlabBlock {
|
||||
return previous.with(LAYERS, previous.get(LAYERS) + 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MultipartBlockStateSupplier getMultipart() {
|
||||
String model_pattern = "layer_x_special";
|
||||
MultipartBlockStateSupplier supplier = MultipartBlockStateSupplier.create(this);
|
||||
for (int i = 1; i <= 8; i++) {
|
||||
Identifier model = ReFramed.id(model_pattern.replace("x", i + ""));
|
||||
supplier
|
||||
.with(GBlockstate.when(FACING, Direction.DOWN, LAYERS, i),
|
||||
GBlockstate.variant(model, true, R0, R0))
|
||||
.with(GBlockstate.when(FACING, Direction.SOUTH, LAYERS, i),
|
||||
GBlockstate.variant(model, true, R90, R0))
|
||||
.with(GBlockstate.when(FACING, Direction.UP, LAYERS, i),
|
||||
GBlockstate.variant(model, true, R180, R0))
|
||||
.with(GBlockstate.when(FACING, Direction.NORTH, LAYERS, i),
|
||||
GBlockstate.variant(model, true, R270, R0))
|
||||
.with(GBlockstate.when(FACING, Direction.WEST, LAYERS, i),
|
||||
GBlockstate.variant(model, true, R90, R90))
|
||||
.with(GBlockstate.when(FACING, Direction.EAST, LAYERS, i),
|
||||
GBlockstate.variant(model, true, R90, R270));
|
||||
}
|
||||
return supplier;
|
||||
}
|
||||
|
||||
static {
|
||||
VoxelListBuilder builder = VoxelListBuilder.create(createCuboidShape(0, 0, 0, 16, 2, 16), 48)
|
||||
.add(createCuboidShape(0, 0, 0, 16, 4, 16))
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
package fr.adrien1106.reframed.block;
|
||||
|
||||
import fr.adrien1106.reframed.util.VoxelHelper;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.ShapeContext;
|
||||
import net.minecraft.item.BlockItem;
|
||||
import net.minecraft.item.ItemPlacementContext;
|
||||
import net.minecraft.state.StateManager;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.shape.VoxelShape;
|
||||
import net.minecraft.world.BlockView;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static net.minecraft.state.property.Properties.AXIS;
|
||||
|
||||
public class ReFramedPillarBlock extends WaterloggableReFramedBlock {
|
||||
|
||||
public static final VoxelShape[] PILLAR_VOXELS;
|
||||
|
||||
public ReFramedPillarBlock(Settings settings) {
|
||||
super(settings);
|
||||
setDefaultState(getDefaultState().with(AXIS, Direction.Axis.Y));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getModelCacheKey(BlockState state) {
|
||||
return state.get(AXIS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getModelStateCount() {
|
||||
return 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
|
||||
super.appendProperties(builder.add(AXIS));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canReplace(BlockState state, ItemPlacementContext context) {
|
||||
return !(context.getPlayer().isSneaking()
|
||||
|| !(context.getStack().getItem() instanceof BlockItem block_item)
|
||||
|| !(
|
||||
block_item.getBlock() == this
|
||||
&& state.get(AXIS) != context.getSide().getAxis()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable BlockState getPlacementState(ItemPlacementContext ctx) {
|
||||
// TODO: PILLARS WALL
|
||||
return super.getPlacementState(ctx).with(AXIS, ctx.getSide().getAxis());
|
||||
}
|
||||
|
||||
@Override
|
||||
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
|
||||
return getPillarShape(state.get(AXIS));
|
||||
}
|
||||
|
||||
public static VoxelShape getPillarShape(Direction.Axis axis) {
|
||||
return PILLAR_VOXELS[axis.ordinal()];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Integer, Integer> getThemeMap(BlockState state, BlockState new_state) {
|
||||
// if (new_state.getBlock() == ReFramed.PILLARS_WALL) return Map.of(1, 1); // TODO: PILLARS WALL
|
||||
return super.getThemeMap(state, new_state);
|
||||
}
|
||||
|
||||
static {
|
||||
final VoxelShape PILLAR = createCuboidShape(0, 4, 4, 16, 12, 12);
|
||||
PILLAR_VOXELS = VoxelHelper.VoxelListBuilder.create(PILLAR, 3)
|
||||
.add(VoxelHelper::rotateZ)
|
||||
.add(VoxelHelper::rotateX)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -1,20 +1,12 @@
|
||||
package fr.adrien1106.reframed.block;
|
||||
|
||||
import fr.adrien1106.reframed.ReFramed;
|
||||
import fr.adrien1106.reframed.generator.BlockStateProvider;
|
||||
import fr.adrien1106.reframed.generator.GBlockstate;
|
||||
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.ShapeContext;
|
||||
import net.minecraft.data.client.MultipartBlockStateSupplier;
|
||||
import net.minecraft.data.server.recipe.RecipeExporter;
|
||||
import net.minecraft.data.server.recipe.RecipeProvider;
|
||||
import net.minecraft.data.server.recipe.ShapedRecipeJsonBuilder;
|
||||
import net.minecraft.item.BlockItem;
|
||||
import net.minecraft.item.ItemPlacementContext;
|
||||
import net.minecraft.recipe.book.RecipeCategory;
|
||||
import net.minecraft.state.StateManager;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.shape.VoxelShape;
|
||||
@@ -22,10 +14,12 @@ import net.minecraft.util.shape.VoxelShapes;
|
||||
import net.minecraft.world.BlockView;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import static net.minecraft.data.client.VariantSettings.Rotation.*;
|
||||
import java.util.Map;
|
||||
|
||||
import static net.minecraft.state.property.Properties.AXIS;
|
||||
import static net.minecraft.state.property.Properties.FACING;
|
||||
|
||||
public class ReFramedSlabBlock extends WaterloggableReFramedBlock implements BlockStateProvider {
|
||||
public class ReFramedSlabBlock extends WaterloggableReFramedBlock {
|
||||
|
||||
protected static final VoxelShape DOWN = VoxelShapes.cuboid(0f, 0f, 0f, 1f, 0.5f, 1f);
|
||||
protected static final VoxelShape UP = VoxelShapes.cuboid(0f, 0.5f, 0f, 1f, 1f, 1f);
|
||||
@@ -53,10 +47,33 @@ public class ReFramedSlabBlock extends WaterloggableReFramedBlock implements Blo
|
||||
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
|
||||
super.appendProperties(builder.add(FACING));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean canReplace(BlockState state, ItemPlacementContext context) {
|
||||
return !(
|
||||
context.getPlayer().isSneaking()
|
||||
|| !(context.getStack().getItem() instanceof BlockItem block_item)
|
||||
|| !(
|
||||
block_item.getBlock() == this
|
||||
&& ((ReFramedSlabsCubeBlock) ReFramed.SLABS_CUBE)
|
||||
.matchesShape(
|
||||
context.getHitPos(),
|
||||
context.getBlockPos(),
|
||||
ReFramed.SLABS_CUBE.getDefaultState().with(AXIS, state.get(FACING).getAxis()),
|
||||
state.get(FACING).getDirection() == Direction.AxisDirection.POSITIVE ? 1 : 2
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BlockState getPlacementState(ItemPlacementContext ctx) {
|
||||
BlockState current_state = ctx.getWorld().getBlockState(ctx.getBlockPos());
|
||||
if (current_state.isOf(this))
|
||||
return ReFramed.SLABS_CUBE.getDefaultState()
|
||||
.with(AXIS, current_state.get(FACING).getAxis());
|
||||
|
||||
return super.getPlacementState(ctx).with(FACING, ctx.getSide().getOpposite());
|
||||
}
|
||||
|
||||
@@ -77,32 +94,8 @@ public class ReFramedSlabBlock extends WaterloggableReFramedBlock implements Blo
|
||||
}
|
||||
|
||||
@Override
|
||||
public MultipartBlockStateSupplier getMultipart() {
|
||||
Identifier model_id = ReFramed.id("slab_special");
|
||||
return MultipartBlockStateSupplier.create(this)
|
||||
.with(GBlockstate.when(FACING, Direction.DOWN),
|
||||
GBlockstate.variant(model_id, true, R0, R0))
|
||||
.with(GBlockstate.when(FACING, Direction.SOUTH),
|
||||
GBlockstate.variant(model_id, true, R90, R0))
|
||||
.with(GBlockstate.when(FACING, Direction.UP),
|
||||
GBlockstate.variant(model_id, true, R180, R0))
|
||||
.with(GBlockstate.when(FACING, Direction.NORTH),
|
||||
GBlockstate.variant(model_id, true, R270, R0))
|
||||
.with(GBlockstate.when(FACING, Direction.WEST),
|
||||
GBlockstate.variant(model_id, true, R90, R90))
|
||||
.with(GBlockstate.when(FACING, Direction.EAST),
|
||||
GBlockstate.variant(model_id, true, R90, R270));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRecipe(RecipeExporter exporter) {
|
||||
RecipeProvider.offerStonecuttingRecipe(exporter, RecipeCategory.BUILDING_BLOCKS, this, ReFramed.CUBE, 2);
|
||||
ShapedRecipeJsonBuilder
|
||||
.create(RecipeCategory.BUILDING_BLOCKS, this, 6)
|
||||
.pattern("III")
|
||||
.input('I', ReFramed.CUBE)
|
||||
.criterion(FabricRecipeProvider.hasItem(ReFramed.CUBE), FabricRecipeProvider.conditionsFromItem(ReFramed.CUBE))
|
||||
.criterion(FabricRecipeProvider.hasItem(this), FabricRecipeProvider.conditionsFromItem(this))
|
||||
.offerTo(exporter);
|
||||
public Map<Integer, Integer> getThemeMap(BlockState state, BlockState new_state) {
|
||||
if (new_state.isOf(ReFramed.SLABS_CUBE)) return Map.of(1, state.get(FACING).getDirection() == Direction.AxisDirection.POSITIVE ? 2 : 1);
|
||||
return super.getThemeMap(state, new_state);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,29 +1,17 @@
|
||||
package fr.adrien1106.reframed.block;
|
||||
|
||||
import fr.adrien1106.reframed.ReFramed;
|
||||
import fr.adrien1106.reframed.generator.BlockStateProvider;
|
||||
import fr.adrien1106.reframed.generator.GBlockstate;
|
||||
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.data.client.MultipartBlockStateSupplier;
|
||||
import net.minecraft.data.server.recipe.RecipeExporter;
|
||||
import net.minecraft.data.server.recipe.RecipeProvider;
|
||||
import net.minecraft.data.server.recipe.ShapelessRecipeJsonBuilder;
|
||||
import net.minecraft.item.ItemPlacementContext;
|
||||
import net.minecraft.recipe.book.RecipeCategory;
|
||||
import net.minecraft.state.StateManager;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.shape.VoxelShape;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import static fr.adrien1106.reframed.block.ReFramedSlabBlock.*;
|
||||
import static net.minecraft.data.client.VariantSettings.Rotation.R0;
|
||||
import static net.minecraft.data.client.VariantSettings.Rotation.R90;
|
||||
import static net.minecraft.state.property.Properties.AXIS;
|
||||
|
||||
public class ReFramedSlabsCubeBlock extends ReFramedDoubleBlock implements BlockStateProvider {
|
||||
public class ReFramedSlabsCubeBlock extends ReFramedDoubleBlock {
|
||||
|
||||
public ReFramedSlabsCubeBlock(Settings settings) {
|
||||
super(settings);
|
||||
@@ -55,37 +43,13 @@ public class ReFramedSlabsCubeBlock extends ReFramedDoubleBlock implements Block
|
||||
public VoxelShape getShape(BlockState state, int i) {
|
||||
return switch (state.get(AXIS)) {
|
||||
case Y -> i == 2 ? UP : DOWN;
|
||||
case Z -> i == 2 ? NORTH : SOUTH;
|
||||
case Z -> i == 2 ? SOUTH : NORTH;
|
||||
case X -> i == 2 ? EAST : WEST;
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTopThemeIndex(BlockState state) {
|
||||
// when the side is shared just return one
|
||||
return state.get(AXIS) == Direction.Axis.Y ? 2: super.getTopThemeIndex(state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MultipartBlockStateSupplier getMultipart() {
|
||||
Identifier model_id = ReFramed.id("double_slab_special");
|
||||
return MultipartBlockStateSupplier.create(this)
|
||||
.with(GBlockstate.when(AXIS, Direction.Axis.Y),
|
||||
GBlockstate.variant(model_id, true, R0, R0))
|
||||
.with(GBlockstate.when(AXIS, Direction.Axis.Z),
|
||||
GBlockstate.variant(model_id, true, R90, R0))
|
||||
.with(GBlockstate.when(AXIS, Direction.Axis.X),
|
||||
GBlockstate.variant(model_id, true, R90, R90));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRecipe(RecipeExporter exporter) {
|
||||
RecipeProvider.offerStonecuttingRecipe(exporter, RecipeCategory.BUILDING_BLOCKS, this, ReFramed.CUBE);
|
||||
ShapelessRecipeJsonBuilder
|
||||
.create(RecipeCategory.BUILDING_BLOCKS, this)
|
||||
.input(ReFramed.SLAB, 2)
|
||||
.criterion(FabricRecipeProvider.hasItem(ReFramed.CUBE), FabricRecipeProvider.conditionsFromItem(ReFramed.CUBE))
|
||||
.criterion(FabricRecipeProvider.hasItem(this), FabricRecipeProvider.conditionsFromItem(this))
|
||||
.offerTo(exporter);
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,35 +1,31 @@
|
||||
package fr.adrien1106.reframed.block;
|
||||
|
||||
import fr.adrien1106.reframed.ReFramed;
|
||||
import fr.adrien1106.reframed.generator.BlockStateProvider;
|
||||
import fr.adrien1106.reframed.generator.GBlockstate;
|
||||
import fr.adrien1106.reframed.util.VoxelHelper;
|
||||
import fr.adrien1106.reframed.util.blocks.BlockHelper;
|
||||
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
|
||||
import fr.adrien1106.reframed.util.blocks.Corner;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.ShapeContext;
|
||||
import net.minecraft.data.client.BlockStateSupplier;
|
||||
import net.minecraft.data.client.MultipartBlockStateSupplier;
|
||||
import net.minecraft.data.server.recipe.RecipeExporter;
|
||||
import net.minecraft.data.server.recipe.RecipeProvider;
|
||||
import net.minecraft.data.server.recipe.ShapelessRecipeJsonBuilder;
|
||||
import net.minecraft.item.BlockItem;
|
||||
import net.minecraft.item.ItemPlacementContext;
|
||||
import net.minecraft.recipe.book.RecipeCategory;
|
||||
import net.minecraft.state.StateManager;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.util.shape.VoxelShape;
|
||||
import net.minecraft.util.shape.VoxelShapes;
|
||||
import net.minecraft.world.BlockView;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import static fr.adrien1106.reframed.util.VoxelHelper.VoxelListBuilder;
|
||||
import static fr.adrien1106.reframed.util.blocks.BlockProperties.CORNER;
|
||||
import static fr.adrien1106.reframed.util.blocks.Corner.*;
|
||||
import static net.minecraft.data.client.VariantSettings.Rotation.*;
|
||||
import java.util.Map;
|
||||
|
||||
public class ReFramedSmallCubeBlock extends WaterloggableReFramedBlock implements BlockStateProvider {
|
||||
import static fr.adrien1106.reframed.util.VoxelHelper.VoxelListBuilder;
|
||||
import static fr.adrien1106.reframed.util.blocks.BlockProperties.*;
|
||||
import static fr.adrien1106.reframed.util.blocks.Corner.*;
|
||||
import static net.minecraft.state.property.Properties.WATERLOGGED;
|
||||
|
||||
public class ReFramedSmallCubeBlock extends WaterloggableReFramedBlock {
|
||||
|
||||
public static final VoxelShape[] SMALL_CUBE_VOXELS;
|
||||
|
||||
@@ -53,8 +49,84 @@ public class ReFramedSmallCubeBlock extends WaterloggableReFramedBlock implement
|
||||
super.appendProperties(builder.add(CORNER));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canReplace(BlockState state, ItemPlacementContext context) {
|
||||
Corner corner = state.get(CORNER);
|
||||
return !(
|
||||
context.getPlayer().isSneaking()
|
||||
|| !(context.getStack().getItem() instanceof BlockItem block_item)
|
||||
|| (
|
||||
!(
|
||||
block_item.getBlock() == ReFramed.HALF_STAIR
|
||||
&& !(corner.hasDirection(context.getSide())
|
||||
|| (corner.hasDirection(context.getSide().getOpposite())
|
||||
&& BlockHelper.cursorMatchesFace(
|
||||
getOutlineShape(state, context.getWorld(), context.getBlockPos(), null),
|
||||
BlockHelper.getRelativePos(context.getHitPos(), context.getBlockPos())
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
&& !(
|
||||
block_item.getBlock() == this
|
||||
&& (
|
||||
((ReFramedSmallCubesStepBlock) ReFramed.SMALL_CUBES_STEP)
|
||||
.matchesShape(
|
||||
context.getHitPos(),
|
||||
context.getBlockPos(),
|
||||
ReFramed.SMALL_CUBES_STEP.getDefaultState().with(EDGE, corner.getEdge(corner.getFirstDirection())),
|
||||
corner.getFirstDirection().getDirection() == Direction.AxisDirection.POSITIVE ? 1 : 2
|
||||
)
|
||||
|| ((ReFramedSmallCubesStepBlock) ReFramed.SMALL_CUBES_STEP)
|
||||
.matchesShape(
|
||||
context.getHitPos(),
|
||||
context.getBlockPos(),
|
||||
ReFramed.SMALL_CUBES_STEP.getDefaultState().with(EDGE, corner.getEdge(corner.getSecondDirection())),
|
||||
corner.getSecondDirection().getDirection() == Direction.AxisDirection.POSITIVE ? 1 : 2
|
||||
)
|
||||
|| ((ReFramedSmallCubesStepBlock) ReFramed.SMALL_CUBES_STEP)
|
||||
.matchesShape(
|
||||
context.getHitPos(),
|
||||
context.getBlockPos(),
|
||||
ReFramed.SMALL_CUBES_STEP.getDefaultState().with(EDGE, corner.getEdge(corner.getThirdDirection())),
|
||||
corner.getThirdDirection().getDirection() == Direction.AxisDirection.POSITIVE ? 1 : 2
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable BlockState getPlacementState(ItemPlacementContext ctx) {
|
||||
BlockPos pos = ctx.getBlockPos();
|
||||
BlockState current_state = ctx.getWorld().getBlockState(pos);
|
||||
if (current_state.isOf(ReFramed.HALF_STAIR))
|
||||
return ReFramed.HALF_STAIRS_SLAB.getDefaultState()
|
||||
.with(CORNER, current_state.get(CORNER))
|
||||
.with(CORNER_FACE, current_state.get(CORNER_FACE))
|
||||
.with(WATERLOGGED, current_state.get(WATERLOGGED));
|
||||
|
||||
|
||||
if (current_state.isOf(this)) {
|
||||
Vec3d hit = ctx.getHitPos();
|
||||
Corner corner = current_state.get(CORNER);
|
||||
ReFramedSmallCubesStepBlock block = ((ReFramedSmallCubesStepBlock) ReFramed.SMALL_CUBES_STEP);
|
||||
BlockState state = block.getDefaultState()
|
||||
.with(EDGE, corner.getEdge(corner.getFirstDirection()))
|
||||
.with(WATERLOGGED, current_state.get(WATERLOGGED));
|
||||
if (block.matchesShape(
|
||||
hit, pos, state,
|
||||
corner.getFirstDirection().getDirection() == Direction.AxisDirection.POSITIVE ? 1 : 2
|
||||
)) return state;
|
||||
state = state.with(EDGE, corner.getEdge(corner.getSecondDirection()));
|
||||
if (block.matchesShape(
|
||||
hit, pos, state,
|
||||
corner.getSecondDirection().getDirection() == Direction.AxisDirection.POSITIVE ? 1 : 2
|
||||
)) return state;
|
||||
return state.with(EDGE, corner.getEdge(corner.getThirdDirection()));
|
||||
}
|
||||
|
||||
return super.getPlacementState(ctx).with(CORNER, BlockHelper.getPlacementCorner(ctx));
|
||||
}
|
||||
|
||||
@@ -64,36 +136,16 @@ public class ReFramedSmallCubeBlock extends WaterloggableReFramedBlock implement
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockStateSupplier getMultipart() {
|
||||
Identifier small_cube_id = ReFramed.id("small_cube_special");
|
||||
return MultipartBlockStateSupplier.create(this)
|
||||
.with(GBlockstate.when(CORNER, NORTH_EAST_DOWN),
|
||||
GBlockstate.variant(small_cube_id, true, R0, R0))
|
||||
.with(GBlockstate.when(CORNER, EAST_SOUTH_DOWN),
|
||||
GBlockstate.variant(small_cube_id, true, R0, R90))
|
||||
.with(GBlockstate.when(CORNER, SOUTH_WEST_DOWN),
|
||||
GBlockstate.variant(small_cube_id, true, R0, R180))
|
||||
.with(GBlockstate.when(CORNER, WEST_NORTH_DOWN),
|
||||
GBlockstate.variant(small_cube_id, true, R0, R270))
|
||||
.with(GBlockstate.when(CORNER, EAST_SOUTH_UP),
|
||||
GBlockstate.variant(small_cube_id, true, R180, R0))
|
||||
.with(GBlockstate.when(CORNER, SOUTH_WEST_UP),
|
||||
GBlockstate.variant(small_cube_id, true, R180, R90))
|
||||
.with(GBlockstate.when(CORNER, WEST_NORTH_UP),
|
||||
GBlockstate.variant(small_cube_id, true, R180, R180))
|
||||
.with(GBlockstate.when(CORNER, NORTH_EAST_UP),
|
||||
GBlockstate.variant(small_cube_id, true, R180, R270));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRecipe(RecipeExporter exporter) {
|
||||
RecipeProvider.offerStonecuttingRecipe(exporter, RecipeCategory.BUILDING_BLOCKS, this, ReFramed.CUBE, 8);
|
||||
ShapelessRecipeJsonBuilder
|
||||
.create(RecipeCategory.BUILDING_BLOCKS, this, 8)
|
||||
.input(ReFramed.CUBE)
|
||||
.criterion(FabricRecipeProvider.hasItem(ReFramed.CUBE), FabricRecipeProvider.conditionsFromItem(ReFramed.CUBE))
|
||||
.criterion(FabricRecipeProvider.hasItem(this), FabricRecipeProvider.conditionsFromItem(this))
|
||||
.offerTo(exporter);
|
||||
public Map<Integer, Integer> getThemeMap(BlockState state, BlockState new_state) {
|
||||
if (new_state.isOf(ReFramed.HALF_STAIRS_SLAB)) return Map.of(1, 2);
|
||||
if (new_state.isOf(ReFramed.SMALL_CUBES_STEP))
|
||||
return Map.of(
|
||||
1,
|
||||
state.get(CORNER)
|
||||
.getOtherDirection(new_state.get(EDGE))
|
||||
.getDirection() == Direction.AxisDirection.POSITIVE ? 2 : 1
|
||||
);
|
||||
return super.getThemeMap(state, new_state);
|
||||
}
|
||||
|
||||
static {
|
||||
|
||||
@@ -1,24 +1,13 @@
|
||||
package fr.adrien1106.reframed.block;
|
||||
|
||||
import fr.adrien1106.reframed.ReFramed;
|
||||
import fr.adrien1106.reframed.generator.BlockStateProvider;
|
||||
import fr.adrien1106.reframed.generator.GBlockstate;
|
||||
import fr.adrien1106.reframed.util.blocks.BlockHelper;
|
||||
import fr.adrien1106.reframed.util.blocks.Corner;
|
||||
import fr.adrien1106.reframed.util.blocks.Edge;
|
||||
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.ShapeContext;
|
||||
import net.minecraft.data.client.BlockStateSupplier;
|
||||
import net.minecraft.data.client.MultipartBlockStateSupplier;
|
||||
import net.minecraft.data.server.recipe.RecipeExporter;
|
||||
import net.minecraft.data.server.recipe.RecipeProvider;
|
||||
import net.minecraft.data.server.recipe.ShapelessRecipeJsonBuilder;
|
||||
import net.minecraft.item.ItemPlacementContext;
|
||||
import net.minecraft.recipe.book.RecipeCategory;
|
||||
import net.minecraft.state.StateManager;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.shape.VoxelShape;
|
||||
import net.minecraft.world.BlockView;
|
||||
@@ -27,11 +16,9 @@ import org.jetbrains.annotations.Nullable;
|
||||
import static fr.adrien1106.reframed.block.ReFramedSmallCubeBlock.SMALL_CUBE_VOXELS;
|
||||
import static fr.adrien1106.reframed.block.ReFramedStepBlock.getStepShape;
|
||||
import static fr.adrien1106.reframed.util.blocks.BlockProperties.EDGE;
|
||||
import static fr.adrien1106.reframed.util.blocks.Edge.*;
|
||||
import static net.minecraft.data.client.VariantSettings.Rotation.*;
|
||||
import static net.minecraft.util.shape.VoxelShapes.empty;
|
||||
|
||||
public class ReFramedSmallCubesStepBlock extends WaterloggableReFramedDoubleBlock implements BlockStateProvider {
|
||||
public class ReFramedSmallCubesStepBlock extends WaterloggableReFramedDoubleBlock {
|
||||
|
||||
public ReFramedSmallCubesStepBlock(Settings settings) {
|
||||
super(settings);
|
||||
@@ -85,49 +72,4 @@ public class ReFramedSmallCubesStepBlock extends WaterloggableReFramedDoubleBloc
|
||||
public int getTopThemeIndex(BlockState state) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockStateSupplier getMultipart() {
|
||||
Identifier model_id = ReFramed.id("small_cubes_step_special");
|
||||
Identifier reverse_model_id = ReFramed.id("small_cubes_step_reverse_special");
|
||||
return MultipartBlockStateSupplier.create(this)
|
||||
/* X AXIS */
|
||||
.with(GBlockstate.when(EDGE, DOWN_EAST),
|
||||
GBlockstate.variant(reverse_model_id, true, R0, R0))
|
||||
.with(GBlockstate.when(EDGE, EAST_UP),
|
||||
GBlockstate.variant(model_id, true, R180, R0))
|
||||
.with(GBlockstate.when(EDGE, UP_WEST),
|
||||
GBlockstate.variant(reverse_model_id, true, R180, R180))
|
||||
.with(GBlockstate.when(EDGE, WEST_DOWN),
|
||||
GBlockstate.variant(model_id, true, R0, R180))
|
||||
/* Y AXIS */
|
||||
.with(GBlockstate.when(EDGE, EAST_SOUTH),
|
||||
GBlockstate.variant(model_id, true, R90, R0))
|
||||
.with(GBlockstate.when(EDGE, SOUTH_WEST),
|
||||
GBlockstate.variant(model_id, true, R90, R90))
|
||||
.with(GBlockstate.when(EDGE, WEST_NORTH),
|
||||
GBlockstate.variant(model_id, true, R90, R180))
|
||||
.with(GBlockstate.when(EDGE, NORTH_EAST),
|
||||
GBlockstate.variant(model_id, true, R90, R270))
|
||||
/* Z AXIS */
|
||||
.with(GBlockstate.when(EDGE, DOWN_SOUTH),
|
||||
GBlockstate.variant(reverse_model_id, true, R0, R90))
|
||||
.with(GBlockstate.when(EDGE, NORTH_DOWN),
|
||||
GBlockstate.variant(model_id, true, R0, R270))
|
||||
.with(GBlockstate.when(EDGE, UP_NORTH),
|
||||
GBlockstate.variant(reverse_model_id, true, R180, R270))
|
||||
.with(GBlockstate.when(EDGE, SOUTH_UP),
|
||||
GBlockstate.variant(model_id, true, R180, R90));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRecipe(RecipeExporter exporter) {
|
||||
RecipeProvider.offerStonecuttingRecipe(exporter, RecipeCategory.BUILDING_BLOCKS, this, ReFramed.CUBE, 4);
|
||||
ShapelessRecipeJsonBuilder
|
||||
.create(RecipeCategory.BUILDING_BLOCKS, this)
|
||||
.input(ReFramed.SMALL_CUBE, 2)
|
||||
.criterion(FabricRecipeProvider.hasItem(ReFramed.CUBE), FabricRecipeProvider.conditionsFromItem(ReFramed.CUBE))
|
||||
.criterion(FabricRecipeProvider.hasItem(this), FabricRecipeProvider.conditionsFromItem(this))
|
||||
.offerTo(exporter);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,25 +1,16 @@
|
||||
package fr.adrien1106.reframed.block;
|
||||
|
||||
import fr.adrien1106.reframed.ReFramed;
|
||||
import fr.adrien1106.reframed.generator.BlockStateProvider;
|
||||
import fr.adrien1106.reframed.generator.GBlockstate;
|
||||
import fr.adrien1106.reframed.util.VoxelHelper;
|
||||
import fr.adrien1106.reframed.util.blocks.BlockHelper;
|
||||
import fr.adrien1106.reframed.util.blocks.Edge;
|
||||
import fr.adrien1106.reframed.util.blocks.StairShape;
|
||||
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.ShapeContext;
|
||||
import net.minecraft.data.client.MultipartBlockStateSupplier;
|
||||
import net.minecraft.data.client.When;
|
||||
import net.minecraft.data.server.recipe.RecipeExporter;
|
||||
import net.minecraft.data.server.recipe.RecipeProvider;
|
||||
import net.minecraft.data.server.recipe.ShapedRecipeJsonBuilder;
|
||||
import net.minecraft.item.BlockItem;
|
||||
import net.minecraft.item.ItemPlacementContext;
|
||||
import net.minecraft.recipe.book.RecipeCategory;
|
||||
import net.minecraft.state.StateManager;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.function.BooleanBiFunction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
@@ -30,16 +21,15 @@ import net.minecraft.world.World;
|
||||
import net.minecraft.world.WorldAccess;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static fr.adrien1106.reframed.util.VoxelHelper.VoxelListBuilder;
|
||||
import static fr.adrien1106.reframed.util.blocks.BlockProperties.EDGE;
|
||||
import static fr.adrien1106.reframed.util.blocks.BlockProperties.STAIR_SHAPE;
|
||||
import static fr.adrien1106.reframed.util.blocks.Edge.*;
|
||||
import static fr.adrien1106.reframed.util.blocks.StairShape.*;
|
||||
import static net.minecraft.data.client.VariantSettings.Rotation.*;
|
||||
|
||||
public class ReFramedStairBlock extends WaterloggableReFramedBlock implements BlockStateProvider {
|
||||
public class ReFramedStairBlock extends WaterloggableReFramedBlock {
|
||||
public static final VoxelShape[] STAIR_VOXELS;
|
||||
private record ModelCacheKey(Edge edge, StairShape shape) {}
|
||||
|
||||
@@ -63,6 +53,24 @@ public class ReFramedStairBlock extends WaterloggableReFramedBlock implements Bl
|
||||
super.appendProperties(builder.add(EDGE, STAIR_SHAPE));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canReplace(BlockState state, ItemPlacementContext context) {
|
||||
return !(
|
||||
context.getPlayer().isSneaking()
|
||||
|| !(context.getStack().getItem() instanceof BlockItem block_item)
|
||||
|| !(
|
||||
block_item.getBlock() == ReFramed.STEP
|
||||
&& ((ReFramedStairsCubeBlock) ReFramed.STAIRS_CUBE)
|
||||
.matchesShape(
|
||||
context.getHitPos(),
|
||||
context.getBlockPos(),
|
||||
state,
|
||||
2
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getStateForNeighborUpdate(BlockState state, Direction direction, BlockState neighbor_state, WorldAccess world, BlockPos pos, BlockPos moved) {
|
||||
return super.getStateForNeighborUpdate(state, direction, neighbor_state, world, pos, moved)
|
||||
@@ -70,11 +78,20 @@ public class ReFramedStairBlock extends WaterloggableReFramedBlock implements Bl
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override // Pretty happy of how clean it is (also got it on first try :) )
|
||||
@Override
|
||||
public BlockState getPlacementState(ItemPlacementContext ctx) {
|
||||
Edge face = BlockHelper.getPlacementEdge(ctx);
|
||||
StairShape shape = BlockHelper.getStairsShape(face, ctx.getWorld(), ctx.getBlockPos());
|
||||
return super.getPlacementState(ctx).with(EDGE, face).with(STAIR_SHAPE, shape);
|
||||
BlockState current_state = ctx.getWorld().getBlockState(ctx.getBlockPos());
|
||||
if (current_state.isOf(ReFramed.STEP)) {
|
||||
Edge edge = current_state.get(EDGE).opposite();
|
||||
StairShape shape = BlockHelper.getStairsShape(edge, ctx.getWorld(), ctx.getBlockPos());
|
||||
return ReFramed.STAIRS_CUBE.getDefaultState()
|
||||
.with(EDGE, edge)
|
||||
.with(STAIR_SHAPE, shape);
|
||||
}
|
||||
|
||||
Edge edge = BlockHelper.getPlacementEdge(ctx);
|
||||
StairShape shape = BlockHelper.getStairsShape(edge, ctx.getWorld(), ctx.getBlockPos());
|
||||
return super.getPlacementState(ctx).with(EDGE, edge).with(STAIR_SHAPE, shape);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -94,245 +111,9 @@ public class ReFramedStairBlock extends WaterloggableReFramedBlock implements Bl
|
||||
}
|
||||
|
||||
@Override
|
||||
public MultipartBlockStateSupplier getMultipart() {
|
||||
return getStairMultipart(this, false);
|
||||
}
|
||||
|
||||
public static MultipartBlockStateSupplier getStairMultipart(Block block, boolean is_double) {
|
||||
String infix = is_double ? "s_cube" : "";
|
||||
Identifier straight_id = ReFramed.id("stair" + infix + "_special");
|
||||
Identifier double_outer_id = ReFramed.id("outers_stair" + infix + "_special");
|
||||
Identifier inner_id = ReFramed.id("inner_stair" + infix + "_special");
|
||||
Identifier outer_id = ReFramed.id("outer_stair" + infix + "_special");
|
||||
Identifier outer_side_id = ReFramed.id("outer_side_stair" + infix + "_special");
|
||||
return MultipartBlockStateSupplier.create(block)
|
||||
/* STRAIGHT X AXIS */
|
||||
.with(GBlockstate.when(EDGE, DOWN_EAST, STAIR_SHAPE, STRAIGHT),
|
||||
GBlockstate.variant(straight_id, true, R0, R0))
|
||||
.with(GBlockstate.when(EDGE, EAST_UP, STAIR_SHAPE, STRAIGHT),
|
||||
GBlockstate.variant(straight_id, true, R180, R0))
|
||||
.with(GBlockstate.when(EDGE, UP_WEST, STAIR_SHAPE, STRAIGHT),
|
||||
GBlockstate.variant(straight_id, true, R180, R180))
|
||||
.with(GBlockstate.when(EDGE, WEST_DOWN, STAIR_SHAPE, STRAIGHT),
|
||||
GBlockstate.variant(straight_id, true, R0, R180))
|
||||
/* STRAIGHT Y AXIS */
|
||||
.with(GBlockstate.when(EDGE, EAST_SOUTH, STAIR_SHAPE, STRAIGHT),
|
||||
GBlockstate.variant(straight_id, true, R90, R0))
|
||||
.with(GBlockstate.when(EDGE, SOUTH_WEST, STAIR_SHAPE, STRAIGHT),
|
||||
GBlockstate.variant(straight_id, true, R90, R90))
|
||||
.with(GBlockstate.when(EDGE, WEST_NORTH, STAIR_SHAPE, STRAIGHT),
|
||||
GBlockstate.variant(straight_id, true, R90, R180))
|
||||
.with(GBlockstate.when(EDGE, NORTH_EAST, STAIR_SHAPE, STRAIGHT),
|
||||
GBlockstate.variant(straight_id, true, R90, R270))
|
||||
/* STRAIGHT Z AXIS */
|
||||
.with(GBlockstate.when(EDGE, DOWN_SOUTH, STAIR_SHAPE, STRAIGHT),
|
||||
GBlockstate.variant(straight_id, true, R0, R90))
|
||||
.with(GBlockstate.when(EDGE, NORTH_DOWN, STAIR_SHAPE, STRAIGHT),
|
||||
GBlockstate.variant(straight_id, true, R0, R270))
|
||||
.with(GBlockstate.when(EDGE, UP_NORTH, STAIR_SHAPE, STRAIGHT),
|
||||
GBlockstate.variant(straight_id, true, R180, R270))
|
||||
.with(GBlockstate.when(EDGE, SOUTH_UP, STAIR_SHAPE, STRAIGHT),
|
||||
GBlockstate.variant(straight_id, true, R180, R90))
|
||||
/* INNER BOTTOM */
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, NORTH_DOWN, STAIR_SHAPE, INNER_RIGHT),
|
||||
GBlockstate.when(EDGE, WEST_NORTH, STAIR_SHAPE, INNER_RIGHT),
|
||||
GBlockstate.when(EDGE, WEST_DOWN, STAIR_SHAPE, INNER_LEFT)),
|
||||
GBlockstate.variant(inner_id, true, R0, R180))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, NORTH_DOWN, STAIR_SHAPE, INNER_LEFT),
|
||||
GBlockstate.when(EDGE, NORTH_EAST, STAIR_SHAPE, INNER_RIGHT),
|
||||
GBlockstate.when(EDGE, DOWN_EAST, STAIR_SHAPE, INNER_LEFT)),
|
||||
GBlockstate.variant(inner_id, true, R0, R270))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, DOWN_SOUTH, STAIR_SHAPE, INNER_LEFT),
|
||||
GBlockstate.when(EDGE, EAST_SOUTH, STAIR_SHAPE, INNER_RIGHT),
|
||||
GBlockstate.when(EDGE, DOWN_EAST, STAIR_SHAPE, INNER_RIGHT)),
|
||||
GBlockstate.variant(inner_id, true, R0, R0))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, DOWN_SOUTH, STAIR_SHAPE, INNER_RIGHT),
|
||||
GBlockstate.when(EDGE, SOUTH_WEST, STAIR_SHAPE, INNER_RIGHT),
|
||||
GBlockstate.when(EDGE, WEST_DOWN, STAIR_SHAPE, INNER_RIGHT)),
|
||||
GBlockstate.variant(inner_id, true, R0, R90))
|
||||
/* INNER TOP */
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, EAST_UP, STAIR_SHAPE, INNER_LEFT),
|
||||
GBlockstate.when(EDGE, NORTH_EAST, STAIR_SHAPE, INNER_LEFT),
|
||||
GBlockstate.when(EDGE, UP_NORTH, STAIR_SHAPE, INNER_LEFT)),
|
||||
GBlockstate.variant(inner_id, true, R180, R0))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, EAST_UP, STAIR_SHAPE, INNER_RIGHT),
|
||||
GBlockstate.when(EDGE, EAST_SOUTH, STAIR_SHAPE, INNER_LEFT),
|
||||
GBlockstate.when(EDGE, SOUTH_UP, STAIR_SHAPE, INNER_LEFT)),
|
||||
GBlockstate.variant(inner_id, true, R180, R90))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, SOUTH_UP, STAIR_SHAPE, INNER_RIGHT),
|
||||
GBlockstate.when(EDGE, SOUTH_WEST, STAIR_SHAPE, INNER_LEFT),
|
||||
GBlockstate.when(EDGE, UP_WEST, STAIR_SHAPE, INNER_RIGHT)),
|
||||
GBlockstate.variant(inner_id, true, R180, R180))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, UP_NORTH, STAIR_SHAPE, INNER_RIGHT),
|
||||
GBlockstate.when(EDGE, WEST_NORTH, STAIR_SHAPE, INNER_LEFT),
|
||||
GBlockstate.when(EDGE, UP_WEST, STAIR_SHAPE, INNER_LEFT)),
|
||||
GBlockstate.variant(inner_id, true, R180, R270))
|
||||
/* OUTER BOTTOM */
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, DOWN_SOUTH, STAIR_SHAPE, SECOND_OUTER_LEFT),
|
||||
GBlockstate.when(EDGE, DOWN_EAST, STAIR_SHAPE, SECOND_OUTER_RIGHT)),
|
||||
GBlockstate.variant(outer_id, true, R0, R0))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, DOWN_SOUTH, STAIR_SHAPE, SECOND_OUTER_RIGHT),
|
||||
GBlockstate.when(EDGE, WEST_DOWN, STAIR_SHAPE, FIRST_OUTER_RIGHT)),
|
||||
GBlockstate.variant(outer_id, true, R0, R90))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, NORTH_DOWN, STAIR_SHAPE, FIRST_OUTER_RIGHT),
|
||||
GBlockstate.when(EDGE, WEST_DOWN, STAIR_SHAPE, FIRST_OUTER_LEFT)),
|
||||
GBlockstate.variant(outer_id, true, R0, R180))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, NORTH_DOWN, STAIR_SHAPE, FIRST_OUTER_LEFT),
|
||||
GBlockstate.when(EDGE, DOWN_EAST, STAIR_SHAPE, SECOND_OUTER_LEFT)),
|
||||
GBlockstate.variant(outer_id, true, R0, R270))
|
||||
/* OUTER TOP */
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, UP_NORTH, STAIR_SHAPE, SECOND_OUTER_LEFT),
|
||||
GBlockstate.when(EDGE, EAST_UP, STAIR_SHAPE, FIRST_OUTER_LEFT)),
|
||||
GBlockstate.variant(outer_id, true, R180, R0))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, SOUTH_UP, STAIR_SHAPE, FIRST_OUTER_LEFT),
|
||||
GBlockstate.when(EDGE, EAST_UP, STAIR_SHAPE, FIRST_OUTER_RIGHT)),
|
||||
GBlockstate.variant(outer_id, true, R180, R90))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, SOUTH_UP, STAIR_SHAPE, FIRST_OUTER_RIGHT),
|
||||
GBlockstate.when(EDGE, UP_WEST, STAIR_SHAPE, SECOND_OUTER_RIGHT)),
|
||||
GBlockstate.variant(outer_id, true, R180, R180))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, UP_NORTH, STAIR_SHAPE, SECOND_OUTER_RIGHT),
|
||||
GBlockstate.when(EDGE, UP_WEST, STAIR_SHAPE, SECOND_OUTER_LEFT)),
|
||||
GBlockstate.variant(outer_id, true, R180, R270))
|
||||
/* OUTER EAST */
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, EAST_SOUTH, STAIR_SHAPE, SECOND_OUTER_RIGHT),
|
||||
GBlockstate.when(EDGE, DOWN_EAST, STAIR_SHAPE, FIRST_OUTER_RIGHT)),
|
||||
GBlockstate.variant(outer_side_id, true, R0, R0))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, EAST_SOUTH, STAIR_SHAPE, SECOND_OUTER_LEFT),
|
||||
GBlockstate.when(EDGE, EAST_UP, STAIR_SHAPE, SECOND_OUTER_RIGHT)),
|
||||
GBlockstate.variant(outer_side_id, true, R90, R0))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, NORTH_EAST, STAIR_SHAPE, FIRST_OUTER_LEFT),
|
||||
GBlockstate.when(EDGE, EAST_UP, STAIR_SHAPE, SECOND_OUTER_LEFT)),
|
||||
GBlockstate.variant(outer_side_id, true, R180, R0))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, NORTH_EAST, STAIR_SHAPE, FIRST_OUTER_RIGHT),
|
||||
GBlockstate.when(EDGE, DOWN_EAST, STAIR_SHAPE, FIRST_OUTER_LEFT)),
|
||||
GBlockstate.variant(outer_side_id, true, R270, R0))
|
||||
/* OUTER SOUTH */
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, SOUTH_WEST, STAIR_SHAPE, SECOND_OUTER_RIGHT),
|
||||
GBlockstate.when(EDGE, DOWN_SOUTH, STAIR_SHAPE, FIRST_OUTER_RIGHT)),
|
||||
GBlockstate.variant(outer_side_id, true, R0, R90))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, SOUTH_WEST, STAIR_SHAPE, SECOND_OUTER_LEFT),
|
||||
GBlockstate.when(EDGE, SOUTH_UP, STAIR_SHAPE, SECOND_OUTER_RIGHT)),
|
||||
GBlockstate.variant(outer_side_id, true, R90, R90))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, EAST_SOUTH, STAIR_SHAPE, FIRST_OUTER_LEFT),
|
||||
GBlockstate.when(EDGE, SOUTH_UP, STAIR_SHAPE, SECOND_OUTER_LEFT)),
|
||||
GBlockstate.variant(outer_side_id, true, R180, R90))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, EAST_SOUTH, STAIR_SHAPE, FIRST_OUTER_RIGHT),
|
||||
GBlockstate.when(EDGE, DOWN_SOUTH, STAIR_SHAPE, FIRST_OUTER_LEFT)),
|
||||
GBlockstate.variant(outer_side_id, true, R270, R90))
|
||||
/* OUTER WEST */
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, WEST_NORTH, STAIR_SHAPE, SECOND_OUTER_RIGHT),
|
||||
GBlockstate.when(EDGE, WEST_DOWN, STAIR_SHAPE, SECOND_OUTER_LEFT)),
|
||||
GBlockstate.variant(outer_side_id, true, R0, R180))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, WEST_NORTH, STAIR_SHAPE, SECOND_OUTER_LEFT),
|
||||
GBlockstate.when(EDGE, UP_WEST, STAIR_SHAPE, FIRST_OUTER_LEFT)),
|
||||
GBlockstate.variant(outer_side_id, true, R90, R180))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, SOUTH_WEST, STAIR_SHAPE, FIRST_OUTER_LEFT),
|
||||
GBlockstate.when(EDGE, UP_WEST, STAIR_SHAPE, FIRST_OUTER_RIGHT)),
|
||||
GBlockstate.variant(outer_side_id, true, R180, R180))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, SOUTH_WEST, STAIR_SHAPE, FIRST_OUTER_RIGHT),
|
||||
GBlockstate.when(EDGE, WEST_DOWN, STAIR_SHAPE, SECOND_OUTER_RIGHT)),
|
||||
GBlockstate.variant(outer_side_id, true, R270, R180))
|
||||
/* OUTER NORTH */
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, NORTH_EAST, STAIR_SHAPE, SECOND_OUTER_RIGHT),
|
||||
GBlockstate.when(EDGE, NORTH_DOWN, STAIR_SHAPE, SECOND_OUTER_LEFT)),
|
||||
GBlockstate.variant(outer_side_id, true, R0, R270))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, NORTH_EAST, STAIR_SHAPE, SECOND_OUTER_LEFT),
|
||||
GBlockstate.when(EDGE, UP_NORTH, STAIR_SHAPE, FIRST_OUTER_LEFT)),
|
||||
GBlockstate.variant(outer_side_id, true, R90, R270))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, WEST_NORTH, STAIR_SHAPE, FIRST_OUTER_LEFT),
|
||||
GBlockstate.when(EDGE, UP_NORTH, STAIR_SHAPE, FIRST_OUTER_RIGHT)),
|
||||
GBlockstate.variant(outer_side_id, true, R180, R270))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, WEST_NORTH, STAIR_SHAPE, FIRST_OUTER_RIGHT),
|
||||
GBlockstate.when(EDGE, NORTH_DOWN, STAIR_SHAPE, SECOND_OUTER_RIGHT)),
|
||||
GBlockstate.variant(outer_side_id, true, R270, R270))
|
||||
/* OUTER BOTTOM */
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, DOWN_SOUTH, STAIR_SHAPE, OUTER_LEFT),
|
||||
GBlockstate.when(EDGE, DOWN_EAST, STAIR_SHAPE, OUTER_RIGHT),
|
||||
GBlockstate.when(EDGE, EAST_SOUTH, STAIR_SHAPE, OUTER_RIGHT)),
|
||||
GBlockstate.variant(double_outer_id, true, R0, R0))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, DOWN_SOUTH, STAIR_SHAPE, OUTER_RIGHT),
|
||||
GBlockstate.when(EDGE, WEST_DOWN, STAIR_SHAPE, OUTER_RIGHT),
|
||||
GBlockstate.when(EDGE, SOUTH_WEST, STAIR_SHAPE, OUTER_RIGHT)),
|
||||
GBlockstate.variant(double_outer_id, true, R0, R90))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, NORTH_DOWN, STAIR_SHAPE, OUTER_RIGHT),
|
||||
GBlockstate.when(EDGE, WEST_DOWN, STAIR_SHAPE, OUTER_LEFT),
|
||||
GBlockstate.when(EDGE, WEST_NORTH, STAIR_SHAPE, OUTER_RIGHT)),
|
||||
GBlockstate.variant(double_outer_id, true, R0, R180))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, NORTH_DOWN, STAIR_SHAPE, OUTER_LEFT),
|
||||
GBlockstate.when(EDGE, DOWN_EAST, STAIR_SHAPE, OUTER_LEFT),
|
||||
GBlockstate.when(EDGE, NORTH_EAST, STAIR_SHAPE, OUTER_RIGHT)),
|
||||
GBlockstate.variant(double_outer_id, true, R0, R270))
|
||||
/* OUTER TOP */
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, UP_NORTH, STAIR_SHAPE, OUTER_LEFT),
|
||||
GBlockstate.when(EDGE, EAST_UP, STAIR_SHAPE, OUTER_LEFT),
|
||||
GBlockstate.when(EDGE, NORTH_EAST, STAIR_SHAPE, OUTER_LEFT)),
|
||||
GBlockstate.variant(double_outer_id, true, R180, R0))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, SOUTH_UP, STAIR_SHAPE, OUTER_LEFT),
|
||||
GBlockstate.when(EDGE, EAST_UP, STAIR_SHAPE, OUTER_RIGHT),
|
||||
GBlockstate.when(EDGE, EAST_SOUTH, STAIR_SHAPE, OUTER_LEFT)),
|
||||
GBlockstate.variant(double_outer_id, true, R180, R90))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, SOUTH_UP, STAIR_SHAPE, OUTER_RIGHT),
|
||||
GBlockstate.when(EDGE, UP_WEST, STAIR_SHAPE, OUTER_RIGHT),
|
||||
GBlockstate.when(EDGE, SOUTH_WEST, STAIR_SHAPE, OUTER_LEFT)),
|
||||
GBlockstate.variant(double_outer_id, true, R180, R180))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, UP_NORTH, STAIR_SHAPE, OUTER_RIGHT),
|
||||
GBlockstate.when(EDGE, UP_WEST, STAIR_SHAPE, OUTER_LEFT),
|
||||
GBlockstate.when(EDGE, WEST_NORTH, STAIR_SHAPE, OUTER_LEFT)),
|
||||
GBlockstate.variant(double_outer_id, true, R180, R270));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRecipe(RecipeExporter exporter) {
|
||||
RecipeProvider.offerStonecuttingRecipe(exporter, RecipeCategory.BUILDING_BLOCKS, this, ReFramed.CUBE);
|
||||
ShapedRecipeJsonBuilder
|
||||
.create(RecipeCategory.BUILDING_BLOCKS, this, 4)
|
||||
.pattern("I ")
|
||||
.pattern("II ")
|
||||
.pattern("III")
|
||||
.input('I', ReFramed.CUBE)
|
||||
.criterion(FabricRecipeProvider.hasItem(ReFramed.CUBE), FabricRecipeProvider.conditionsFromItem(ReFramed.CUBE))
|
||||
.criterion(FabricRecipeProvider.hasItem(this), FabricRecipeProvider.conditionsFromItem(this))
|
||||
.offerTo(exporter);
|
||||
public Map<Integer, Integer> getThemeMap(BlockState state, BlockState new_state) {
|
||||
if (new_state.isOf(ReFramed.STAIRS_CUBE)) return Map.of(1, 1);
|
||||
return super.getThemeMap(state, new_state);
|
||||
}
|
||||
|
||||
static {
|
||||
@@ -382,51 +163,51 @@ public class ReFramedStairBlock extends WaterloggableReFramedBlock implements Bl
|
||||
.add(25, VoxelHelper::rotateCX).add(26, VoxelHelper::rotateCX)
|
||||
// WEST_DOWN
|
||||
.add(0, VoxelHelper::rotateCY)
|
||||
.add(10).add(1)
|
||||
.add(12).add(3)
|
||||
.add(16).add(5)
|
||||
.add(7, VoxelHelper::rotateCY).add(8, VoxelHelper::rotateCY)
|
||||
.add(1).add(10)
|
||||
.add(3).add(12)
|
||||
.add(5).add(16)
|
||||
.add(8, VoxelHelper::rotateCY).add(7, VoxelHelper::rotateCY)
|
||||
// DOWN_EAST
|
||||
.add(36, VoxelHelper::rotateZ)
|
||||
.add(11).add(2)
|
||||
.add(13).add(4)
|
||||
.add(2).add(11)
|
||||
.add(4).add(13)
|
||||
.add(41, VoxelHelper::rotateZ).add(42, VoxelHelper::rotateZ)
|
||||
.add(17).add(6)
|
||||
.add(6).add(17)
|
||||
// EAST_UP
|
||||
.add(45, VoxelHelper::rotateZ)
|
||||
.add(20).add(29)
|
||||
.add(22).add(31)
|
||||
.add(24).add(35)
|
||||
.add(29).add(20)
|
||||
.add(31).add(22)
|
||||
.add(35).add(24)
|
||||
.add(52, VoxelHelper::rotateZ).add(53, VoxelHelper::rotateZ)
|
||||
// UP_WEST
|
||||
.add(54, VoxelHelper::rotateZ)
|
||||
.add(19).add(28)
|
||||
.add(21).add(30)
|
||||
.add(28).add(19)
|
||||
.add(30).add(21)
|
||||
.add(59, VoxelHelper::rotateZ).add(60, VoxelHelper::rotateZ)
|
||||
.add(23).add(34)
|
||||
.add(34).add(23)
|
||||
// WEST_NORTH
|
||||
.add(0, VoxelHelper::rotateCZ)
|
||||
.add(1).add(28)
|
||||
.add(3).add(30)
|
||||
.add(7).add(32)
|
||||
.add(44).add(69)
|
||||
.add(43).add(68)
|
||||
// NORTH_EAST
|
||||
.add(72, VoxelHelper::rotateY)
|
||||
.add(2).add(29)
|
||||
.add(4).add(31)
|
||||
.add(51).add(62)
|
||||
.add(50).add(61)
|
||||
.add(8).add(33)
|
||||
// EAST_SOUTH
|
||||
.add(81, VoxelHelper::rotateY)
|
||||
.add(11).add(20)
|
||||
.add(13).add(22)
|
||||
.add(15).add(26)
|
||||
.add(50).add(61)
|
||||
.add(51).add(62)
|
||||
// SOUTH_WEST
|
||||
.add(90, VoxelHelper::rotateY)
|
||||
.add(10).add(19)
|
||||
.add(12).add(21)
|
||||
.add(43).add(68)
|
||||
.add(44).add(69)
|
||||
.add(14).add(25)
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -1,19 +1,11 @@
|
||||
package fr.adrien1106.reframed.block;
|
||||
|
||||
import fr.adrien1106.reframed.ReFramed;
|
||||
import fr.adrien1106.reframed.generator.BlockStateProvider;
|
||||
import fr.adrien1106.reframed.util.blocks.BlockHelper;
|
||||
import fr.adrien1106.reframed.util.blocks.Edge;
|
||||
import fr.adrien1106.reframed.util.blocks.StairShape;
|
||||
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.data.client.MultipartBlockStateSupplier;
|
||||
import net.minecraft.data.server.recipe.RecipeExporter;
|
||||
import net.minecraft.data.server.recipe.RecipeProvider;
|
||||
import net.minecraft.data.server.recipe.ShapelessRecipeJsonBuilder;
|
||||
import net.minecraft.item.ItemPlacementContext;
|
||||
import net.minecraft.recipe.book.RecipeCategory;
|
||||
import net.minecraft.state.StateManager;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
@@ -27,7 +19,7 @@ import static fr.adrien1106.reframed.util.VoxelHelper.VoxelListBuilder;
|
||||
import static fr.adrien1106.reframed.util.blocks.BlockProperties.EDGE;
|
||||
import static fr.adrien1106.reframed.util.blocks.BlockProperties.STAIR_SHAPE;
|
||||
|
||||
public class ReFramedStairsCubeBlock extends ReFramedDoubleBlock implements BlockStateProvider {
|
||||
public class ReFramedStairsCubeBlock extends ReFramedDoubleBlock {
|
||||
|
||||
private static final VoxelShape[] STAIRS_CUBE_VOXELS = VoxelListBuilder.buildFrom(STAIR_VOXELS);
|
||||
private record ModelCacheKey(Edge edge, StairShape shape) {}
|
||||
@@ -80,21 +72,4 @@ public class ReFramedStairsCubeBlock extends ReFramedDoubleBlock implements Bloc
|
||||
StairShape shape = state.get(STAIR_SHAPE);
|
||||
return i == 2 ? STAIRS_CUBE_VOXELS[edge.getID() * 9 + shape.getID()] : getStairShape(edge, shape);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MultipartBlockStateSupplier getMultipart() {
|
||||
return getStairMultipart(this, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRecipe(RecipeExporter exporter) {
|
||||
RecipeProvider.offerStonecuttingRecipe(exporter, RecipeCategory.BUILDING_BLOCKS, this, ReFramed.CUBE);
|
||||
ShapelessRecipeJsonBuilder
|
||||
.create(RecipeCategory.BUILDING_BLOCKS, this)
|
||||
.input(ReFramed.STAIR)
|
||||
.input(ReFramed.STEP)
|
||||
.criterion(FabricRecipeProvider.hasItem(ReFramed.CUBE), FabricRecipeProvider.conditionsFromItem(ReFramed.CUBE))
|
||||
.criterion(FabricRecipeProvider.hasItem(this), FabricRecipeProvider.conditionsFromItem(this))
|
||||
.offerTo(exporter);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,35 +1,31 @@
|
||||
package fr.adrien1106.reframed.block;
|
||||
|
||||
import fr.adrien1106.reframed.ReFramed;
|
||||
import fr.adrien1106.reframed.generator.BlockStateProvider;
|
||||
import fr.adrien1106.reframed.generator.GBlockstate;
|
||||
import fr.adrien1106.reframed.util.VoxelHelper;
|
||||
import fr.adrien1106.reframed.util.blocks.BlockHelper;
|
||||
import fr.adrien1106.reframed.util.blocks.Edge;
|
||||
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.ShapeContext;
|
||||
import net.minecraft.data.client.BlockStateSupplier;
|
||||
import net.minecraft.data.client.MultipartBlockStateSupplier;
|
||||
import net.minecraft.data.server.recipe.RecipeExporter;
|
||||
import net.minecraft.data.server.recipe.RecipeProvider;
|
||||
import net.minecraft.data.server.recipe.ShapedRecipeJsonBuilder;
|
||||
import net.minecraft.item.BlockItem;
|
||||
import net.minecraft.item.ItemPlacementContext;
|
||||
import net.minecraft.recipe.book.RecipeCategory;
|
||||
import net.minecraft.state.StateManager;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.util.shape.VoxelShape;
|
||||
import net.minecraft.world.BlockView;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static fr.adrien1106.reframed.util.VoxelHelper.VoxelListBuilder;
|
||||
import static fr.adrien1106.reframed.util.blocks.BlockProperties.EDGE;
|
||||
import static fr.adrien1106.reframed.util.blocks.Edge.*;
|
||||
import static net.minecraft.data.client.VariantSettings.Rotation.*;
|
||||
import static fr.adrien1106.reframed.util.blocks.BlockProperties.STAIR_SHAPE;
|
||||
import static net.minecraft.state.property.Properties.*;
|
||||
import static net.minecraft.state.property.Properties.WATERLOGGED;
|
||||
|
||||
public class ReFramedStepBlock extends WaterloggableReFramedBlock implements BlockStateProvider {
|
||||
public class ReFramedStepBlock extends WaterloggableReFramedBlock {
|
||||
|
||||
public static final VoxelShape[] STEP_VOXELS;
|
||||
|
||||
@@ -53,9 +49,84 @@ public class ReFramedStepBlock extends WaterloggableReFramedBlock implements Blo
|
||||
super.appendProperties(builder.add(EDGE));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canReplace(BlockState state, ItemPlacementContext context) {
|
||||
Edge edge = state.get(EDGE);
|
||||
return !(
|
||||
context.getPlayer().isSneaking()
|
||||
|| !(context.getStack().getItem() instanceof BlockItem block_item)
|
||||
|| (
|
||||
!(
|
||||
block_item.getBlock() == ReFramed.STAIR
|
||||
&& ((ReFramedStairsCubeBlock) ReFramed.STAIRS_CUBE)
|
||||
.matchesShape(
|
||||
context.getHitPos(),
|
||||
context.getBlockPos(),
|
||||
ReFramed.STAIRS_CUBE.getDefaultState().with(EDGE, edge.opposite()),
|
||||
1
|
||||
)
|
||||
|
||||
)
|
||||
&& !(
|
||||
block_item.getBlock() == this
|
||||
&& (
|
||||
((ReFramedStepsSlabBlock) ReFramed.STEPS_SLAB)
|
||||
.matchesShape(
|
||||
context.getHitPos(),
|
||||
context.getBlockPos(),
|
||||
ReFramed.STEPS_SLAB.getDefaultState()
|
||||
.with(FACING, edge.getFirstDirection())
|
||||
.with(AXIS, edge.getSecondDirection().getAxis()),
|
||||
edge.getSecondDirection().getDirection() == Direction.AxisDirection.POSITIVE ? 1 : 2
|
||||
)
|
||||
|| ((ReFramedStepsSlabBlock) ReFramed.STEPS_SLAB)
|
||||
.matchesShape(
|
||||
context.getHitPos(),
|
||||
context.getBlockPos(),
|
||||
ReFramed.STEPS_SLAB.getDefaultState()
|
||||
.with(FACING, edge.getSecondDirection())
|
||||
.with(AXIS, edge.getFirstDirection().getAxis()),
|
||||
edge.getFirstDirection().getDirection() == Direction.AxisDirection.POSITIVE ? 1 : 2
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BlockState getPlacementState(ItemPlacementContext ctx) {
|
||||
BlockPos pos = ctx.getBlockPos();
|
||||
BlockState current_state = ctx.getWorld().getBlockState(pos);
|
||||
if (current_state.isOf(ReFramed.STAIR))
|
||||
return ReFramed.STAIRS_CUBE.getDefaultState()
|
||||
.with(EDGE, current_state.get(EDGE))
|
||||
.with(STAIR_SHAPE, current_state.get(STAIR_SHAPE));
|
||||
|
||||
|
||||
if (current_state.isOf(this)) {
|
||||
Vec3d hit = ctx.getHitPos();
|
||||
Edge edge = current_state.get(EDGE);
|
||||
Direction dir = edge.getFirstDirection();
|
||||
ReFramedStepsSlabBlock block = ((ReFramedStepsSlabBlock) ReFramed.STEPS_SLAB);
|
||||
BlockState state = block.getDefaultState()
|
||||
.with(FACING, dir)
|
||||
.with(AXIS, edge.getOtherDirection(dir).getAxis())
|
||||
.with(WATERLOGGED, current_state.get(WATERLOGGED));
|
||||
if (!block.matchesShape(
|
||||
hit, pos,
|
||||
state,
|
||||
edge.getOtherDirection(dir).getDirection() == Direction.AxisDirection.POSITIVE ? 1 : 2
|
||||
)) {
|
||||
dir = edge.getSecondDirection();
|
||||
state = state
|
||||
.with(FACING, dir)
|
||||
.with(AXIS, edge.getOtherDirection(dir).getAxis());
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
return super.getPlacementState(ctx).with(EDGE, BlockHelper.getPlacementEdge(ctx));
|
||||
}
|
||||
|
||||
@@ -69,48 +140,16 @@ public class ReFramedStepBlock extends WaterloggableReFramedBlock implements Blo
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockStateSupplier getMultipart() {
|
||||
Identifier model_id = ReFramed.id("step_special");
|
||||
return MultipartBlockStateSupplier.create(this)
|
||||
/* X AXIS */
|
||||
.with(GBlockstate.when(EDGE, DOWN_EAST),
|
||||
GBlockstate.variant(model_id, true, R0, R0))
|
||||
.with(GBlockstate.when(EDGE, EAST_UP),
|
||||
GBlockstate.variant(model_id, true, R180, R0))
|
||||
.with(GBlockstate.when(EDGE, UP_WEST),
|
||||
GBlockstate.variant(model_id, true, R180, R180))
|
||||
.with(GBlockstate.when(EDGE, WEST_DOWN),
|
||||
GBlockstate.variant(model_id, true, R0, R180))
|
||||
/* Y AXIS */
|
||||
.with(GBlockstate.when(EDGE, EAST_SOUTH),
|
||||
GBlockstate.variant(model_id, true, R90, R0))
|
||||
.with(GBlockstate.when(EDGE, SOUTH_WEST),
|
||||
GBlockstate.variant(model_id, true, R90, R90))
|
||||
.with(GBlockstate.when(EDGE, WEST_NORTH),
|
||||
GBlockstate.variant(model_id, true, R90, R180))
|
||||
.with(GBlockstate.when(EDGE, NORTH_EAST),
|
||||
GBlockstate.variant(model_id, true, R90, R270))
|
||||
/* Z AXIS */
|
||||
.with(GBlockstate.when(EDGE, DOWN_SOUTH),
|
||||
GBlockstate.variant(model_id, true, R0, R90))
|
||||
.with(GBlockstate.when(EDGE, NORTH_DOWN),
|
||||
GBlockstate.variant(model_id, true, R0, R270))
|
||||
.with(GBlockstate.when(EDGE, UP_NORTH),
|
||||
GBlockstate.variant(model_id, true, R180, R270))
|
||||
.with(GBlockstate.when(EDGE, SOUTH_UP),
|
||||
GBlockstate.variant(model_id, true, R180, R90));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRecipe(RecipeExporter exporter) {
|
||||
RecipeProvider.offerStonecuttingRecipe(exporter, RecipeCategory.BUILDING_BLOCKS, this, ReFramed.CUBE, 4);
|
||||
ShapedRecipeJsonBuilder
|
||||
.create(RecipeCategory.BUILDING_BLOCKS, this, 8)
|
||||
.pattern("II")
|
||||
.input('I', ReFramed.CUBE)
|
||||
.criterion(FabricRecipeProvider.hasItem(ReFramed.CUBE), FabricRecipeProvider.conditionsFromItem(ReFramed.CUBE))
|
||||
.criterion(FabricRecipeProvider.hasItem(this), FabricRecipeProvider.conditionsFromItem(this))
|
||||
.offerTo(exporter);
|
||||
public Map<Integer, Integer> getThemeMap(BlockState state, BlockState new_state) {
|
||||
if (new_state.isOf(ReFramed.STAIRS_CUBE)) return Map.of(1, 2);
|
||||
if (new_state.isOf(ReFramed.STEPS_SLAB))
|
||||
return Map.of(
|
||||
1,
|
||||
state.get(EDGE)
|
||||
.getOtherDirection(new_state.get(FACING))
|
||||
.getDirection() == Direction.AxisDirection.POSITIVE ? 2 : 1
|
||||
);
|
||||
return super.getThemeMap(state, new_state);
|
||||
}
|
||||
|
||||
static {
|
||||
|
||||
@@ -1,22 +1,12 @@
|
||||
package fr.adrien1106.reframed.block;
|
||||
|
||||
import fr.adrien1106.reframed.ReFramed;
|
||||
import fr.adrien1106.reframed.generator.BlockStateProvider;
|
||||
import fr.adrien1106.reframed.generator.GBlockstate;
|
||||
import fr.adrien1106.reframed.util.blocks.BlockHelper;
|
||||
import fr.adrien1106.reframed.util.blocks.Edge;
|
||||
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.ShapeContext;
|
||||
import net.minecraft.data.client.MultipartBlockStateSupplier;
|
||||
import net.minecraft.data.server.recipe.RecipeExporter;
|
||||
import net.minecraft.data.server.recipe.RecipeProvider;
|
||||
import net.minecraft.data.server.recipe.ShapelessRecipeJsonBuilder;
|
||||
import net.minecraft.item.ItemPlacementContext;
|
||||
import net.minecraft.recipe.book.RecipeCategory;
|
||||
import net.minecraft.state.StateManager;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.Direction.Axis;
|
||||
@@ -27,12 +17,11 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import static fr.adrien1106.reframed.block.ReFramedSlabBlock.getSlabShape;
|
||||
import static fr.adrien1106.reframed.block.ReFramedStepBlock.getStepShape;
|
||||
import static net.minecraft.data.client.VariantSettings.Rotation.*;
|
||||
import static net.minecraft.state.property.Properties.AXIS;
|
||||
import static net.minecraft.state.property.Properties.FACING;
|
||||
import static net.minecraft.util.shape.VoxelShapes.empty;
|
||||
|
||||
public class ReFramedStepsSlabBlock extends WaterloggableReFramedDoubleBlock implements BlockStateProvider {
|
||||
public class ReFramedStepsSlabBlock extends WaterloggableReFramedDoubleBlock {
|
||||
private record ModelCacheKey(Direction facing, Axis axis) {}
|
||||
|
||||
public ReFramedStepsSlabBlock(Settings settings) {
|
||||
@@ -81,7 +70,7 @@ public class ReFramedStepsSlabBlock extends WaterloggableReFramedDoubleBlock imp
|
||||
switch (axis) {
|
||||
case X -> i == 1 ? Direction.WEST : Direction.EAST;
|
||||
case Y -> i == 1 ? Direction.DOWN : Direction.UP;
|
||||
case Z -> i == 1 ? Direction.SOUTH : Direction.NORTH;
|
||||
case Z -> i == 1 ? Direction.NORTH : Direction.SOUTH;
|
||||
}
|
||||
));
|
||||
}
|
||||
@@ -90,47 +79,4 @@ public class ReFramedStepsSlabBlock extends WaterloggableReFramedDoubleBlock imp
|
||||
public int getTopThemeIndex(BlockState state) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MultipartBlockStateSupplier getMultipart() {
|
||||
Identifier step_id = ReFramed.id("steps_slab_special");
|
||||
Identifier step_side_id = ReFramed.id("steps_slab_side_special");
|
||||
return MultipartBlockStateSupplier.create(this)
|
||||
.with(GBlockstate.when(FACING, Direction.DOWN, AXIS, Axis.X),
|
||||
GBlockstate.variant(step_id, true, R0, R180))
|
||||
.with(GBlockstate.when(FACING, Direction.DOWN, AXIS, Axis.Z),
|
||||
GBlockstate.variant(step_id, true, R0, R90))
|
||||
.with(GBlockstate.when(FACING, Direction.UP, AXIS, Axis.X),
|
||||
GBlockstate.variant(step_id, true, R180, R180))
|
||||
.with(GBlockstate.when(FACING, Direction.UP, AXIS, Axis.Z),
|
||||
GBlockstate.variant(step_id, true, R180, R90))
|
||||
|
||||
.with(GBlockstate.when(FACING, Direction.EAST, AXIS, Axis.Z),
|
||||
GBlockstate.variant(step_side_id, true, R180, R0))
|
||||
.with(GBlockstate.when(FACING, Direction.EAST, AXIS, Axis.Y),
|
||||
GBlockstate.variant(step_side_id, true, R90, R0))
|
||||
.with(GBlockstate.when(FACING, Direction.SOUTH, AXIS, Axis.X),
|
||||
GBlockstate.variant(step_side_id, true, R180, R90))
|
||||
.with(GBlockstate.when(FACING, Direction.SOUTH, AXIS, Axis.Y),
|
||||
GBlockstate.variant(step_side_id, true, R90, R90))
|
||||
.with(GBlockstate.when(FACING, Direction.WEST, AXIS, Axis.Z),
|
||||
GBlockstate.variant(step_side_id, true, R0, R180))
|
||||
.with(GBlockstate.when(FACING, Direction.WEST, AXIS, Axis.Y),
|
||||
GBlockstate.variant(step_side_id, true, R90, R180))
|
||||
.with(GBlockstate.when(FACING, Direction.NORTH, AXIS, Axis.X),
|
||||
GBlockstate.variant(step_side_id, true, R0, R270))
|
||||
.with(GBlockstate.when(FACING, Direction.NORTH, AXIS, Axis.Y),
|
||||
GBlockstate.variant(step_side_id, true, R90, R270));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRecipe(RecipeExporter exporter) {
|
||||
RecipeProvider.offerStonecuttingRecipe(exporter, RecipeCategory.BUILDING_BLOCKS, this, ReFramed.CUBE, 2);
|
||||
ShapelessRecipeJsonBuilder
|
||||
.create(RecipeCategory.BUILDING_BLOCKS, this)
|
||||
.input(ReFramed.STEP, 2)
|
||||
.criterion(FabricRecipeProvider.hasItem(ReFramed.CUBE), FabricRecipeProvider.conditionsFromItem(ReFramed.CUBE))
|
||||
.criterion(FabricRecipeProvider.hasItem(this), FabricRecipeProvider.conditionsFromItem(this))
|
||||
.offerTo(exporter);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,217 @@
|
||||
package fr.adrien1106.reframed.block;
|
||||
|
||||
import fr.adrien1106.reframed.util.VoxelHelper;
|
||||
import net.minecraft.block.*;
|
||||
import net.minecraft.block.enums.WallShape;
|
||||
import net.minecraft.item.ItemPlacementContext;
|
||||
import net.minecraft.registry.tag.BlockTags;
|
||||
import net.minecraft.state.StateManager;
|
||||
import net.minecraft.state.property.Property;
|
||||
import net.minecraft.util.function.BooleanBiFunction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.shape.VoxelShape;
|
||||
import net.minecraft.util.shape.VoxelShapes;
|
||||
import net.minecraft.world.BlockView;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.WorldAccess;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static net.minecraft.state.property.Properties.*;
|
||||
|
||||
public class ReframedWallBlock extends WaterloggableReFramedBlock {
|
||||
|
||||
public static final VoxelShape[] WALL_VOXELS;
|
||||
|
||||
private record ModelCacheKey(boolean up, WallShape east, WallShape north, WallShape west, WallShape south) {}
|
||||
|
||||
public ReframedWallBlock(Settings settings) {
|
||||
super(settings);
|
||||
setDefaultState(getDefaultState()
|
||||
.with(UP, true)
|
||||
.with(EAST_WALL_SHAPE, WallShape.NONE)
|
||||
.with(NORTH_WALL_SHAPE, WallShape.NONE)
|
||||
.with(WEST_WALL_SHAPE, WallShape.NONE)
|
||||
.with(SOUTH_WALL_SHAPE, WallShape.NONE)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getModelCacheKey(BlockState state) {
|
||||
return new ModelCacheKey(
|
||||
state.get(UP),
|
||||
state.get(EAST_WALL_SHAPE),
|
||||
state.get(NORTH_WALL_SHAPE),
|
||||
state.get(WEST_WALL_SHAPE),
|
||||
state.get(SOUTH_WALL_SHAPE)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getModelStateCount() {
|
||||
return 162;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
|
||||
super.appendProperties(builder.add(UP, EAST_WALL_SHAPE, NORTH_WALL_SHAPE, SOUTH_WALL_SHAPE, WEST_WALL_SHAPE));
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getStateForNeighborUpdate(BlockState state, Direction dir, BlockState other_state, WorldAccess world, BlockPos pos, BlockPos moved) {
|
||||
BlockState new_state = super.getStateForNeighborUpdate(state, dir, other_state, world, pos, moved);
|
||||
if (dir == Direction.DOWN) return new_state;
|
||||
BlockState top_state = dir == Direction.UP? other_state: world.getBlockState(pos.up());
|
||||
boolean fs = top_state.isSideSolidFullSquare(world, pos.up(), Direction.DOWN);
|
||||
VoxelShape top_shape = fs ? null : top_state.getCollisionShape(world, pos.up()).getFace(Direction.DOWN);
|
||||
if (dir == Direction.UP) {
|
||||
for (Direction d : Direction.Type.HORIZONTAL) {
|
||||
Property<WallShape> wall_shape = getWallShape(d);
|
||||
if (state.get(wall_shape) == WallShape.NONE) continue;
|
||||
new_state = new_state.with(
|
||||
wall_shape,
|
||||
fs
|
||||
|| (top_state.contains(wall_shape) && top_state.get(wall_shape) != WallShape.NONE)
|
||||
|| shouldUseTall(WALL_VOXELS[dir.ordinal() + 3], top_shape)
|
||||
? WallShape.TALL
|
||||
: WallShape.LOW
|
||||
);
|
||||
}
|
||||
return new_state.with(UP, shouldHavePost(new_state, top_state, top_shape));
|
||||
}
|
||||
|
||||
boolean side_full = other_state.isSideSolidFullSquare(world, moved, dir.getOpposite());
|
||||
if (shouldConnectTo(other_state, side_full, dir.getOpposite())) {
|
||||
new_state = new_state.with(
|
||||
getWallShape(dir),
|
||||
fs || shouldUseTall(WALL_VOXELS[dir.ordinal() + 3], top_shape)
|
||||
? WallShape.TALL
|
||||
: WallShape.LOW
|
||||
);
|
||||
} else new_state = new_state.with(getWallShape(dir), WallShape.NONE);
|
||||
return new_state.with(UP, shouldHavePost(new_state, top_state, top_shape));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable BlockState getPlacementState(ItemPlacementContext ctx) {
|
||||
BlockState state = super.getPlacementState(ctx);
|
||||
World world = ctx.getWorld();
|
||||
BlockPos pos = ctx.getBlockPos();
|
||||
BlockState top_state = world.getBlockState(pos.up());
|
||||
boolean fs = top_state.isSideSolidFullSquare(world, pos.up(), Direction.DOWN);
|
||||
VoxelShape top_shape = fs ? null : top_state.getCollisionShape(world, pos.up()).getFace(Direction.DOWN);
|
||||
for (Direction dir : Direction.Type.HORIZONTAL) {
|
||||
BlockPos offset = pos.offset(dir);
|
||||
BlockState neighbor = world.getBlockState(offset);
|
||||
boolean side_full = neighbor.isSideSolidFullSquare(world, offset, dir.getOpposite());
|
||||
if (shouldConnectTo(neighbor, side_full, dir.getOpposite())) {
|
||||
state = state.with(
|
||||
getWallShape(dir),
|
||||
fs || shouldUseTall(WALL_VOXELS[dir.ordinal() + 3], top_shape)
|
||||
? WallShape.TALL
|
||||
: WallShape.LOW
|
||||
);
|
||||
}
|
||||
}
|
||||
return state.with(UP, shouldHavePost(state, top_state, top_shape));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState new_state, boolean moved) {
|
||||
super.onStateReplaced(state, world, pos, new_state, moved);
|
||||
|
||||
if(!state.isOf(new_state.getBlock())) world.removeBlockEntity(pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
|
||||
VoxelShape shape = state.get(UP) ? WALL_VOXELS[0]: VoxelShapes.empty();
|
||||
for (Direction dir : Direction.Type.HORIZONTAL) {
|
||||
WallShape wall_shape = state.get(getWallShape(dir));
|
||||
if (wall_shape != WallShape.NONE)
|
||||
shape = VoxelShapes.union(shape, WALL_VOXELS[1 + (wall_shape.ordinal()-1) * 4 + (dir.ordinal() - 2)]);
|
||||
}
|
||||
return shape;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VoxelShape getCollisionShape(BlockState state, BlockView view, BlockPos pos, ShapeContext ctx) {
|
||||
VoxelShape shape = state.get(UP) ? WALL_VOXELS[9]: VoxelShapes.empty();
|
||||
for (Direction dir : Direction.Type.HORIZONTAL) {
|
||||
if (state.get(getWallShape(dir)) != WallShape.NONE)
|
||||
shape = VoxelShapes.union(shape, WALL_VOXELS[8 + dir.ordinal()]);
|
||||
}
|
||||
return shape;
|
||||
}
|
||||
|
||||
private static boolean shouldHavePost(BlockState state, BlockState top_state, VoxelShape top_shape) {
|
||||
// above has post
|
||||
if (top_state.contains(NORTH_WALL_SHAPE) && top_state.get(UP)) return true;
|
||||
|
||||
if (Stream.of(Direction.SOUTH, Direction.EAST) // Opposites are different
|
||||
.anyMatch(dir -> state.get(getWallShape(dir)) != state.get(getWallShape(dir.getOpposite())))
|
||||
) return true;
|
||||
|
||||
// no sides
|
||||
if (Direction.Type.HORIZONTAL.stream().allMatch(dir -> state.get(getWallShape(dir)) == WallShape.NONE))
|
||||
return true;
|
||||
|
||||
// tall Matching sides
|
||||
if (Stream.of(Direction.SOUTH, Direction.EAST)
|
||||
.anyMatch(dir ->
|
||||
state.get(getWallShape(dir)) == WallShape.TALL
|
||||
&& state.get(getWallShape(dir.getOpposite())) == WallShape.TALL
|
||||
)) return false;
|
||||
|
||||
return top_state.isIn(BlockTags.WALL_POST_OVERRIDE) || top_shape == null || shouldUseTall(WALL_VOXELS[0], top_shape);
|
||||
}
|
||||
|
||||
private static boolean shouldConnectTo(BlockState state, boolean side_full, Direction side) {
|
||||
Block block = state.getBlock();
|
||||
boolean bl = block instanceof FenceGateBlock && FenceGateBlock.canWallConnect(state, side);
|
||||
return state.isIn(BlockTags.WALLS) || !WallBlock.cannotConnect(state) && side_full || block instanceof PaneBlock || bl;
|
||||
}
|
||||
|
||||
private static boolean shouldUseTall(VoxelShape self_shape, VoxelShape other_shape) {
|
||||
return !VoxelShapes.matchesAnywhere(
|
||||
self_shape,
|
||||
other_shape,
|
||||
BooleanBiFunction.ONLY_FIRST
|
||||
);
|
||||
}
|
||||
|
||||
private static Property<WallShape> getWallShape(Direction dir) {
|
||||
return switch (dir) {
|
||||
case EAST -> EAST_WALL_SHAPE;
|
||||
case NORTH -> NORTH_WALL_SHAPE;
|
||||
case WEST -> WEST_WALL_SHAPE;
|
||||
case SOUTH -> SOUTH_WALL_SHAPE;
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
|
||||
static {
|
||||
VoxelShape POST = createCuboidShape(4, 0, 4, 12, 16, 12);
|
||||
VoxelShape POST_COLLISION = createCuboidShape(4, 0, 4, 12, 24, 12);
|
||||
VoxelShape LOW = createCuboidShape(5, 0, 0, 11, 14, 8);
|
||||
VoxelShape TALL = createCuboidShape(5, 0, 0, 11, 16, 8);
|
||||
VoxelShape SIDE_COLLISION = createCuboidShape(5, 0, 0, 11, 24, 8);
|
||||
WALL_VOXELS = VoxelHelper.VoxelListBuilder.create(POST, 14)
|
||||
.add(LOW)
|
||||
.add(VoxelHelper::mirrorZ)
|
||||
.add(VoxelHelper::rotateY)
|
||||
.add(VoxelHelper::mirrorX)
|
||||
.add(TALL)
|
||||
.add(VoxelHelper::mirrorZ)
|
||||
.add(VoxelHelper::rotateY)
|
||||
.add(VoxelHelper::mirrorX)
|
||||
.add(POST_COLLISION)
|
||||
.add(SIDE_COLLISION)
|
||||
.add(VoxelHelper::mirrorZ)
|
||||
.add(VoxelHelper::rotateY)
|
||||
.add(VoxelHelper::mirrorX)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
public class WaterloggableReFramedDoubleBlock extends ReFramedDoubleBlock implements Waterloggable {
|
||||
public WaterloggableReFramedDoubleBlock(Settings settings) {
|
||||
super(settings);
|
||||
setDefaultState(getDefaultState().with(Properties.WATERLOGGED, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -27,67 +27,110 @@ public class ReFramedClient implements ClientModInitializer {
|
||||
BlockRenderLayerMap.INSTANCE.putBlocks(RenderLayer.getCutout(), ReFramed.BLOCKS.toArray(new Block[0]));
|
||||
|
||||
// CUBE
|
||||
HELPER.addReFramedModel("cube_special" , HELPER.auto(new Identifier("block/cube")));
|
||||
HELPER.addReFramedModel("cube" , HELPER.auto(new Identifier("block/cube")));
|
||||
// SMALL_CUBE
|
||||
HELPER.addReFramedModel("small_cube_special" , HELPER.auto(ReFramed.id("block/small_cube/base")));
|
||||
HELPER.addReFramedModel("small_cube" , HELPER.auto(ReFramed.id("block/small_cube/base")));
|
||||
// SMALL_CUBES_STEP
|
||||
HELPER.addReFramedModel("small_cubes_step_special" , HELPER.autoDouble(ReFramed.id("block/small_cube/base"), ReFramed.id("block/small_cube/step/base")));
|
||||
HELPER.addReFramedModel("small_cubes_step_reverse_special" , HELPER.autoDouble(ReFramed.id("block/small_cube/step/base"), ReFramed.id("block/small_cube/base")));
|
||||
HELPER.addReFramedModel("small_cubes_step" , HELPER.autoDouble(ReFramed.id("block/small_cube/base"), ReFramed.id("block/small_cube/step/base")));
|
||||
HELPER.addReFramedModel("small_cubes_step_reverse" , HELPER.autoDouble(ReFramed.id("block/small_cube/step/base"), ReFramed.id("block/small_cube/base")));
|
||||
// SLAB
|
||||
HELPER.addReFramedModel("slab_special" , HELPER.auto(new Identifier("block/slab")));
|
||||
HELPER.addReFramedModel("slab" , HELPER.auto(new Identifier("block/slab")));
|
||||
// SLAB_CUBE
|
||||
HELPER.addReFramedModel("double_slab_special" , HELPER.autoDouble(new Identifier("block/slab"), new Identifier("block/slab_top")));
|
||||
HELPER.addReFramedModel("double_slab" , HELPER.autoDouble(new Identifier("block/slab"), new Identifier("block/slab_top")));
|
||||
// STAIR
|
||||
HELPER.addReFramedModel("stair_special" , HELPER.auto(ReFramed.id("block/stair/straight")));
|
||||
HELPER.addReFramedModel("outers_stair_special" , HELPER.auto(ReFramed.id("block/stair/double_outer")));
|
||||
HELPER.addReFramedModel("inner_stair_special" , HELPER.auto(ReFramed.id("block/stair/inner")));
|
||||
HELPER.addReFramedModel("outer_stair_special" , HELPER.auto(ReFramed.id("block/stair/outer")));
|
||||
HELPER.addReFramedModel("outer_side_stair_special" , HELPER.auto(ReFramed.id("block/stair/outer_side")));
|
||||
HELPER.addReFramedModel("stair" , HELPER.auto(ReFramed.id("block/stair/straight")));
|
||||
HELPER.addReFramedModel("outers_stair" , HELPER.auto(ReFramed.id("block/stair/double_outer")));
|
||||
HELPER.addReFramedModel("inner_stair" , HELPER.auto(ReFramed.id("block/stair/inner")));
|
||||
HELPER.addReFramedModel("outer_stair" , HELPER.auto(ReFramed.id("block/stair/outer")));
|
||||
HELPER.addReFramedModel("outer_side_stair" , HELPER.auto(ReFramed.id("block/stair/outer_side")));
|
||||
// STAIRS_CUBE
|
||||
HELPER.addReFramedModel("stairs_cube_special" , HELPER.autoDouble(ReFramed.id("block/stair/straight"), ReFramed.id("block/stair/cube/straight")));
|
||||
HELPER.addReFramedModel("outers_stairs_cube_special" , HELPER.autoDouble(ReFramed.id("block/stair/double_outer"), ReFramed.id("block/stair/cube/double_outer")));
|
||||
HELPER.addReFramedModel("inner_stairs_cube_special" , HELPER.autoDouble(ReFramed.id("block/stair/inner"), ReFramed.id("block/stair/cube/inner")));
|
||||
HELPER.addReFramedModel("outer_stairs_cube_special" , HELPER.autoDouble(ReFramed.id("block/stair/outer"), ReFramed.id("block/stair/cube/outer")));
|
||||
HELPER.addReFramedModel("outer_side_stairs_cube_special" , HELPER.autoDouble(ReFramed.id("block/stair/outer_side"), ReFramed.id("block/stair/cube/outer_side")));
|
||||
HELPER.addReFramedModel("stairs_cube" , HELPER.autoDouble(ReFramed.id("block/stair/straight"), ReFramed.id("block/stair/cube/straight")));
|
||||
HELPER.addReFramedModel("outers_stairs_cube" , HELPER.autoDouble(ReFramed.id("block/stair/double_outer"), ReFramed.id("block/stair/cube/double_outer")));
|
||||
HELPER.addReFramedModel("inner_stairs_cube" , HELPER.autoDouble(ReFramed.id("block/stair/inner"), ReFramed.id("block/stair/cube/inner")));
|
||||
HELPER.addReFramedModel("outer_stairs_cube" , HELPER.autoDouble(ReFramed.id("block/stair/outer"), ReFramed.id("block/stair/cube/outer")));
|
||||
HELPER.addReFramedModel("outer_side_stairs_cube" , HELPER.autoDouble(ReFramed.id("block/stair/outer_side"), ReFramed.id("block/stair/cube/outer_side")));
|
||||
// HALF_STAIR
|
||||
HELPER.addReFramedModel("half_stair_down_special" , HELPER.auto(ReFramed.id("block/half_stair/down")));
|
||||
HELPER.addReFramedModel("half_stair_side_special" , HELPER.auto(ReFramed.id("block/half_stair/side")));
|
||||
HELPER.addReFramedModel("half_stair_down" , HELPER.auto(ReFramed.id("block/half_stair/down")));
|
||||
HELPER.addReFramedModel("half_stair_side" , HELPER.auto(ReFramed.id("block/half_stair/side")));
|
||||
// HALF_STAIRS_SLAB
|
||||
HELPER.addReFramedModel("half_stairs_slab_down_special" , HELPER.autoDouble(ReFramed.id("block/half_stair/down"), ReFramed.id("block/half_stair/slab/down")));
|
||||
HELPER.addReFramedModel("half_stairs_slab_side_special" , HELPER.autoDouble(ReFramed.id("block/half_stair/side"), ReFramed.id("block/half_stair/slab/side")));
|
||||
HELPER.addReFramedModel("half_stairs_slab_down" , HELPER.autoDouble(ReFramed.id("block/half_stair/down"), ReFramed.id("block/half_stair/slab/down")));
|
||||
HELPER.addReFramedModel("half_stairs_slab_side" , HELPER.autoDouble(ReFramed.id("block/half_stair/side"), ReFramed.id("block/half_stair/slab/side")));
|
||||
// HALF_STAIRS_STAIR
|
||||
HELPER.addReFramedModel("half_stairs_stair_down_special" , HELPER.autoDouble(ReFramed.id("block/half_stair/down"), ReFramed.id("block/half_stair/stair/down")));
|
||||
HELPER.addReFramedModel("half_stairs_stair_side_special" , HELPER.autoDouble(ReFramed.id("block/half_stair/side"), ReFramed.id("block/half_stair/stair/side")));
|
||||
HELPER.addReFramedModel("half_stairs_stair_reverse_special" , HELPER.autoDouble(ReFramed.id("block/half_stair/stair/side"), ReFramed.id("block/half_stair/side")));
|
||||
HELPER.addReFramedModel("half_stairs_stair_down" , HELPER.autoDouble(ReFramed.id("block/half_stair/down"), ReFramed.id("block/half_stair/stair/down")));
|
||||
HELPER.addReFramedModel("half_stairs_stair_side" , HELPER.autoDouble(ReFramed.id("block/half_stair/side"), ReFramed.id("block/half_stair/stair/side")));
|
||||
HELPER.addReFramedModel("half_stairs_stair_reverse" , HELPER.autoDouble(ReFramed.id("block/half_stair/stair/side"), ReFramed.id("block/half_stair/side")));
|
||||
// STEP
|
||||
HELPER.addReFramedModel("step_special" , HELPER.auto(ReFramed.id("block/step/down")));
|
||||
HELPER.addReFramedModel("step" , HELPER.auto(ReFramed.id("block/step/down")));
|
||||
// STEPS_SLAB
|
||||
HELPER.addReFramedModel("steps_slab_special" , HELPER.autoDouble(ReFramed.id("block/step/down"), ReFramed.id("block/step/slab/down")));
|
||||
HELPER.addReFramedModel("steps_slab_side_special" , HELPER.autoDouble(ReFramed.id("block/step/side"), ReFramed.id("block/step/slab/side")));
|
||||
HELPER.addReFramedModel("steps_slab" , HELPER.autoDouble(ReFramed.id("block/step/down"), ReFramed.id("block/step/slab/down")));
|
||||
HELPER.addReFramedModel("steps_slab_side" , HELPER.autoDouble(ReFramed.id("block/step/side"), ReFramed.id("block/step/slab/side")));
|
||||
// LAYER
|
||||
HELPER.addReFramedModel("layer_1_special" , HELPER.auto(new Identifier("block/snow_height2")));
|
||||
HELPER.addReFramedModel("layer_2_special" , HELPER.auto(new Identifier("block/snow_height4")));
|
||||
HELPER.addReFramedModel("layer_3_special" , HELPER.auto(new Identifier("block/snow_height6")));
|
||||
HELPER.addReFramedModel("layer_4_special" , HELPER.auto(new Identifier("block/snow_height8")));
|
||||
HELPER.addReFramedModel("layer_5_special" , HELPER.auto(new Identifier("block/snow_height10")));
|
||||
HELPER.addReFramedModel("layer_6_special" , HELPER.auto(new Identifier("block/snow_height12")));
|
||||
HELPER.addReFramedModel("layer_7_special" , HELPER.auto(new Identifier("block/snow_height14")));
|
||||
HELPER.addReFramedModel("layer_8_special" , HELPER.auto(new Identifier("block/cube")));
|
||||
HELPER.addReFramedModel("layer_1" , HELPER.auto(new Identifier("block/snow_height2")));
|
||||
HELPER.addReFramedModel("layer_2" , HELPER.auto(new Identifier("block/snow_height4")));
|
||||
HELPER.addReFramedModel("layer_3" , HELPER.auto(new Identifier("block/snow_height6")));
|
||||
HELPER.addReFramedModel("layer_4" , HELPER.auto(new Identifier("block/snow_height8")));
|
||||
HELPER.addReFramedModel("layer_5" , HELPER.auto(new Identifier("block/snow_height10")));
|
||||
HELPER.addReFramedModel("layer_6" , HELPER.auto(new Identifier("block/snow_height12")));
|
||||
HELPER.addReFramedModel("layer_7" , HELPER.auto(new Identifier("block/snow_height14")));
|
||||
HELPER.addReFramedModel("layer_8" , HELPER.auto(new Identifier("block/cube")));
|
||||
// PILLAR
|
||||
HELPER.addReFramedModel("pillar" , HELPER.auto(ReFramed.id("block/pillar")));
|
||||
// WALL
|
||||
HELPER.addReFramedModel("wall_inventory" , HELPER.auto(ReFramed.id("block/wall/inventory/default")));
|
||||
// --------------------- pillar
|
||||
HELPER.addReFramedModel("wall_core" , HELPER.auto(ReFramed.id("block/wall/pillar/core")));
|
||||
HELPER.addReFramedModel("wall_pillar_low" , HELPER.auto(ReFramed.id("block/wall/pillar/low")));
|
||||
HELPER.addReFramedModel("wall_pillar_tall" , HELPER.auto(ReFramed.id("block/wall/pillar/tall")));
|
||||
HELPER.addReFramedModel("wall_pillar_none" , HELPER.auto(ReFramed.id("block/wall/pillar/none")));
|
||||
// --------------------- side
|
||||
HELPER.addReFramedModel("wall_side_low" , HELPER.auto(ReFramed.id("block/wall/side/low")));
|
||||
HELPER.addReFramedModel("wall_side_tall" , HELPER.auto(ReFramed.id("block/wall/side/tall")));
|
||||
// --------------------- junction
|
||||
HELPER.addReFramedModel("wall_low_e" , HELPER.auto(ReFramed.id("block/wall/junction/low")));
|
||||
HELPER.addReFramedModel("wall_tall_e" , HELPER.auto(ReFramed.id("block/wall/junction/tall")));
|
||||
// --------------------- junction_i
|
||||
HELPER.addReFramedModel("wall_low_i" , HELPER.auto(ReFramed.id("block/wall/junction/low_i")));
|
||||
HELPER.addReFramedModel("wall_tall_i" , HELPER.auto(ReFramed.id("block/wall/junction/tall_i")));
|
||||
HELPER.addReFramedModel("wall_low_tall_i" , HELPER.auto(ReFramed.id("block/wall/junction/low_tall_i")));
|
||||
// --------------------- junction_c
|
||||
HELPER.addReFramedModel("wall_low_c" , HELPER.auto(ReFramed.id("block/wall/junction/low_c")));
|
||||
HELPER.addReFramedModel("wall_tall_c" , HELPER.auto(ReFramed.id("block/wall/junction/tall_c")));
|
||||
HELPER.addReFramedModel("wall_low_tall_c" , HELPER.auto(ReFramed.id("block/wall/junction/low_tall_c")));
|
||||
HELPER.addReFramedModel("wall_tall_low_c" , HELPER.auto(ReFramed.id("block/wall/junction/tall_low_c")));
|
||||
// --------------------- junction_t
|
||||
HELPER.addReFramedModel("wall_low_t" , HELPER.auto(ReFramed.id("block/wall/junction/low_t")));
|
||||
HELPER.addReFramedModel("wall_tall_t" , HELPER.auto(ReFramed.id("block/wall/junction/tall_t")));
|
||||
HELPER.addReFramedModel("wall_tall_low_c_t" , HELPER.auto(ReFramed.id("block/wall/junction/tall_low_c_t")));
|
||||
HELPER.addReFramedModel("wall_tall_i_low_t" , HELPER.auto(ReFramed.id("block/wall/junction/tall_i_low_t")));
|
||||
HELPER.addReFramedModel("wall_low_i_tall_t" , HELPER.auto(ReFramed.id("block/wall/junction/low_i_tall_t")));
|
||||
HELPER.addReFramedModel("wall_low_tall_c_t" , HELPER.auto(ReFramed.id("block/wall/junction/low_tall_c_t")));
|
||||
HELPER.addReFramedModel("wall_low_c_tall_t" , HELPER.auto(ReFramed.id("block/wall/junction/low_c_tall_t")));
|
||||
HELPER.addReFramedModel("wall_tall_c_low_t" , HELPER.auto(ReFramed.id("block/wall/junction/tall_c_low_t")));
|
||||
// --------------------- junction_x
|
||||
HELPER.addReFramedModel("wall_low_x" , HELPER.auto(ReFramed.id("block/wall/junction/low_x")));
|
||||
HELPER.addReFramedModel("wall_tall_x" , HELPER.auto(ReFramed.id("block/wall/junction/tall_x")));
|
||||
HELPER.addReFramedModel("wall_tall_i_low_i_x" , HELPER.auto(ReFramed.id("block/wall/junction/tall_i_low_i_x")));
|
||||
HELPER.addReFramedModel("wall_tall_low_t_x" , HELPER.auto(ReFramed.id("block/wall/junction/tall_low_t_x")));
|
||||
HELPER.addReFramedModel("wall_tall_c_low_c_x" , HELPER.auto(ReFramed.id("block/wall/junction/tall_c_low_c_x")));
|
||||
HELPER.addReFramedModel("wall_tall_t_low_x" , HELPER.auto(ReFramed.id("block/wall/junction/tall_t_low_x")));
|
||||
|
||||
|
||||
//item model assignments (in lieu of models/item/___.json)
|
||||
HELPER.assignItemModel("cube_special" , ReFramed.CUBE);
|
||||
HELPER.assignItemModel("small_cube_special" , ReFramed.SMALL_CUBE);
|
||||
HELPER.assignItemModel("small_cubes_step_special" , ReFramed.SMALL_CUBES_STEP);
|
||||
HELPER.assignItemModel("slab_special" , ReFramed.SLAB);
|
||||
HELPER.assignItemModel("double_slab_special" , ReFramed.SLABS_CUBE);
|
||||
HELPER.assignItemModel("stair_special" , ReFramed.STAIR);
|
||||
HELPER.assignItemModel("stairs_cube_special" , ReFramed.STAIRS_CUBE);
|
||||
HELPER.assignItemModel("half_stair_down_special" , ReFramed.HALF_STAIR);
|
||||
HELPER.assignItemModel("half_stairs_slab_down_special" , ReFramed.HALF_STAIRS_SLAB);
|
||||
HELPER.assignItemModel("half_stairs_stair_down_special", ReFramed.HALF_STAIRS_STAIR);
|
||||
HELPER.assignItemModel("step_special" , ReFramed.STEP);
|
||||
HELPER.assignItemModel("steps_slab_special" , ReFramed.STEPS_SLAB);
|
||||
HELPER.assignItemModel("layer_1_special" , ReFramed.LAYER);
|
||||
HELPER.assignItemModel("cube" , ReFramed.CUBE);
|
||||
HELPER.assignItemModel("small_cube" , ReFramed.SMALL_CUBE);
|
||||
HELPER.assignItemModel("small_cubes_step" , ReFramed.SMALL_CUBES_STEP);
|
||||
HELPER.assignItemModel("slab" , ReFramed.SLAB);
|
||||
HELPER.assignItemModel("double_slab" , ReFramed.SLABS_CUBE);
|
||||
HELPER.assignItemModel("stair" , ReFramed.STAIR);
|
||||
HELPER.assignItemModel("stairs_cube" , ReFramed.STAIRS_CUBE);
|
||||
HELPER.assignItemModel("half_stair_down" , ReFramed.HALF_STAIR);
|
||||
HELPER.assignItemModel("half_stairs_slab_down" , ReFramed.HALF_STAIRS_SLAB);
|
||||
HELPER.assignItemModel("half_stairs_stair_down", ReFramed.HALF_STAIRS_STAIR);
|
||||
HELPER.assignItemModel("step" , ReFramed.STEP);
|
||||
HELPER.assignItemModel("steps_slab" , ReFramed.STEPS_SLAB);
|
||||
HELPER.assignItemModel("layer_1" , ReFramed.LAYER);
|
||||
HELPER.assignItemModel("pillar" , ReFramed.PILLAR);
|
||||
HELPER.assignItemModel("wall_inventory" , ReFramed.WALL);
|
||||
}
|
||||
|
||||
private void privateInit() {
|
||||
@@ -105,7 +148,7 @@ public class ReFramedClient implements ClientModInitializer {
|
||||
//supporting code for the TemplatesModelProvider
|
||||
ModelLoadingRegistry.INSTANCE.registerResourceProvider(rm -> PROVIDER); //block models
|
||||
ModelLoadingRegistry.INSTANCE.registerVariantProvider(rm -> PROVIDER); //item models
|
||||
|
||||
|
||||
ResourceManagerHelper.get(ResourceType.CLIENT_RESOURCES).registerReloadListener(new SimpleSynchronousResourceReloadListener() {
|
||||
@Override public Identifier getFabricId() { return ReFramed.id("dump-caches"); }
|
||||
@Override public void reload(ResourceManager blah) { PROVIDER.dumpCache(); }
|
||||
|
||||
@@ -40,15 +40,15 @@ public class ReFramedClientHelper {
|
||||
}
|
||||
|
||||
public void addReFramedModel(String id, UnbakedModel unbaked) {
|
||||
prov.addReFramedModel(ReFramed.id(id), unbaked);
|
||||
prov.addReFramedModel(ReFramed.id(id + "_special"), unbaked);
|
||||
}
|
||||
|
||||
public void assignItemModel(String id, ItemConvertible... item_convertibles) {
|
||||
prov.assignItemModel(ReFramed.id(id), item_convertibles);
|
||||
prov.assignItemModel(ReFramed.id(id + "_special"), item_convertibles);
|
||||
}
|
||||
|
||||
public CamoAppearanceManager getCamoApperanceManager(Function<SpriteIdentifier, Sprite> spriteLookup) {
|
||||
return prov.getCamoApperanceManager(spriteLookup);
|
||||
public CamoAppearanceManager getCamoAppearanceManager(Function<SpriteIdentifier, Sprite> spriteLookup) {
|
||||
return prov.getCamoAppearanceManager(spriteLookup);
|
||||
}
|
||||
|
||||
public @NotNull Renderer getFabricRenderer() {
|
||||
|
||||
@@ -44,7 +44,7 @@ public class ReFramedModelProvider implements ModelResourceProvider, ModelVarian
|
||||
|
||||
/// camo appearance manager cache
|
||||
|
||||
public CamoAppearanceManager getCamoApperanceManager(Function<SpriteIdentifier, Sprite> spriteLookup) {
|
||||
public CamoAppearanceManager getCamoAppearanceManager(Function<SpriteIdentifier, Sprite> spriteLookup) {
|
||||
//This is kind of needlessly sketchy using the "volatile double checked locking" pattern.
|
||||
//I'd like all frame models to use the same CamoApperanceManager, despite the model
|
||||
//baking process happening concurrently on several threads, but I also don't want to
|
||||
@@ -70,6 +70,7 @@ public class ReFramedModelProvider implements ModelResourceProvider, ModelVarian
|
||||
}
|
||||
|
||||
public void dumpCache() {
|
||||
CamoAppearanceManager.dumpCahe();
|
||||
appearanceManager = null; //volatile write
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,8 @@ import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.render.model.BakedModel;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.BlockRenderView;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface DynamicBakedModel {
|
||||
BakedModel computeQuads(BlockRenderView level, BlockState state, BlockPos pos, int theme_index);
|
||||
BakedModel computeQuads(@Nullable BlockRenderView level, BlockState origin_state, @Nullable BlockPos pos, int theme_index);
|
||||
}
|
||||
|
||||
@@ -114,7 +114,9 @@ public abstract class RetexturingBakedModel extends ForwardingBakedModel {
|
||||
if (camo instanceof WeightedComputedAppearance wca) model_id = wca.getAppearanceIndex(seed);
|
||||
|
||||
int tint = 0xFF000000 | MinecraftClient.getInstance().getBlockColors().getColor(theme, world, pos, 0);
|
||||
Mesh untintedMesh = getRetexturedMesh(new MeshCacheKey(frame_block.getModelCacheKey(state), camo, model_id), state);
|
||||
MeshCacheKey key = new MeshCacheKey(frame_block.getModelCacheKey(state), camo, model_id);
|
||||
// do not clutter the cache with single-use meshes
|
||||
Mesh untintedMesh = camo.hashCode() == -1 ? transformMesh(key, state) : getRetexturedMesh(key, state);
|
||||
|
||||
//The specific tint might vary a lot; imagine grass color smoothly changing. Trying to bake the tint into
|
||||
//the cached mesh will pollute it with a ton of single-use meshes with only slightly different colors.
|
||||
|
||||
@@ -33,7 +33,7 @@ public class UnbakedAutoRetexturedModel extends UnbakedRetexturedModel {
|
||||
public BakedModel bake(Baker baker, Function<SpriteIdentifier, Sprite> texture_getter, ModelBakeSettings bake_settings, Identifier identifier) {
|
||||
return new RetexturingBakedModel(
|
||||
baker.bake(parent, bake_settings),
|
||||
ReFramedClient.HELPER.getCamoApperanceManager(texture_getter),
|
||||
ReFramedClient.HELPER.getCamoAppearanceManager(texture_getter),
|
||||
theme_index,
|
||||
bake_settings,
|
||||
item_state,
|
||||
|
||||
@@ -41,7 +41,7 @@ public class UnbakedJsonRetexturedModel extends UnbakedRetexturedModel {
|
||||
|
||||
return new RetexturingBakedModel(
|
||||
baker.bake(parent, bake_settings),
|
||||
ReFramedClient.HELPER.getCamoApperanceManager(spriteLookup),
|
||||
ReFramedClient.HELPER.getCamoAppearanceManager(spriteLookup),
|
||||
theme_index,
|
||||
bake_settings,
|
||||
item_state,
|
||||
|
||||
@@ -20,8 +20,9 @@ public abstract class UnbakedRetexturedModel implements UnbakedModel {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public void setThemeIndex(int theme_index) {
|
||||
public UnbakedRetexturedModel setThemeIndex(int theme_index) {
|
||||
this.theme_index = theme_index;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -6,6 +6,7 @@ import fr.adrien1106.reframed.ReFramed;
|
||||
import fr.adrien1106.reframed.client.ReFramedClient;
|
||||
import fr.adrien1106.reframed.client.model.DynamicBakedModel;
|
||||
import fr.adrien1106.reframed.client.model.QuadPosBounds;
|
||||
import fr.adrien1106.reframed.compat.RebakedModel;
|
||||
import fr.adrien1106.reframed.mixin.model.WeightedBakedModelAccessor;
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
@@ -39,6 +40,12 @@ import java.util.function.Function;
|
||||
@Environment(EnvType.CLIENT)
|
||||
public class CamoAppearanceManager {
|
||||
|
||||
|
||||
protected static final SpriteIdentifier DEFAULT_SPRITE_MAIN = new SpriteIdentifier(PlayerScreenHandler.BLOCK_ATLAS_TEXTURE, new Identifier(ReFramed.MODID, "block/framed_block"));
|
||||
protected static final SpriteIdentifier DEFAULT_SPRITE_SECONDARY = new SpriteIdentifier(PlayerScreenHandler.BLOCK_ATLAS_TEXTURE, new Identifier(ReFramed.MODID, "block/framed_accent_block"));
|
||||
private static final SpriteIdentifier BARRIER_SPRITE_ID = new SpriteIdentifier(PlayerScreenHandler.BLOCK_ATLAS_TEXTURE, new Identifier("minecraft:item/barrier"));
|
||||
private static final Cache<BlockState, CamoAppearance> APPEARANCE_CACHE = CacheBuilder.newBuilder().maximumSize(2048).build();
|
||||
|
||||
public CamoAppearanceManager(Function<SpriteIdentifier, Sprite> spriteLookup) {
|
||||
MaterialFinder finder = ReFramedClient.HELPER.getFabricRenderer().materialFinder();
|
||||
for(BlendMode blend : BlendMode.values()) {
|
||||
@@ -59,22 +66,20 @@ public class CamoAppearanceManager {
|
||||
sprite = spriteLookup.apply(BARRIER_SPRITE_ID);
|
||||
this.barrierItemAppearance = new SingleSpriteAppearance(sprite, materials.get(BlendMode.CUTOUT), serial_number.getAndIncrement());
|
||||
}
|
||||
|
||||
protected static final SpriteIdentifier DEFAULT_SPRITE_MAIN = new SpriteIdentifier(PlayerScreenHandler.BLOCK_ATLAS_TEXTURE, new Identifier(ReFramed.MODID, "block/framed_block"));
|
||||
protected static final SpriteIdentifier DEFAULT_SPRITE_SECONDARY = new SpriteIdentifier(PlayerScreenHandler.BLOCK_ATLAS_TEXTURE, new Identifier(ReFramed.MODID, "block/framed_accent_block"));
|
||||
private static final SpriteIdentifier BARRIER_SPRITE_ID = new SpriteIdentifier(PlayerScreenHandler.BLOCK_ATLAS_TEXTURE, new Identifier("minecraft:item/barrier"));
|
||||
|
||||
private final CamoAppearance default_appearance;
|
||||
private final CamoAppearance accent_appearance;
|
||||
private final CamoAppearance barrierItemAppearance;
|
||||
|
||||
private static final Cache<BlockState, CamoAppearance> APPEARANCE_CACHE = CacheBuilder.newBuilder().maximumSize(2048).build();
|
||||
|
||||
private final AtomicInteger serial_number = new AtomicInteger(0); //Mutable
|
||||
|
||||
private final EnumMap<BlendMode, RenderMaterial> ao_materials = new EnumMap<>(BlendMode.class);
|
||||
private final EnumMap<BlendMode, RenderMaterial> materials = new EnumMap<>(BlendMode.class); //Immutable contents
|
||||
|
||||
|
||||
public static void dumpCahe() {
|
||||
APPEARANCE_CACHE.invalidateAll();
|
||||
}
|
||||
|
||||
public CamoAppearance getDefaultAppearance(int appearance) {
|
||||
return appearance == 2 ? accent_appearance: default_appearance;
|
||||
}
|
||||
@@ -82,20 +87,24 @@ public class CamoAppearanceManager {
|
||||
public CamoAppearance getCamoAppearance(BlockRenderView world, BlockState state, BlockPos pos, int theme_index, boolean item) {
|
||||
BakedModel model = MinecraftClient.getInstance().getBlockRenderManager().getModel(state);
|
||||
|
||||
// add support for connected textures and more generally any compatible models injected so that they return baked quads
|
||||
// add support for connected textures that uses dynamic baking
|
||||
if (model instanceof DynamicBakedModel dynamic_model) {
|
||||
// cache items as they get rendered more often
|
||||
if (item && APPEARANCE_CACHE.asMap().containsKey(state)) return APPEARANCE_CACHE.getIfPresent(state);
|
||||
|
||||
CamoAppearance appearance = computeAppearance(dynamic_model.computeQuads(world, state, pos, theme_index), state);
|
||||
if (item) APPEARANCE_CACHE.put(state, appearance);
|
||||
return appearance;
|
||||
model = dynamic_model.computeQuads(world, state, pos, theme_index);
|
||||
// if model isn't rebaked its just wrapped (i.e. not dynamic and may be cached)
|
||||
if (model instanceof RebakedModel) {
|
||||
CamoAppearance appearance = computeAppearance(model, state, !item);
|
||||
if (item) APPEARANCE_CACHE.put(state, appearance);
|
||||
return appearance;
|
||||
}
|
||||
}
|
||||
|
||||
// refresh cache
|
||||
if (APPEARANCE_CACHE.asMap().containsKey(state)) return APPEARANCE_CACHE.getIfPresent(state);
|
||||
|
||||
CamoAppearance appearance = computeAppearance(model, state);
|
||||
CamoAppearance appearance = computeAppearance(model, state, false);
|
||||
APPEARANCE_CACHE.put(state, appearance);
|
||||
return appearance;
|
||||
}
|
||||
@@ -109,7 +118,7 @@ public class CamoAppearanceManager {
|
||||
// The computeIfAbsent map update will work without corrupting the map, but there will be some "wasted effort" computing the value twice.
|
||||
// The results are going to be the same, apart from their serialNumbers differing (= their equals & hashCode differing).
|
||||
// Tiny amount of wasted space in some caches if CamoAppearances are used as a map key, then. IMO it's not a critical issue.
|
||||
private CamoAppearance computeAppearance(BakedModel model, BlockState state) {
|
||||
private CamoAppearance computeAppearance(BakedModel model, BlockState state, boolean is_dynamic) {
|
||||
if(state.getBlock() == Blocks.BARRIER) return barrierItemAppearance;
|
||||
|
||||
if (!(model instanceof WeightedBakedModelAccessor weighted_model)) {
|
||||
@@ -117,7 +126,7 @@ public class CamoAppearanceManager {
|
||||
getAppearance(model),
|
||||
getCachedMaterial(state, true),
|
||||
getCachedMaterial(state, false),
|
||||
serial_number.getAndIncrement()
|
||||
is_dynamic ? -1 : serial_number.getAndIncrement()
|
||||
);
|
||||
}
|
||||
List<Weighted.Present<Appearance>> appearances = weighted_model.getModels().stream()
|
||||
@@ -128,7 +137,7 @@ public class CamoAppearanceManager {
|
||||
appearances,
|
||||
getCachedMaterial(state, true),
|
||||
getCachedMaterial(state, false),
|
||||
serial_number.getAndIncrement()
|
||||
is_dynamic ? -1 : serial_number.getAndIncrement()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,177 @@
|
||||
package fr.adrien1106.reframed.client.util;
|
||||
|
||||
import com.google.common.cache.Cache;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import fr.adrien1106.reframed.block.ReFramedBlock;
|
||||
import fr.adrien1106.reframed.client.ReFramedClient;
|
||||
import fr.adrien1106.reframed.client.model.QuadPosBounds;
|
||||
import fr.adrien1106.reframed.util.blocks.ThemeableBlockEntity;
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.fabricmc.fabric.api.renderer.v1.Renderer;
|
||||
import net.fabricmc.fabric.api.renderer.v1.material.RenderMaterial;
|
||||
import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter;
|
||||
import net.fabricmc.fabric.api.renderer.v1.model.ForwardingBakedModel;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.util.function.BooleanBiFunction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.random.Random;
|
||||
import net.minecraft.util.shape.VoxelShape;
|
||||
import net.minecraft.util.shape.VoxelShapes;
|
||||
import net.minecraft.world.BlockRenderView;
|
||||
import net.minecraft.world.BlockView;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import static net.minecraft.util.shape.VoxelShapes.combine;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public class RenderHelper {
|
||||
|
||||
|
||||
// self culling cache of the models not made thread local so that it is only computed once
|
||||
private static final Cache<CullElement, Integer[]> INNER_CULL_MAP = CacheBuilder.newBuilder().maximumSize(1024).build();
|
||||
private record CullElement(Block block, Object state_key, int model) {}
|
||||
|
||||
/**
|
||||
* compute which quad might cull with another model quad
|
||||
* @param state - the state of the model
|
||||
* @param models - list of models on the same block
|
||||
*/
|
||||
public static void computeInnerCull(BlockState state, List<ForwardingBakedModel> models) {
|
||||
if (!(state.getBlock() instanceof ReFramedBlock frame_block)) return;
|
||||
Object key = frame_block.getModelCacheKey(state);
|
||||
if (INNER_CULL_MAP.asMap().containsKey(new CullElement(frame_block, key, 1))) return;
|
||||
|
||||
Renderer r = ReFramedClient.HELPER.getFabricRenderer();
|
||||
QuadEmitter quad_emitter = r.meshBuilder().getEmitter();
|
||||
RenderMaterial material = r.materialFinder().clear().find();
|
||||
Random random = Random.create();
|
||||
|
||||
List<List<QuadPosBounds>> model_bounds = models.stream()
|
||||
.map(ForwardingBakedModel::getWrappedModel)
|
||||
.filter(Objects::nonNull)
|
||||
.map(wrapped -> wrapped.getQuads(state, null, random))
|
||||
.map(quads -> quads.stream().map(quad -> {
|
||||
quad_emitter.fromVanilla(quad, material, null);
|
||||
return QuadPosBounds.read(quad_emitter, false);
|
||||
}).toList()).toList();
|
||||
|
||||
Integer[] cull_array;
|
||||
for(int self_id = 1; self_id <= model_bounds.size(); self_id++) {
|
||||
List<QuadPosBounds> self_bounds = model_bounds.get(self_id - 1);
|
||||
cull_array = new Integer[self_bounds.size()];
|
||||
for (int self_quad = 0; self_quad < cull_array.length; self_quad++) {
|
||||
QuadPosBounds self_bound = self_bounds.get(self_quad);
|
||||
for(int other_id = 1; other_id <= model_bounds.size(); other_id++) {
|
||||
if (other_id == self_id) continue;
|
||||
if (model_bounds.get(other_id - 1).stream().anyMatch(other_bound -> other_bound.equals(self_bound))) {
|
||||
cull_array[self_quad] = other_id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
INNER_CULL_MAP.put(new CullElement(frame_block, key, self_id), cull_array);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean shouldDrawInnerFace(BlockState state, BlockRenderView view, BlockPos pos, int quad_index, int theme_index) {
|
||||
if ( !(state.getBlock() instanceof ReFramedBlock frame_block)
|
||||
|| !(view.getBlockEntity(pos) instanceof ThemeableBlockEntity frame_entity)
|
||||
) return true;
|
||||
CullElement key = new CullElement(frame_block, frame_block.getModelCacheKey(state), theme_index);
|
||||
if (!INNER_CULL_MAP.asMap().containsKey(key)) return true;
|
||||
|
||||
// needs to be Integer object because array is initialized with null not 0
|
||||
Integer cull_theme = Objects.requireNonNull(INNER_CULL_MAP.getIfPresent(key))[quad_index];
|
||||
if (cull_theme == null) return true; // no culling possible
|
||||
|
||||
BlockState self_theme = frame_entity.getTheme(theme_index);
|
||||
BlockState other_theme = frame_entity.getTheme(cull_theme);
|
||||
|
||||
if (self_theme.isSideInvisible(other_theme, null)) return false;
|
||||
return !self_theme.isOpaque() || !other_theme.isOpaque();
|
||||
}
|
||||
|
||||
// Doing this method from scratch as it is simpler to do than injecting everywhere
|
||||
public static boolean shouldDrawSide(BlockState self_state, BlockView world, BlockPos pos, Direction side, BlockPos other_pos, int theme_index) {
|
||||
ThemeableBlockEntity self = world.getBlockEntity(pos) instanceof ThemeableBlockEntity e ? e : null;
|
||||
ThemeableBlockEntity other = world.getBlockEntity(other_pos) instanceof ThemeableBlockEntity e ? e : null;
|
||||
BlockState other_state = world.getBlockState(other_pos);
|
||||
|
||||
// normal behaviour
|
||||
if (self == null && other == null) return Block.shouldDrawSide(self_state, world, pos, side, other_pos);
|
||||
|
||||
// self is a normal Block
|
||||
if (self == null && other_state.getBlock() instanceof ReFramedBlock other_block) {
|
||||
VoxelShape self_shape = self_state.getCullingShape(world, pos);
|
||||
if (self_shape.isEmpty()) return true;
|
||||
|
||||
int i = 0;
|
||||
VoxelShape other_shape = VoxelShapes.empty();
|
||||
for (BlockState s: other.getThemes()) {
|
||||
i++;
|
||||
if (self_state.isSideInvisible(s, side) || s.isOpaque())
|
||||
other_shape = combine(
|
||||
other_shape,
|
||||
other_block
|
||||
.getShape(other_state, i)
|
||||
.getFace(side.getOpposite()),
|
||||
BooleanBiFunction.OR
|
||||
);
|
||||
}
|
||||
|
||||
// determine if side needs to be rendered
|
||||
return VoxelShapes.matchesAnywhere(self_shape, other_shape, BooleanBiFunction.ONLY_FIRST);
|
||||
}
|
||||
|
||||
BlockState self_theme = self.getTheme(theme_index);
|
||||
// other is normal Block
|
||||
if (other == null && self_state.getBlock() instanceof ReFramedBlock self_block) {
|
||||
// Transparent is simple if self and the neighbor are invisible don't render side (like default)
|
||||
if (self_theme.isSideInvisible(other_state, side)) return false;
|
||||
|
||||
// Opaque is also simple as each model are rendered one by one
|
||||
if (other_state.isOpaque()) {
|
||||
// no cache section :( because it differs between each instance of the frame
|
||||
VoxelShape self_shape = self_block.getShape(self_state, theme_index).getFace(side);
|
||||
if (self_shape.isEmpty()) return true;
|
||||
VoxelShape other_shape = other_state.getCullingFace(world, other_pos, side.getOpposite());
|
||||
|
||||
// determine if side needs to be rendered
|
||||
return VoxelShapes.matchesAnywhere(self_shape, other_shape, BooleanBiFunction.ONLY_FIRST);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Both are frames
|
||||
// here both are computed in the same zone as there will necessarily a shape comparison
|
||||
if (self_state.getBlock() instanceof ReFramedBlock self_block && other_state.getBlock() instanceof ReFramedBlock other_block) {
|
||||
VoxelShape self_shape = self_block.getShape(self_state, theme_index).getFace(side);
|
||||
if (self_shape.isEmpty()) return true;
|
||||
|
||||
int i = 0;
|
||||
VoxelShape other_shape = VoxelShapes.empty();
|
||||
for (BlockState s: other.getThemes()) {
|
||||
i++;
|
||||
if (self_theme.isSideInvisible(s, side) || s.isOpaque())
|
||||
other_shape = combine(
|
||||
other_shape,
|
||||
other_block
|
||||
.getShape(other_state, i)
|
||||
.getFace(side.getOpposite()),
|
||||
BooleanBiFunction.OR
|
||||
);
|
||||
}
|
||||
|
||||
// determine if side needs to be rendered
|
||||
return VoxelShapes.matchesAnywhere(self_shape, other_shape, BooleanBiFunction.ONLY_FIRST);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package fr.adrien1106.reframed.compat;
|
||||
|
||||
import me.pepperbell.continuity.client.model.QuadProcessors;
|
||||
import me.pepperbell.continuity.impl.client.ProcessingContextImpl;
|
||||
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.texture.Sprite;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.random.Random;
|
||||
import net.minecraft.world.BlockRenderView;
|
||||
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public interface ICTMQuadTransform extends RenderContext.QuadTransform {
|
||||
|
||||
void invokePrepare(BlockRenderView view, BlockState state, BlockPos pos, Supplier<Random> random, boolean manual_culling, Function<Sprite, QuadProcessors.Slice> slice);
|
||||
|
||||
ProcessingContextImpl getProcessingContext();
|
||||
|
||||
void invokeReset();
|
||||
}
|
||||
@@ -12,10 +12,10 @@ import net.minecraft.util.math.random.Random;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class RebakedAthenaModel implements BakedModel {
|
||||
public class RebakedModel implements BakedModel {
|
||||
protected final Map<Direction, List<BakedQuad>> face_quads;
|
||||
|
||||
public RebakedAthenaModel(Map<Direction, List<BakedQuad>> face_quads) {
|
||||
public RebakedModel(Map<Direction, List<BakedQuad>> face_quads) {
|
||||
this.face_quads = face_quads;
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ public class RebakedAthenaModel implements BakedModel {
|
||||
|
||||
@Override
|
||||
public boolean useAmbientOcclusion() {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -51,11 +51,11 @@ public class RebakedAthenaModel implements BakedModel {
|
||||
|
||||
@Override
|
||||
public ModelTransformation getTransformation() {
|
||||
return null;
|
||||
return ModelTransformation.NONE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelOverrideList getOverrides() {
|
||||
return null;
|
||||
return ModelOverrideList.EMPTY;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
package fr.adrien1106.reframed.generator;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.data.client.BlockStateSupplier;
|
||||
|
||||
public interface BlockStateProvider {
|
||||
BlockStateSupplier getMultipart();
|
||||
BlockStateSupplier getMultipart(Block block);
|
||||
}
|
||||
|
||||
@@ -1,14 +1,23 @@
|
||||
package fr.adrien1106.reframed.generator;
|
||||
|
||||
import fr.adrien1106.reframed.ReFramed;
|
||||
import fr.adrien1106.reframed.block.*;
|
||||
import fr.adrien1106.reframed.generator.block.*;
|
||||
import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput;
|
||||
import net.fabricmc.fabric.api.datagen.v1.provider.FabricTagProvider.BlockTagProvider;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.registry.RegistryWrapper.WrapperLookup;
|
||||
import net.minecraft.registry.tag.BlockTags;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class GBlockTag extends BlockTagProvider {
|
||||
private static final Map<Class<? extends Block>, TagGetter> providers = new HashMap<>();
|
||||
static {
|
||||
providers.put(ReframedWallBlock.class, new Wall());
|
||||
}
|
||||
|
||||
public GBlockTag(FabricDataOutput output, CompletableFuture<WrapperLookup> registries) {
|
||||
super(output, registries);
|
||||
@@ -17,6 +26,10 @@ public class GBlockTag extends BlockTagProvider {
|
||||
@Override
|
||||
protected void configure(WrapperLookup arg) {
|
||||
FabricTagBuilder builder = getOrCreateTagBuilder(BlockTags.AXE_MINEABLE);
|
||||
ReFramed.BLOCKS.forEach(builder::add);
|
||||
ReFramed.BLOCKS.forEach((block) -> {
|
||||
if (providers.containsKey(block.getClass()))
|
||||
providers.get(block.getClass()).getTags().forEach((tag) -> getOrCreateTagBuilder(tag).add(block));
|
||||
builder.add(block);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,39 @@
|
||||
package fr.adrien1106.reframed.generator;
|
||||
|
||||
import fr.adrien1106.reframed.ReFramed;
|
||||
import fr.adrien1106.reframed.block.*;
|
||||
import fr.adrien1106.reframed.generator.block.*;
|
||||
import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput;
|
||||
import net.fabricmc.fabric.api.datagen.v1.provider.FabricModelProvider;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.data.client.*;
|
||||
import net.minecraft.state.property.Property;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import static net.minecraft.data.client.VariantSettings.Rotation.R0;
|
||||
|
||||
public class GBlockstate extends FabricModelProvider {
|
||||
private static final Map<Class<? extends Block>, BlockStateProvider> providers = new HashMap<>();
|
||||
static {
|
||||
providers.put(ReFramedHalfStairBlock.class, new HalfStair());
|
||||
providers.put(ReFramedHalfStairsSlabBlock.class, new HalfStairsSlab());
|
||||
providers.put(ReFramedHalfStairsStairBlock.class, new HalfStairsStair());
|
||||
providers.put(ReFramedLayerBlock.class, new Layer());
|
||||
providers.put(ReFramedPillarBlock.class, new Pillar());
|
||||
providers.put(ReFramedSlabBlock.class, new Slab());
|
||||
providers.put(ReFramedSlabsCubeBlock.class, new SlabsCube());
|
||||
providers.put(ReFramedSmallCubeBlock.class, new SmallCube());
|
||||
providers.put(ReFramedSmallCubesStepBlock.class, new SmallCubesStep());
|
||||
providers.put(ReFramedStairBlock.class, new Stair());
|
||||
providers.put(ReFramedStairsCubeBlock.class, new StairsCube());
|
||||
providers.put(ReFramedStepBlock.class, new Step());
|
||||
providers.put(ReFramedStepsSlabBlock.class, new StepsSlab());
|
||||
providers.put(ReframedWallBlock.class, new Wall());
|
||||
}
|
||||
|
||||
public GBlockstate(FabricDataOutput output) {
|
||||
super(output);
|
||||
@@ -23,7 +45,7 @@ public class GBlockstate extends FabricModelProvider {
|
||||
.forEach(model_generator::excludeFromSimpleItemModelGeneration);
|
||||
ReFramed.BLOCKS.stream()
|
||||
.map(block -> {
|
||||
if (block instanceof BlockStateProvider multipart_block) return multipart_block.getMultipart();
|
||||
if (providers.containsKey(block.getClass())) return providers.get(block.getClass()).getMultipart(block);
|
||||
return VariantsBlockStateSupplier.create(
|
||||
block,
|
||||
GBlockstate.variant(
|
||||
@@ -38,7 +60,9 @@ public class GBlockstate extends FabricModelProvider {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateItemModels(ItemModelGenerator itemModelGenerator) {}
|
||||
public void generateItemModels(ItemModelGenerator model_generator) {
|
||||
ReFramed.ITEMS.forEach(item -> model_generator.register(item, Models.GENERATED));
|
||||
}
|
||||
|
||||
public static BlockStateVariant variant(Identifier model, boolean uv_lock, VariantSettings.Rotation x, VariantSettings.Rotation y) {
|
||||
BlockStateVariant variant = BlockStateVariant.create().put(VariantSettings.MODEL, model);
|
||||
@@ -52,11 +76,57 @@ public class GBlockstate extends FabricModelProvider {
|
||||
return When.create().set(property_1, value_1);
|
||||
}
|
||||
|
||||
public static <T extends Comparable<T>, U extends Comparable<U>> When when(Property<T> property_1, T value_1, Property<U> property_2, U value_2) {
|
||||
return When.allOf(when(property_1, value_1), when(property_2, value_2));
|
||||
public static <T extends Comparable<T>,
|
||||
U extends Comparable<U>> When when(Property<T> property_1, T value_1,
|
||||
Property<U> property_2, U value_2) {
|
||||
return When.allOf(
|
||||
when(property_1, value_1),
|
||||
when(property_2, value_2)
|
||||
);
|
||||
}
|
||||
|
||||
public static <T extends Comparable<T>, U extends Comparable<U>, V extends Comparable<V>> When when(Property<T> property_1, T value_1, Property<U> property_2, U value_2, Property<V> property_3, V value_3) {
|
||||
return When.allOf(when(property_1, value_1), when(property_2, value_2), when(property_3, value_3));
|
||||
public static <T extends Comparable<T>,
|
||||
U extends Comparable<U>,
|
||||
V extends Comparable<V>> When when(Property<T> property_1, T value_1,
|
||||
Property<U> property_2, U value_2,
|
||||
Property<V> property_3, V value_3) {
|
||||
return When.allOf(
|
||||
when(property_1, value_1),
|
||||
when(property_2, value_2),
|
||||
when(property_3, value_3)
|
||||
);
|
||||
}
|
||||
|
||||
public static <T extends Comparable<T>,
|
||||
U extends Comparable<U>,
|
||||
V extends Comparable<V>,
|
||||
W extends Comparable<W>> When when(Property<T> property_1, T value_1,
|
||||
Property<U> property_2, U value_2,
|
||||
Property<V> property_3, V value_3,
|
||||
Property<W> property_4, W value_4) {
|
||||
return When.allOf(
|
||||
when(property_1, value_1),
|
||||
when(property_2, value_2),
|
||||
when(property_3, value_3),
|
||||
when(property_4, value_4)
|
||||
);
|
||||
}
|
||||
|
||||
public static <T extends Comparable<T>,
|
||||
U extends Comparable<U>,
|
||||
V extends Comparable<V>,
|
||||
W extends Comparable<W>,
|
||||
X extends Comparable<X>> When when(Property<T> property_1, T value_1,
|
||||
Property<U> property_2, U value_2,
|
||||
Property<V> property_3, V value_3,
|
||||
Property<W> property_4, W value_4,
|
||||
Property<X> property_5, X value_5) {
|
||||
return When.allOf(
|
||||
when(property_1, value_1),
|
||||
when(property_2, value_2),
|
||||
when(property_3, value_3),
|
||||
when(property_4, value_4),
|
||||
when(property_5, value_5)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,7 @@ public class GLanguage extends FabricLanguageProvider {
|
||||
builder.add(Registries.ITEM_GROUP.getKey(ReFramed.ITEM_GROUP).get(), "Frames");
|
||||
builder.add("advancements.reframed.description", "Get all the frame types.");
|
||||
ReFramed.BLOCKS.forEach(block -> builder.add(block, beautify(Registries.BLOCK.getId(block).getPath()) + " Frame"));
|
||||
ReFramed.ITEMS.forEach(block -> builder.add(block, beautify(Registries.ITEM.getId(block).getPath())));
|
||||
}
|
||||
|
||||
private static String beautify(String name) {
|
||||
|
||||
@@ -1,11 +1,45 @@
|
||||
package fr.adrien1106.reframed.generator;
|
||||
|
||||
import fr.adrien1106.reframed.ReFramed;
|
||||
import fr.adrien1106.reframed.block.*;
|
||||
import fr.adrien1106.reframed.generator.block.*;
|
||||
import fr.adrien1106.reframed.generator.item.Blueprint;
|
||||
import fr.adrien1106.reframed.generator.item.Hammer;
|
||||
import fr.adrien1106.reframed.generator.item.Screwdriver;
|
||||
import fr.adrien1106.reframed.item.ReFramedBlueprintItem;
|
||||
import fr.adrien1106.reframed.item.ReFramedHammerItem;
|
||||
import fr.adrien1106.reframed.item.ReFramedScrewdriverItem;
|
||||
import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput;
|
||||
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
|
||||
import net.minecraft.data.server.recipe.RecipeExporter;
|
||||
import net.minecraft.item.ItemConvertible;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class GRecipe extends FabricRecipeProvider {
|
||||
private static final Map<Class<? extends ItemConvertible>, RecipeSetter> providers = new HashMap<>();
|
||||
static {
|
||||
providers.put(ReFramedBlock.class, new Cube());
|
||||
providers.put(ReFramedHalfStairBlock.class, new HalfStair());
|
||||
providers.put(ReFramedHalfStairsSlabBlock.class, new HalfStairsSlab());
|
||||
providers.put(ReFramedHalfStairsStairBlock.class, new HalfStairsStair());
|
||||
providers.put(ReFramedLayerBlock.class, new Layer());
|
||||
providers.put(ReFramedPillarBlock.class, new Pillar());
|
||||
providers.put(ReFramedSlabBlock.class, new Slab());
|
||||
providers.put(ReFramedSlabsCubeBlock.class, new SlabsCube());
|
||||
providers.put(ReFramedSmallCubeBlock.class, new SmallCube());
|
||||
providers.put(ReFramedSmallCubesStepBlock.class, new SmallCubesStep());
|
||||
providers.put(ReFramedStairBlock.class, new Stair());
|
||||
providers.put(ReFramedStairsCubeBlock.class, new StairsCube());
|
||||
providers.put(ReFramedStepBlock.class, new Step());
|
||||
providers.put(ReFramedStepsSlabBlock.class, new StepsSlab());
|
||||
providers.put(ReframedWallBlock.class, new Wall());
|
||||
providers.put(ReFramedBlueprintItem.class, new Blueprint());
|
||||
providers.put(ReFramedHammerItem.class, new Hammer());
|
||||
providers.put(ReFramedScrewdriverItem.class, new Screwdriver());
|
||||
}
|
||||
|
||||
public GRecipe(FabricDataOutput output) {
|
||||
super(output);
|
||||
}
|
||||
@@ -13,7 +47,10 @@ public class GRecipe extends FabricRecipeProvider {
|
||||
@Override
|
||||
public void generate(RecipeExporter exporter) {
|
||||
ReFramed.BLOCKS.forEach(block -> {
|
||||
if (block instanceof RecipeSetter provider) provider.setRecipe(exporter);
|
||||
if (providers.containsKey(block.getClass())) providers.get(block.getClass()).setRecipe(exporter, block);
|
||||
});
|
||||
ReFramed.ITEMS.forEach(item -> {
|
||||
if (providers.containsKey(item.getClass())) providers.get(item.getClass()).setRecipe(exporter, item);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
package fr.adrien1106.reframed.generator;
|
||||
|
||||
import net.minecraft.data.server.recipe.RecipeExporter;
|
||||
import net.minecraft.item.ItemConvertible;
|
||||
|
||||
public interface RecipeSetter {
|
||||
|
||||
void setRecipe(RecipeExporter exporter);
|
||||
void setRecipe(RecipeExporter exporter, ItemConvertible convertible);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
package fr.adrien1106.reframed.generator;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.registry.tag.TagKey;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface TagGetter {
|
||||
|
||||
List<TagKey<Block>> getTags();
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package fr.adrien1106.reframed.generator.block;
|
||||
|
||||
import fr.adrien1106.reframed.generator.RecipeSetter;
|
||||
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
|
||||
import net.minecraft.data.server.recipe.RecipeExporter;
|
||||
import net.minecraft.data.server.recipe.ShapedRecipeJsonBuilder;
|
||||
import net.minecraft.item.ItemConvertible;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.recipe.book.RecipeCategory;
|
||||
|
||||
public class Cube implements RecipeSetter {
|
||||
|
||||
@Override
|
||||
public void setRecipe(RecipeExporter exporter, ItemConvertible convertible) {
|
||||
ShapedRecipeJsonBuilder
|
||||
.create(RecipeCategory.BUILDING_BLOCKS, convertible)
|
||||
.pattern("III")
|
||||
.pattern("I~I")
|
||||
.pattern("III")
|
||||
.input('I', Items.BAMBOO)
|
||||
.input('~', Items.STRING)
|
||||
.criterion(FabricRecipeProvider.hasItem(Items.BAMBOO), FabricRecipeProvider.conditionsFromItem(Items.BAMBOO))
|
||||
.criterion(FabricRecipeProvider.hasItem(convertible), FabricRecipeProvider.conditionsFromItem(convertible))
|
||||
.offerTo(exporter);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
package fr.adrien1106.reframed.generator.block;
|
||||
|
||||
import fr.adrien1106.reframed.ReFramed;
|
||||
import fr.adrien1106.reframed.generator.BlockStateProvider;
|
||||
import fr.adrien1106.reframed.generator.GBlockstate;
|
||||
import fr.adrien1106.reframed.generator.RecipeSetter;
|
||||
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.data.client.BlockStateSupplier;
|
||||
import net.minecraft.data.client.MultipartBlockStateSupplier;
|
||||
import net.minecraft.data.server.recipe.RecipeExporter;
|
||||
import net.minecraft.data.server.recipe.RecipeProvider;
|
||||
import net.minecraft.data.server.recipe.ShapedRecipeJsonBuilder;
|
||||
import net.minecraft.item.ItemConvertible;
|
||||
import net.minecraft.recipe.book.RecipeCategory;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import static fr.adrien1106.reframed.util.blocks.BlockProperties.CORNER;
|
||||
import static fr.adrien1106.reframed.util.blocks.BlockProperties.CORNER_FACE;
|
||||
import static fr.adrien1106.reframed.util.blocks.Corner.*;
|
||||
import static fr.adrien1106.reframed.util.blocks.Corner.NORTH_EAST_UP;
|
||||
import static net.minecraft.data.client.VariantSettings.Rotation.*;
|
||||
|
||||
public class HalfStair implements RecipeSetter, BlockStateProvider {
|
||||
|
||||
@Override
|
||||
public void setRecipe(RecipeExporter exporter, ItemConvertible convertible) {
|
||||
RecipeProvider.offerStonecuttingRecipe(exporter, RecipeCategory.BUILDING_BLOCKS, convertible, ReFramed.CUBE, 2);
|
||||
ShapedRecipeJsonBuilder
|
||||
.create(RecipeCategory.BUILDING_BLOCKS, convertible, 4)
|
||||
.pattern("I ")
|
||||
.pattern("II")
|
||||
.input('I', ReFramed.CUBE)
|
||||
.criterion(FabricRecipeProvider.hasItem(ReFramed.CUBE), FabricRecipeProvider.conditionsFromItem(ReFramed.CUBE))
|
||||
.criterion(FabricRecipeProvider.hasItem(convertible), FabricRecipeProvider.conditionsFromItem(convertible))
|
||||
.offerTo(exporter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockStateSupplier getMultipart(Block block) {
|
||||
return getMultipart(
|
||||
block,
|
||||
ReFramed.id("half_stair_down_special"),
|
||||
ReFramed.id("half_stair_side_special")
|
||||
);
|
||||
}
|
||||
|
||||
public static BlockStateSupplier getMultipart(Block block, Identifier model_down, Identifier model_side) {
|
||||
return MultipartBlockStateSupplier.create(block)
|
||||
.with(GBlockstate.when(CORNER, NORTH_EAST_DOWN, CORNER_FACE, 1),
|
||||
GBlockstate.variant(model_side, true, R0, R0))
|
||||
.with(GBlockstate.when(CORNER, NORTH_EAST_DOWN, CORNER_FACE, 0),
|
||||
GBlockstate.variant(model_side, true, R90, R270))
|
||||
.with(GBlockstate.when(CORNER, NORTH_EAST_DOWN, CORNER_FACE, 2),
|
||||
GBlockstate.variant(model_down, true, R0, R0))
|
||||
|
||||
.with(GBlockstate.when(CORNER, EAST_SOUTH_DOWN, CORNER_FACE, 1),
|
||||
GBlockstate.variant(model_side, true, R0, R90))
|
||||
.with(GBlockstate.when(CORNER, EAST_SOUTH_DOWN, CORNER_FACE, 0),
|
||||
GBlockstate.variant(model_side, true, R90, R0))
|
||||
.with(GBlockstate.when(CORNER, EAST_SOUTH_DOWN, CORNER_FACE, 2),
|
||||
GBlockstate.variant(model_down, true, R0, R90))
|
||||
|
||||
.with(GBlockstate.when(CORNER, SOUTH_WEST_DOWN, CORNER_FACE, 1),
|
||||
GBlockstate.variant(model_side, true, R0, R180))
|
||||
.with(GBlockstate.when(CORNER, SOUTH_WEST_DOWN, CORNER_FACE, 0),
|
||||
GBlockstate.variant(model_side, true, R90, R90))
|
||||
.with(GBlockstate.when(CORNER, SOUTH_WEST_DOWN, CORNER_FACE, 2),
|
||||
GBlockstate.variant(model_down, true, R0, R180))
|
||||
|
||||
.with(GBlockstate.when(CORNER, WEST_NORTH_DOWN, CORNER_FACE, 1),
|
||||
GBlockstate.variant(model_side, true, R0, R270))
|
||||
.with(GBlockstate.when(CORNER, WEST_NORTH_DOWN, CORNER_FACE, 0),
|
||||
GBlockstate.variant(model_side, true, R90, R180))
|
||||
.with(GBlockstate.when(CORNER, WEST_NORTH_DOWN, CORNER_FACE, 2),
|
||||
GBlockstate.variant(model_down, true, R0, R270))
|
||||
|
||||
.with(GBlockstate.when(CORNER, EAST_SOUTH_UP, CORNER_FACE, 0),
|
||||
GBlockstate.variant(model_side, true, R180, R0))
|
||||
.with(GBlockstate.when(CORNER, EAST_SOUTH_UP, CORNER_FACE, 1),
|
||||
GBlockstate.variant(model_side, true, R270, R90))
|
||||
.with(GBlockstate.when(CORNER, EAST_SOUTH_UP, CORNER_FACE, 2),
|
||||
GBlockstate.variant(model_down, true, R180, R0))
|
||||
|
||||
.with(GBlockstate.when(CORNER, SOUTH_WEST_UP, CORNER_FACE, 0),
|
||||
GBlockstate.variant(model_side, true, R180, R90))
|
||||
.with(GBlockstate.when(CORNER, SOUTH_WEST_UP, CORNER_FACE, 1),
|
||||
GBlockstate.variant(model_side, true, R270, R180))
|
||||
.with(GBlockstate.when(CORNER, SOUTH_WEST_UP, CORNER_FACE, 2),
|
||||
GBlockstate.variant(model_down, true, R180, R90))
|
||||
|
||||
.with(GBlockstate.when(CORNER, WEST_NORTH_UP, CORNER_FACE, 0),
|
||||
GBlockstate.variant(model_side, true, R180, R180))
|
||||
.with(GBlockstate.when(CORNER, WEST_NORTH_UP, CORNER_FACE, 1),
|
||||
GBlockstate.variant(model_side, true, R270, R270))
|
||||
.with(GBlockstate.when(CORNER, WEST_NORTH_UP, CORNER_FACE, 2),
|
||||
GBlockstate.variant(model_down, true, R180, R180))
|
||||
|
||||
.with(GBlockstate.when(CORNER, NORTH_EAST_UP, CORNER_FACE, 0),
|
||||
GBlockstate.variant(model_side, true, R180, R270))
|
||||
.with(GBlockstate.when(CORNER, NORTH_EAST_UP, CORNER_FACE, 1),
|
||||
GBlockstate.variant(model_side, true, R270, R0))
|
||||
.with(GBlockstate.when(CORNER, NORTH_EAST_UP, CORNER_FACE, 2),
|
||||
GBlockstate.variant(model_down, true, R180, R270));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package fr.adrien1106.reframed.generator.block;
|
||||
|
||||
import fr.adrien1106.reframed.ReFramed;
|
||||
import fr.adrien1106.reframed.generator.BlockStateProvider;
|
||||
import fr.adrien1106.reframed.generator.RecipeSetter;
|
||||
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.data.client.BlockStateSupplier;
|
||||
import net.minecraft.data.server.recipe.RecipeExporter;
|
||||
import net.minecraft.data.server.recipe.RecipeProvider;
|
||||
import net.minecraft.data.server.recipe.ShapelessRecipeJsonBuilder;
|
||||
import net.minecraft.item.ItemConvertible;
|
||||
import net.minecraft.recipe.book.RecipeCategory;
|
||||
|
||||
public class HalfStairsSlab implements RecipeSetter, BlockStateProvider {
|
||||
|
||||
@Override
|
||||
public void setRecipe(RecipeExporter exporter, ItemConvertible convertible) {
|
||||
RecipeProvider.offerStonecuttingRecipe(exporter, RecipeCategory.BUILDING_BLOCKS, convertible, ReFramed.CUBE, 2);
|
||||
ShapelessRecipeJsonBuilder
|
||||
.create(RecipeCategory.BUILDING_BLOCKS, convertible)
|
||||
.input(ReFramed.HALF_STAIR)
|
||||
.input(ReFramed.SMALL_CUBE)
|
||||
.criterion(FabricRecipeProvider.hasItem(ReFramed.CUBE), FabricRecipeProvider.conditionsFromItem(ReFramed.CUBE))
|
||||
.criterion(FabricRecipeProvider.hasItem(convertible), FabricRecipeProvider.conditionsFromItem(convertible))
|
||||
.offerTo(exporter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockStateSupplier getMultipart(Block block) {
|
||||
return HalfStair.getMultipart(
|
||||
block,
|
||||
ReFramed.id("half_stairs_slab_down_special"),
|
||||
ReFramed.id("half_stairs_slab_side_special")
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package fr.adrien1106.reframed.generator.block;
|
||||
|
||||
import fr.adrien1106.reframed.ReFramed;
|
||||
import fr.adrien1106.reframed.generator.BlockStateProvider;
|
||||
import fr.adrien1106.reframed.generator.GBlockstate;
|
||||
import fr.adrien1106.reframed.generator.RecipeSetter;
|
||||
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.data.client.BlockStateSupplier;
|
||||
import net.minecraft.data.client.MultipartBlockStateSupplier;
|
||||
import net.minecraft.data.server.recipe.RecipeExporter;
|
||||
import net.minecraft.data.server.recipe.RecipeProvider;
|
||||
import net.minecraft.data.server.recipe.ShapelessRecipeJsonBuilder;
|
||||
import net.minecraft.item.ItemConvertible;
|
||||
import net.minecraft.recipe.book.RecipeCategory;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import static fr.adrien1106.reframed.util.blocks.BlockProperties.EDGE;
|
||||
import static fr.adrien1106.reframed.util.blocks.Edge.*;
|
||||
import static fr.adrien1106.reframed.util.blocks.Edge.WEST_DOWN;
|
||||
import static net.minecraft.data.client.VariantSettings.Rotation.*;
|
||||
|
||||
public class HalfStairsStair implements RecipeSetter, BlockStateProvider {
|
||||
|
||||
@Override
|
||||
public void setRecipe(RecipeExporter exporter, ItemConvertible convertible) {
|
||||
RecipeProvider.offerStonecuttingRecipe(exporter, RecipeCategory.BUILDING_BLOCKS, convertible, ReFramed.CUBE, 2);
|
||||
ShapelessRecipeJsonBuilder
|
||||
.create(RecipeCategory.BUILDING_BLOCKS, convertible)
|
||||
.input(ReFramed.HALF_STAIR, 2)
|
||||
.criterion(FabricRecipeProvider.hasItem(ReFramed.CUBE), FabricRecipeProvider.conditionsFromItem(ReFramed.CUBE))
|
||||
.criterion(FabricRecipeProvider.hasItem(convertible), FabricRecipeProvider.conditionsFromItem(convertible))
|
||||
.offerTo(exporter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockStateSupplier getMultipart(Block block) {
|
||||
Identifier model_id = ReFramed.id("half_stairs_stair_down_special");
|
||||
Identifier side_model_id = ReFramed.id("half_stairs_stair_side_special");
|
||||
Identifier reverse_model_id = ReFramed.id("half_stairs_stair_reverse_special");
|
||||
return MultipartBlockStateSupplier.create(block)
|
||||
/* X AXIS */
|
||||
.with(GBlockstate.when(EDGE, NORTH_DOWN),
|
||||
GBlockstate.variant(side_model_id, true, R90, R180))
|
||||
.with(GBlockstate.when(EDGE, DOWN_SOUTH),
|
||||
GBlockstate.variant(side_model_id, true, R0, R180))
|
||||
.with(GBlockstate.when(EDGE, SOUTH_UP),
|
||||
GBlockstate.variant(side_model_id, true, R270, R180))
|
||||
.with(GBlockstate.when(EDGE, UP_NORTH),
|
||||
GBlockstate.variant(side_model_id, true, R180, R180))
|
||||
/* Y AXIS */
|
||||
.with(GBlockstate.when(EDGE, NORTH_EAST),
|
||||
GBlockstate.variant(model_id, true, R0, R0))
|
||||
.with(GBlockstate.when(EDGE, EAST_SOUTH),
|
||||
GBlockstate.variant(model_id, true, R0, R90))
|
||||
.with(GBlockstate.when(EDGE, SOUTH_WEST),
|
||||
GBlockstate.variant(model_id, true, R0, R180))
|
||||
.with(GBlockstate.when(EDGE, WEST_NORTH),
|
||||
GBlockstate.variant(model_id, true, R0, R270))
|
||||
/* Z AXIS */
|
||||
.with(GBlockstate.when(EDGE, DOWN_EAST),
|
||||
GBlockstate.variant(reverse_model_id, true, R0, R90))
|
||||
.with(GBlockstate.when(EDGE, EAST_UP),
|
||||
GBlockstate.variant(side_model_id, true, R180, R270))
|
||||
.with(GBlockstate.when(EDGE, UP_WEST),
|
||||
GBlockstate.variant(reverse_model_id, true, R180, R90))
|
||||
.with(GBlockstate.when(EDGE, WEST_DOWN),
|
||||
GBlockstate.variant(side_model_id, true, R0, R270));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package fr.adrien1106.reframed.generator.block;
|
||||
|
||||
import fr.adrien1106.reframed.ReFramed;
|
||||
import fr.adrien1106.reframed.generator.BlockStateProvider;
|
||||
import fr.adrien1106.reframed.generator.GBlockstate;
|
||||
import fr.adrien1106.reframed.generator.RecipeSetter;
|
||||
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.data.client.MultipartBlockStateSupplier;
|
||||
import net.minecraft.data.server.recipe.RecipeExporter;
|
||||
import net.minecraft.data.server.recipe.RecipeProvider;
|
||||
import net.minecraft.data.server.recipe.ShapedRecipeJsonBuilder;
|
||||
import net.minecraft.item.ItemConvertible;
|
||||
import net.minecraft.recipe.book.RecipeCategory;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.Direction;
|
||||
|
||||
import static net.minecraft.data.client.VariantSettings.Rotation.*;
|
||||
import static net.minecraft.state.property.Properties.FACING;
|
||||
import static net.minecraft.state.property.Properties.LAYERS;
|
||||
|
||||
public class Layer implements RecipeSetter, BlockStateProvider {
|
||||
|
||||
@Override
|
||||
public void setRecipe(RecipeExporter exporter, ItemConvertible convertible) {
|
||||
RecipeProvider.offerStonecuttingRecipe(exporter, RecipeCategory.BUILDING_BLOCKS, convertible, ReFramed.CUBE, 8);
|
||||
ShapedRecipeJsonBuilder
|
||||
.create(RecipeCategory.BUILDING_BLOCKS, convertible, 16)
|
||||
.pattern("II")
|
||||
.input('I', ReFramed.CUBE)
|
||||
.criterion(FabricRecipeProvider.hasItem(ReFramed.CUBE), FabricRecipeProvider.conditionsFromItem(ReFramed.CUBE))
|
||||
.criterion(FabricRecipeProvider.hasItem(convertible), FabricRecipeProvider.conditionsFromItem(convertible))
|
||||
.offerTo(exporter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MultipartBlockStateSupplier getMultipart(Block block) {
|
||||
String model_pattern = "layer_x_special";
|
||||
MultipartBlockStateSupplier supplier = MultipartBlockStateSupplier.create(block);
|
||||
for (int i = 1; i <= 8; i++) {
|
||||
Identifier model = ReFramed.id(model_pattern.replace("x", i + ""));
|
||||
supplier
|
||||
.with(GBlockstate.when(FACING, Direction.DOWN, LAYERS, i),
|
||||
GBlockstate.variant(model, true, R0, R0))
|
||||
.with(GBlockstate.when(FACING, Direction.SOUTH, LAYERS, i),
|
||||
GBlockstate.variant(model, true, R90, R0))
|
||||
.with(GBlockstate.when(FACING, Direction.UP, LAYERS, i),
|
||||
GBlockstate.variant(model, true, R180, R0))
|
||||
.with(GBlockstate.when(FACING, Direction.NORTH, LAYERS, i),
|
||||
GBlockstate.variant(model, true, R270, R0))
|
||||
.with(GBlockstate.when(FACING, Direction.WEST, LAYERS, i),
|
||||
GBlockstate.variant(model, true, R90, R90))
|
||||
.with(GBlockstate.when(FACING, Direction.EAST, LAYERS, i),
|
||||
GBlockstate.variant(model, true, R90, R270));
|
||||
}
|
||||
return supplier;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package fr.adrien1106.reframed.generator.block;
|
||||
|
||||
import fr.adrien1106.reframed.ReFramed;
|
||||
import fr.adrien1106.reframed.generator.BlockStateProvider;
|
||||
import fr.adrien1106.reframed.generator.GBlockstate;
|
||||
import fr.adrien1106.reframed.generator.RecipeSetter;
|
||||
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.data.client.BlockStateSupplier;
|
||||
import net.minecraft.data.client.MultipartBlockStateSupplier;
|
||||
import net.minecraft.data.server.recipe.RecipeExporter;
|
||||
import net.minecraft.data.server.recipe.RecipeProvider;
|
||||
import net.minecraft.data.server.recipe.ShapedRecipeJsonBuilder;
|
||||
import net.minecraft.item.ItemConvertible;
|
||||
import net.minecraft.recipe.book.RecipeCategory;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.Direction;
|
||||
|
||||
import static net.minecraft.data.client.VariantSettings.Rotation.R0;
|
||||
import static net.minecraft.data.client.VariantSettings.Rotation.R90;
|
||||
import static net.minecraft.state.property.Properties.AXIS;
|
||||
|
||||
public class Pillar implements RecipeSetter, BlockStateProvider {
|
||||
|
||||
@Override
|
||||
public void setRecipe(RecipeExporter exporter, ItemConvertible convertible) {
|
||||
RecipeProvider.offerStonecuttingRecipe(exporter, RecipeCategory.BUILDING_BLOCKS, convertible, ReFramed.CUBE, 4);
|
||||
ShapedRecipeJsonBuilder
|
||||
.create(RecipeCategory.BUILDING_BLOCKS, convertible, 8)
|
||||
.pattern("I")
|
||||
.pattern("I")
|
||||
.input('I', ReFramed.CUBE)
|
||||
.criterion(FabricRecipeProvider.hasItem(ReFramed.CUBE), FabricRecipeProvider.conditionsFromItem(ReFramed.CUBE))
|
||||
.criterion(FabricRecipeProvider.hasItem(convertible), FabricRecipeProvider.conditionsFromItem(convertible))
|
||||
.offerTo(exporter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockStateSupplier getMultipart(Block block) {
|
||||
Identifier model_id = ReFramed.id("pillar_special");
|
||||
return MultipartBlockStateSupplier.create(block)
|
||||
.with(GBlockstate.when(AXIS, Direction.Axis.X),
|
||||
GBlockstate.variant(model_id, true, R90, R90))
|
||||
.with(GBlockstate.when(AXIS, Direction.Axis.Y),
|
||||
GBlockstate.variant(model_id, true, R0, R0))
|
||||
.with(GBlockstate.when(AXIS, Direction.Axis.Z),
|
||||
GBlockstate.variant(model_id, true, R90, R0));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package fr.adrien1106.reframed.generator.block;
|
||||
|
||||
import fr.adrien1106.reframed.ReFramed;
|
||||
import fr.adrien1106.reframed.generator.BlockStateProvider;
|
||||
import fr.adrien1106.reframed.generator.GBlockstate;
|
||||
import fr.adrien1106.reframed.generator.RecipeSetter;
|
||||
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.data.client.MultipartBlockStateSupplier;
|
||||
import net.minecraft.data.server.recipe.RecipeExporter;
|
||||
import net.minecraft.data.server.recipe.RecipeProvider;
|
||||
import net.minecraft.data.server.recipe.ShapedRecipeJsonBuilder;
|
||||
import net.minecraft.item.ItemConvertible;
|
||||
import net.minecraft.recipe.book.RecipeCategory;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.Direction;
|
||||
|
||||
import static net.minecraft.data.client.VariantSettings.Rotation.*;
|
||||
import static net.minecraft.state.property.Properties.FACING;
|
||||
|
||||
public class Slab implements RecipeSetter, BlockStateProvider {
|
||||
|
||||
@Override
|
||||
public void setRecipe(RecipeExporter exporter, ItemConvertible convertible) {
|
||||
RecipeProvider.offerStonecuttingRecipe(exporter, RecipeCategory.BUILDING_BLOCKS, convertible, ReFramed.CUBE, 2);
|
||||
ShapedRecipeJsonBuilder
|
||||
.create(RecipeCategory.BUILDING_BLOCKS, convertible, 6)
|
||||
.pattern("III")
|
||||
.input('I', ReFramed.CUBE)
|
||||
.criterion(FabricRecipeProvider.hasItem(ReFramed.CUBE), FabricRecipeProvider.conditionsFromItem(ReFramed.CUBE))
|
||||
.criterion(FabricRecipeProvider.hasItem(convertible), FabricRecipeProvider.conditionsFromItem(convertible))
|
||||
.offerTo(exporter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MultipartBlockStateSupplier getMultipart(Block block) {
|
||||
Identifier model_id = ReFramed.id("slab_special");
|
||||
return MultipartBlockStateSupplier.create(block)
|
||||
.with(GBlockstate.when(FACING, Direction.DOWN),
|
||||
GBlockstate.variant(model_id, true, R0, R0))
|
||||
.with(GBlockstate.when(FACING, Direction.SOUTH),
|
||||
GBlockstate.variant(model_id, true, R90, R0))
|
||||
.with(GBlockstate.when(FACING, Direction.UP),
|
||||
GBlockstate.variant(model_id, true, R180, R0))
|
||||
.with(GBlockstate.when(FACING, Direction.NORTH),
|
||||
GBlockstate.variant(model_id, true, R270, R0))
|
||||
.with(GBlockstate.when(FACING, Direction.WEST),
|
||||
GBlockstate.variant(model_id, true, R90, R90))
|
||||
.with(GBlockstate.when(FACING, Direction.EAST),
|
||||
GBlockstate.variant(model_id, true, R90, R270));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package fr.adrien1106.reframed.generator.block;
|
||||
|
||||
import fr.adrien1106.reframed.ReFramed;
|
||||
import fr.adrien1106.reframed.generator.BlockStateProvider;
|
||||
import fr.adrien1106.reframed.generator.GBlockstate;
|
||||
import fr.adrien1106.reframed.generator.RecipeSetter;
|
||||
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.data.client.MultipartBlockStateSupplier;
|
||||
import net.minecraft.data.server.recipe.RecipeExporter;
|
||||
import net.minecraft.data.server.recipe.RecipeProvider;
|
||||
import net.minecraft.data.server.recipe.ShapelessRecipeJsonBuilder;
|
||||
import net.minecraft.item.ItemConvertible;
|
||||
import net.minecraft.recipe.book.RecipeCategory;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.Direction;
|
||||
|
||||
import static net.minecraft.data.client.VariantSettings.Rotation.*;
|
||||
import static net.minecraft.data.client.VariantSettings.Rotation.R90;
|
||||
import static net.minecraft.state.property.Properties.AXIS;
|
||||
|
||||
public class SlabsCube implements RecipeSetter, BlockStateProvider {
|
||||
|
||||
@Override
|
||||
public void setRecipe(RecipeExporter exporter, ItemConvertible convertible) {
|
||||
RecipeProvider.offerStonecuttingRecipe(exporter, RecipeCategory.BUILDING_BLOCKS, convertible, ReFramed.CUBE);
|
||||
ShapelessRecipeJsonBuilder
|
||||
.create(RecipeCategory.BUILDING_BLOCKS, convertible)
|
||||
.input(ReFramed.SLAB, 2)
|
||||
.criterion(FabricRecipeProvider.hasItem(ReFramed.CUBE), FabricRecipeProvider.conditionsFromItem(ReFramed.CUBE))
|
||||
.criterion(FabricRecipeProvider.hasItem(convertible), FabricRecipeProvider.conditionsFromItem(convertible))
|
||||
.offerTo(exporter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MultipartBlockStateSupplier getMultipart(Block block) {
|
||||
Identifier model_id = ReFramed.id("double_slab_special");
|
||||
return MultipartBlockStateSupplier.create(block)
|
||||
.with(GBlockstate.when(AXIS, Direction.Axis.Y),
|
||||
GBlockstate.variant(model_id, true, R0, R0))
|
||||
.with(GBlockstate.when(AXIS, Direction.Axis.Z),
|
||||
GBlockstate.variant(model_id, true, R270, R0))
|
||||
.with(GBlockstate.when(AXIS, Direction.Axis.X),
|
||||
GBlockstate.variant(model_id, true, R90, R90));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package fr.adrien1106.reframed.generator.block;
|
||||
|
||||
import fr.adrien1106.reframed.ReFramed;
|
||||
import fr.adrien1106.reframed.generator.BlockStateProvider;
|
||||
import fr.adrien1106.reframed.generator.GBlockstate;
|
||||
import fr.adrien1106.reframed.generator.RecipeSetter;
|
||||
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.data.client.BlockStateSupplier;
|
||||
import net.minecraft.data.client.MultipartBlockStateSupplier;
|
||||
import net.minecraft.data.server.recipe.RecipeExporter;
|
||||
import net.minecraft.data.server.recipe.RecipeProvider;
|
||||
import net.minecraft.data.server.recipe.ShapelessRecipeJsonBuilder;
|
||||
import net.minecraft.item.ItemConvertible;
|
||||
import net.minecraft.recipe.book.RecipeCategory;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import static fr.adrien1106.reframed.util.blocks.BlockProperties.CORNER;
|
||||
import static fr.adrien1106.reframed.util.blocks.Corner.*;
|
||||
import static fr.adrien1106.reframed.util.blocks.Corner.NORTH_EAST_UP;
|
||||
import static net.minecraft.data.client.VariantSettings.Rotation.*;
|
||||
|
||||
public class SmallCube implements RecipeSetter, BlockStateProvider {
|
||||
|
||||
@Override
|
||||
public void setRecipe(RecipeExporter exporter, ItemConvertible convertible) {
|
||||
RecipeProvider.offerStonecuttingRecipe(exporter, RecipeCategory.BUILDING_BLOCKS, convertible, ReFramed.CUBE, 8);
|
||||
ShapelessRecipeJsonBuilder
|
||||
.create(RecipeCategory.BUILDING_BLOCKS, convertible, 8)
|
||||
.input(ReFramed.CUBE)
|
||||
.criterion(FabricRecipeProvider.hasItem(ReFramed.CUBE), FabricRecipeProvider.conditionsFromItem(ReFramed.CUBE))
|
||||
.criterion(FabricRecipeProvider.hasItem(convertible), FabricRecipeProvider.conditionsFromItem(convertible))
|
||||
.offerTo(exporter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockStateSupplier getMultipart(Block block) {
|
||||
Identifier small_cube_id = ReFramed.id("small_cube_special");
|
||||
return MultipartBlockStateSupplier.create(block)
|
||||
.with(GBlockstate.when(CORNER, NORTH_EAST_DOWN),
|
||||
GBlockstate.variant(small_cube_id, true, R0, R0))
|
||||
.with(GBlockstate.when(CORNER, EAST_SOUTH_DOWN),
|
||||
GBlockstate.variant(small_cube_id, true, R0, R90))
|
||||
.with(GBlockstate.when(CORNER, SOUTH_WEST_DOWN),
|
||||
GBlockstate.variant(small_cube_id, true, R0, R180))
|
||||
.with(GBlockstate.when(CORNER, WEST_NORTH_DOWN),
|
||||
GBlockstate.variant(small_cube_id, true, R0, R270))
|
||||
.with(GBlockstate.when(CORNER, EAST_SOUTH_UP),
|
||||
GBlockstate.variant(small_cube_id, true, R180, R0))
|
||||
.with(GBlockstate.when(CORNER, SOUTH_WEST_UP),
|
||||
GBlockstate.variant(small_cube_id, true, R180, R90))
|
||||
.with(GBlockstate.when(CORNER, WEST_NORTH_UP),
|
||||
GBlockstate.variant(small_cube_id, true, R180, R180))
|
||||
.with(GBlockstate.when(CORNER, NORTH_EAST_UP),
|
||||
GBlockstate.variant(small_cube_id, true, R180, R270));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package fr.adrien1106.reframed.generator.block;
|
||||
|
||||
import fr.adrien1106.reframed.ReFramed;
|
||||
import fr.adrien1106.reframed.generator.BlockStateProvider;
|
||||
import fr.adrien1106.reframed.generator.GBlockstate;
|
||||
import fr.adrien1106.reframed.generator.RecipeSetter;
|
||||
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.data.client.BlockStateSupplier;
|
||||
import net.minecraft.data.client.MultipartBlockStateSupplier;
|
||||
import net.minecraft.data.server.recipe.RecipeExporter;
|
||||
import net.minecraft.data.server.recipe.RecipeProvider;
|
||||
import net.minecraft.data.server.recipe.ShapelessRecipeJsonBuilder;
|
||||
import net.minecraft.item.ItemConvertible;
|
||||
import net.minecraft.recipe.book.RecipeCategory;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import static fr.adrien1106.reframed.util.blocks.BlockProperties.EDGE;
|
||||
import static fr.adrien1106.reframed.util.blocks.Edge.*;
|
||||
import static fr.adrien1106.reframed.util.blocks.Edge.SOUTH_UP;
|
||||
import static net.minecraft.data.client.VariantSettings.Rotation.*;
|
||||
|
||||
public class SmallCubesStep implements RecipeSetter, BlockStateProvider {
|
||||
|
||||
@Override
|
||||
public void setRecipe(RecipeExporter exporter, ItemConvertible convertible) {
|
||||
RecipeProvider.offerStonecuttingRecipe(exporter, RecipeCategory.BUILDING_BLOCKS, convertible, ReFramed.CUBE, 4);
|
||||
ShapelessRecipeJsonBuilder
|
||||
.create(RecipeCategory.BUILDING_BLOCKS, convertible)
|
||||
.input(ReFramed.SMALL_CUBE, 2)
|
||||
.criterion(FabricRecipeProvider.hasItem(ReFramed.CUBE), FabricRecipeProvider.conditionsFromItem(ReFramed.CUBE))
|
||||
.criterion(FabricRecipeProvider.hasItem(convertible), FabricRecipeProvider.conditionsFromItem(convertible))
|
||||
.offerTo(exporter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockStateSupplier getMultipart(Block block) {
|
||||
Identifier model_id = ReFramed.id("small_cubes_step_special");
|
||||
Identifier reverse_model_id = ReFramed.id("small_cubes_step_reverse_special");
|
||||
return MultipartBlockStateSupplier.create(block)
|
||||
/* X AXIS */
|
||||
.with(GBlockstate.when(EDGE, DOWN_EAST),
|
||||
GBlockstate.variant(model_id, true, R0, R0))
|
||||
.with(GBlockstate.when(EDGE, EAST_UP),
|
||||
GBlockstate.variant(reverse_model_id, true, R180, R0))
|
||||
.with(GBlockstate.when(EDGE, UP_WEST),
|
||||
GBlockstate.variant(model_id, true, R180, R180))
|
||||
.with(GBlockstate.when(EDGE, WEST_DOWN),
|
||||
GBlockstate.variant(reverse_model_id, true, R0, R180))
|
||||
/* Y AXIS */
|
||||
.with(GBlockstate.when(EDGE, EAST_SOUTH),
|
||||
GBlockstate.variant(model_id, true, R90, R0))
|
||||
.with(GBlockstate.when(EDGE, SOUTH_WEST),
|
||||
GBlockstate.variant(model_id, true, R90, R90))
|
||||
.with(GBlockstate.when(EDGE, WEST_NORTH),
|
||||
GBlockstate.variant(model_id, true, R90, R180))
|
||||
.with(GBlockstate.when(EDGE, NORTH_EAST),
|
||||
GBlockstate.variant(model_id, true, R90, R270))
|
||||
/* Z AXIS */
|
||||
.with(GBlockstate.when(EDGE, DOWN_SOUTH),
|
||||
GBlockstate.variant(reverse_model_id, true, R0, R90))
|
||||
.with(GBlockstate.when(EDGE, NORTH_DOWN),
|
||||
GBlockstate.variant(model_id, true, R0, R270))
|
||||
.with(GBlockstate.when(EDGE, UP_NORTH),
|
||||
GBlockstate.variant(reverse_model_id, true, R180, R270))
|
||||
.with(GBlockstate.when(EDGE, SOUTH_UP),
|
||||
GBlockstate.variant(model_id, true, R180, R90));
|
||||
}
|
||||
}
|
||||
267
src/main/java/fr/adrien1106/reframed/generator/block/Stair.java
Normal file
267
src/main/java/fr/adrien1106/reframed/generator/block/Stair.java
Normal file
@@ -0,0 +1,267 @@
|
||||
package fr.adrien1106.reframed.generator.block;
|
||||
|
||||
import fr.adrien1106.reframed.ReFramed;
|
||||
import fr.adrien1106.reframed.generator.BlockStateProvider;
|
||||
import fr.adrien1106.reframed.generator.GBlockstate;
|
||||
import fr.adrien1106.reframed.generator.RecipeSetter;
|
||||
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.data.client.MultipartBlockStateSupplier;
|
||||
import net.minecraft.data.client.When;
|
||||
import net.minecraft.data.server.recipe.RecipeExporter;
|
||||
import net.minecraft.data.server.recipe.RecipeProvider;
|
||||
import net.minecraft.data.server.recipe.ShapedRecipeJsonBuilder;
|
||||
import net.minecraft.item.ItemConvertible;
|
||||
import net.minecraft.recipe.book.RecipeCategory;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import static fr.adrien1106.reframed.util.blocks.BlockProperties.EDGE;
|
||||
import static fr.adrien1106.reframed.util.blocks.BlockProperties.STAIR_SHAPE;
|
||||
import static fr.adrien1106.reframed.util.blocks.Edge.*;
|
||||
import static fr.adrien1106.reframed.util.blocks.StairShape.*;
|
||||
import static net.minecraft.data.client.VariantSettings.Rotation.*;
|
||||
|
||||
public class Stair implements RecipeSetter, BlockStateProvider {
|
||||
|
||||
@Override
|
||||
public void setRecipe(RecipeExporter exporter, ItemConvertible convertible) {
|
||||
RecipeProvider.offerStonecuttingRecipe(exporter, RecipeCategory.BUILDING_BLOCKS, convertible, ReFramed.CUBE);
|
||||
ShapedRecipeJsonBuilder
|
||||
.create(RecipeCategory.BUILDING_BLOCKS, convertible, 4)
|
||||
.pattern("I ")
|
||||
.pattern("II ")
|
||||
.pattern("III")
|
||||
.input('I', ReFramed.CUBE)
|
||||
.criterion(FabricRecipeProvider.hasItem(ReFramed.CUBE), FabricRecipeProvider.conditionsFromItem(ReFramed.CUBE))
|
||||
.criterion(FabricRecipeProvider.hasItem(convertible), FabricRecipeProvider.conditionsFromItem(convertible))
|
||||
.offerTo(exporter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MultipartBlockStateSupplier getMultipart(Block block) {
|
||||
return getMultipart(block, false);
|
||||
}
|
||||
|
||||
public static MultipartBlockStateSupplier getMultipart(Block block, boolean is_double) {
|
||||
String infix = is_double ? "s_cube" : "";
|
||||
Identifier straight_id = ReFramed.id("stair" + infix + "_special");
|
||||
Identifier double_outer_id = ReFramed.id("outers_stair" + infix + "_special");
|
||||
Identifier inner_id = ReFramed.id("inner_stair" + infix + "_special");
|
||||
Identifier outer_id = ReFramed.id("outer_stair" + infix + "_special");
|
||||
Identifier outer_side_id = ReFramed.id("outer_side_stair" + infix + "_special");
|
||||
return MultipartBlockStateSupplier.create(block)
|
||||
/* STRAIGHT X AXIS */
|
||||
.with(GBlockstate.when(EDGE, DOWN_EAST, STAIR_SHAPE, STRAIGHT),
|
||||
GBlockstate.variant(straight_id, true, R0, R0))
|
||||
.with(GBlockstate.when(EDGE, EAST_UP, STAIR_SHAPE, STRAIGHT),
|
||||
GBlockstate.variant(straight_id, true, R180, R0))
|
||||
.with(GBlockstate.when(EDGE, UP_WEST, STAIR_SHAPE, STRAIGHT),
|
||||
GBlockstate.variant(straight_id, true, R180, R180))
|
||||
.with(GBlockstate.when(EDGE, WEST_DOWN, STAIR_SHAPE, STRAIGHT),
|
||||
GBlockstate.variant(straight_id, true, R0, R180))
|
||||
/* STRAIGHT Y AXIS */
|
||||
.with(GBlockstate.when(EDGE, EAST_SOUTH, STAIR_SHAPE, STRAIGHT),
|
||||
GBlockstate.variant(straight_id, true, R90, R0))
|
||||
.with(GBlockstate.when(EDGE, SOUTH_WEST, STAIR_SHAPE, STRAIGHT),
|
||||
GBlockstate.variant(straight_id, true, R90, R90))
|
||||
.with(GBlockstate.when(EDGE, WEST_NORTH, STAIR_SHAPE, STRAIGHT),
|
||||
GBlockstate.variant(straight_id, true, R90, R180))
|
||||
.with(GBlockstate.when(EDGE, NORTH_EAST, STAIR_SHAPE, STRAIGHT),
|
||||
GBlockstate.variant(straight_id, true, R90, R270))
|
||||
/* STRAIGHT Z AXIS */
|
||||
.with(GBlockstate.when(EDGE, DOWN_SOUTH, STAIR_SHAPE, STRAIGHT),
|
||||
GBlockstate.variant(straight_id, true, R0, R90))
|
||||
.with(GBlockstate.when(EDGE, NORTH_DOWN, STAIR_SHAPE, STRAIGHT),
|
||||
GBlockstate.variant(straight_id, true, R0, R270))
|
||||
.with(GBlockstate.when(EDGE, UP_NORTH, STAIR_SHAPE, STRAIGHT),
|
||||
GBlockstate.variant(straight_id, true, R180, R270))
|
||||
.with(GBlockstate.when(EDGE, SOUTH_UP, STAIR_SHAPE, STRAIGHT),
|
||||
GBlockstate.variant(straight_id, true, R180, R90))
|
||||
/* INNER BOTTOM */
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, NORTH_DOWN, STAIR_SHAPE, INNER_RIGHT),
|
||||
GBlockstate.when(EDGE, WEST_NORTH, STAIR_SHAPE, INNER_RIGHT),
|
||||
GBlockstate.when(EDGE, WEST_DOWN, STAIR_SHAPE, INNER_RIGHT)),
|
||||
GBlockstate.variant(inner_id, true, R0, R180))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, NORTH_DOWN, STAIR_SHAPE, INNER_LEFT),
|
||||
GBlockstate.when(EDGE, NORTH_EAST, STAIR_SHAPE, INNER_RIGHT),
|
||||
GBlockstate.when(EDGE, DOWN_EAST, STAIR_SHAPE, INNER_RIGHT)),
|
||||
GBlockstate.variant(inner_id, true, R0, R270))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, DOWN_SOUTH, STAIR_SHAPE, INNER_LEFT),
|
||||
GBlockstate.when(EDGE, EAST_SOUTH, STAIR_SHAPE, INNER_RIGHT),
|
||||
GBlockstate.when(EDGE, DOWN_EAST, STAIR_SHAPE, INNER_LEFT)),
|
||||
GBlockstate.variant(inner_id, true, R0, R0))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, DOWN_SOUTH, STAIR_SHAPE, INNER_RIGHT),
|
||||
GBlockstate.when(EDGE, SOUTH_WEST, STAIR_SHAPE, INNER_RIGHT),
|
||||
GBlockstate.when(EDGE, WEST_DOWN, STAIR_SHAPE, INNER_LEFT)),
|
||||
GBlockstate.variant(inner_id, true, R0, R90))
|
||||
/* INNER TOP */
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, EAST_UP, STAIR_SHAPE, INNER_RIGHT),
|
||||
GBlockstate.when(EDGE, NORTH_EAST, STAIR_SHAPE, INNER_LEFT),
|
||||
GBlockstate.when(EDGE, UP_NORTH, STAIR_SHAPE, INNER_LEFT)),
|
||||
GBlockstate.variant(inner_id, true, R180, R0))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, EAST_UP, STAIR_SHAPE, INNER_LEFT),
|
||||
GBlockstate.when(EDGE, EAST_SOUTH, STAIR_SHAPE, INNER_LEFT),
|
||||
GBlockstate.when(EDGE, SOUTH_UP, STAIR_SHAPE, INNER_LEFT)),
|
||||
GBlockstate.variant(inner_id, true, R180, R90))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, SOUTH_UP, STAIR_SHAPE, INNER_RIGHT),
|
||||
GBlockstate.when(EDGE, SOUTH_WEST, STAIR_SHAPE, INNER_LEFT),
|
||||
GBlockstate.when(EDGE, UP_WEST, STAIR_SHAPE, INNER_LEFT)),
|
||||
GBlockstate.variant(inner_id, true, R180, R180))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, UP_NORTH, STAIR_SHAPE, INNER_RIGHT),
|
||||
GBlockstate.when(EDGE, WEST_NORTH, STAIR_SHAPE, INNER_LEFT),
|
||||
GBlockstate.when(EDGE, UP_WEST, STAIR_SHAPE, INNER_RIGHT)),
|
||||
GBlockstate.variant(inner_id, true, R180, R270))
|
||||
/* OUTER BOTTOM */
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, DOWN_SOUTH, STAIR_SHAPE, SECOND_OUTER_LEFT),
|
||||
GBlockstate.when(EDGE, DOWN_EAST, STAIR_SHAPE, SECOND_OUTER_LEFT)),
|
||||
GBlockstate.variant(outer_id, true, R0, R0))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, DOWN_SOUTH, STAIR_SHAPE, SECOND_OUTER_RIGHT),
|
||||
GBlockstate.when(EDGE, WEST_DOWN, STAIR_SHAPE, FIRST_OUTER_LEFT)),
|
||||
GBlockstate.variant(outer_id, true, R0, R90))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, NORTH_DOWN, STAIR_SHAPE, FIRST_OUTER_RIGHT),
|
||||
GBlockstate.when(EDGE, WEST_DOWN, STAIR_SHAPE, FIRST_OUTER_RIGHT)),
|
||||
GBlockstate.variant(outer_id, true, R0, R180))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, NORTH_DOWN, STAIR_SHAPE, FIRST_OUTER_LEFT),
|
||||
GBlockstate.when(EDGE, DOWN_EAST, STAIR_SHAPE, SECOND_OUTER_RIGHT)),
|
||||
GBlockstate.variant(outer_id, true, R0, R270))
|
||||
/* OUTER TOP */
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, UP_NORTH, STAIR_SHAPE, SECOND_OUTER_LEFT),
|
||||
GBlockstate.when(EDGE, EAST_UP, STAIR_SHAPE, FIRST_OUTER_RIGHT)),
|
||||
GBlockstate.variant(outer_id, true, R180, R0))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, SOUTH_UP, STAIR_SHAPE, FIRST_OUTER_LEFT),
|
||||
GBlockstate.when(EDGE, EAST_UP, STAIR_SHAPE, FIRST_OUTER_LEFT)),
|
||||
GBlockstate.variant(outer_id, true, R180, R90))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, SOUTH_UP, STAIR_SHAPE, FIRST_OUTER_RIGHT),
|
||||
GBlockstate.when(EDGE, UP_WEST, STAIR_SHAPE, SECOND_OUTER_LEFT)),
|
||||
GBlockstate.variant(outer_id, true, R180, R180))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, UP_NORTH, STAIR_SHAPE, SECOND_OUTER_RIGHT),
|
||||
GBlockstate.when(EDGE, UP_WEST, STAIR_SHAPE, SECOND_OUTER_RIGHT)),
|
||||
GBlockstate.variant(outer_id, true, R180, R270))
|
||||
/* OUTER EAST */
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, EAST_SOUTH, STAIR_SHAPE, SECOND_OUTER_RIGHT),
|
||||
GBlockstate.when(EDGE, DOWN_EAST, STAIR_SHAPE, FIRST_OUTER_LEFT)),
|
||||
GBlockstate.variant(outer_side_id, true, R0, R0))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, EAST_SOUTH, STAIR_SHAPE, SECOND_OUTER_LEFT),
|
||||
GBlockstate.when(EDGE, EAST_UP, STAIR_SHAPE, SECOND_OUTER_LEFT)),
|
||||
GBlockstate.variant(outer_side_id, true, R90, R0))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, NORTH_EAST, STAIR_SHAPE, FIRST_OUTER_LEFT),
|
||||
GBlockstate.when(EDGE, EAST_UP, STAIR_SHAPE, SECOND_OUTER_RIGHT)),
|
||||
GBlockstate.variant(outer_side_id, true, R180, R0))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, NORTH_EAST, STAIR_SHAPE, FIRST_OUTER_RIGHT),
|
||||
GBlockstate.when(EDGE, DOWN_EAST, STAIR_SHAPE, FIRST_OUTER_RIGHT)),
|
||||
GBlockstate.variant(outer_side_id, true, R270, R0))
|
||||
/* OUTER SOUTH */
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, SOUTH_WEST, STAIR_SHAPE, SECOND_OUTER_RIGHT),
|
||||
GBlockstate.when(EDGE, DOWN_SOUTH, STAIR_SHAPE, FIRST_OUTER_RIGHT)),
|
||||
GBlockstate.variant(outer_side_id, true, R0, R90))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, SOUTH_WEST, STAIR_SHAPE, SECOND_OUTER_LEFT),
|
||||
GBlockstate.when(EDGE, SOUTH_UP, STAIR_SHAPE, SECOND_OUTER_RIGHT)),
|
||||
GBlockstate.variant(outer_side_id, true, R90, R90))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, EAST_SOUTH, STAIR_SHAPE, FIRST_OUTER_LEFT),
|
||||
GBlockstate.when(EDGE, SOUTH_UP, STAIR_SHAPE, SECOND_OUTER_LEFT)),
|
||||
GBlockstate.variant(outer_side_id, true, R180, R90))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, EAST_SOUTH, STAIR_SHAPE, FIRST_OUTER_RIGHT),
|
||||
GBlockstate.when(EDGE, DOWN_SOUTH, STAIR_SHAPE, FIRST_OUTER_LEFT)),
|
||||
GBlockstate.variant(outer_side_id, true, R270, R90))
|
||||
/* OUTER WEST */
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, WEST_NORTH, STAIR_SHAPE, SECOND_OUTER_RIGHT),
|
||||
GBlockstate.when(EDGE, WEST_DOWN, STAIR_SHAPE, SECOND_OUTER_RIGHT)),
|
||||
GBlockstate.variant(outer_side_id, true, R0, R180))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, WEST_NORTH, STAIR_SHAPE, SECOND_OUTER_LEFT),
|
||||
GBlockstate.when(EDGE, UP_WEST, STAIR_SHAPE, FIRST_OUTER_RIGHT)),
|
||||
GBlockstate.variant(outer_side_id, true, R90, R180))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, SOUTH_WEST, STAIR_SHAPE, FIRST_OUTER_LEFT),
|
||||
GBlockstate.when(EDGE, UP_WEST, STAIR_SHAPE, FIRST_OUTER_LEFT)),
|
||||
GBlockstate.variant(outer_side_id, true, R180, R180))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, SOUTH_WEST, STAIR_SHAPE, FIRST_OUTER_RIGHT),
|
||||
GBlockstate.when(EDGE, WEST_DOWN, STAIR_SHAPE, SECOND_OUTER_LEFT)),
|
||||
GBlockstate.variant(outer_side_id, true, R270, R180))
|
||||
/* OUTER NORTH */
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, NORTH_EAST, STAIR_SHAPE, SECOND_OUTER_RIGHT),
|
||||
GBlockstate.when(EDGE, NORTH_DOWN, STAIR_SHAPE, SECOND_OUTER_LEFT)),
|
||||
GBlockstate.variant(outer_side_id, true, R0, R270))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, NORTH_EAST, STAIR_SHAPE, SECOND_OUTER_LEFT),
|
||||
GBlockstate.when(EDGE, UP_NORTH, STAIR_SHAPE, FIRST_OUTER_LEFT)),
|
||||
GBlockstate.variant(outer_side_id, true, R90, R270))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, WEST_NORTH, STAIR_SHAPE, FIRST_OUTER_LEFT),
|
||||
GBlockstate.when(EDGE, UP_NORTH, STAIR_SHAPE, FIRST_OUTER_RIGHT)),
|
||||
GBlockstate.variant(outer_side_id, true, R180, R270))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, WEST_NORTH, STAIR_SHAPE, FIRST_OUTER_RIGHT),
|
||||
GBlockstate.when(EDGE, NORTH_DOWN, STAIR_SHAPE, SECOND_OUTER_RIGHT)),
|
||||
GBlockstate.variant(outer_side_id, true, R270, R270))
|
||||
/* OUTER BOTTOM */
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, DOWN_SOUTH, STAIR_SHAPE, OUTER_LEFT),
|
||||
GBlockstate.when(EDGE, DOWN_EAST, STAIR_SHAPE, OUTER_LEFT),
|
||||
GBlockstate.when(EDGE, EAST_SOUTH, STAIR_SHAPE, OUTER_RIGHT)),
|
||||
GBlockstate.variant(double_outer_id, true, R0, R0))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, DOWN_SOUTH, STAIR_SHAPE, OUTER_RIGHT),
|
||||
GBlockstate.when(EDGE, WEST_DOWN, STAIR_SHAPE, OUTER_LEFT),
|
||||
GBlockstate.when(EDGE, SOUTH_WEST, STAIR_SHAPE, OUTER_RIGHT)),
|
||||
GBlockstate.variant(double_outer_id, true, R0, R90))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, NORTH_DOWN, STAIR_SHAPE, OUTER_RIGHT),
|
||||
GBlockstate.when(EDGE, WEST_DOWN, STAIR_SHAPE, OUTER_RIGHT),
|
||||
GBlockstate.when(EDGE, WEST_NORTH, STAIR_SHAPE, OUTER_RIGHT)),
|
||||
GBlockstate.variant(double_outer_id, true, R0, R180))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, NORTH_DOWN, STAIR_SHAPE, OUTER_LEFT),
|
||||
GBlockstate.when(EDGE, DOWN_EAST, STAIR_SHAPE, OUTER_RIGHT),
|
||||
GBlockstate.when(EDGE, NORTH_EAST, STAIR_SHAPE, OUTER_RIGHT)),
|
||||
GBlockstate.variant(double_outer_id, true, R0, R270))
|
||||
/* OUTER TOP */
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, UP_NORTH, STAIR_SHAPE, OUTER_LEFT),
|
||||
GBlockstate.when(EDGE, EAST_UP, STAIR_SHAPE, OUTER_RIGHT),
|
||||
GBlockstate.when(EDGE, NORTH_EAST, STAIR_SHAPE, OUTER_LEFT)),
|
||||
GBlockstate.variant(double_outer_id, true, R180, R0))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, SOUTH_UP, STAIR_SHAPE, OUTER_LEFT),
|
||||
GBlockstate.when(EDGE, EAST_UP, STAIR_SHAPE, OUTER_LEFT),
|
||||
GBlockstate.when(EDGE, EAST_SOUTH, STAIR_SHAPE, OUTER_LEFT)),
|
||||
GBlockstate.variant(double_outer_id, true, R180, R90))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, SOUTH_UP, STAIR_SHAPE, OUTER_RIGHT),
|
||||
GBlockstate.when(EDGE, UP_WEST, STAIR_SHAPE, OUTER_LEFT),
|
||||
GBlockstate.when(EDGE, SOUTH_WEST, STAIR_SHAPE, OUTER_LEFT)),
|
||||
GBlockstate.variant(double_outer_id, true, R180, R180))
|
||||
.with(When.anyOf(
|
||||
GBlockstate.when(EDGE, UP_NORTH, STAIR_SHAPE, OUTER_RIGHT),
|
||||
GBlockstate.when(EDGE, UP_WEST, STAIR_SHAPE, OUTER_RIGHT),
|
||||
GBlockstate.when(EDGE, WEST_NORTH, STAIR_SHAPE, OUTER_LEFT)),
|
||||
GBlockstate.variant(double_outer_id, true, R180, R270));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package fr.adrien1106.reframed.generator.block;
|
||||
|
||||
import fr.adrien1106.reframed.ReFramed;
|
||||
import fr.adrien1106.reframed.generator.BlockStateProvider;
|
||||
import fr.adrien1106.reframed.generator.RecipeSetter;
|
||||
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.data.client.MultipartBlockStateSupplier;
|
||||
import net.minecraft.data.server.recipe.RecipeExporter;
|
||||
import net.minecraft.data.server.recipe.RecipeProvider;
|
||||
import net.minecraft.data.server.recipe.ShapelessRecipeJsonBuilder;
|
||||
import net.minecraft.item.ItemConvertible;
|
||||
import net.minecraft.recipe.book.RecipeCategory;
|
||||
|
||||
public class StairsCube implements RecipeSetter, BlockStateProvider {
|
||||
|
||||
@Override
|
||||
public void setRecipe(RecipeExporter exporter, ItemConvertible convertible) {
|
||||
RecipeProvider.offerStonecuttingRecipe(exporter, RecipeCategory.BUILDING_BLOCKS, convertible, ReFramed.CUBE);
|
||||
ShapelessRecipeJsonBuilder
|
||||
.create(RecipeCategory.BUILDING_BLOCKS, convertible)
|
||||
.input(ReFramed.STAIR)
|
||||
.input(ReFramed.STEP)
|
||||
.criterion(FabricRecipeProvider.hasItem(ReFramed.CUBE), FabricRecipeProvider.conditionsFromItem(ReFramed.CUBE))
|
||||
.criterion(FabricRecipeProvider.hasItem(convertible), FabricRecipeProvider.conditionsFromItem(convertible))
|
||||
.offerTo(exporter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MultipartBlockStateSupplier getMultipart(Block block) {
|
||||
return Stair.getMultipart(block, true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package fr.adrien1106.reframed.generator.block;
|
||||
|
||||
import fr.adrien1106.reframed.ReFramed;
|
||||
import fr.adrien1106.reframed.generator.BlockStateProvider;
|
||||
import fr.adrien1106.reframed.generator.GBlockstate;
|
||||
import fr.adrien1106.reframed.generator.RecipeSetter;
|
||||
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.data.client.BlockStateSupplier;
|
||||
import net.minecraft.data.client.MultipartBlockStateSupplier;
|
||||
import net.minecraft.data.server.recipe.RecipeExporter;
|
||||
import net.minecraft.data.server.recipe.RecipeProvider;
|
||||
import net.minecraft.data.server.recipe.ShapedRecipeJsonBuilder;
|
||||
import net.minecraft.item.ItemConvertible;
|
||||
import net.minecraft.recipe.book.RecipeCategory;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import static fr.adrien1106.reframed.util.blocks.BlockProperties.EDGE;
|
||||
import static fr.adrien1106.reframed.util.blocks.Edge.*;
|
||||
import static fr.adrien1106.reframed.util.blocks.Edge.SOUTH_UP;
|
||||
import static net.minecraft.data.client.VariantSettings.Rotation.*;
|
||||
|
||||
public class Step implements RecipeSetter, BlockStateProvider {
|
||||
|
||||
@Override
|
||||
public void setRecipe(RecipeExporter exporter, ItemConvertible convertible) {
|
||||
RecipeProvider.offerStonecuttingRecipe(exporter, RecipeCategory.BUILDING_BLOCKS, convertible, ReFramed.CUBE, 4);
|
||||
ShapedRecipeJsonBuilder
|
||||
.create(RecipeCategory.BUILDING_BLOCKS, convertible, 8)
|
||||
.pattern("II")
|
||||
.input('I', ReFramed.CUBE)
|
||||
.criterion(FabricRecipeProvider.hasItem(ReFramed.CUBE), FabricRecipeProvider.conditionsFromItem(ReFramed.CUBE))
|
||||
.criterion(FabricRecipeProvider.hasItem(convertible), FabricRecipeProvider.conditionsFromItem(convertible))
|
||||
.offerTo(exporter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockStateSupplier getMultipart(Block block) {
|
||||
Identifier model_id = ReFramed.id("step_special");
|
||||
return MultipartBlockStateSupplier.create(block)
|
||||
/* X AXIS */
|
||||
.with(GBlockstate.when(EDGE, DOWN_EAST),
|
||||
GBlockstate.variant(model_id, true, R0, R0))
|
||||
.with(GBlockstate.when(EDGE, EAST_UP),
|
||||
GBlockstate.variant(model_id, true, R180, R0))
|
||||
.with(GBlockstate.when(EDGE, UP_WEST),
|
||||
GBlockstate.variant(model_id, true, R180, R180))
|
||||
.with(GBlockstate.when(EDGE, WEST_DOWN),
|
||||
GBlockstate.variant(model_id, true, R0, R180))
|
||||
/* Y AXIS */
|
||||
.with(GBlockstate.when(EDGE, EAST_SOUTH),
|
||||
GBlockstate.variant(model_id, true, R90, R0))
|
||||
.with(GBlockstate.when(EDGE, SOUTH_WEST),
|
||||
GBlockstate.variant(model_id, true, R90, R90))
|
||||
.with(GBlockstate.when(EDGE, WEST_NORTH),
|
||||
GBlockstate.variant(model_id, true, R90, R180))
|
||||
.with(GBlockstate.when(EDGE, NORTH_EAST),
|
||||
GBlockstate.variant(model_id, true, R90, R270))
|
||||
/* Z AXIS */
|
||||
.with(GBlockstate.when(EDGE, DOWN_SOUTH),
|
||||
GBlockstate.variant(model_id, true, R0, R90))
|
||||
.with(GBlockstate.when(EDGE, NORTH_DOWN),
|
||||
GBlockstate.variant(model_id, true, R0, R270))
|
||||
.with(GBlockstate.when(EDGE, UP_NORTH),
|
||||
GBlockstate.variant(model_id, true, R180, R270))
|
||||
.with(GBlockstate.when(EDGE, SOUTH_UP),
|
||||
GBlockstate.variant(model_id, true, R180, R90));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package fr.adrien1106.reframed.generator.block;
|
||||
|
||||
import fr.adrien1106.reframed.ReFramed;
|
||||
import fr.adrien1106.reframed.generator.BlockStateProvider;
|
||||
import fr.adrien1106.reframed.generator.GBlockstate;
|
||||
import fr.adrien1106.reframed.generator.RecipeSetter;
|
||||
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.data.client.MultipartBlockStateSupplier;
|
||||
import net.minecraft.data.server.recipe.RecipeExporter;
|
||||
import net.minecraft.data.server.recipe.RecipeProvider;
|
||||
import net.minecraft.data.server.recipe.ShapelessRecipeJsonBuilder;
|
||||
import net.minecraft.item.ItemConvertible;
|
||||
import net.minecraft.recipe.book.RecipeCategory;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.Direction;
|
||||
|
||||
import static net.minecraft.data.client.VariantSettings.Rotation.*;
|
||||
import static net.minecraft.data.client.VariantSettings.Rotation.R270;
|
||||
import static net.minecraft.state.property.Properties.AXIS;
|
||||
import static net.minecraft.state.property.Properties.FACING;
|
||||
|
||||
public class StepsSlab implements RecipeSetter, BlockStateProvider {
|
||||
|
||||
@Override
|
||||
public void setRecipe(RecipeExporter exporter, ItemConvertible convertible) {
|
||||
RecipeProvider.offerStonecuttingRecipe(exporter, RecipeCategory.BUILDING_BLOCKS, convertible, ReFramed.CUBE, 2);
|
||||
ShapelessRecipeJsonBuilder
|
||||
.create(RecipeCategory.BUILDING_BLOCKS, convertible)
|
||||
.input(ReFramed.STEP, 2)
|
||||
.criterion(FabricRecipeProvider.hasItem(ReFramed.CUBE), FabricRecipeProvider.conditionsFromItem(ReFramed.CUBE))
|
||||
.criterion(FabricRecipeProvider.hasItem(convertible), FabricRecipeProvider.conditionsFromItem(convertible))
|
||||
.offerTo(exporter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MultipartBlockStateSupplier getMultipart(Block block) {
|
||||
Identifier step_id = ReFramed.id("steps_slab_special");
|
||||
Identifier step_side_id = ReFramed.id("steps_slab_side_special");
|
||||
return MultipartBlockStateSupplier.create(block)
|
||||
.with(GBlockstate.when(FACING, Direction.DOWN, AXIS, Direction.Axis.X),
|
||||
GBlockstate.variant(step_id, true, R0, R180))
|
||||
.with(GBlockstate.when(FACING, Direction.DOWN, AXIS, Direction.Axis.Z),
|
||||
GBlockstate.variant(step_id, true, R0, R270))
|
||||
.with(GBlockstate.when(FACING, Direction.UP, AXIS, Direction.Axis.X),
|
||||
GBlockstate.variant(step_id, true, R180, R180))
|
||||
.with(GBlockstate.when(FACING, Direction.UP, AXIS, Direction.Axis.Z),
|
||||
GBlockstate.variant(step_id, true, R180, R270))
|
||||
.with(GBlockstate.when(FACING, Direction.EAST, AXIS, Direction.Axis.Z),
|
||||
GBlockstate.variant(step_side_id, true, R0, R0))
|
||||
.with(GBlockstate.when(FACING, Direction.EAST, AXIS, Direction.Axis.Y),
|
||||
GBlockstate.variant(step_side_id, true, R90, R0))
|
||||
.with(GBlockstate.when(FACING, Direction.SOUTH, AXIS, Direction.Axis.X),
|
||||
GBlockstate.variant(step_side_id, true, R180, R90))
|
||||
.with(GBlockstate.when(FACING, Direction.SOUTH, AXIS, Direction.Axis.Y),
|
||||
GBlockstate.variant(step_side_id, true, R90, R90))
|
||||
.with(GBlockstate.when(FACING, Direction.WEST, AXIS, Direction.Axis.Z),
|
||||
GBlockstate.variant(step_side_id, true, R180, R180))
|
||||
.with(GBlockstate.when(FACING, Direction.WEST, AXIS, Direction.Axis.Y),
|
||||
GBlockstate.variant(step_side_id, true, R90, R180))
|
||||
.with(GBlockstate.when(FACING, Direction.NORTH, AXIS, Direction.Axis.X),
|
||||
GBlockstate.variant(step_side_id, true, R0, R270))
|
||||
.with(GBlockstate.when(FACING, Direction.NORTH, AXIS, Direction.Axis.Y),
|
||||
GBlockstate.variant(step_side_id, true, R90, R270));
|
||||
}
|
||||
}
|
||||
788
src/main/java/fr/adrien1106/reframed/generator/block/Wall.java
Normal file
788
src/main/java/fr/adrien1106/reframed/generator/block/Wall.java
Normal file
@@ -0,0 +1,788 @@
|
||||
package fr.adrien1106.reframed.generator.block;
|
||||
|
||||
import fr.adrien1106.reframed.ReFramed;
|
||||
import fr.adrien1106.reframed.generator.BlockStateProvider;
|
||||
import fr.adrien1106.reframed.generator.GBlockstate;
|
||||
import fr.adrien1106.reframed.generator.RecipeSetter;
|
||||
import fr.adrien1106.reframed.generator.TagGetter;
|
||||
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.data.client.BlockStateSupplier;
|
||||
import net.minecraft.data.client.MultipartBlockStateSupplier;
|
||||
import net.minecraft.data.server.recipe.RecipeExporter;
|
||||
import net.minecraft.data.server.recipe.RecipeProvider;
|
||||
import net.minecraft.data.server.recipe.ShapedRecipeJsonBuilder;
|
||||
import net.minecraft.item.ItemConvertible;
|
||||
import net.minecraft.recipe.book.RecipeCategory;
|
||||
import net.minecraft.registry.tag.BlockTags;
|
||||
import net.minecraft.registry.tag.TagKey;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static net.minecraft.block.enums.WallShape.*;
|
||||
import static net.minecraft.data.client.VariantSettings.Rotation.*;
|
||||
import static net.minecraft.state.property.Properties.*;
|
||||
|
||||
public class Wall implements RecipeSetter, TagGetter, BlockStateProvider {
|
||||
|
||||
@Override
|
||||
public void setRecipe(RecipeExporter exporter, ItemConvertible convertible) {
|
||||
RecipeProvider.offerStonecuttingRecipe(exporter, RecipeCategory.BUILDING_BLOCKS, convertible, ReFramed.CUBE, 1);
|
||||
ShapedRecipeJsonBuilder
|
||||
.create(RecipeCategory.BUILDING_BLOCKS, convertible, 4)
|
||||
.pattern("III")
|
||||
.pattern("III")
|
||||
.input('I', ReFramed.CUBE)
|
||||
.criterion(FabricRecipeProvider.hasItem(ReFramed.CUBE), FabricRecipeProvider.conditionsFromItem(ReFramed.CUBE))
|
||||
.criterion(FabricRecipeProvider.hasItem(convertible), FabricRecipeProvider.conditionsFromItem(convertible))
|
||||
.offerTo(exporter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TagKey<Block>> getTags() {
|
||||
return List.of(BlockTags.WALLS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockStateSupplier getMultipart(Block block) {
|
||||
Identifier
|
||||
side_low = ReFramed.id("wall_side_low_special"),
|
||||
side_tall = ReFramed.id("wall_side_tall_special"),
|
||||
pillar_low = ReFramed.id("wall_pillar_low_special"),
|
||||
pillar_tall = ReFramed.id("wall_pillar_tall_special"),
|
||||
pillar_none = ReFramed.id("wall_pillar_none_special"),
|
||||
low_e = ReFramed.id("wall_low_e_special"),
|
||||
tall_e = ReFramed.id("wall_tall_e_special"),
|
||||
low_i = ReFramed.id("wall_low_i_special"),
|
||||
tall_i = ReFramed.id("wall_tall_i_special"),
|
||||
low_tall_i = ReFramed.id("wall_low_tall_i_special"),
|
||||
low_c = ReFramed.id("wall_low_c_special"),
|
||||
tall_c = ReFramed.id("wall_tall_c_special"),
|
||||
low_tall_c = ReFramed.id("wall_low_tall_c_special"),
|
||||
tall_low_c = ReFramed.id("wall_tall_low_c_special"),
|
||||
low_t = ReFramed.id("wall_low_t_special"),
|
||||
tall_t = ReFramed.id("wall_tall_t_special"),
|
||||
tall_low_c_t = ReFramed.id("wall_tall_low_c_t_special"),
|
||||
tall_i_low_t = ReFramed.id("wall_tall_i_low_t_special"),
|
||||
low_i_tall_t = ReFramed.id("wall_low_i_tall_t_special"),
|
||||
low_tall_c_t = ReFramed.id("wall_low_tall_c_t_special"),
|
||||
low_c_tall_t = ReFramed.id("wall_low_c_tall_t_special"),
|
||||
tall_c_low_t = ReFramed.id("wall_tall_c_low_t_special"),
|
||||
tall_i_low_i_x = ReFramed.id("wall_tall_i_low_i_x_special"),
|
||||
tall_low_t_x = ReFramed.id("wall_tall_low_t_x_special"),
|
||||
tall_c_low_c_x = ReFramed.id("wall_tall_c_low_c_x_special"),
|
||||
tall_t_low_x = ReFramed.id("wall_tall_t_low_x_special");
|
||||
return MultipartBlockStateSupplier.create(block)
|
||||
// PILLAR CORE
|
||||
.with(GBlockstate.when(UP, true),
|
||||
GBlockstate.variant(ReFramed.id("wall_core_special"), true, R0, R0))
|
||||
// LOW
|
||||
.with(GBlockstate.when(NORTH_WALL_SHAPE, LOW),
|
||||
GBlockstate.variant(side_low, true, R0, R0))
|
||||
.with(GBlockstate.when(EAST_WALL_SHAPE, LOW),
|
||||
GBlockstate.variant(side_low, true, R0, R90))
|
||||
.with(GBlockstate.when(SOUTH_WALL_SHAPE, LOW),
|
||||
GBlockstate.variant(side_low, true, R0, R180))
|
||||
.with(GBlockstate.when(WEST_WALL_SHAPE, LOW),
|
||||
GBlockstate.variant(side_low, true, R0, R270))
|
||||
// TALL
|
||||
.with(GBlockstate.when(NORTH_WALL_SHAPE, TALL),
|
||||
GBlockstate.variant(side_tall, true, R0, R0))
|
||||
.with(GBlockstate.when(EAST_WALL_SHAPE, TALL),
|
||||
GBlockstate.variant(side_tall, true, R0, R90))
|
||||
.with(GBlockstate.when(SOUTH_WALL_SHAPE, TALL),
|
||||
GBlockstate.variant(side_tall, true, R0, R180))
|
||||
.with(GBlockstate.when(WEST_WALL_SHAPE, TALL),
|
||||
GBlockstate.variant(side_tall, true, R0, R270))
|
||||
// PILLAR LOW
|
||||
.with(GBlockstate.when(NORTH_WALL_SHAPE, LOW, UP, true),
|
||||
GBlockstate.variant(pillar_low, true, R0, R0))
|
||||
.with(GBlockstate.when(EAST_WALL_SHAPE, LOW, UP, true),
|
||||
GBlockstate.variant(pillar_low, true, R0, R90))
|
||||
.with(GBlockstate.when(SOUTH_WALL_SHAPE, LOW, UP, true),
|
||||
GBlockstate.variant(pillar_low, true, R0, R180))
|
||||
.with(GBlockstate.when(WEST_WALL_SHAPE, LOW, UP, true),
|
||||
GBlockstate.variant(pillar_low, true, R0, R270))
|
||||
// PILLAR TALL
|
||||
.with(GBlockstate.when(NORTH_WALL_SHAPE, TALL, UP, true),
|
||||
GBlockstate.variant(pillar_tall, true, R0, R0))
|
||||
.with(GBlockstate.when(EAST_WALL_SHAPE, TALL, UP, true),
|
||||
GBlockstate.variant(pillar_tall, true, R0, R90))
|
||||
.with(GBlockstate.when(SOUTH_WALL_SHAPE, TALL, UP, true),
|
||||
GBlockstate.variant(pillar_tall, true, R0, R180))
|
||||
.with(GBlockstate.when(WEST_WALL_SHAPE, TALL, UP, true),
|
||||
GBlockstate.variant(pillar_tall, true, R0, R270))
|
||||
// PILLAR NONE
|
||||
.with(GBlockstate.when(NORTH_WALL_SHAPE, NONE, UP, true),
|
||||
GBlockstate.variant(pillar_none, true, R0, R0))
|
||||
.with(GBlockstate.when(EAST_WALL_SHAPE, NONE, UP, true),
|
||||
GBlockstate.variant(pillar_none, true, R0, R90))
|
||||
.with(GBlockstate.when(SOUTH_WALL_SHAPE, NONE, UP, true),
|
||||
GBlockstate.variant(pillar_none, true, R0, R180))
|
||||
.with(GBlockstate.when(WEST_WALL_SHAPE, NONE, UP, true),
|
||||
GBlockstate.variant(pillar_none, true, R0, R270))
|
||||
// JUNCTION LOW
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, LOW,
|
||||
EAST_WALL_SHAPE, NONE,
|
||||
SOUTH_WALL_SHAPE, NONE,
|
||||
WEST_WALL_SHAPE, NONE,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(low_e, true, R0, R0))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, NONE,
|
||||
EAST_WALL_SHAPE, LOW,
|
||||
SOUTH_WALL_SHAPE, NONE,
|
||||
WEST_WALL_SHAPE, NONE,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(low_e, true, R0, R90))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, NONE,
|
||||
EAST_WALL_SHAPE, NONE,
|
||||
SOUTH_WALL_SHAPE, LOW,
|
||||
WEST_WALL_SHAPE, NONE,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(low_e, true, R0, R180))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, NONE,
|
||||
EAST_WALL_SHAPE, NONE,
|
||||
SOUTH_WALL_SHAPE, NONE,
|
||||
WEST_WALL_SHAPE, LOW,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(low_e, true, R0, R270))
|
||||
// JUNCTION TALL
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, TALL,
|
||||
EAST_WALL_SHAPE, NONE,
|
||||
SOUTH_WALL_SHAPE, NONE,
|
||||
WEST_WALL_SHAPE, NONE,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(tall_e, true, R0, R0))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, NONE,
|
||||
EAST_WALL_SHAPE, TALL,
|
||||
SOUTH_WALL_SHAPE, NONE,
|
||||
WEST_WALL_SHAPE, NONE,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(tall_e, true, R0, R90))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, NONE,
|
||||
EAST_WALL_SHAPE, NONE,
|
||||
SOUTH_WALL_SHAPE, TALL,
|
||||
WEST_WALL_SHAPE, NONE,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(tall_e, true, R0, R180))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, NONE,
|
||||
EAST_WALL_SHAPE, NONE,
|
||||
SOUTH_WALL_SHAPE, NONE,
|
||||
WEST_WALL_SHAPE, TALL,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(tall_e, true, R0, R270))
|
||||
// JUNCTION LOW I
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, LOW,
|
||||
EAST_WALL_SHAPE, NONE,
|
||||
SOUTH_WALL_SHAPE, LOW,
|
||||
WEST_WALL_SHAPE, NONE,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(low_i, true, R0, R0))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, NONE,
|
||||
EAST_WALL_SHAPE, LOW,
|
||||
SOUTH_WALL_SHAPE, NONE,
|
||||
WEST_WALL_SHAPE, LOW,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(low_i, true, R0, R90))
|
||||
// JUNCTION TALL I
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, TALL,
|
||||
EAST_WALL_SHAPE, NONE,
|
||||
SOUTH_WALL_SHAPE, TALL,
|
||||
WEST_WALL_SHAPE, NONE,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(tall_i, true, R0, R0))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, NONE,
|
||||
EAST_WALL_SHAPE, TALL,
|
||||
SOUTH_WALL_SHAPE, NONE,
|
||||
WEST_WALL_SHAPE, TALL,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(tall_i, true, R0, R90))
|
||||
// JUNCTION LOW TALL I
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, LOW,
|
||||
EAST_WALL_SHAPE, NONE,
|
||||
SOUTH_WALL_SHAPE, TALL,
|
||||
WEST_WALL_SHAPE, NONE,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(low_tall_i, true, R0, R0))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, NONE,
|
||||
EAST_WALL_SHAPE, LOW,
|
||||
SOUTH_WALL_SHAPE, NONE,
|
||||
WEST_WALL_SHAPE, TALL,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(low_tall_i, true, R0, R90))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, TALL,
|
||||
EAST_WALL_SHAPE, NONE,
|
||||
SOUTH_WALL_SHAPE, LOW,
|
||||
WEST_WALL_SHAPE, NONE,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(low_tall_i, true, R0, R180))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, NONE,
|
||||
EAST_WALL_SHAPE, TALL,
|
||||
SOUTH_WALL_SHAPE, NONE,
|
||||
WEST_WALL_SHAPE, LOW,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(low_tall_i, true, R0, R270))
|
||||
// JUNCTION LOW C
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, LOW,
|
||||
EAST_WALL_SHAPE, NONE,
|
||||
SOUTH_WALL_SHAPE, NONE,
|
||||
WEST_WALL_SHAPE, LOW,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(low_c, true, R0, R0))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, LOW,
|
||||
EAST_WALL_SHAPE, LOW,
|
||||
SOUTH_WALL_SHAPE, NONE,
|
||||
WEST_WALL_SHAPE, NONE,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(low_c, true, R0, R90))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, NONE,
|
||||
EAST_WALL_SHAPE, LOW,
|
||||
SOUTH_WALL_SHAPE, LOW,
|
||||
WEST_WALL_SHAPE, NONE,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(low_c, true, R0, R180))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, NONE,
|
||||
EAST_WALL_SHAPE, NONE,
|
||||
SOUTH_WALL_SHAPE, LOW,
|
||||
WEST_WALL_SHAPE, LOW,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(low_c, true, R0, R270))
|
||||
// JUNCTION TALL C
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, TALL,
|
||||
EAST_WALL_SHAPE, NONE,
|
||||
SOUTH_WALL_SHAPE, NONE,
|
||||
WEST_WALL_SHAPE, TALL,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(tall_c, true, R0, R0))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, TALL,
|
||||
EAST_WALL_SHAPE, TALL,
|
||||
SOUTH_WALL_SHAPE, NONE,
|
||||
WEST_WALL_SHAPE, NONE,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(tall_c, true, R0, R90))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, NONE,
|
||||
EAST_WALL_SHAPE, TALL,
|
||||
SOUTH_WALL_SHAPE, TALL,
|
||||
WEST_WALL_SHAPE, NONE,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(tall_c, true, R0, R180))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, NONE,
|
||||
EAST_WALL_SHAPE, NONE,
|
||||
SOUTH_WALL_SHAPE, TALL,
|
||||
WEST_WALL_SHAPE, TALL,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(tall_c, true, R0, R270))
|
||||
// JUNCTION LOW TALL C
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, LOW,
|
||||
EAST_WALL_SHAPE, NONE,
|
||||
SOUTH_WALL_SHAPE, NONE,
|
||||
WEST_WALL_SHAPE, TALL,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(low_tall_c, true, R0, R0))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, TALL,
|
||||
EAST_WALL_SHAPE, LOW,
|
||||
SOUTH_WALL_SHAPE, NONE,
|
||||
WEST_WALL_SHAPE, NONE,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(low_tall_c, true, R0, R90))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, NONE,
|
||||
EAST_WALL_SHAPE, TALL,
|
||||
SOUTH_WALL_SHAPE, LOW,
|
||||
WEST_WALL_SHAPE, NONE,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(low_tall_c, true, R0, R180))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, NONE,
|
||||
EAST_WALL_SHAPE, NONE,
|
||||
SOUTH_WALL_SHAPE, TALL,
|
||||
WEST_WALL_SHAPE, LOW,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(low_tall_c, true, R0, R270))
|
||||
// JUNCTION TALL LOW C
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, TALL,
|
||||
EAST_WALL_SHAPE, NONE,
|
||||
SOUTH_WALL_SHAPE, NONE,
|
||||
WEST_WALL_SHAPE, LOW,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(tall_low_c, true, R0, R0))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, LOW,
|
||||
EAST_WALL_SHAPE, TALL,
|
||||
SOUTH_WALL_SHAPE, NONE,
|
||||
WEST_WALL_SHAPE, NONE,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(tall_low_c, true, R0, R90))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, NONE,
|
||||
EAST_WALL_SHAPE, LOW,
|
||||
SOUTH_WALL_SHAPE, TALL,
|
||||
WEST_WALL_SHAPE, NONE,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(tall_low_c, true, R0, R180))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, NONE,
|
||||
EAST_WALL_SHAPE, NONE,
|
||||
SOUTH_WALL_SHAPE, LOW,
|
||||
WEST_WALL_SHAPE, TALL,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(tall_low_c, true, R0, R270))
|
||||
// JUNCTION LOW T
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, LOW,
|
||||
EAST_WALL_SHAPE, LOW,
|
||||
SOUTH_WALL_SHAPE, NONE,
|
||||
WEST_WALL_SHAPE, LOW,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(low_t, true, R0, R0))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, LOW,
|
||||
EAST_WALL_SHAPE, LOW,
|
||||
SOUTH_WALL_SHAPE, LOW,
|
||||
WEST_WALL_SHAPE, NONE,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(low_t, true, R0, R90))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, NONE,
|
||||
EAST_WALL_SHAPE, LOW,
|
||||
SOUTH_WALL_SHAPE, LOW,
|
||||
WEST_WALL_SHAPE, LOW,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(low_t, true, R0, R180))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, LOW,
|
||||
EAST_WALL_SHAPE, NONE,
|
||||
SOUTH_WALL_SHAPE, LOW,
|
||||
WEST_WALL_SHAPE, LOW,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(low_t, true, R0, R270))
|
||||
// JUNCTION TALL T
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, TALL,
|
||||
EAST_WALL_SHAPE, TALL,
|
||||
SOUTH_WALL_SHAPE, NONE,
|
||||
WEST_WALL_SHAPE, TALL,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(tall_t, true, R0, R0))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, TALL,
|
||||
EAST_WALL_SHAPE, TALL,
|
||||
SOUTH_WALL_SHAPE, TALL,
|
||||
WEST_WALL_SHAPE, NONE,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(tall_t, true, R0, R90))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, NONE,
|
||||
EAST_WALL_SHAPE, TALL,
|
||||
SOUTH_WALL_SHAPE, TALL,
|
||||
WEST_WALL_SHAPE, TALL,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(tall_t, true, R0, R180))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, TALL,
|
||||
EAST_WALL_SHAPE, NONE,
|
||||
SOUTH_WALL_SHAPE, TALL,
|
||||
WEST_WALL_SHAPE, TALL,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(tall_t, true, R0, R270))
|
||||
// JUNCTION TALL LOW C T
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, LOW,
|
||||
EAST_WALL_SHAPE, TALL,
|
||||
SOUTH_WALL_SHAPE, NONE,
|
||||
WEST_WALL_SHAPE, LOW,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(tall_low_c_t, true, R0, R0))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, LOW,
|
||||
EAST_WALL_SHAPE, LOW,
|
||||
SOUTH_WALL_SHAPE, TALL,
|
||||
WEST_WALL_SHAPE, NONE,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(tall_low_c_t, true, R0, R90))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, NONE,
|
||||
EAST_WALL_SHAPE, LOW,
|
||||
SOUTH_WALL_SHAPE, LOW,
|
||||
WEST_WALL_SHAPE, TALL,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(tall_low_c_t, true, R0, R180))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, TALL,
|
||||
EAST_WALL_SHAPE, NONE,
|
||||
SOUTH_WALL_SHAPE, LOW,
|
||||
WEST_WALL_SHAPE, LOW,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(tall_low_c_t, true, R0, R270))
|
||||
// JUNCTION TALL I LOW T
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, LOW,
|
||||
EAST_WALL_SHAPE, TALL,
|
||||
SOUTH_WALL_SHAPE, NONE,
|
||||
WEST_WALL_SHAPE, TALL,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(tall_i_low_t, true, R0, R0))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, TALL,
|
||||
EAST_WALL_SHAPE, LOW,
|
||||
SOUTH_WALL_SHAPE, TALL,
|
||||
WEST_WALL_SHAPE, NONE,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(tall_i_low_t, true, R0, R90))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, NONE,
|
||||
EAST_WALL_SHAPE, TALL,
|
||||
SOUTH_WALL_SHAPE, LOW,
|
||||
WEST_WALL_SHAPE, TALL,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(tall_i_low_t, true, R0, R180))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, TALL,
|
||||
EAST_WALL_SHAPE, NONE,
|
||||
SOUTH_WALL_SHAPE, TALL,
|
||||
WEST_WALL_SHAPE, LOW,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(tall_i_low_t, true, R0, R270))
|
||||
// JUNCTION LOW I TALL T
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, TALL,
|
||||
EAST_WALL_SHAPE, LOW,
|
||||
SOUTH_WALL_SHAPE, NONE,
|
||||
WEST_WALL_SHAPE, LOW,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(low_i_tall_t, true, R0, R0))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, LOW,
|
||||
EAST_WALL_SHAPE, TALL,
|
||||
SOUTH_WALL_SHAPE, LOW,
|
||||
WEST_WALL_SHAPE, NONE,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(low_i_tall_t, true, R0, R90))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, NONE,
|
||||
EAST_WALL_SHAPE, LOW,
|
||||
SOUTH_WALL_SHAPE, TALL,
|
||||
WEST_WALL_SHAPE, LOW,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(low_i_tall_t, true, R0, R180))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, LOW,
|
||||
EAST_WALL_SHAPE, NONE,
|
||||
SOUTH_WALL_SHAPE, LOW,
|
||||
WEST_WALL_SHAPE, TALL,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(low_i_tall_t, true, R0, R270))
|
||||
// JUNCTION LOW TALL C T
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, TALL,
|
||||
EAST_WALL_SHAPE, LOW,
|
||||
SOUTH_WALL_SHAPE, NONE,
|
||||
WEST_WALL_SHAPE, TALL,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(low_tall_c_t, true, R0, R0))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, TALL,
|
||||
EAST_WALL_SHAPE, TALL,
|
||||
SOUTH_WALL_SHAPE, LOW,
|
||||
WEST_WALL_SHAPE, NONE,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(low_tall_c_t, true, R0, R90))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, NONE,
|
||||
EAST_WALL_SHAPE, TALL,
|
||||
SOUTH_WALL_SHAPE, TALL,
|
||||
WEST_WALL_SHAPE, LOW,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(low_tall_c_t, true, R0, R180))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, LOW,
|
||||
EAST_WALL_SHAPE, NONE,
|
||||
SOUTH_WALL_SHAPE, TALL,
|
||||
WEST_WALL_SHAPE, TALL,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(low_tall_c_t, true, R0, R270))
|
||||
// JUNCTION LOW C TALL T
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, LOW,
|
||||
EAST_WALL_SHAPE, LOW,
|
||||
SOUTH_WALL_SHAPE, NONE,
|
||||
WEST_WALL_SHAPE, TALL,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(low_c_tall_t, true, R0, R0))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, TALL,
|
||||
EAST_WALL_SHAPE, LOW,
|
||||
SOUTH_WALL_SHAPE, LOW,
|
||||
WEST_WALL_SHAPE, NONE,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(low_c_tall_t, true, R0, R90))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, NONE,
|
||||
EAST_WALL_SHAPE, TALL,
|
||||
SOUTH_WALL_SHAPE, LOW,
|
||||
WEST_WALL_SHAPE, LOW,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(low_c_tall_t, true, R0, R180))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, LOW,
|
||||
EAST_WALL_SHAPE, NONE,
|
||||
SOUTH_WALL_SHAPE, TALL,
|
||||
WEST_WALL_SHAPE, LOW,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(low_c_tall_t, true, R0, R270))
|
||||
// JUNCTION TALL C LOW T
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, TALL,
|
||||
EAST_WALL_SHAPE, TALL,
|
||||
SOUTH_WALL_SHAPE, NONE,
|
||||
WEST_WALL_SHAPE, LOW,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(tall_c_low_t, true, R0, R0))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, LOW,
|
||||
EAST_WALL_SHAPE, TALL,
|
||||
SOUTH_WALL_SHAPE, TALL,
|
||||
WEST_WALL_SHAPE, NONE,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(tall_c_low_t, true, R0, R90))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, NONE,
|
||||
EAST_WALL_SHAPE, LOW,
|
||||
SOUTH_WALL_SHAPE, TALL,
|
||||
WEST_WALL_SHAPE, TALL,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(tall_c_low_t, true, R0, R180))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, TALL,
|
||||
EAST_WALL_SHAPE, NONE,
|
||||
SOUTH_WALL_SHAPE, LOW,
|
||||
WEST_WALL_SHAPE, TALL,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(tall_c_low_t, true, R0, R270))
|
||||
// JUNCTION X
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, LOW,
|
||||
EAST_WALL_SHAPE, LOW,
|
||||
SOUTH_WALL_SHAPE, LOW,
|
||||
WEST_WALL_SHAPE, LOW,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(ReFramed.id("wall_low_x_special"), true, R0, R0))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, TALL,
|
||||
EAST_WALL_SHAPE, TALL,
|
||||
SOUTH_WALL_SHAPE, TALL,
|
||||
WEST_WALL_SHAPE, TALL,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(ReFramed.id("wall_tall_x_special"), true, R0, R0))
|
||||
// JUNCTION I X
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, LOW,
|
||||
EAST_WALL_SHAPE, TALL,
|
||||
SOUTH_WALL_SHAPE, LOW,
|
||||
WEST_WALL_SHAPE, TALL,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(tall_i_low_i_x, true, R0, R0))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, TALL,
|
||||
EAST_WALL_SHAPE, LOW,
|
||||
SOUTH_WALL_SHAPE, TALL,
|
||||
WEST_WALL_SHAPE, LOW,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(tall_i_low_i_x, true, R0, R90))
|
||||
// JUNCTION TALL LOW T X
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, LOW,
|
||||
EAST_WALL_SHAPE, TALL,
|
||||
SOUTH_WALL_SHAPE, LOW,
|
||||
WEST_WALL_SHAPE, LOW,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(tall_low_t_x, true, R0, R0))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, LOW,
|
||||
EAST_WALL_SHAPE, LOW,
|
||||
SOUTH_WALL_SHAPE, TALL,
|
||||
WEST_WALL_SHAPE, LOW,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(tall_low_t_x, true, R0, R90))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, LOW,
|
||||
EAST_WALL_SHAPE, LOW,
|
||||
SOUTH_WALL_SHAPE, LOW,
|
||||
WEST_WALL_SHAPE, TALL,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(tall_low_t_x, true, R0, R180))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, TALL,
|
||||
EAST_WALL_SHAPE, LOW,
|
||||
SOUTH_WALL_SHAPE, LOW,
|
||||
WEST_WALL_SHAPE, LOW,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(tall_low_t_x, true, R0, R270))
|
||||
// JUNCTION TALL C LOW C X
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, TALL,
|
||||
EAST_WALL_SHAPE, TALL,
|
||||
SOUTH_WALL_SHAPE, LOW,
|
||||
WEST_WALL_SHAPE, LOW,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(tall_c_low_c_x, true, R0, R0))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, LOW,
|
||||
EAST_WALL_SHAPE, TALL,
|
||||
SOUTH_WALL_SHAPE, TALL,
|
||||
WEST_WALL_SHAPE, LOW,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(tall_c_low_c_x, true, R0, R90))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, LOW,
|
||||
EAST_WALL_SHAPE, LOW,
|
||||
SOUTH_WALL_SHAPE, TALL,
|
||||
WEST_WALL_SHAPE, TALL,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(tall_c_low_c_x, true, R0, R180))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, TALL,
|
||||
EAST_WALL_SHAPE, LOW,
|
||||
SOUTH_WALL_SHAPE, LOW,
|
||||
WEST_WALL_SHAPE, TALL,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(tall_c_low_c_x, true, R0, R270))
|
||||
// JUNCTION TALL C LOW C X
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, TALL,
|
||||
EAST_WALL_SHAPE, TALL,
|
||||
SOUTH_WALL_SHAPE, LOW,
|
||||
WEST_WALL_SHAPE, TALL,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(tall_t_low_x, true, R0, R0))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, TALL,
|
||||
EAST_WALL_SHAPE, TALL,
|
||||
SOUTH_WALL_SHAPE, TALL,
|
||||
WEST_WALL_SHAPE, LOW,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(tall_t_low_x, true, R0, R90))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, LOW,
|
||||
EAST_WALL_SHAPE, TALL,
|
||||
SOUTH_WALL_SHAPE, TALL,
|
||||
WEST_WALL_SHAPE, TALL,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(tall_t_low_x, true, R0, R180))
|
||||
.with(GBlockstate.when(
|
||||
NORTH_WALL_SHAPE, TALL,
|
||||
EAST_WALL_SHAPE, LOW,
|
||||
SOUTH_WALL_SHAPE, TALL,
|
||||
WEST_WALL_SHAPE, TALL,
|
||||
UP, false
|
||||
),
|
||||
GBlockstate.variant(tall_t_low_x, true, R0, R270));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package fr.adrien1106.reframed.generator.item;
|
||||
|
||||
import fr.adrien1106.reframed.generator.RecipeSetter;
|
||||
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
|
||||
import net.minecraft.data.server.recipe.RecipeExporter;
|
||||
import net.minecraft.data.server.recipe.ShapedRecipeJsonBuilder;
|
||||
import net.minecraft.item.ItemConvertible;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.recipe.book.RecipeCategory;
|
||||
|
||||
public class Blueprint implements RecipeSetter {
|
||||
|
||||
@Override
|
||||
public void setRecipe(RecipeExporter exporter, ItemConvertible convertible) {
|
||||
ShapedRecipeJsonBuilder
|
||||
.create(RecipeCategory.TOOLS, convertible, 3)
|
||||
.pattern("PI")
|
||||
.pattern("PP")
|
||||
.input('P', Items.PAPER)
|
||||
.input('I', Items.INK_SAC)
|
||||
.criterion(FabricRecipeProvider.hasItem(Items.PAPER), FabricRecipeProvider.conditionsFromItem(Items.PAPER))
|
||||
.criterion(FabricRecipeProvider.hasItem(convertible), FabricRecipeProvider.conditionsFromItem(convertible))
|
||||
.offerTo(exporter);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package fr.adrien1106.reframed.generator.item;
|
||||
|
||||
import fr.adrien1106.reframed.ReFramed;
|
||||
import fr.adrien1106.reframed.generator.RecipeSetter;
|
||||
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
|
||||
import net.minecraft.data.server.recipe.RecipeExporter;
|
||||
import net.minecraft.data.server.recipe.ShapedRecipeJsonBuilder;
|
||||
import net.minecraft.item.ItemConvertible;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.recipe.book.RecipeCategory;
|
||||
|
||||
public class Hammer implements RecipeSetter {
|
||||
|
||||
@Override
|
||||
public void setRecipe(RecipeExporter exporter, ItemConvertible convertible) {
|
||||
ShapedRecipeJsonBuilder
|
||||
.create(RecipeCategory.TOOLS, convertible)
|
||||
.pattern(" CI")
|
||||
.pattern(" ~C")
|
||||
.pattern("~ ")
|
||||
.input('I', Items.IRON_INGOT)
|
||||
.input('C', ReFramed.CUBE)
|
||||
.input('~', Items.STICK)
|
||||
.criterion(FabricRecipeProvider.hasItem(ReFramed.CUBE), FabricRecipeProvider.conditionsFromItem(ReFramed.CUBE))
|
||||
.criterion(FabricRecipeProvider.hasItem(convertible), FabricRecipeProvider.conditionsFromItem(convertible))
|
||||
.offerTo(exporter);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package fr.adrien1106.reframed.generator.item;
|
||||
|
||||
import fr.adrien1106.reframed.ReFramed;
|
||||
import fr.adrien1106.reframed.generator.RecipeSetter;
|
||||
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
|
||||
import net.minecraft.data.server.recipe.RecipeExporter;
|
||||
import net.minecraft.data.server.recipe.ShapedRecipeJsonBuilder;
|
||||
import net.minecraft.item.ItemConvertible;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.recipe.book.RecipeCategory;
|
||||
|
||||
public class Screwdriver implements RecipeSetter {
|
||||
|
||||
@Override
|
||||
public void setRecipe(RecipeExporter exporter, ItemConvertible convertible) {
|
||||
ShapedRecipeJsonBuilder
|
||||
.create(RecipeCategory.TOOLS, convertible)
|
||||
.pattern(" I")
|
||||
.pattern(" I ")
|
||||
.pattern("C ")
|
||||
.input('I', Items.IRON_INGOT)
|
||||
.input('C', ReFramed.CUBE)
|
||||
.criterion(FabricRecipeProvider.hasItem(ReFramed.CUBE), FabricRecipeProvider.conditionsFromItem(ReFramed.CUBE))
|
||||
.criterion(FabricRecipeProvider.hasItem(convertible), FabricRecipeProvider.conditionsFromItem(convertible))
|
||||
.offerTo(exporter);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package fr.adrien1106.reframed.item;
|
||||
|
||||
import fr.adrien1106.reframed.ReFramed;
|
||||
import fr.adrien1106.reframed.block.ReFramedEntity;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.ItemUsageContext;
|
||||
import net.minecraft.sound.SoundCategory;
|
||||
import net.minecraft.sound.SoundEvents;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class ReFramedBlueprintItem extends Item {
|
||||
public ReFramedBlueprintItem(Settings settings) {
|
||||
super(settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionResult useOnBlock(ItemUsageContext context) {
|
||||
BlockPos pos = context.getBlockPos();
|
||||
World world = context.getWorld();
|
||||
if (!(world.getBlockEntity(pos) instanceof ReFramedEntity frame_entity)
|
||||
|| frame_entity.getThemes().stream().noneMatch(state -> state.getBlock() != Blocks.AIR)
|
||||
) return ActionResult.PASS;
|
||||
|
||||
context.getStack().decrement(1);
|
||||
ItemStack stack = ReFramed.BLUEPRINT_WRITTEN.getDefaultStack();
|
||||
frame_entity.setStackNbt(stack);
|
||||
context.getPlayer().giveItemStack(stack);
|
||||
world.playSound(context.getPlayer(), context.getPlayer().getBlockPos(), SoundEvents.ITEM_BOOK_PUT, SoundCategory.PLAYERS);
|
||||
|
||||
return ActionResult.SUCCESS;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
package fr.adrien1106.reframed.item;
|
||||
|
||||
import fr.adrien1106.reframed.ReFramed;
|
||||
import fr.adrien1106.reframed.block.ReFramedEntity;
|
||||
import net.minecraft.block.AbstractBlock;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.client.item.TooltipContext;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.item.BlockItem;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.ItemUsageContext;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.nbt.NbtHelper;
|
||||
import net.minecraft.registry.Registries;
|
||||
import net.minecraft.sound.SoundCategory;
|
||||
import net.minecraft.sound.SoundEvents;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.Formatting;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.TypedActionResult;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static fr.adrien1106.reframed.block.ReFramedEntity.BLOCKSTATE_KEY;
|
||||
|
||||
public class ReFramedBlueprintWrittenItem extends Item {
|
||||
public ReFramedBlueprintWrittenItem(Settings settings) {
|
||||
super(settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypedActionResult<ItemStack> use(World world, PlayerEntity player, Hand hand) {
|
||||
ItemStack stack = player.getStackInHand(hand);
|
||||
if (!player.isSneaking() || !stack.hasNbt()) return super.use(world, player, hand);
|
||||
stack.decrement(1);
|
||||
player.giveItemStack(ReFramed.BLUEPRINT.getDefaultStack());
|
||||
world.playSound(player, player.getBlockPos(), SoundEvents.ITEM_BOOK_PUT, SoundCategory.PLAYERS);
|
||||
|
||||
return TypedActionResult.success(stack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionResult useOnBlock(ItemUsageContext context) {
|
||||
BlockPos pos = context.getBlockPos();
|
||||
World world = context.getWorld();
|
||||
if (!(world.getBlockEntity(pos) instanceof ReFramedEntity frame_entity)
|
||||
|| frame_entity.getThemes().stream().anyMatch(state -> state.getBlock() != Blocks.AIR)
|
||||
|| !context.getStack().hasNbt()
|
||||
) return ActionResult.PASS;
|
||||
|
||||
NbtCompound tag = BlockItem.getBlockEntityNbt(context.getStack());
|
||||
if(tag == null) return ActionResult.FAIL;
|
||||
|
||||
PlayerEntity player = context.getPlayer();
|
||||
if (!player.isCreative()) { // verify player has blocks and remove them
|
||||
PlayerInventory inventory = player.getInventory();
|
||||
List<ItemStack> stacks = getBlockStates(tag).values().stream()
|
||||
.map(AbstractBlock.AbstractBlockState::getBlock)
|
||||
.map(Block::asItem)
|
||||
.map(Item::getDefaultStack)
|
||||
.toList();
|
||||
if (stacks.stream().anyMatch(stack -> !inventory.contains(stack)))
|
||||
return ActionResult.FAIL;
|
||||
stacks.stream().map(inventory::getSlotWithStack).forEach(index -> inventory.removeStack(index, 1));
|
||||
player.playSound(SoundEvents.ENTITY_ITEM_PICKUP, 0.5f, 0.5f);
|
||||
}
|
||||
frame_entity.readNbt(tag);
|
||||
world.playSound(player, player.getBlockPos(), SoundEvents.ITEM_BOOK_PAGE_TURN, SoundCategory.PLAYERS);
|
||||
|
||||
return ActionResult.SUCCESS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendTooltip(ItemStack stack, @Nullable World world, List<Text> tooltip, TooltipContext context) {
|
||||
NbtCompound tag = BlockItem.getBlockEntityNbt(stack);
|
||||
if(tag == null) return;
|
||||
|
||||
Map<Integer, BlockState> states = getBlockStates(tag);
|
||||
states.forEach((index, state) -> tooltip.add(
|
||||
Text.literal("Theme " + index + ": ")
|
||||
.append(
|
||||
Text.translatable(state.getBlock().getTranslationKey())
|
||||
.formatted(Formatting.GRAY)
|
||||
)
|
||||
));
|
||||
super.appendTooltip(stack, world, tooltip, context);
|
||||
}
|
||||
|
||||
private static Map<Integer, BlockState> getBlockStates(NbtCompound tag) {
|
||||
return tag.getKeys().stream()
|
||||
.filter(key ->
|
||||
key.startsWith(BLOCKSTATE_KEY)
|
||||
&& key.replace(BLOCKSTATE_KEY,"").chars().allMatch(Character::isDigit)
|
||||
)
|
||||
.collect(Collectors.toMap(
|
||||
key -> Integer.parseInt(key.substring(BLOCKSTATE_KEY.length())),
|
||||
key -> NbtHelper.toBlockState(
|
||||
Registries.BLOCK.getReadOnlyWrapper(),
|
||||
tag.getCompound(key)
|
||||
)
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package fr.adrien1106.reframed.item;
|
||||
|
||||
import fr.adrien1106.reframed.ReFramed;
|
||||
import fr.adrien1106.reframed.block.ReFramedDoubleBlock;
|
||||
import fr.adrien1106.reframed.util.blocks.ThemeableBlockEntity;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.ItemUsageContext;
|
||||
import net.minecraft.sound.SoundCategory;
|
||||
import net.minecraft.sound.SoundEvents;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class ReFramedHammerItem extends Item {
|
||||
public ReFramedHammerItem(Settings settings) {
|
||||
super(settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionResult useOnBlock(ItemUsageContext context) {
|
||||
World world = context.getWorld();
|
||||
BlockPos pos = context.getBlockPos();
|
||||
if (!(world.getBlockEntity(pos) instanceof ThemeableBlockEntity frame_entity)) return ActionResult.PASS;
|
||||
BlockState state = world.getBlockState(pos);
|
||||
PlayerEntity player = context.getPlayer();
|
||||
int theme_index = state.getBlock() instanceof ReFramedDoubleBlock b
|
||||
? b.getHitShape(
|
||||
state,
|
||||
context.getHitPos(),
|
||||
context.getBlockPos(),
|
||||
context.getSide()
|
||||
)
|
||||
: 1;
|
||||
|
||||
if (frame_entity.getTheme(theme_index).getBlock() == Blocks.AIR) return ActionResult.PASS;
|
||||
|
||||
if (!player.isCreative()) {
|
||||
player.giveItemStack(new ItemStack(frame_entity.getTheme(theme_index).getBlock()));
|
||||
world.playSound(player, pos, SoundEvents.ENTITY_ITEM_PICKUP, SoundCategory.BLOCKS, 1f, 1.1f);
|
||||
}
|
||||
frame_entity.setTheme(Blocks.AIR.getDefaultState(), theme_index);
|
||||
ReFramed.chunkRerenderProxy.accept(world, pos);
|
||||
return ActionResult.SUCCESS;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package fr.adrien1106.reframed.item;
|
||||
|
||||
import fr.adrien1106.reframed.ReFramed;
|
||||
import fr.adrien1106.reframed.block.ReFramedDoubleBlock;
|
||||
import fr.adrien1106.reframed.util.blocks.ThemeableBlockEntity;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemUsageContext;
|
||||
import net.minecraft.sound.BlockSoundGroup;
|
||||
import net.minecraft.sound.SoundCategory;
|
||||
import net.minecraft.state.property.Properties;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class ReFramedScrewdriverItem extends Item {
|
||||
|
||||
public ReFramedScrewdriverItem(Settings settings) {
|
||||
super(settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionResult useOnBlock(ItemUsageContext context) {
|
||||
World world = context.getWorld();
|
||||
BlockPos pos = context.getBlockPos();
|
||||
if (!(world.getBlockEntity(pos) instanceof ThemeableBlockEntity frame_entity)) return ActionResult.PASS;
|
||||
BlockState state = world.getBlockState(pos);
|
||||
PlayerEntity player = context.getPlayer();
|
||||
int theme_index = state.getBlock() instanceof ReFramedDoubleBlock b
|
||||
? b.getHitShape(
|
||||
state,
|
||||
context.getHitPos(),
|
||||
context.getBlockPos(),
|
||||
context.getSide()
|
||||
)
|
||||
: 1;
|
||||
|
||||
|
||||
BlockState theme = frame_entity.getTheme(theme_index);
|
||||
if (!theme.contains(Properties.AXIS)) return ActionResult.PASS;
|
||||
|
||||
Direction.Axis axis = theme.get(Properties.AXIS);
|
||||
BlockSoundGroup group = theme.getSoundGroup();
|
||||
world.playSound(player, pos, group.getPlaceSound(), SoundCategory.BLOCKS, group.getVolume(), group.getPitch());
|
||||
frame_entity.setTheme(theme.with(
|
||||
Properties.AXIS,
|
||||
switch (axis) {
|
||||
case X -> Direction.Axis.Y;
|
||||
case Y -> Direction.Axis.Z;
|
||||
case Z -> Direction.Axis.X;
|
||||
}
|
||||
), theme_index);
|
||||
ReFramed.chunkRerenderProxy.accept(world, pos);
|
||||
return ActionResult.SUCCESS;
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import org.slf4j.LoggerFactory;
|
||||
import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
|
||||
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@@ -16,24 +17,27 @@ public class CompatMixinPlugin implements IMixinConfigPlugin {
|
||||
|
||||
private static final FabricLoader LOADER = FabricLoader.getInstance();
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger("ReFramed MIXIN");
|
||||
private static final List<String> COMPAT_MOD = List.of("athena", "indium", "sodium");
|
||||
private static final Map<String, Supplier<Boolean>> CONDITIONS = Map.of(
|
||||
"fr.adrien1106.reframed.mixin.compat.AthenaBakedModelMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(0)),
|
||||
"fr.adrien1106.reframed.mixin.compat.AthenaWrappedGetterMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(0)),
|
||||
"fr.adrien1106.reframed.mixin.render.TerrainRenderContextMixin", () -> !LOADER.isModLoaded(COMPAT_MOD.get(1)),
|
||||
"fr.adrien1106.reframed.mixin.render.BlockRenderInfoMixin", () -> !LOADER.isModLoaded(COMPAT_MOD.get(1)),
|
||||
"fr.adrien1106.reframed.mixin.render.AbstractBlockRenderContextMixin", () -> !LOADER.isModLoaded(COMPAT_MOD.get(1)),
|
||||
"fr.adrien1106.reframed.mixin.compat.IndiumTerrainRenderContextMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(1)),
|
||||
"fr.adrien1106.reframed.mixin.compat.IndiumTerrainBlockRenderInfoMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(1)),
|
||||
"fr.adrien1106.reframed.mixin.compat.IndiumAbstractBlockRenderContextMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(1)),
|
||||
"fr.adrien1106.reframed.mixin.compat.SodiumBlockOcclusionCacheMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(2))
|
||||
);
|
||||
private static final List<String> COMPAT_MOD = List.of("athena", "indium", "sodium", "special-model-loader", "continuity");
|
||||
private static final Map<String, Supplier<Boolean>> CONDITIONS = new HashMap<>();
|
||||
static {
|
||||
CONDITIONS.put("fr.adrien1106.reframed.mixin.compat.AthenaBakedModelMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(0)));
|
||||
CONDITIONS.put("fr.adrien1106.reframed.mixin.compat.AthenaWrappedGetterMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(0)));
|
||||
CONDITIONS.put("fr.adrien1106.reframed.mixin.render.TerrainRenderContextMixin", () -> !LOADER.isModLoaded(COMPAT_MOD.get(1)));
|
||||
CONDITIONS.put("fr.adrien1106.reframed.mixin.render.BlockRenderInfoMixin", () -> !LOADER.isModLoaded(COMPAT_MOD.get(1)));
|
||||
CONDITIONS.put("fr.adrien1106.reframed.mixin.render.AbstractBlockRenderContextMixin", () -> !LOADER.isModLoaded(COMPAT_MOD.get(1)));
|
||||
CONDITIONS.put("fr.adrien1106.reframed.mixin.compat.IndiumTerrainRenderContextMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(1)));
|
||||
CONDITIONS.put("fr.adrien1106.reframed.mixin.compat.IndiumTerrainBlockRenderInfoMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(1)));
|
||||
CONDITIONS.put("fr.adrien1106.reframed.mixin.compat.IndiumAbstractBlockRenderContextMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(1)));
|
||||
CONDITIONS.put("fr.adrien1106.reframed.mixin.compat.SodiumBlockOcclusionCacheMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(2)));
|
||||
CONDITIONS.put("fr.adrien1106.reframed.mixin.compat.ContinuityConnectionPredicateMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(4)));
|
||||
CONDITIONS.put("fr.adrien1106.reframed.mixin.compat.ContinuityCTMBakedModelMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(4)));
|
||||
CONDITIONS.put("fr.adrien1106.reframed.mixin.compat.ContinuityCTMQuadTransformMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(4)));
|
||||
CONDITIONS.put("fr.adrien1106.reframed.mixin.compat.ContinuityModelWrappingHandlerMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(4)));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onLoad(String mixin_package) {
|
||||
|
||||
}
|
||||
public void onLoad(String mixin_package) {}
|
||||
|
||||
@Override
|
||||
public String getRefMapperConfig() {
|
||||
@@ -46,9 +50,7 @@ public class CompatMixinPlugin implements IMixinConfigPlugin {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptTargets(Set<String> mine, Set<String> others) {
|
||||
|
||||
}
|
||||
public void acceptTargets(Set<String> mine, Set<String> others) {}
|
||||
|
||||
@Override
|
||||
public List<String> getMixins() {
|
||||
@@ -56,9 +58,7 @@ public class CompatMixinPlugin implements IMixinConfigPlugin {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preApply(String target_class_name, ClassNode target_class, String mixin_class_name, IMixinInfo mixin_info) {
|
||||
|
||||
}
|
||||
public void preApply(String target_class_name, ClassNode target_class, String mixin_class_name, IMixinInfo mixin_info) {}
|
||||
|
||||
@Override
|
||||
public void postApply(String target_class, ClassNode target, String mixin_class, IMixinInfo mixin_info) {
|
||||
|
||||
@@ -5,7 +5,7 @@ import earth.terrarium.athena.api.client.fabric.WrappedGetter;
|
||||
import earth.terrarium.athena.api.client.models.AthenaBlockModel;
|
||||
import fr.adrien1106.reframed.client.ReFramedClient;
|
||||
import fr.adrien1106.reframed.client.model.DynamicBakedModel;
|
||||
import fr.adrien1106.reframed.compat.RebakedAthenaModel;
|
||||
import fr.adrien1106.reframed.compat.RebakedModel;
|
||||
import fr.adrien1106.reframed.util.blocks.ThemeableBlockEntity;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import net.fabricmc.fabric.api.renderer.v1.Renderer;
|
||||
@@ -18,6 +18,7 @@ import net.minecraft.client.texture.Sprite;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.world.BlockRenderView;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
@@ -35,27 +36,27 @@ public abstract class AthenaBakedModelMixin implements DynamicBakedModel, BakedM
|
||||
* Reuses the emitQuad method to compute the quads to be used by the frame
|
||||
*
|
||||
* @param level - the world
|
||||
* @param state - the current block camo
|
||||
* @param origin_state - the current block camo
|
||||
* @param pos - the block position
|
||||
* @return - the rebakedmodel containing the computed quads
|
||||
*/
|
||||
@Override
|
||||
public BakedModel computeQuads(BlockRenderView level, BlockState state, BlockPos pos, int theme_index) {
|
||||
public BakedModel computeQuads(@Nullable BlockRenderView level, BlockState origin_state, @Nullable BlockPos pos, int theme_index) {
|
||||
Map<Direction, List<BakedQuad>> face_quads = new HashMap<>();
|
||||
Renderer r = ReFramedClient.HELPER.getFabricRenderer();
|
||||
QuadEmitter emitter = r.meshBuilder().getEmitter();
|
||||
|
||||
WrappedGetter getter = new WrappedGetter(level);
|
||||
BlockState state = level != null && pos != null
|
||||
&& level.getBlockEntity(pos) instanceof ThemeableBlockEntity framed_entity
|
||||
? framed_entity.getTheme(theme_index)
|
||||
: origin_state;
|
||||
Arrays.stream(Direction.values()).forEach(direction -> {
|
||||
face_quads.put(direction, new ArrayList<>());
|
||||
|
||||
(level == null || pos == null
|
||||
? model.getDefaultQuads(direction).get(direction)
|
||||
: model.getQuads(
|
||||
getter,
|
||||
level.getBlockEntity(pos) instanceof ThemeableBlockEntity framed_entity
|
||||
? framed_entity.getTheme(theme_index)
|
||||
: state, pos, direction)
|
||||
: model.getQuads(getter, state, pos, direction)
|
||||
).forEach(sprite -> face_quads.computeIfPresent(direction, (d, quads) -> {
|
||||
Sprite texture = textures.get(sprite.sprite());
|
||||
if (texture == null) return quads;
|
||||
@@ -76,6 +77,6 @@ public abstract class AthenaBakedModelMixin implements DynamicBakedModel, BakedM
|
||||
}));
|
||||
});
|
||||
|
||||
return new RebakedAthenaModel(face_quads);
|
||||
return new RebakedModel(face_quads);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,10 +13,13 @@ import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
@Mixin(WrappedGetter.class)
|
||||
public class AthenaWrappedGetterMixin {
|
||||
|
||||
@Redirect(method = "query",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/world/BlockRenderView;" +
|
||||
"getBlockState(Lnet/minecraft/util/math/BlockPos;)" +
|
||||
"Lnet/minecraft/block/BlockState;"))
|
||||
@Redirect(
|
||||
method = "query",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/world/BlockRenderView;getBlockState(Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/block/BlockState;"
|
||||
)
|
||||
) // TODO better connected textures
|
||||
private BlockState queryCamoState(BlockRenderView world, BlockPos pos, @Local(argsOnly = true) BlockState reference_state) {
|
||||
// get Any that will connect or return any other (/!\ isOf is an uncertain check)
|
||||
if (world.getBlockEntity(pos) instanceof ThemeableBlockEntity framed_entity)
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
package fr.adrien1106.reframed.mixin.compat;
|
||||
|
||||
import fr.adrien1106.reframed.client.ReFramedClient;
|
||||
import fr.adrien1106.reframed.client.model.DynamicBakedModel;
|
||||
import fr.adrien1106.reframed.compat.ICTMQuadTransform;
|
||||
import fr.adrien1106.reframed.compat.RebakedModel;
|
||||
import fr.adrien1106.reframed.util.blocks.ThemeableBlockEntity;
|
||||
import me.pepperbell.continuity.client.config.ContinuityConfig;
|
||||
import me.pepperbell.continuity.client.model.CTMBakedModel;
|
||||
import me.pepperbell.continuity.client.model.ModelObjectsContainer;
|
||||
import me.pepperbell.continuity.client.model.QuadProcessors;
|
||||
import me.pepperbell.continuity.client.util.RenderUtil;
|
||||
import net.fabricmc.fabric.api.renderer.v1.Renderer;
|
||||
import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter;
|
||||
import net.fabricmc.fabric.api.renderer.v1.model.ForwardingBakedModel;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.render.model.BakedModel;
|
||||
import net.minecraft.client.render.model.BakedQuad;
|
||||
import net.minecraft.client.texture.Sprite;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.random.Random;
|
||||
import net.minecraft.world.BlockRenderView;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@Mixin(CTMBakedModel.class)
|
||||
public abstract class ContinuityCTMBakedModelMixin extends ForwardingBakedModel implements DynamicBakedModel {
|
||||
|
||||
@Shadow protected abstract Function<Sprite, QuadProcessors.Slice> getSliceFunc(BlockState state);
|
||||
|
||||
@Override
|
||||
public BakedModel computeQuads(@Nullable BlockRenderView level, BlockState origin_state, @Nullable BlockPos pos, int theme_index) {
|
||||
if (wrapped instanceof DynamicBakedModel wrapped_dynamic) // support wrap of dynamic models
|
||||
return wrapped_dynamic.computeQuads(level, origin_state, pos, theme_index);
|
||||
|
||||
|
||||
ModelObjectsContainer container = ModelObjectsContainer.get();
|
||||
// normally baked model / wrapped or feature disabled or item (i.e. no need to compute quads)
|
||||
if (level == null || pos == null
|
||||
|| !ContinuityConfig.INSTANCE.connectedTextures.get()
|
||||
|| !container.featureStates.getConnectedTexturesState().isEnabled()
|
||||
) return wrapped;
|
||||
|
||||
Map<Direction, List<BakedQuad>> face_quads = new HashMap<>();
|
||||
|
||||
Renderer r = ReFramedClient.HELPER.getFabricRenderer();
|
||||
QuadEmitter emitter = r.meshBuilder().getEmitter();
|
||||
|
||||
// get applicable state
|
||||
BlockState state = level.getBlockEntity(pos) instanceof ThemeableBlockEntity framed_entity
|
||||
? framed_entity.getTheme(theme_index)
|
||||
: origin_state;
|
||||
|
||||
// get random supplier
|
||||
Random random = Random.create();
|
||||
Supplier<Random> random_supplier = () -> {
|
||||
random.setSeed(state.getRenderingSeed(pos));
|
||||
return random;
|
||||
};
|
||||
|
||||
// get quad transform and prepare
|
||||
ICTMQuadTransform transform = ((ICTMQuadTransform) container.ctmQuadTransform);
|
||||
transform.invokePrepare(
|
||||
level,
|
||||
state,
|
||||
pos,
|
||||
random_supplier,
|
||||
ContinuityConfig.INSTANCE.useManualCulling.get(),
|
||||
getSliceFunc(state)
|
||||
);
|
||||
Arrays.stream(Direction.values()).forEach(direction -> {
|
||||
face_quads.put(direction, new ArrayList<>());
|
||||
|
||||
wrapped.getQuads(state, direction, random_supplier.get()).forEach(quad -> face_quads.computeIfPresent(direction, (d, quads) -> {
|
||||
emitter.fromVanilla(quad, emitter.material(), direction);
|
||||
transform.transform(emitter);
|
||||
quads.add(emitter.toBakedQuad(RenderUtil.getSpriteFinder().find(emitter)));
|
||||
return quads;
|
||||
}));
|
||||
// transform.getProcessingContext().getExtraQuadEmitter(); // TODO start here for overlay support
|
||||
});
|
||||
|
||||
transform.getProcessingContext().reset(); // reset instead of outputting to emitter
|
||||
transform.invokeReset();
|
||||
|
||||
return new RebakedModel(face_quads);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package fr.adrien1106.reframed.mixin.compat;
|
||||
|
||||
import fr.adrien1106.reframed.compat.ICTMQuadTransform;
|
||||
import fr.adrien1106.reframed.util.blocks.ThemeableBlockEntity;
|
||||
import me.pepperbell.continuity.client.model.CullingCache;
|
||||
import me.pepperbell.continuity.client.model.QuadProcessors;
|
||||
import me.pepperbell.continuity.impl.client.ProcessingContextImpl;
|
||||
import net.fabricmc.fabric.api.renderer.v1.mesh.QuadView;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.texture.Sprite;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.random.Random;
|
||||
import net.minecraft.world.BlockRenderView;
|
||||
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.Redirect;
|
||||
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@Mixin(targets = "me.pepperbell.continuity.client.model.CTMBakedModel$CTMQuadTransform")
|
||||
public abstract class ContinuityCTMQuadTransformMixin implements ICTMQuadTransform {
|
||||
@Shadow(remap = false) @Final protected ProcessingContextImpl processingContext;
|
||||
|
||||
@Shadow public abstract void prepare(BlockRenderView view, BlockState state, BlockPos pos, Supplier<Random> random, boolean manual_culling, Function<Sprite, QuadProcessors.Slice> slice);
|
||||
@Shadow(remap = false) public abstract void reset();
|
||||
|
||||
@Redirect(
|
||||
method = "transform",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lme/pepperbell/continuity/client/model/CullingCache;shouldCull(Lnet/fabricmc/fabric/api/renderer/v1/mesh/QuadView;Lnet/minecraft/world/BlockRenderView;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;)Z"
|
||||
)
|
||||
)
|
||||
private boolean camo_replacement(CullingCache cache, QuadView quad, BlockRenderView view, BlockPos pos, BlockState state) {
|
||||
if (view.getBlockEntity(pos) instanceof ThemeableBlockEntity) return false;
|
||||
return cache.shouldCull(quad, view, pos, state);
|
||||
}
|
||||
|
||||
// uses this because invoker did not want to work for some reason
|
||||
public void invokePrepare(BlockRenderView view, BlockState state, BlockPos pos, Supplier<Random> random, boolean manual_culling, Function<Sprite, QuadProcessors.Slice> slice) {
|
||||
prepare(view, state, pos, random, manual_culling, slice);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProcessingContextImpl getProcessingContext() {
|
||||
return processingContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invokeReset() {
|
||||
reset();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package fr.adrien1106.reframed.mixin.compat;
|
||||
|
||||
import com.llamalad7.mixinextras.sugar.Local;
|
||||
import fr.adrien1106.reframed.util.blocks.ThemeableBlockEntity;
|
||||
import me.pepperbell.continuity.client.processor.ConnectionPredicate;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.BlockRenderView;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
@Mixin(ConnectionPredicate.class)
|
||||
public interface ContinuityConnectionPredicateMixin {
|
||||
|
||||
@Redirect(
|
||||
method = "shouldConnect(Lnet/minecraft/world/BlockRenderView;Lnet/minecraft/block/BlockState;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/util/math/Direction;Lnet/minecraft/client/texture/Sprite;)Z",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/world/BlockRenderView;getBlockState(Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/block/BlockState;"
|
||||
)
|
||||
) // TODO better connected textures
|
||||
private BlockState getBlockState(BlockRenderView view, BlockPos pos, @Local(argsOnly = true) BlockState state) {
|
||||
if (!(view.getBlockEntity(pos) instanceof ThemeableBlockEntity frame_entity)) return view.getBlockState(pos);
|
||||
return frame_entity.getThemes()
|
||||
.stream()
|
||||
.filter(theme -> theme.getBlock() == state.getBlock())
|
||||
.findFirst()
|
||||
.orElse(frame_entity.getTheme(0));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package fr.adrien1106.reframed.mixin.compat;
|
||||
|
||||
import fr.adrien1106.reframed.block.ReFramedBlock;
|
||||
import me.pepperbell.continuity.client.resource.ModelWrappingHandler;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.registry.DefaultedRegistry;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
@Mixin(ModelWrappingHandler.class)
|
||||
public class ContinuityModelWrappingHandlerMixin {
|
||||
|
||||
@Redirect(
|
||||
method = "createBlockStateModelIdMap",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/registry/DefaultedRegistry;iterator()Ljava/util/Iterator;"
|
||||
)
|
||||
)
|
||||
private static Iterator<Block> filterFrames(DefaultedRegistry<Block> registry) {
|
||||
return registry
|
||||
.stream()
|
||||
.filter(block -> !(block instanceof ReFramedBlock))
|
||||
.iterator();
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package fr.adrien1106.reframed.mixin.compat;
|
||||
|
||||
import com.llamalad7.mixinextras.sugar.Local;
|
||||
import fr.adrien1106.reframed.util.blocks.BlockHelper;
|
||||
import fr.adrien1106.reframed.client.util.RenderHelper;
|
||||
import fr.adrien1106.reframed.util.mixin.IBlockRenderInfoMixin;
|
||||
import link.infra.indium.renderer.mesh.MutableQuadViewImpl;
|
||||
import link.infra.indium.renderer.render.AbstractBlockRenderContext;
|
||||
@@ -24,6 +24,6 @@ public abstract class IndiumAbstractBlockRenderContextMixin {
|
||||
private boolean shouldDrawInnerQuad(AbstractBlockRenderContext instance, Direction face, @Local(argsOnly = true) MutableQuadViewImpl quad) {
|
||||
if (face != null || quad.tag() == 0 || !(blockInfo instanceof IBlockRenderInfoMixin info) || info.getThemeIndex() == 0) return isFaceCulled(face);
|
||||
|
||||
return !BlockHelper.shouldDrawInnerFace(blockInfo.blockState, blockInfo.blockView, blockInfo.blockPos, quad.tag() >>> 8, info.getThemeIndex());
|
||||
return !RenderHelper.shouldDrawInnerFace(blockInfo.blockState, blockInfo.blockView, blockInfo.blockPos, quad.tag() >>> 8, info.getThemeIndex());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package fr.adrien1106.reframed.mixin.compat;
|
||||
|
||||
import fr.adrien1106.reframed.util.blocks.BlockHelper;
|
||||
import fr.adrien1106.reframed.client.util.RenderHelper;
|
||||
import fr.adrien1106.reframed.util.mixin.IBlockRenderInfoMixin;
|
||||
import fr.adrien1106.reframed.util.blocks.ThemeableBlockEntity;
|
||||
import link.infra.indium.renderer.render.BlockRenderInfo;
|
||||
@@ -32,7 +32,7 @@ public abstract class IndiumTerrainBlockRenderInfoMixin extends BlockRenderInfo
|
||||
if (!(view.getBlockEntity(pos) instanceof ThemeableBlockEntity
|
||||
|| view.getBlockEntity(other_pos) instanceof ThemeableBlockEntity))
|
||||
return instance.shouldDrawSide(state, view, pos, face);
|
||||
return BlockHelper.shouldDrawSide(state, view, pos, face, other_pos, theme_index);
|
||||
return RenderHelper.shouldDrawSide(state, view, pos, face, other_pos, theme_index);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package fr.adrien1106.reframed.mixin.compat;
|
||||
|
||||
import fr.adrien1106.reframed.client.model.MultiRetexturableModel;
|
||||
import fr.adrien1106.reframed.util.blocks.BlockHelper;
|
||||
import fr.adrien1106.reframed.client.util.RenderHelper;
|
||||
import fr.adrien1106.reframed.util.mixin.IBlockRenderInfoMixin;
|
||||
import fr.adrien1106.reframed.util.mixin.IMultipartBakedModelMixin;
|
||||
import link.infra.indium.renderer.render.AbstractBlockRenderContext;
|
||||
@@ -32,7 +32,7 @@ public abstract class IndiumTerrainRenderContextMixin extends AbstractBlockRende
|
||||
|| !(wrapped.getModel(ctx.state()) instanceof MultiRetexturableModel retexturing_model)) return;
|
||||
|
||||
List<ForwardingBakedModel> models = retexturing_model.models();
|
||||
BlockHelper.computeInnerCull(ctx.state(), models);
|
||||
RenderHelper.computeInnerCull(ctx.state(), models);
|
||||
int i = 0;
|
||||
for (BakedModel model : models) {
|
||||
i++;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package fr.adrien1106.reframed.mixin.compat;
|
||||
|
||||
import com.llamalad7.mixinextras.sugar.Local;
|
||||
import fr.adrien1106.reframed.util.blocks.BlockHelper;
|
||||
import fr.adrien1106.reframed.client.util.RenderHelper;
|
||||
import fr.adrien1106.reframed.util.blocks.ThemeableBlockEntity;
|
||||
import me.jellysquid.mods.sodium.client.render.chunk.compile.pipeline.BlockOcclusionCache;
|
||||
import net.minecraft.block.BlockState;
|
||||
@@ -19,12 +19,12 @@ public class SodiumBlockOcclusionCacheMixin {
|
||||
@Inject(
|
||||
method = "shouldDrawSide",
|
||||
at = @At(
|
||||
value = "INVOKE_ASSIGN",
|
||||
target = "Lnet/minecraft/world/BlockView;getBlockState(Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/block/BlockState;",
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/util/math/BlockPos$Mutable;set(III)Lnet/minecraft/util/math/BlockPos$Mutable;",
|
||||
shift = At.Shift.AFTER
|
||||
), cancellable = true)
|
||||
private void shouldDrawFrameNeighborSide(BlockState self_state, BlockView view, BlockPos self_pos, Direction face, CallbackInfoReturnable<Boolean> cir, @Local BlockPos.Mutable other_pos) {
|
||||
if (!(view.getBlockEntity(other_pos) instanceof ThemeableBlockEntity)) return;
|
||||
cir.setReturnValue(BlockHelper.shouldDrawSide(self_state, view, self_pos, face, other_pos, 0));
|
||||
cir.setReturnValue(RenderHelper.shouldDrawSide(self_state, view, self_pos, face, other_pos, 0));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
package fr.adrien1106.reframed.mixin.logic;
|
||||
|
||||
import fr.adrien1106.reframed.block.ReFramedBlock;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.item.BlockItem;
|
||||
import net.minecraft.item.ItemPlacementContext;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
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(BlockItem.class)
|
||||
public class BlockItemMixin {
|
||||
|
||||
@Unique private final ThreadLocal<BlockState> old_state = new ThreadLocal<>();
|
||||
@Unique private final ThreadLocal<BlockEntity> old_entity = new ThreadLocal<>();
|
||||
|
||||
@Redirect(
|
||||
method = "place(Lnet/minecraft/item/ItemPlacementContext;)Lnet/minecraft/util/ActionResult;",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/block/Block;onPlaced(Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;Lnet/minecraft/entity/LivingEntity;Lnet/minecraft/item/ItemStack;)V"
|
||||
)
|
||||
)
|
||||
private void placeMoreInfo(Block block, World world, BlockPos pos, BlockState state, LivingEntity placer, ItemStack itemStack) {
|
||||
if (!(block instanceof ReFramedBlock frame_block)) {
|
||||
block.onPlaced(world, pos, state, placer, itemStack);
|
||||
return;
|
||||
}
|
||||
frame_block.onPlaced(world, pos, state, placer, itemStack, old_state.get(), old_entity.get());
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "place(Lnet/minecraft/item/ItemPlacementContext;)Lnet/minecraft/util/ActionResult;",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/item/BlockItem;place(Lnet/minecraft/item/ItemPlacementContext;Lnet/minecraft/block/BlockState;)Z",
|
||||
shift = At.Shift.BEFORE
|
||||
)
|
||||
)
|
||||
private void savePreviousInfo(ItemPlacementContext context, CallbackInfoReturnable<ActionResult> cir) {
|
||||
World world = context.getWorld();
|
||||
BlockPos pos = context.getBlockPos();
|
||||
old_state.set(world.getBlockState(pos));
|
||||
old_entity.set(world.getBlockEntity(pos));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package fr.adrien1106.reframed.mixin.render;
|
||||
|
||||
import com.llamalad7.mixinextras.sugar.Local;
|
||||
import fr.adrien1106.reframed.util.blocks.BlockHelper;
|
||||
import fr.adrien1106.reframed.client.util.RenderHelper;
|
||||
import fr.adrien1106.reframed.util.mixin.IBlockRenderInfoMixin;
|
||||
import net.fabricmc.fabric.impl.client.indigo.renderer.mesh.MutableQuadViewImpl;
|
||||
import net.fabricmc.fabric.impl.client.indigo.renderer.render.AbstractBlockRenderContext;
|
||||
@@ -31,6 +31,6 @@ public abstract class AbstractBlockRenderContextMixin {
|
||||
private boolean shouldDrawInnerQuad(AbstractBlockRenderContext instance, Direction face, @Local(argsOnly = true) MutableQuadViewImpl quad) {
|
||||
if (face != null || quad.tag() == 0 || !(blockInfo instanceof IBlockRenderInfoMixin info) || info.getThemeIndex() == 0) return isFaceCulled(face);
|
||||
|
||||
return !BlockHelper.shouldDrawInnerFace(blockInfo.blockState, blockInfo.blockView, blockInfo.blockPos, quad.tag() >>> 8, info.getThemeIndex());
|
||||
return !RenderHelper.shouldDrawInnerFace(blockInfo.blockState, blockInfo.blockView, blockInfo.blockPos, quad.tag() >>> 8, info.getThemeIndex());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package fr.adrien1106.reframed.mixin.render;
|
||||
|
||||
import com.llamalad7.mixinextras.sugar.Local;
|
||||
import fr.adrien1106.reframed.util.blocks.BlockHelper;
|
||||
import fr.adrien1106.reframed.client.util.RenderHelper;
|
||||
import fr.adrien1106.reframed.util.mixin.IBlockRenderInfoMixin;
|
||||
import fr.adrien1106.reframed.util.blocks.ThemeableBlockEntity;
|
||||
import net.fabricmc.fabric.impl.client.indigo.renderer.render.BlockRenderInfo;
|
||||
@@ -37,7 +37,7 @@ public abstract class BlockRenderInfoMixin implements IBlockRenderInfoMixin {
|
||||
|
||||
@Redirect(method = "shouldDrawFace", at = @At(value = "INVOKE", target = "Lnet/minecraft/block/Block;shouldDrawSide(Lnet/minecraft/block/BlockState;Lnet/minecraft/world/BlockView;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/util/math/Direction;Lnet/minecraft/util/math/BlockPos;)Z"))
|
||||
private boolean shouldDrawAdjacentCamoSide(BlockState state, BlockView world, BlockPos pos, Direction side, BlockPos other_pos) {
|
||||
return BlockHelper.shouldDrawSide(state, world, pos, side, other_pos, theme_index);
|
||||
return RenderHelper.shouldDrawSide(state, world, pos, side, other_pos, theme_index);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package fr.adrien1106.reframed.mixin.render;
|
||||
|
||||
import fr.adrien1106.reframed.client.model.MultiRetexturableModel;
|
||||
import fr.adrien1106.reframed.util.blocks.BlockHelper;
|
||||
import fr.adrien1106.reframed.client.util.RenderHelper;
|
||||
import fr.adrien1106.reframed.util.mixin.IBlockRenderInfoMixin;
|
||||
import fr.adrien1106.reframed.util.mixin.IMultipartBakedModelMixin;
|
||||
import net.fabricmc.fabric.api.renderer.v1.model.ForwardingBakedModel;
|
||||
@@ -31,7 +31,7 @@ public abstract class TerrainRenderContextMixin extends AbstractBlockRenderConte
|
||||
|| !(wrapped.getModel(state) instanceof MultiRetexturableModel retexturing_model)) return;
|
||||
|
||||
List<ForwardingBakedModel> models = retexturing_model.models();
|
||||
BlockHelper.computeInnerCull(state, models);
|
||||
RenderHelper.computeInnerCull(state, models);
|
||||
int i = 0;
|
||||
for (BakedModel model : models) {
|
||||
i++;
|
||||
|
||||
@@ -1,19 +1,8 @@
|
||||
package fr.adrien1106.reframed.util.blocks;
|
||||
|
||||
import com.google.common.cache.Cache;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import fr.adrien1106.reframed.block.ReFramedBlock;
|
||||
import fr.adrien1106.reframed.block.ReFramedEntity;
|
||||
import fr.adrien1106.reframed.block.ReFramedStairBlock;
|
||||
import fr.adrien1106.reframed.block.ReFramedStairsCubeBlock;
|
||||
import fr.adrien1106.reframed.client.ReFramedClient;
|
||||
import fr.adrien1106.reframed.client.model.QuadPosBounds;
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.fabricmc.fabric.api.renderer.v1.Renderer;
|
||||
import net.fabricmc.fabric.api.renderer.v1.material.RenderMaterial;
|
||||
import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter;
|
||||
import net.fabricmc.fabric.api.renderer.v1.model.ForwardingBakedModel;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockEntityProvider;
|
||||
import net.minecraft.block.BlockState;
|
||||
@@ -25,33 +14,27 @@ import net.minecraft.sound.SoundEvents;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.Pair;
|
||||
import net.minecraft.util.function.BooleanBiFunction;
|
||||
import net.minecraft.util.hit.BlockHitResult;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.util.math.random.Random;
|
||||
import net.minecraft.util.shape.VoxelShape;
|
||||
import net.minecraft.util.shape.VoxelShapes;
|
||||
import net.minecraft.world.BlockRenderView;
|
||||
import net.minecraft.world.BlockView;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static fr.adrien1106.reframed.util.blocks.BlockProperties.EDGE;
|
||||
import static fr.adrien1106.reframed.util.blocks.BlockProperties.LIGHT;
|
||||
import static fr.adrien1106.reframed.util.blocks.StairShape.*;
|
||||
import static net.minecraft.util.shape.VoxelShapes.combine;
|
||||
|
||||
public class BlockHelper {
|
||||
|
||||
// self culling cache of the models not made thread local so that it is only computed once
|
||||
private static final Cache<CullElement, Integer[]> INNER_CULL_MAP = CacheBuilder.newBuilder().maximumSize(1024).build();
|
||||
private record CullElement(Block block, Object state_key, int model) {}
|
||||
|
||||
public static Corner getPlacementCorner(ItemPlacementContext ctx) {
|
||||
Direction side = ctx.getSide().getOpposite();
|
||||
Vec3d pos = getHitPos(ctx.getHitPos(), ctx.getBlockPos());
|
||||
@@ -147,14 +130,14 @@ public class BlockHelper {
|
||||
return shape;
|
||||
}
|
||||
|
||||
public static String getNeighborPos(Edge face, Direction direction, Boolean reverse, Direction reference, BlockView world, BlockPos pos) {
|
||||
public static String getNeighborPos(Edge edge, Direction direction, Boolean reverse, Direction reference, BlockView world, BlockPos pos) {
|
||||
BlockState block_state = world.getBlockState(
|
||||
pos.offset(reverse ? direction.getOpposite() : direction)
|
||||
);
|
||||
|
||||
if (isStair(block_state) && block_state.get(EDGE).hasDirection(reference)) {
|
||||
if (block_state.get(EDGE).hasDirection(face.getLeftDirection())) return "left";
|
||||
else if (block_state.get(EDGE).hasDirection(face.getRightDirection())) return "right";
|
||||
if (block_state.get(EDGE).hasDirection(edge.getLeftDirection())) return "left";
|
||||
else if (block_state.get(EDGE).hasDirection(edge.getRightDirection())) return "right";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
@@ -167,8 +150,8 @@ public class BlockHelper {
|
||||
public static ActionResult useCamo(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit, int theme_index) {
|
||||
if(!(world.getBlockEntity(pos) instanceof ReFramedEntity block_entity)) return ActionResult.PASS;
|
||||
|
||||
// Changing the theme
|
||||
ItemStack held = player.getStackInHand(hand);
|
||||
// Changing the theme
|
||||
if(held.getItem() instanceof BlockItem block_item && block_entity.getTheme(theme_index).getBlock() == Blocks.AIR) {
|
||||
Block block = block_item.getBlock();
|
||||
ItemPlacementContext ctx = new ItemPlacementContext(new ItemUsageContext(player, hand, hit));
|
||||
@@ -232,148 +215,6 @@ public class BlockHelper {
|
||||
return ActionResult.PASS;
|
||||
}
|
||||
|
||||
/**
|
||||
* compute which quad might cull with another model quad
|
||||
* @param state - the state of the model
|
||||
* @param models - list of models on the same block
|
||||
*/
|
||||
@Environment(EnvType.CLIENT)
|
||||
public static void computeInnerCull(BlockState state, List<ForwardingBakedModel> models) {
|
||||
if (!(state.getBlock() instanceof ReFramedBlock frame_block)) return;
|
||||
Object key = frame_block.getModelCacheKey(state);
|
||||
if (INNER_CULL_MAP.asMap().containsKey(new CullElement(frame_block, key, 1))) return;
|
||||
|
||||
Renderer r = ReFramedClient.HELPER.getFabricRenderer();
|
||||
QuadEmitter quad_emitter = r.meshBuilder().getEmitter();
|
||||
RenderMaterial material = r.materialFinder().clear().find();
|
||||
Random random = Random.create();
|
||||
|
||||
List<List<QuadPosBounds>> model_bounds = models.stream()
|
||||
.map(ForwardingBakedModel::getWrappedModel)
|
||||
.filter(Objects::nonNull)
|
||||
.map(wrapped -> wrapped.getQuads(state, null, random))
|
||||
.map(quads -> quads.stream().map(quad -> {
|
||||
quad_emitter.fromVanilla(quad, material, null);
|
||||
return QuadPosBounds.read(quad_emitter, false);
|
||||
}).toList()).toList();
|
||||
|
||||
Integer[] cull_array;
|
||||
for(int self_id = 1; self_id <= model_bounds.size(); self_id++) {
|
||||
List<QuadPosBounds> self_bounds = model_bounds.get(self_id - 1);
|
||||
cull_array = new Integer[self_bounds.size()];
|
||||
for (int self_quad = 0; self_quad < cull_array.length; self_quad++) {
|
||||
QuadPosBounds self_bound = self_bounds.get(self_quad);
|
||||
for(int other_id = 1; other_id <= model_bounds.size(); other_id++) {
|
||||
if (other_id == self_id) continue;
|
||||
if (model_bounds.get(other_id - 1).stream().anyMatch(other_bound -> other_bound.equals(self_bound))) {
|
||||
cull_array[self_quad] = other_id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
INNER_CULL_MAP.put(new CullElement(frame_block, key, self_id), cull_array);
|
||||
}
|
||||
}
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public static boolean shouldDrawInnerFace(BlockState state, BlockRenderView view, BlockPos pos, int quad_index, int theme_index) {
|
||||
if ( !(state.getBlock() instanceof ReFramedBlock frame_block)
|
||||
|| !(view.getBlockEntity(pos) instanceof ThemeableBlockEntity frame_entity)
|
||||
) return true;
|
||||
CullElement key = new CullElement(frame_block, frame_block.getModelCacheKey(state), theme_index);
|
||||
if (!INNER_CULL_MAP.asMap().containsKey(key)) return true;
|
||||
|
||||
// needs to be Integer object because array is initialized with null not 0
|
||||
Integer cull_theme = Objects.requireNonNull(INNER_CULL_MAP.getIfPresent(key))[quad_index];
|
||||
if (cull_theme == null) return true; // no culling possible
|
||||
|
||||
BlockState self_theme = frame_entity.getTheme(theme_index);
|
||||
BlockState other_theme = frame_entity.getTheme(cull_theme);
|
||||
|
||||
if (self_theme.isSideInvisible(other_theme, null)) return false;
|
||||
return !self_theme.isOpaque() || !other_theme.isOpaque();
|
||||
}
|
||||
|
||||
// Doing this method from scratch as it is simpler to do than injecting everywhere
|
||||
@Environment(EnvType.CLIENT)
|
||||
public static boolean shouldDrawSide(BlockState self_state, BlockView world, BlockPos pos, Direction side, BlockPos other_pos, int theme_index) {
|
||||
ThemeableBlockEntity self = world.getBlockEntity(pos) instanceof ThemeableBlockEntity e ? e : null;
|
||||
ThemeableBlockEntity other = world.getBlockEntity(other_pos) instanceof ThemeableBlockEntity e ? e : null;
|
||||
BlockState other_state = world.getBlockState(other_pos);
|
||||
|
||||
// normal behaviour
|
||||
if (self == null && other == null) return Block.shouldDrawSide(self_state, world, pos, side, other_pos);
|
||||
|
||||
// self is a normal Block
|
||||
if (self == null && other_state.getBlock() instanceof ReFramedBlock other_block) {
|
||||
VoxelShape self_shape = self_state.getCullingShape(world, pos);
|
||||
if (self_shape.isEmpty()) return true;
|
||||
|
||||
int i = 0;
|
||||
VoxelShape other_shape = VoxelShapes.empty();
|
||||
for (BlockState s: other.getThemes()) {
|
||||
i++;
|
||||
if (self_state.isSideInvisible(s, side) || s.isOpaque())
|
||||
other_shape = combine(
|
||||
other_shape,
|
||||
other_block
|
||||
.getShape(other_state, i)
|
||||
.getFace(side.getOpposite()),
|
||||
BooleanBiFunction.OR
|
||||
);
|
||||
}
|
||||
|
||||
// determine if side needs to be rendered
|
||||
return VoxelShapes.matchesAnywhere(self_shape, other_shape, BooleanBiFunction.ONLY_FIRST);
|
||||
}
|
||||
|
||||
BlockState self_theme = self.getTheme(theme_index);
|
||||
// other is normal Block
|
||||
if (other == null && self_state.getBlock() instanceof ReFramedBlock self_block) {
|
||||
// Transparent is simple if self and the neighbor are invisible don't render side (like default)
|
||||
if (self_theme.isSideInvisible(other_state, side)) return false;
|
||||
|
||||
// Opaque is also simple as each model are rendered one by one
|
||||
if (other_state.isOpaque()) {
|
||||
// no cache section :( because it differs between each instance of the frame
|
||||
VoxelShape self_shape = self_block.getShape(self_state, theme_index).getFace(side);
|
||||
if (self_shape.isEmpty()) return true;
|
||||
VoxelShape other_shape = other_state.getCullingFace(world, other_pos, side.getOpposite());
|
||||
|
||||
// determine if side needs to be rendered
|
||||
return VoxelShapes.matchesAnywhere(self_shape, other_shape, BooleanBiFunction.ONLY_FIRST);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Both are frames
|
||||
// here both are computed in the same zone as there will necessarily a shape comparison
|
||||
if (self_state.getBlock() instanceof ReFramedBlock self_block && other_state.getBlock() instanceof ReFramedBlock other_block) {
|
||||
VoxelShape self_shape = self_block.getShape(self_state, theme_index).getFace(side);
|
||||
if (self_shape.isEmpty()) return true;
|
||||
|
||||
int i = 0;
|
||||
VoxelShape other_shape = VoxelShapes.empty();
|
||||
for (BlockState s: other.getThemes()) {
|
||||
i++;
|
||||
if (self_theme.isSideInvisible(s, side) || s.isOpaque())
|
||||
other_shape = combine(
|
||||
other_shape,
|
||||
other_block
|
||||
.getShape(other_state, i)
|
||||
.getFace(side.getOpposite()),
|
||||
BooleanBiFunction.OR
|
||||
);
|
||||
}
|
||||
|
||||
// determine if side needs to be rendered
|
||||
return VoxelShapes.matchesAnywhere(self_shape, other_shape, BooleanBiFunction.ONLY_FIRST);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean cursorMatchesFace(VoxelShape shape, Vec3d pos) {
|
||||
Map<Direction.Axis, Double> axes = Arrays.stream(Direction.Axis.values())
|
||||
.collect(Collectors.toMap(
|
||||
|
||||
@@ -37,6 +37,18 @@ public enum Corner implements StringIdentifiable {
|
||||
return asString();
|
||||
}
|
||||
|
||||
public Direction getFirstDirection() {
|
||||
return first_direction;
|
||||
}
|
||||
|
||||
public Direction getSecondDirection() {
|
||||
return second_direction;
|
||||
}
|
||||
|
||||
public Direction getThirdDirection() {
|
||||
return third_direction;
|
||||
}
|
||||
|
||||
public boolean hasDirection(Direction direction) {
|
||||
return this.first_direction.equals(direction)
|
||||
|| this.second_direction.equals(direction)
|
||||
@@ -94,4 +106,17 @@ public enum Corner implements StringIdentifiable {
|
||||
Direction other_2 = second_direction == direction || first_direction == direction ? third_direction : second_direction;
|
||||
return getByDirections(direction, other_1.getOpposite(), other_2.getOpposite());
|
||||
}
|
||||
|
||||
public Edge getEdge(Direction direction) {
|
||||
return Edge.getByDirections(
|
||||
first_direction == direction ? second_direction : first_direction,
|
||||
second_direction == direction || first_direction == direction ? third_direction : second_direction
|
||||
);
|
||||
}
|
||||
|
||||
public Direction getOtherDirection(Edge edge) {
|
||||
if (edge.getFirstDirection() != second_direction && edge.getSecondDirection() != second_direction) return second_direction;
|
||||
if (edge.getFirstDirection() != third_direction && edge.getSecondDirection() != third_direction) return third_direction;
|
||||
return first_direction;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,18 +49,10 @@ public enum Edge implements StringIdentifiable {
|
||||
return second_direction;
|
||||
}
|
||||
public Direction getRightDirection() {
|
||||
return switch (axis) {
|
||||
case X -> Direction.WEST;
|
||||
case Y -> Direction.DOWN;
|
||||
case Z -> Direction.SOUTH;
|
||||
};
|
||||
return Direction.from(axis, Direction.AxisDirection.NEGATIVE);
|
||||
}
|
||||
public Direction getLeftDirection() {
|
||||
return switch (axis) {
|
||||
case X -> Direction.EAST;
|
||||
case Y -> Direction.UP;
|
||||
case Z -> Direction.NORTH;
|
||||
};
|
||||
return Direction.from(axis, Direction.AxisDirection.POSITIVE);
|
||||
}
|
||||
|
||||
public boolean hasDirection(Direction direction) {
|
||||
@@ -68,16 +60,32 @@ public enum Edge implements StringIdentifiable {
|
||||
|| this.second_direction.equals(direction);
|
||||
}
|
||||
|
||||
public Direction.Axis getAxis() {
|
||||
return this.axis;
|
||||
}
|
||||
|
||||
public int getID() {
|
||||
return this.ID;
|
||||
}
|
||||
|
||||
public Edge opposite() {
|
||||
return getByDirections(first_direction.getOpposite(), second_direction.getOpposite());
|
||||
}
|
||||
|
||||
public static Edge getByDirections(Direction direction_1, Direction direction_2) {
|
||||
return Arrays.stream(Edge.values())
|
||||
.filter(value -> value.hasDirection(direction_1) && value.hasDirection(direction_2))
|
||||
.findFirst().orElse(Edge.NORTH_DOWN);
|
||||
}
|
||||
|
||||
public boolean isSide(Direction side) {
|
||||
return getRightDirection() == side || getLeftDirection() == side;
|
||||
}
|
||||
|
||||
public Direction getOtherDirection(Direction direction) {
|
||||
return first_direction == direction ? second_direction : first_direction;
|
||||
}
|
||||
|
||||
public static Edge fromId(int id) {
|
||||
return Arrays.stream(Edge.values())
|
||||
.filter(value -> value.getID() == id)
|
||||
|
||||
21
src/main/resources/assets/reframed/models/block/pillar.json
Normal file
21
src/main/resources/assets/reframed/models/block/pillar.json
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"credit": "Made with Blockbench",
|
||||
"parent": "block/block",
|
||||
"textures": {
|
||||
"particle": "#side"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"from": [4, 0, 4],
|
||||
"to": [12, 16, 12],
|
||||
"faces": {
|
||||
"north": {"uv": [4, 0, 12, 16], "texture": "#side"},
|
||||
"east": {"uv": [4, 0, 12, 16], "texture": "#side"},
|
||||
"south": {"uv": [4, 0, 12, 16], "texture": "#side"},
|
||||
"west": {"uv": [4, 0, 12, 16], "texture": "#side"},
|
||||
"up": {"uv": [4, 4, 12, 12], "texture": "#top", "cullface": "up"},
|
||||
"down": {"uv": [4, 4, 12, 12], "texture": "#bottom", "cullface": "down"}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"credit": "Made with Blockbench",
|
||||
"parent": "block/block",
|
||||
"textures": {
|
||||
"particle": "#side"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"from": [4, 0, 4],
|
||||
"to": [5, 14, 5],
|
||||
"faces": {
|
||||
"north": {"uv": [11, 2, 12, 16], "texture": "#side"},
|
||||
"west": {"uv": [4, 2, 5, 16], "texture": "#side"},
|
||||
"down": {"uv": [4, 11, 5, 12], "texture": "#bottom", "cullface": "down"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [5, 0, 4],
|
||||
"to": [11, 14, 5],
|
||||
"faces": {
|
||||
"north": {"uv": [5, 2, 11, 16], "texture": "#side"},
|
||||
"down": {"uv": [5, 11, 11, 12], "texture": "#bottom", "cullface": "down"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [4, 14, 4],
|
||||
"to": [11, 16, 5],
|
||||
"faces": {
|
||||
"north": {"uv": [5, 0, 12, 2], "texture": "#side"},
|
||||
"west": {"uv": [4, 0, 5, 2], "texture": "#side"},
|
||||
"up": {"uv": [5, 4, 12, 5], "texture": "#top", "cullface": "up"}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"credit": "Made with Blockbench",
|
||||
"parent": "block/block",
|
||||
"textures": {
|
||||
"particle": "#side"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"from": [4, 0, 4],
|
||||
"to": [5, 16, 5],
|
||||
"faces": {
|
||||
"north": {"uv": [11, 0, 12, 16], "texture": "#side"},
|
||||
"west": {"uv": [4, 0, 5, 16], "texture": "#side"},
|
||||
"up": {"uv": [4, 4, 5, 5], "texture": "#top", "cullface": "up"},
|
||||
"down": {"uv": [4, 11, 5, 12], "texture": "#bottom", "cullface": "down"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [5, 0, 4],
|
||||
"to": [11, 16, 5],
|
||||
"faces": {
|
||||
"north": {"uv": [5, 0, 11, 16], "texture": "#side"},
|
||||
"up": {"uv": [5, 4, 11, 5], "texture": "#top", "cullface": "up"},
|
||||
"down": {"uv": [5, 11, 11, 12], "texture": "#bottom", "cullface": "down"}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"credit": "Made with Blockbench",
|
||||
"parent": "block/block",
|
||||
"textures": {
|
||||
"particle": "#side"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"from": [5, 0, 0],
|
||||
"to": [11, 14, 4],
|
||||
"faces": {
|
||||
"north": {"uv": [5, 2, 11, 16], "texture": "#side", "cullface": "north"},
|
||||
"east": {"uv": [12, 2, 16, 16], "texture": "#side"},
|
||||
"south": {"uv": [5, 2, 11, 16], "texture": "#side"},
|
||||
"west": {"uv": [0, 2, 4, 16], "texture": "#side"},
|
||||
"up": {"uv": [5, 0, 11, 4], "texture": "#top"},
|
||||
"down": {"uv": [5, 12, 11, 16], "texture": "#bottom", "cullface": "down"}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"credit": "Made with Blockbench",
|
||||
"parent": "block/block",
|
||||
"textures": {
|
||||
"particle": "#side"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"from": [5, 0, 0],
|
||||
"to": [11, 16, 4],
|
||||
"faces": {
|
||||
"north": {"uv": [5, 0, 11, 16], "texture": "#side", "cullface": "north"},
|
||||
"east": {"uv": [12, 0, 16, 16], "texture": "#side"},
|
||||
"south": {"uv": [5, 0, 11, 16], "texture": "#side"},
|
||||
"west": {"uv": [0, 0, 4, 16], "texture": "#side"},
|
||||
"up": {"uv": [5, 0, 11, 4], "texture": "#top", "cullface": "up"},
|
||||
"down": {"uv": [5, 12, 11, 16], "texture": "#bottom", "cullface": "down"}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"credit": "Made with Blockbench",
|
||||
"parent": "block/block",
|
||||
"textures": {
|
||||
"particle": "#side"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"from": [5, 0, 0],
|
||||
"to": [11, 14, 4],
|
||||
"faces": {
|
||||
"north": {"uv": [5, 2, 11, 16], "texture": "#side", "cullface": "north"},
|
||||
"east": {"uv": [12, 2, 16, 16], "texture": "#side"},
|
||||
"west": {"uv": [0, 2, 4, 16], "texture": "#side"},
|
||||
"up": {"uv": [5, 0, 11, 4], "texture": "#top"},
|
||||
"down": {"uv": [5, 12, 11, 16], "texture": "#bottom"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [5, 0, 12],
|
||||
"to": [11, 14, 16],
|
||||
"faces": {
|
||||
"east": {"uv": [0, 2, 4, 16], "texture": "#side"},
|
||||
"south": {"uv": [5, 2, 11, 16], "texture": "#side", "cullface": "south"},
|
||||
"west": {"uv": [12, 2, 16, 16], "texture": "#side"},
|
||||
"up": {"uv": [5, 12, 11, 16], "texture": "#top"},
|
||||
"down": {"uv": [5, 0, 11, 4], "texture": "#bottom"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [4, 0, 4],
|
||||
"to": [12, 16, 12],
|
||||
"faces": {
|
||||
"north": {"uv": [4, 0, 12, 16], "texture": "#side"},
|
||||
"east": {"uv": [4, 0, 12, 16], "texture": "#side"},
|
||||
"south": {"uv": [4, 0, 12, 16], "texture": "#side", "cullface": "south"},
|
||||
"west": {"uv": [4, 0, 12, 16], "texture": "#side"},
|
||||
"up": {"uv": [4, 4, 12, 12], "texture": "#top"},
|
||||
"down": {"uv": [4, 4, 12, 12], "texture": "#bottom"}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"credit": "Made with Blockbench",
|
||||
"parent": "block/block",
|
||||
"textures": {
|
||||
"particle": "#side"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"from": [5, 0, 4],
|
||||
"to": [11, 14, 8],
|
||||
"faces": {
|
||||
"east": {"uv": [8, 2, 12, 16], "texture": "#side"},
|
||||
"south": {"uv": [5, 2, 11, 16], "texture": "#side"},
|
||||
"west": {"uv": [4, 2, 8, 16], "texture": "#side"},
|
||||
"up": {"uv": [5, 4, 11, 8], "texture": "#top"},
|
||||
"down": {"uv": [5, 8, 11, 12], "texture": "#bottom", "cullface": "down"}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
{
|
||||
"credit": "Made with Blockbench",
|
||||
"parent": "block/block",
|
||||
"textures": {
|
||||
"particle": "#side"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"from": [5, 0, 4],
|
||||
"to": [11, 14, 5],
|
||||
"faces": {
|
||||
"east": {"uv": [11, 2, 12, 16], "texture": "#side"},
|
||||
"west": {"uv": [4, 2, 5, 16], "texture": "#side"},
|
||||
"up": {"uv": [5, 4, 11, 5], "texture": "#top"},
|
||||
"down": {"uv": [5, 11, 11, 12], "texture": "#bottom", "cullface": "down"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [8, 0, 5],
|
||||
"to": [11, 14, 8],
|
||||
"faces": {
|
||||
"east": {"uv": [8, 2, 11, 16], "texture": "#side"},
|
||||
"south": {"uv": [8, 2, 11, 16], "texture": "#side"},
|
||||
"up": {"uv": [8, 5, 11, 8], "texture": "#top"},
|
||||
"down": {"uv": [8, 8, 11, 11], "texture": "#bottom", "cullface": "down"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [5, 0, 8],
|
||||
"to": [8, 14, 11],
|
||||
"faces": {
|
||||
"east": {"uv": [5, 2, 8, 16], "texture": "#side"},
|
||||
"south": {"uv": [5, 2, 8, 16], "texture": "#side"},
|
||||
"up": {"uv": [5, 8, 8, 11], "texture": "#top"},
|
||||
"down": {"uv": [5, 5, 8, 8], "texture": "#bottom", "cullface": "down"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [5, 0, 5],
|
||||
"to": [8, 14, 8],
|
||||
"faces": {
|
||||
"up": {"uv": [5, 5, 8, 8], "texture": "#top"},
|
||||
"down": {"uv": [5, 8, 8, 11], "texture": "#bottom", "cullface": "down"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [4, 0, 5],
|
||||
"to": [5, 14, 11],
|
||||
"faces": {
|
||||
"north": {"uv": [11, 2, 12, 16], "texture": "#side"},
|
||||
"south": {"uv": [4, 2, 5, 16], "texture": "#side"},
|
||||
"up": {"uv": [4, 5, 5, 11], "texture": "#top"},
|
||||
"down": {"uv": [4, 5, 5, 11], "texture": "#bottom", "cullface": "down"}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
{
|
||||
"credit": "Made with Blockbench",
|
||||
"parent": "block/block",
|
||||
"textures": {
|
||||
"particle": "#side"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"from": [5, 0, 4],
|
||||
"to": [11, 14, 5],
|
||||
"faces": {
|
||||
"east": {"uv": [11, 2, 12, 16], "texture": "#side"},
|
||||
"west": {"uv": [4, 2, 5, 16], "texture": "#side"},
|
||||
"up": {"uv": [5, 4, 11, 5], "texture": "#top"},
|
||||
"down": {"uv": [5, 11, 11, 12], "texture": "#bottom", "cullface": "down"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [8, 0, 5],
|
||||
"to": [11, 14, 11],
|
||||
"faces": {
|
||||
"south": {"uv": [8, 2, 11, 16], "texture": "#side"},
|
||||
"up": {"uv": [8, 5, 11, 11], "texture": "#top"},
|
||||
"down": {"uv": [8, 5, 11, 11], "texture": "#bottom", "cullface": "down"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [5, 14, 5],
|
||||
"to": [8, 16, 11],
|
||||
"faces": {
|
||||
"north": {"uv": [8, 0, 11, 2], "texture": "#side"},
|
||||
"east": {"uv": [5, 0, 11, 2], "texture": "#side"},
|
||||
"south": {"uv": [5, 0, 8, 2], "texture": "#side"},
|
||||
"up": {"uv": [5, 5, 8, 11], "texture": "#top", "cullface": "up"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [5, 0, 5],
|
||||
"to": [8, 14, 11],
|
||||
"faces": {
|
||||
"south": {"uv": [5, 2, 8, 16], "texture": "#side"},
|
||||
"down": {"uv": [5, 5, 8, 11], "texture": "#bottom", "cullface": "down"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [11, 0, 5],
|
||||
"to": [12, 14, 11],
|
||||
"faces": {
|
||||
"north": {"uv": [4, 2, 5, 16], "texture": "#side"},
|
||||
"south": {"uv": [11, 2, 12, 16], "texture": "#side"},
|
||||
"up": {"uv": [11, 5, 12, 11], "texture": "#top"},
|
||||
"down": {"uv": [11, 5, 12, 11], "texture": "#bottom", "cullface": "down"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [4, 0, 5],
|
||||
"to": [5, 16, 11],
|
||||
"faces": {
|
||||
"north": {"uv": [11, 0, 12, 16], "texture": "#side"},
|
||||
"south": {"uv": [4, 0, 5, 16], "texture": "#side"},
|
||||
"up": {"uv": [4, 5, 5, 11], "texture": "#top", "cullface": "up"},
|
||||
"down": {"uv": [4, 5, 5, 11], "texture": "#bottom", "cullface": "down"}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"credit": "Made with Blockbench",
|
||||
"parent": "block/block",
|
||||
"textures": {
|
||||
"particle": "#side"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"from": [5, 0, 4],
|
||||
"to": [11, 14, 12],
|
||||
"faces": {
|
||||
"east": {"uv": [4, 2, 12, 16], "texture": "#side"},
|
||||
"west": {"uv": [4, 2, 12, 16], "texture": "#side"},
|
||||
"up": {"uv": [5, 4, 11, 12], "texture": "#top"},
|
||||
"down": {"uv": [5, 4, 11, 12], "texture": "#bottom", "cullface": "down"}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
{
|
||||
"credit": "Made with Blockbench",
|
||||
"parent": "block/block",
|
||||
"textures": {
|
||||
"particle": "#side"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"from": [5, 0, 4],
|
||||
"to": [11, 16, 5],
|
||||
"faces": {
|
||||
"east": {"uv": [11, 0, 12, 16], "texture": "#side"},
|
||||
"west": {"uv": [4, 0, 5, 16], "texture": "#side"},
|
||||
"up": {"uv": [5, 4, 11, 5], "texture": "#top", "cullface": "up"},
|
||||
"down": {"uv": [5, 11, 11, 12], "texture": "#bottom", "cullface": "down"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [5, 0, 8],
|
||||
"to": [11, 14, 11],
|
||||
"faces": {
|
||||
"south": {"uv": [5, 2, 11, 16], "texture": "#side"},
|
||||
"up": {"uv": [5, 8, 11, 11], "texture": "#top"},
|
||||
"down": {"uv": [5, 5, 11, 8], "texture": "#bottom", "cullface": "down"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [5, 14, 5],
|
||||
"to": [11, 16, 8],
|
||||
"faces": {
|
||||
"east": {"uv": [8, 0, 11, 2], "texture": "#side"},
|
||||
"south": {"uv": [5, 0, 11, 2], "texture": "#side"},
|
||||
"west": {"uv": [5, 0, 8, 2], "texture": "#side"},
|
||||
"up": {"uv": [5, 5, 11, 8], "texture": "#top", "cullface": "up"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [5, 0, 5],
|
||||
"to": [11, 14, 8],
|
||||
"faces": {
|
||||
"down": {"uv": [5, 8, 11, 11], "texture": "#bottom", "cullface": "down"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [4, 0, 5],
|
||||
"to": [5, 14, 11],
|
||||
"faces": {
|
||||
"north": {"uv": [11, 2, 12, 16], "texture": "#side"},
|
||||
"south": {"uv": [4, 2, 5, 16], "texture": "#side"},
|
||||
"up": {"uv": [4, 5, 5, 11], "texture": "#top"},
|
||||
"down": {"uv": [4, 5, 5, 11], "texture": "#bottom", "cullface": "down"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [11, 0, 5],
|
||||
"to": [12, 14, 11],
|
||||
"faces": {
|
||||
"north": {"uv": [4, 2, 5, 16], "texture": "#side"},
|
||||
"south": {"uv": [11, 2, 12, 16], "texture": "#side"},
|
||||
"up": {"uv": [11, 5, 12, 11], "texture": "#top"},
|
||||
"down": {"uv": [11, 5, 12, 11], "texture": "#bottom", "cullface": "down"}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"credit": "Made with Blockbench",
|
||||
"parent": "block/block",
|
||||
"textures": {
|
||||
"particle": "#side"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"from": [5, 0, 4],
|
||||
"to": [11, 14, 5],
|
||||
"faces": {
|
||||
"east": {"uv": [11, 2, 12, 16], "texture": "#side"},
|
||||
"west": {"uv": [4, 2, 5, 16], "texture": "#side"},
|
||||
"up": {"uv": [5, 4, 11, 5], "texture": "#top"},
|
||||
"down": {"uv": [5, 11, 11, 12], "texture": "#bottom", "cullface": "down"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [5, 0, 5],
|
||||
"to": [11, 14, 11],
|
||||
"faces": {
|
||||
"south": {"uv": [5, 2, 11, 16], "texture": "#side"},
|
||||
"up": {"uv": [5, 5, 11, 11], "texture": "#top"},
|
||||
"down": {"uv": [5, 5, 11, 11], "texture": "#bottom", "cullface": "down"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [4, 0, 5],
|
||||
"to": [5, 14, 11],
|
||||
"faces": {
|
||||
"north": {"uv": [11, 2, 12, 16], "texture": "#side"},
|
||||
"south": {"uv": [4, 2, 5, 16], "texture": "#side"},
|
||||
"up": {"uv": [4, 5, 5, 11], "texture": "#top"},
|
||||
"down": {"uv": [4, 5, 5, 11], "texture": "#bottom", "cullface": "down"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [11, 0, 5],
|
||||
"to": [12, 14, 11],
|
||||
"faces": {
|
||||
"north": {"uv": [4, 2, 5, 16], "texture": "#side"},
|
||||
"south": {"uv": [11, 2, 12, 16], "texture": "#side"},
|
||||
"up": {"uv": [11, 5, 12, 11], "texture": "#top"},
|
||||
"down": {"uv": [11, 5, 12, 11], "texture": "#bottom", "cullface": "down"}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
{
|
||||
"credit": "Made with Blockbench",
|
||||
"parent": "block/block",
|
||||
"textures": {
|
||||
"particle": "#side"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"from": [5, 0, 4],
|
||||
"to": [11, 14, 5],
|
||||
"faces": {
|
||||
"east": {"uv": [11, 2, 12, 16], "texture": "#side"},
|
||||
"west": {"uv": [4, 2, 5, 16], "texture": "#side"},
|
||||
"up": {"uv": [5, 4, 11, 5], "texture": "#top"},
|
||||
"down": {"uv": [5, 11, 11, 12], "texture": "#bottom", "cullface": "down"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [8, 0, 5],
|
||||
"to": [11, 14, 8],
|
||||
"faces": {
|
||||
"east": {"uv": [8, 2, 11, 16], "texture": "#side"},
|
||||
"south": {"uv": [8, 2, 11, 16], "texture": "#side"},
|
||||
"up": {"uv": [8, 5, 11, 8], "texture": "#top"},
|
||||
"down": {"uv": [8, 8, 11, 11], "texture": "#bottom", "cullface": "down"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [5, 14, 5],
|
||||
"to": [8, 16, 8],
|
||||
"faces": {
|
||||
"north": {"uv": [8, 0, 11, 2], "texture": "#side"},
|
||||
"east": {"uv": [8, 0, 11, 2], "texture": "#side"},
|
||||
"up": {"uv": [5, 5, 8, 8], "texture": "#top", "cullface": "up"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [5, 0, 8],
|
||||
"to": [8, 16, 11],
|
||||
"faces": {
|
||||
"east": {"uv": [5, 0, 8, 16], "texture": "#side"},
|
||||
"south": {"uv": [5, 0, 8, 16], "texture": "#side"},
|
||||
"up": {"uv": [5, 8, 8, 11], "texture": "#top", "cullface": "up"},
|
||||
"down": {"uv": [5, 5, 8, 8], "texture": "#bottom", "cullface": "down"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [5, 0, 5],
|
||||
"to": [8, 14, 8],
|
||||
"faces": {
|
||||
"down": {"uv": [5, 8, 8, 11], "texture": "#bottom", "cullface": "down"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [4, 0, 5],
|
||||
"to": [5, 16, 11],
|
||||
"faces": {
|
||||
"north": {"uv": [11, 0, 12, 16], "texture": "#side"},
|
||||
"south": {"uv": [4, 0, 5, 16], "texture": "#side"},
|
||||
"up": {"uv": [4, 5, 5, 11], "texture": "#top", "cullface": "up"},
|
||||
"down": {"uv": [4, 5, 5, 11], "texture": "#bottom", "cullface": "down"}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
{
|
||||
"credit": "Made with Blockbench",
|
||||
"parent": "block/block",
|
||||
"textures": {
|
||||
"particle": "#side"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"from": [5, 0, 4],
|
||||
"to": [11, 16, 5],
|
||||
"faces": {
|
||||
"east": {"uv": [11, 0, 12, 16], "texture": "#side"},
|
||||
"west": {"uv": [4, 0, 5, 16], "texture": "#side"},
|
||||
"up": {"uv": [5, 4, 11, 5], "texture": "#top", "cullface": "up"},
|
||||
"down": {"uv": [5, 11, 11, 12], "texture": "#bottom", "cullface": "down"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [8, 0, 8],
|
||||
"to": [11, 14, 11],
|
||||
"faces": {
|
||||
"south": {"uv": [8, 2, 11, 16], "texture": "#side"},
|
||||
"up": {"uv": [8, 8, 11, 11], "texture": "#top"},
|
||||
"down": {"uv": [8, 5, 11, 8], "texture": "#bottom", "cullface": "down"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [8, 14, 5],
|
||||
"to": [11, 16, 8],
|
||||
"faces": {
|
||||
"east": {"uv": [8, 0, 11, 2], "texture": "#side"},
|
||||
"south": {"uv": [8, 0, 11, 2], "texture": "#side"},
|
||||
"up": {"uv": [8, 5, 11, 8], "texture": "#top", "cullface": "up"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [5, 14, 8],
|
||||
"to": [8, 16, 11],
|
||||
"faces": {
|
||||
"east": {"uv": [5, 0, 8, 2], "texture": "#side"},
|
||||
"south": {"uv": [5, 0, 8, 2], "texture": "#side"},
|
||||
"up": {"uv": [5, 8, 8, 11], "texture": "#top", "cullface": "up"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [5, 14, 5],
|
||||
"to": [8, 16, 8],
|
||||
"faces": {
|
||||
"up": {"uv": [5, 5, 8, 8], "texture": "#top", "cullface": "up"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [5, 0, 5],
|
||||
"to": [11, 14, 8],
|
||||
"faces": {
|
||||
"down": {"uv": [5, 8, 11, 11], "texture": "#bottom", "cullface": "down"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [5, 0, 8],
|
||||
"to": [8, 14, 11],
|
||||
"faces": {
|
||||
"south": {"uv": [5, 2, 8, 16], "texture": "#side"},
|
||||
"down": {"uv": [5, 5, 8, 8], "texture": "#bottom", "cullface": "down"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [4, 0, 5],
|
||||
"to": [5, 16, 11],
|
||||
"faces": {
|
||||
"north": {"uv": [11, 0, 12, 16], "texture": "#side"},
|
||||
"south": {"uv": [4, 0, 5, 16], "texture": "#side"},
|
||||
"up": {"uv": [4, 5, 5, 11], "texture": "#top", "cullface": "up"},
|
||||
"down": {"uv": [4, 5, 5, 11], "texture": "#bottom", "cullface": "down"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [11, 0, 5],
|
||||
"to": [12, 14, 11],
|
||||
"faces": {
|
||||
"north": {"uv": [4, 2, 5, 16], "texture": "#side"},
|
||||
"south": {"uv": [11, 2, 12, 16], "texture": "#side"},
|
||||
"up": {"uv": [11, 5, 12, 11], "texture": "#top"},
|
||||
"down": {"uv": [11, 5, 12, 11], "texture": "#bottom", "cullface": "down"}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"credit": "Made with Blockbench",
|
||||
"parent": "block/block",
|
||||
"textures": {
|
||||
"particle": "#side"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"from": [5, 0, 4],
|
||||
"to": [11, 14, 8],
|
||||
"faces": {
|
||||
"east": {"uv": [8, 2, 12, 16], "texture": "#side"},
|
||||
"west": {"uv": [4, 2, 8, 16], "texture": "#side"},
|
||||
"up": {"uv": [5, 4, 11, 8], "texture": "#top"},
|
||||
"down": {"uv": [5, 8, 11, 12], "texture": "#bottom", "cullface": "down"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [5, 14, 8],
|
||||
"to": [11, 16, 12],
|
||||
"faces": {
|
||||
"north": {"uv": [5, 0, 11, 2], "texture": "#side"},
|
||||
"east": {"uv": [4, 0, 8, 2], "texture": "#side"},
|
||||
"west": {"uv": [8, 0, 12, 2], "texture": "#side"},
|
||||
"up": {"uv": [5, 8, 11, 12], "texture": "#top", "cullface": "up"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [5, 0, 8],
|
||||
"to": [11, 14, 12],
|
||||
"faces": {
|
||||
"east": {"uv": [4, 2, 8, 16], "texture": "#side"},
|
||||
"west": {"uv": [8, 2, 12, 16], "texture": "#side"},
|
||||
"down": {"uv": [5, 4, 11, 8], "texture": "#bottom", "cullface": "down"}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
{
|
||||
"credit": "Made with Blockbench",
|
||||
"parent": "block/block",
|
||||
"textures": {
|
||||
"particle": "#side"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"from": [5, 0, 4],
|
||||
"to": [11, 14, 5],
|
||||
"faces": {
|
||||
"east": {"uv": [11, 2, 12, 16], "texture": "#side"},
|
||||
"west": {"uv": [4, 2, 5, 16], "texture": "#side"},
|
||||
"up": {"uv": [5, 4, 11, 5], "texture": "#top"},
|
||||
"down": {"uv": [5, 11, 11, 12], "texture": "#bottom", "cullface": "down"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [5, 0, 11],
|
||||
"to": [11, 14, 12],
|
||||
"faces": {
|
||||
"east": {"uv": [4, 2, 5, 16], "texture": "#side"},
|
||||
"west": {"uv": [11, 2, 12, 16], "texture": "#side"},
|
||||
"up": {"uv": [5, 11, 11, 12], "texture": "#top"},
|
||||
"down": {"uv": [5, 4, 11, 5], "texture": "#bottom", "cullface": "down"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [5, 0, 5],
|
||||
"to": [11, 14, 11],
|
||||
"faces": {
|
||||
"up": {"uv": [5, 5, 11, 11], "texture": "#top"},
|
||||
"down": {"uv": [5, 5, 11, 11], "texture": "#bottom", "cullface": "down"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [4, 0, 5],
|
||||
"to": [5, 14, 11],
|
||||
"faces": {
|
||||
"north": {"uv": [11, 2, 12, 16], "texture": "#side"},
|
||||
"south": {"uv": [4, 2, 5, 16], "texture": "#side"},
|
||||
"up": {"uv": [4, 5, 5, 11], "texture": "#top"},
|
||||
"down": {"uv": [4, 5, 5, 11], "texture": "#bottom", "cullface": "down"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [11, 0, 5],
|
||||
"to": [12, 14, 11],
|
||||
"faces": {
|
||||
"north": {"uv": [4, 2, 5, 16], "texture": "#side"},
|
||||
"south": {"uv": [11, 2, 12, 16], "texture": "#side"},
|
||||
"up": {"uv": [11, 5, 12, 11], "texture": "#top"},
|
||||
"down": {"uv": [11, 5, 12, 11], "texture": "#bottom", "cullface": "down"}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user