From 936c50e13caffce12babf1e5c7262457449552ac Mon Sep 17 00:00:00 2001 From: Paula Date: Fri, 31 May 2024 16:57:15 +0200 Subject: [PATCH] new Attempt -> not functional yet MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit das hier ist ein backup, das noch unglaublich viele Fehler hat aber es war echt anstrengend, deswegen brauchen wir das. Bitte löschen sobald funktionierender release (hoffentlich) irgendwann kommt. --- .../java/modchest/REServerModClient.java | 4 + .../modchest/assets/OverlayAssetListener.java | 105 +++++ src/client/java/modchest/assets/Parent.java | 68 ++++ .../modchest/assets/overlay/ColoredLike.java | 26 ++ .../modchest/assets/overlay/Offsetter.java | 42 ++ .../assets/overlay/OffsetterRegistry.java | 28 ++ .../modchest/assets/overlay/Offsetters.java | 37 ++ .../java/modchest/assets/overlay/Overlay.java | 133 +++++++ .../assets/overlay/SidedOffsetters.java | 76 ++++ .../assets/overlay/TextureSource.java | 161 ++++++++ .../assets/overlay/TextureSourceKind.java | 24 ++ .../assets/overlay/ZeroOffsetter.java | 35 ++ .../modchest/block/custom/gridCodecs.java | 68 ++++ .../modchest/block/custom/gridConfig.java | 20 + .../block/custom/gridModelChange.java | 168 ++++++++ .../block/custom/gridPreviewOutline.java | 203 ++++++++++ src/client/java/modchest/gui/gridScreen.java | 18 + .../packet/gridRenderRequestS2CPacket.java | 294 +++++++++++--- .../modchest/rendering/gridBlockRender.java | 24 -- .../java/modchest/transform/BaseApplier.java | 96 +++++ .../java/modchest/transform/ColorApplier.java | 56 +++ .../modchest/transform/LazyColorApplier.java | 26 ++ .../modchest/transform/MaterialApplier.java | 62 +++ .../modchest/transform/SpriteApplier.java | 66 ++++ .../modchest/transform/TransformResult.java | 31 ++ .../modchest/transform/gridTransform.java | 207 ++++++++++ src/client/java/modchest/util/QuadUtil.java | 27 ++ src/client/java/modchest/util/ToOptional.java | 27 ++ src/main/java/modchest/REServerMod.java | 31 ++ src/main/java/modchest/block/custom/grid.java | 5 - .../java/modchest/block/custom/grid/grid.java | 40 ++ .../modchest/block/custom/grid/gridBlock.java | 151 +++++++ .../block/custom/grid/gridCarpet.java | 10 + .../modchest/block/custom/grid/gridDoor.java | 10 + .../modchest/block/custom/grid/gridFence.java | 10 + .../block/custom/grid/gridFenceGate.java | 11 + .../modchest/block/custom/grid/gridLayer.java | 11 + .../modchest/block/custom/grid/gridPane.java | 11 + .../modchest/block/custom/grid/gridPath.java | 17 + .../block/custom/grid/gridPressurePlate.java | 11 + .../modchest/block/custom/grid/gridSlab.java | 87 ++++ .../block/custom/grid/gridSlotInfo.java | 13 + .../block/custom/grid/gridStairs.java | 12 + .../modchest/block/custom/grid/gridTorch.java | 13 + .../block/custom/grid/gridTrapdoor.java | 11 + .../modchest/block/custom/grid/gridWall.java | 11 + .../block/custom/grid/gridWallTorch.java | 13 + .../java/modchest/block/custom/gridBlock.java | 50 --- .../modchest/block/entity/gridEntity.java | 370 ++++++++++++++++++ .../block/entity/modBlockEntities.java | 6 + src/main/java/modchest/block/modBlocks.java | 2 +- .../modchest/data/OverlayDataListener.java | 77 ++++ .../java/modchest/event/useBlockCallback.java | 20 +- .../modchest/event/useEntityCallback.java | 62 +++ src/main/java/modchest/grid/Registrar.java | 16 + .../java/modchest/grid/data/Sections.java | 110 ++++++ .../java/modchest/grid/data/gridData.java | 129 ++++++ src/main/java/modchest/grid/gridBlock.java | 18 + .../modchest/grid/gridBlockEntityTypes.java | 36 ++ src/main/java/modchest/grid/gridBlocks.java | 93 +++++ src/main/java/modchest/grid/gridItems.java | 20 + src/main/java/modchest/grid/gridMeta.java | 37 ++ .../java/modchest/grid/gridProperties.java | 7 + .../java/modchest/gui/SingleItemSlots.java | 14 + .../modchest/gui/ValidatedSingleItemSlot.java | 20 + .../java/modchest/gui/gridGuiDescription.java | 32 ++ .../java/modchest/item/custom/Hammer.java | 225 +++++++++++ .../modchest/item/custom/SpecialItems.java | 53 +++ .../mixin/local/SinglePartGridBlock.java | 63 +++ .../modchest/mixin/local/gridBehaviour.java | 330 ++++++++++++++++ .../mixin/local/gridEntityProvider.java | 55 +++ .../modchest/mixin/mc/BakedQuadAccess.java | 13 + .../modchest/mixin/mc/BlockItemAccess.java | 15 + .../modchest/mixin/mc/FenceBlockMixin.java | 27 ++ .../modchest/mixin/mc/GetItemBeforeEmpty.java | 13 + .../modchest/mixin/mc/ItemRendererMixin.java | 53 +++ .../modchest/mixin/mc/WallBlockMixin.java | 90 +++++ .../mixin/mc/WorldRendererAccess.java | 15 + src/main/java/modchest/util/Float4.java | 35 ++ .../java/modchest/util/FunctionalUtil.java | 22 ++ .../modchest/util/GetItemBeforeEmptyUtil.java | 16 + src/main/java/modchest/util/GuiUtil.java | 29 ++ src/main/java/modchest/util/Identifiable.java | 21 + src/main/java/modchest/util/Section.java | 86 ++++ src/main/java/modchest/util/ValidQuery.java | 75 ++++ src/main/java/modchest/util/initializer.java | 6 +- .../modchest/textures/block/texture_test.png | Bin 0 -> 769 bytes 87 files changed, 4814 insertions(+), 157 deletions(-) create mode 100644 src/client/java/modchest/assets/OverlayAssetListener.java create mode 100644 src/client/java/modchest/assets/Parent.java create mode 100644 src/client/java/modchest/assets/overlay/ColoredLike.java create mode 100644 src/client/java/modchest/assets/overlay/Offsetter.java create mode 100644 src/client/java/modchest/assets/overlay/OffsetterRegistry.java create mode 100644 src/client/java/modchest/assets/overlay/Offsetters.java create mode 100644 src/client/java/modchest/assets/overlay/Overlay.java create mode 100644 src/client/java/modchest/assets/overlay/SidedOffsetters.java create mode 100644 src/client/java/modchest/assets/overlay/TextureSource.java create mode 100644 src/client/java/modchest/assets/overlay/TextureSourceKind.java create mode 100644 src/client/java/modchest/assets/overlay/ZeroOffsetter.java create mode 100644 src/client/java/modchest/block/custom/gridCodecs.java create mode 100644 src/client/java/modchest/block/custom/gridConfig.java create mode 100644 src/client/java/modchest/block/custom/gridModelChange.java create mode 100644 src/client/java/modchest/block/custom/gridPreviewOutline.java create mode 100644 src/client/java/modchest/gui/gridScreen.java delete mode 100644 src/client/java/modchest/rendering/gridBlockRender.java create mode 100644 src/client/java/modchest/transform/BaseApplier.java create mode 100644 src/client/java/modchest/transform/ColorApplier.java create mode 100644 src/client/java/modchest/transform/LazyColorApplier.java create mode 100644 src/client/java/modchest/transform/MaterialApplier.java create mode 100644 src/client/java/modchest/transform/SpriteApplier.java create mode 100644 src/client/java/modchest/transform/TransformResult.java create mode 100644 src/client/java/modchest/transform/gridTransform.java create mode 100644 src/client/java/modchest/util/QuadUtil.java create mode 100644 src/client/java/modchest/util/ToOptional.java delete mode 100644 src/main/java/modchest/block/custom/grid.java create mode 100644 src/main/java/modchest/block/custom/grid/grid.java create mode 100644 src/main/java/modchest/block/custom/grid/gridBlock.java create mode 100644 src/main/java/modchest/block/custom/grid/gridCarpet.java create mode 100644 src/main/java/modchest/block/custom/grid/gridDoor.java create mode 100644 src/main/java/modchest/block/custom/grid/gridFence.java create mode 100644 src/main/java/modchest/block/custom/grid/gridFenceGate.java create mode 100644 src/main/java/modchest/block/custom/grid/gridLayer.java create mode 100644 src/main/java/modchest/block/custom/grid/gridPane.java create mode 100644 src/main/java/modchest/block/custom/grid/gridPath.java create mode 100644 src/main/java/modchest/block/custom/grid/gridPressurePlate.java create mode 100644 src/main/java/modchest/block/custom/grid/gridSlab.java create mode 100644 src/main/java/modchest/block/custom/grid/gridSlotInfo.java create mode 100644 src/main/java/modchest/block/custom/grid/gridStairs.java create mode 100644 src/main/java/modchest/block/custom/grid/gridTorch.java create mode 100644 src/main/java/modchest/block/custom/grid/gridTrapdoor.java create mode 100644 src/main/java/modchest/block/custom/grid/gridWall.java create mode 100644 src/main/java/modchest/block/custom/grid/gridWallTorch.java delete mode 100644 src/main/java/modchest/block/custom/gridBlock.java create mode 100644 src/main/java/modchest/block/entity/gridEntity.java create mode 100644 src/main/java/modchest/data/OverlayDataListener.java create mode 100644 src/main/java/modchest/event/useEntityCallback.java create mode 100644 src/main/java/modchest/grid/Registrar.java create mode 100644 src/main/java/modchest/grid/data/Sections.java create mode 100644 src/main/java/modchest/grid/data/gridData.java create mode 100644 src/main/java/modchest/grid/gridBlock.java create mode 100644 src/main/java/modchest/grid/gridBlockEntityTypes.java create mode 100644 src/main/java/modchest/grid/gridBlocks.java create mode 100644 src/main/java/modchest/grid/gridItems.java create mode 100644 src/main/java/modchest/grid/gridMeta.java create mode 100644 src/main/java/modchest/grid/gridProperties.java create mode 100644 src/main/java/modchest/gui/SingleItemSlots.java create mode 100644 src/main/java/modchest/gui/ValidatedSingleItemSlot.java create mode 100644 src/main/java/modchest/gui/gridGuiDescription.java create mode 100644 src/main/java/modchest/item/custom/Hammer.java create mode 100644 src/main/java/modchest/item/custom/SpecialItems.java create mode 100644 src/main/java/modchest/mixin/local/SinglePartGridBlock.java create mode 100644 src/main/java/modchest/mixin/local/gridBehaviour.java create mode 100644 src/main/java/modchest/mixin/local/gridEntityProvider.java create mode 100644 src/main/java/modchest/mixin/mc/BakedQuadAccess.java create mode 100644 src/main/java/modchest/mixin/mc/BlockItemAccess.java create mode 100644 src/main/java/modchest/mixin/mc/FenceBlockMixin.java create mode 100644 src/main/java/modchest/mixin/mc/GetItemBeforeEmpty.java create mode 100644 src/main/java/modchest/mixin/mc/ItemRendererMixin.java create mode 100644 src/main/java/modchest/mixin/mc/WallBlockMixin.java create mode 100644 src/main/java/modchest/mixin/mc/WorldRendererAccess.java create mode 100644 src/main/java/modchest/util/Float4.java create mode 100644 src/main/java/modchest/util/FunctionalUtil.java create mode 100644 src/main/java/modchest/util/GetItemBeforeEmptyUtil.java create mode 100644 src/main/java/modchest/util/GuiUtil.java create mode 100644 src/main/java/modchest/util/Identifiable.java create mode 100644 src/main/java/modchest/util/Section.java create mode 100644 src/main/java/modchest/util/ValidQuery.java create mode 100644 src/main/resources/assets/modchest/textures/block/texture_test.png diff --git a/src/client/java/modchest/REServerModClient.java b/src/client/java/modchest/REServerModClient.java index 8297868..277899d 100644 --- a/src/client/java/modchest/REServerModClient.java +++ b/src/client/java/modchest/REServerModClient.java @@ -1,5 +1,7 @@ package modchest; +import modchest.assets.OverlayAssetListener; +import modchest.block.custom.gridCodecs; import modchest.networking.modNetworkingClient; import net.fabricmc.api.ClientModInitializer; import net.minecraft.client.util.ModelIdentifier; @@ -9,6 +11,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class REServerModClient implements ClientModInitializer { + public static gridCodecs CODECS; + public static OverlayAssetListener CLIENT_OVERLAYS; public static final Logger LOGGER = LoggerFactory.getLogger("modchest"); // Erster Error Logger @Override public void onInitializeClient() { diff --git a/src/client/java/modchest/assets/OverlayAssetListener.java b/src/client/java/modchest/assets/OverlayAssetListener.java new file mode 100644 index 0000000..99d0d8f --- /dev/null +++ b/src/client/java/modchest/assets/OverlayAssetListener.java @@ -0,0 +1,105 @@ +package modchest.assets; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.BufferUnderflowException; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; + +import org.spongepowered.include.com.google.gson.Gson; + +import com.google.gson.JsonElement; +import com.mojang.serialization.DataResult; +import com.mojang.serialization.JsonOps; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.resource.SimpleResourceReloadListener; +import net.minecraft.client.gui.screen.Overlay; +import net.minecraft.resource.ResourceManager; +import net.minecraft.util.Identifier; +import net.minecraft.util.Pair; +import net.minecraft.util.Unit; +import net.minecraft.util.profiler.Profiler; + +@Environment(EnvType.CLIENT) +public class OverlayAssetListener implements SimpleResourceReloadListener> { + private final Map overlayInfoMap = new HashMap<>(); + + public Overlay getOverlayFor(final Identifier id) { + return Overlay.ofNullable(overlayInfoMap.get(id)); + } + + @Override + public CompletableFuture> load(ResourceManager manager, Profiler profiler, + Executor executor) { + return CompletableFuture.supplyAsync(() -> { + overlayInfoMap.clear(); + return resourceManager.findResources("modchest/overlays", s -> s.endsWith(".json")); + }, executor); + } + + private DataResult parseOverlayAndDependencies(final ResourceManager resourceManager, + final Identifier rootOverlayId) { + final Set loadedDependencies = new HashSet<>(); + + if (!overlayInfoMap.containsKey(rootOverlayId)) { + return parseOverlay(resourceManager, loadedDependencies, rootOverlayId); + } else { + return DataResult.success(Unit.INSTANCE); + } + } + + private DataResult parseOverlay(final ResourceManager resourceManager, + final Set loadedDependencies, final Identifier overlayId) { + final JsonElement element; + try { + element = new Gson().fromJson( + new BufferedReader(new InputStreamReader(resourceManager.getResource(overlayId).getInputStream())), + JsonElement.class); + } catch (final IOException e) { + return DataResult.error("Exception while loading an overlay:"); + } + + final DataResult> result = Overlay.Some.PARENT_CODEC + .decode(JsonOps.INSTANCE, element) + .flatMap(pair -> pair.getFirst().map(parentId -> { + if (!loadedDependencies.add(parentId)) { + return DataResult.error("Circular dependency;" + pair.getFirst() + "and" + overlayId + "."); + } else { + parseOverlay(resourceManager, loadedDependencies, parentId); + return DataResult.success(Unit.INSTANCE); + } + }).orElse(DataResult.success(Unit.INSTANCE))) + .flatMap(unit -> Overlay.Some.CODEC.decode(JsonOps.INSTANCE, element)); + + result.get().mapLeft(pair -> { + overlayInfoMap.put(overlayId, pair.getFirst()); + }); + return result.map(p -> Unit.INSTANCE); + } + + @Override + public CompletableFuture apply(Collection data, ResourceManager manager, Profiler profiler, + Executor executor) { + return CompletableFuture.runAsync(() -> { + for (final Identifier id : identifiers) { + final DataResult result = parseOverlayAndDependencies(manager, id); + result.get().ifRight(partial -> META.LOGGER + .warn("Error while parsing overlay \"" + id + "\": " + partial.message())); + } + }, executor); + } + + @Override + public Identifier getFabricId() { + return id; + } + +} diff --git a/src/client/java/modchest/assets/Parent.java b/src/client/java/modchest/assets/Parent.java new file mode 100644 index 0000000..15d544e --- /dev/null +++ b/src/client/java/modchest/assets/Parent.java @@ -0,0 +1,68 @@ +package modchest.assets; + +import java.util.Optional; +import java.util.function.Function; +import java.util.function.Supplier; + +import org.jetbrains.annotations.Nullable; +import org.lwjgl.system.NonnullDefault; + +import modchest.util.ToOptional; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.util.Identifier; + +@Environment(EnvType.CLIENT) +public abstract class Parent implements ToOptional { + public static Parent ofNullable(@Nullable final Identifier parentId) { + if (parentId == null) { + return NONE; + } else { + return new Some(parentId); + } + } + + public abstract Optional id(); + public abstract T run(@NonnullDefault Function f, T whenNone); + + public static class Some extends Parent implements ToOptional.Some { + + private final @NonnullDefault Identifier parent; + + public Some(final @NonnullDefault Identifier parent) { + this.parent = parent; + } + + @Override + public Optional id() { + return Optional.of(parent); + } + + @Override + public T run(Function f, T whenNone) { + return f.apply(parent); + } + } + + public static final Parent NONE = new Parent() { + @Override + public Optional id() { + return Optional.empty(); + } + + @Override + public T run(@NonnullDefault final Function f, final T whenNone) { + return whenNone; + } + + @Override + public T match(final Function some, final Supplier none) { + return none.get(); + } + + @Override + public Optional toOptional() { + return Optional.empty(); + } + }; +} diff --git a/src/client/java/modchest/assets/overlay/ColoredLike.java b/src/client/java/modchest/assets/overlay/ColoredLike.java new file mode 100644 index 0000000..a1146a3 --- /dev/null +++ b/src/client/java/modchest/assets/overlay/ColoredLike.java @@ -0,0 +1,26 @@ +package modchest.assets.overlay; + +import com.mojang.serialization.Codec; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.block.BlockState; +import net.minecraft.util.Identifier; +import net.minecraft.util.registry.Registry; + +@Environment(EnvType.CLIENT) +public class ColoredLike { + public static final Codec CODEC = Identifier.CODEC + .xmap(id -> Registry.BLOCK.get(id).getDefaultState(), state -> Registry.BLOCK.getId(state.getBlock())) + .xmap(ColoredLike::new, coloredLike -> coloredLike.colorSource); + + private final BlockState colorSource; + + public ColoredLike(final BlockState colorSource) { + this.colorSource = colorSource; + } + + public BlockState colorSource() { + return colorSource; + } +} diff --git a/src/client/java/modchest/assets/overlay/Offsetter.java b/src/client/java/modchest/assets/overlay/Offsetter.java new file mode 100644 index 0000000..50e86f5 --- /dev/null +++ b/src/client/java/modchest/assets/overlay/Offsetter.java @@ -0,0 +1,42 @@ +package modchest.assets.overlay; + +import java.util.Optional; +import java.util.function.Function; +import java.util.function.Supplier; +import modchest.util.ToOptional; + +import modchest.util.Float4; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.util.Identifier; + +@Environment(EnvType.CLIENT) +public interface Offsetter extends ToOptional { + Float4 offsett(Float4 original); + + public Identifier getId(); + + Identifier NONE_ID = META.id("none"); + + Offsetter NONE = new Offsetter() { + @Override + public Optional toOptional() { + return Optional.empty(); + } + + @Override + public T match(final Function some, final Supplier none) { + return none.get(); + } + + @Override + public Identifier getId() { + return NONE_ID; + } + + @Override + public Float4 offsett(Float4 original) { + return original; + } + }; +} diff --git a/src/client/java/modchest/assets/overlay/OffsetterRegistry.java b/src/client/java/modchest/assets/overlay/OffsetterRegistry.java new file mode 100644 index 0000000..98fbc02 --- /dev/null +++ b/src/client/java/modchest/assets/overlay/OffsetterRegistry.java @@ -0,0 +1,28 @@ +package modchest.assets.overlay; + +import java.util.HashMap; +import java.util.Map; + +import com.mojang.serialization.Codec; + +import modchest.util.Identifiable; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.util.Identifier; + +@Environment(EnvType.CLIENT) +public class OffsetterRegistry { + private OffsetterRegistry() { + } + + private static final Map>> registeredOffsetters = new HashMap<>(); + + private static void register(final Identifier id, final Codec codec) { + registeredOffsetters.put(id, new Identifiable<>(codec, id)); + } + + public static Identifiable> get(final Identifier id) { + return registeredOffsetters.get(id); + } + +} diff --git a/src/client/java/modchest/assets/overlay/Offsetters.java b/src/client/java/modchest/assets/overlay/Offsetters.java new file mode 100644 index 0000000..e2aea18 --- /dev/null +++ b/src/client/java/modchest/assets/overlay/Offsetters.java @@ -0,0 +1,37 @@ +package modchest.assets.overlay; + +import org.jetbrains.annotations.Nullable; + +import java.util.Optional; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +@Environment(EnvType.CLIENT) +public class Offsetters { + public static final Codec CODEC = RecordCodecBuilder.create(inst -> inst.group( + CODECS.OFFSETTER.optionalFieldOf("u").forGetter(o -> o.u.toOptional()), + CODECS.OFFSETTER.optionalFieldOf("v").forGetter(o -> o.v.toOptional()) + ).apply(inst, Offsetters::new)); + + public static final Offsetters NONE = new Offsetters(); + + public final Offsetter u; + public final Offsetter v; + + @SuppressWarnings("OptionalUsedAsFieldOrParameterType") + public Offsetters(final Optional u, final Optional v) { + this.u = u.orElse(Offsetter.NONE); + this.v = v.orElse(Offsetter.NONE); + } + + private Offsetters() { + this.u = Offsetter.NONE; + this.v = Offsetter.NONE; + } + + +} diff --git a/src/client/java/modchest/assets/overlay/Overlay.java b/src/client/java/modchest/assets/overlay/Overlay.java new file mode 100644 index 0000000..ffb2d9b --- /dev/null +++ b/src/client/java/modchest/assets/overlay/Overlay.java @@ -0,0 +1,133 @@ +package modchest.assets.overlay; + +import java.util.Optional; +import java.util.function.Function; +import java.util.function.Supplier; + +import org.jetbrains.annotations.Nullable; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; + +import modchest.assets.Parent; +import modchest.assets.Parent.Some; +import modchest.transform.TransformResult; +import modchest.util.Float4; +import modchest.util.ToOptional; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView; +import net.minecraft.util.Identifier; +import net.minecraft.util.math.Direction; + +@Environment(EnvType.CLIENT) +public abstract class Overlay implements ToOptional { + public static Overlay ofNullable(final @Nullable Some some) { + if (some == null) { + return NONE; + } else { + return some; + } + } + + public abstract TransformResult apply(MutableQuadView mqv, Float4 us, Float4 vs, Direction dir); + + public abstract TextureSource textureSource(); + + public abstract Optional coloredLike(); + + public abstract SidedOffsetters.Base sideOffsetters(); + + public static final Overlay NONE = new Overlay() { + @Override + public TransformResult apply(MutableQuadView mqv, Float4 us, Float4 vs, Direction dir) { + return TransformResult.NOTHING_TO_DO; + } + + @Override + public TextureSource textureSource() { + return TextureSource.NONE; + } + + @Override + public Optional coloredLike() { + return Optional.empty(); + } + + @Override + public SidedOffsetters.Base sideOffsetters() { + return SidedOffsetters.NONE; + } + + @Override + public Optional toOptional() { + return Optional.empty(); + } + + @Override + public T match(Function some, Supplier none) { + return none.get(); + } + }; + + public static class Some extends Overlay implements ToOptional.Some { + public static final Codec> PARENT_CODEC = RecordCodecBuilder.create(inst -> inst.group( + Identifier.CODEC.optionalFieldOf("parent").forGetter(i -> i)).apply(inst, i -> i)); + + public static final Codec CODEC = RecordCodecBuilder.create(inst -> inst.group( + Identifier.CODEC.optionalFieldOf("parent").forGetter(o -> o.parent.id()), + TextureSource.CODEC.optionalFieldOf("textureSource").forGetter(o -> o.textureSource.toOptional()), + ColoredLike.CODEC.optionalFieldOf("coloredLike").forGetter(o -> o.coloredLike), + SidedOffsetters.CODEC.optionalFieldOf("offsets").forGetter(o -> o.sideOffsetters.toOptional())) + .apply(inst, Overlay.Some::new)); + + private final Parent parent; + private final TextureSource textureSource; + private final Optional coloredLike; + private final SidedOffsetters.Base sideOffsetters; + + public Some(final Optional parent, final Optional textureSource, + final Optional coloredLike, final Optional sideOffsetters) { + this.parent = Parent.ofNullable(parent.orElse(null)); + this.textureSource = textureSource.ofNullable(parent.orElse(null)); + this.coloredLike = coloredLike; + this.sideOffsetters = sideOffsetters.orElse(SidedOffsetters.NONE); + } + + @Override + public TransformResult apply(MutableQuadView mqv, Float4 us, Float4 vs, Direction dir) { + final Float4 finalUs = sidedOffsetters().applyUs(us, dir); + float Float4 finalVs = sidedOffsetters().applyVs(vs, dir); + return textureSource().apply(mqv, finalUs, finalVs, dir); + } + + @Override + public TextureSource textureSource() { + if (textureSource != TextureSource.NONE) { + return textureSource; + } else { + return parent.run(parent -> CLIENT_OVERLAYS.getOverlayFor(parent).textureSource(), TextureSource.NONE); + } + } + + @Override + public Optional coloredLike() { + if (coloredLike.isPresent()) { + return coloredLike; + } else { + return parent.run(parent -> CLIENT_OVERLAYS.getOverlayFor(parent).coloredLike(), Optional.empty()); + } + } + + @Override + public Base sideOffsetters() { + if (sideOffsetters != SidedOffsetters.NONE) { + return sidedOffsetters; + } else { + return parent.run(parent -> CLIENT_OVERLAYS.getOverlayFor(parent).sidedOffsetters(), + SidedOffsetters.NONE); + } + } + } + +} diff --git a/src/client/java/modchest/assets/overlay/SidedOffsetters.java b/src/client/java/modchest/assets/overlay/SidedOffsetters.java new file mode 100644 index 0000000..c95dd6d --- /dev/null +++ b/src/client/java/modchest/assets/overlay/SidedOffsetters.java @@ -0,0 +1,76 @@ +package modchest.assets.overlay; + +import java.util.Map; +import java.util.Optional; +import java.util.function.Function; +import java.util.function.Supplier; + +import com.mojang.serialization.Codec; + +import modchest.util.Float4; +import modchest.util.ToOptional; +import modchest.util.initializer; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.util.math.Direction; + +@Environment(EnvType.CLIENT) +public abstract class SidedOffsetters { + private SidedOffsetters() { + } + + public static final Codec CODEC = Some.CODEC.xmap(some -> some, base -> (Some) base); + public static final Base NONE = new Base() { + + @Override + public Optional toOptional() { + return Optional.empty(); + } + + @Override + public Float4 applyUs(final Float4 origUs, Direction dir) { + return origUs; + } + + @Override + public Float4 applyVs(final Float4 origVs, Direction dir) { + return origVs; + } + + @Override + public T match(Function some, Supplier none) { + return none.get(); + } + }; + + public interface Base extends ToOptional { + Float4 applyUs(Float4 origUs, Direction dir); + + Float4 applyVs(Float4 origVs, Direction dir); + } + + public static class Some implements Base, ToOptional.Some { + public static final Codec CODEC = CODECS.sidedMapOf(Offsetters.CODEC) + .xmap(SidedOffsetters.Some::new, so -> so.map); + private final Map map; + + public Some(final Map map) { + for (final Direction dir : Direction.values()) { + map.putIfAbsent(dir, Offsetters.NONE); + } + this.map = map; + } + + @Override + public Float4 applyUs(Float4 origUs, Direction dir) { + return map.get(dir).u.offsett(origUs); + } + + @Override + public Float4 applyVs(Float4 origVs, Direction dir) { + return map.get(dir).v.offsett(origVs); + } + + } + +} diff --git a/src/client/java/modchest/assets/overlay/TextureSource.java b/src/client/java/modchest/assets/overlay/TextureSource.java new file mode 100644 index 0000000..7cffb81 --- /dev/null +++ b/src/client/java/modchest/assets/overlay/TextureSource.java @@ -0,0 +1,161 @@ +package modchest.assets.overlay; + +import java.rmi.registry.Registry; +import java.util.EnumMap; +import java.util.Optional; +import java.util.function.Function; +import java.util.function.Supplier; + +import org.spongepowered.asm.mixin.Final; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; + +import modchest.transform.MaterialApplier; +import modchest.transform.SpriteApplier; +import modchest.transform.TransformResult; +import modchest.util.Float4; +import modchest.util.ToOptional; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView; +import net.minecraft.block.BlockState; +import net.minecraft.block.Material; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.texture.Sprite; +import net.minecraft.client.texture.SpriteAtlasTexture; +import net.minecraft.util.Identifier; +import net.minecraft.util.math.Direction; + +@Environment(EnvType.CLIENT) +public abstract class TextureSource implements ToOptional { + public static class Entry { + public final SpriteApplier textureApplier; + public final MaterialApplier materialApplier; + + public static final Entry NONE = new Entry(); + + private Entry() { + this.textureApplier = SpriteApplier.NONE; + this.materialApplier = MaterialApplier.NONE; + } + + @SuppressWarnings("deprecation") + public Entry(Identifier texture, Optional materialSource) { + final Sprite sprite = MinecraftClient.getInstance().getSpriteAtlas(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE) + .apply(texture); + this.textureApplier = SpriteApplier.ofNullable(sprite); + final Optional materialSourceState = materialSource + .map(id -> Registry.BLOCK.get(id).getDefaultState()); + this.materialApplier = MaterialApplier.ofSpriteAndBlockState(sprite, materialSourceState.orElse(null)); + } + + } + + public static final Codec CODEC = Codec.STRING + .flatXmap(TextureSourceKind::fromString, kind -> DataResult.success(kind.toString())) + .dispatch(ts -> ts.kind, kind -> { + switch (kind) { + case SINGLE: + return RecordCodecBuilder.create( + inst -> inst.group(Single.SINGLE_CODEC.fieldOf("value").forGetter(i -> (Single) i)) + .apply(inst, i -> i)); + case SIDED: + return RecordCodecBuilder.create( + inst -> inst.group(Sided.SIDED_CODEC.fieldOf("value").forGetter(i -> (Single) i)) + .apply(inst, i -> i)); + default: + throw new IllegalStateException("Invalid TextureSourceKind:" + kind); + } + }); + + public final TextureSourceKind kind; + + protected TextureSource(final TextureSourceKind kind) { + this.kind = kind; + } + + public TransformResult apply(final MutableQuadView mqv, final Float4 us, Float4 vs, final Direction side) { + final Entry entry = entryFor(side); + entry.materialApplier.apply(mqv); + return entry.textureApplier.apply(mqv, us, vs); + } + + protected abstract Entry entryFor(final Direction side); + + public static class Single extends TextureSource implements ToOptional.Some { + public static final Codec SINGLE_CODEC = RecordCodecBuilder.create(inst -> inst + .group(Identifier.CODEC.fieldOf("texture").forGetter(s -> s.entry.textureApplier.id()), + Identifier.CODEC.optionalFieldOf("materialSource").forGetter(s -> s.entry.materialApplier.id())) + .apply(inst, Single::new)); + private final Entry entry; + + public Single(final Identifier texture, final Optional materialSourceId) { + super(TextureSourceKind.SINGLE); + entry = new Entry(texture, materialSourceId); + } + + @Override + protected Entry entryFor(Direction side) { + return entry; + } + } + + public static class Sided extends TextureSource implements ToOptional.Some { + public static final Codec SIDED_CODEC; + + static { + final Codec sidedValueCodec = RecordCodecBuilder.create(inst -> inst.group( + Identifier.CODEC.fieldOf("texture").forGetter(e -> e.textureApplier.id()), + Identifier.CODEC.optionalFieldOf("materialFrom").forGetter(e -> e.materialApplier.id())) + .apply(inst, Entry::new)); + + SIDED_CODEC = CODECS.sidedMapOf(sidedValueCodec).xmap( + map -> new Sided(new EnumMap<>(map)), + sided -> sided.entries); + } + + private final EnumMap entries; + + public Sided(final EnumMap entries) { + super(TextureSourceKind.SIDED); + for (final Direction dir : Direction.values()) { + entries.putIfAbsent(dir, Entry.NONE); + } + this.entries = entries; + } + + @Override + public Optional toOptional() { + return Optional.of(this); + } + + @Override + protected Entry entryFor(Direction side) { + return entries.get(side); + } + } + + public static final TextureSource NONE = new TextureSource(null) { + @Override + public Optional toOptional() { + return Optional.empty(); + } + + @Override + public T match(Function some, Supplier none) { + return none.get(); + } + + @Override + public TransformResult apply(MutableQuadView mqv, Float4 us, Float4 vs, Direction side) { + return TransformResult.NOTHING_TO_DO; + } + + @Override + protected Entry entryFor(Direction side) { + return null; + } + }; + +} diff --git a/src/client/java/modchest/assets/overlay/TextureSourceKind.java b/src/client/java/modchest/assets/overlay/TextureSourceKind.java new file mode 100644 index 0000000..6aa9c2e --- /dev/null +++ b/src/client/java/modchest/assets/overlay/TextureSourceKind.java @@ -0,0 +1,24 @@ +package modchest.assets.overlay; + +import com.ibm.icu.impl.locale.LocaleDistance.Data; +import com.mojang.serialization.DataResult; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +@Environment(EnvType.CLIENT) +public enum TextureSourceKind { + SINGLE, + SIDED; + + public static DataResult fromString(final String string) { + switch (string) { + case "single": + return DataResult.success(SINGLE); + case "sided": + return DataResult.success(SIDED); + default: + return DataResult.error("Invalid texture source:" + string); + } + } +} diff --git a/src/client/java/modchest/assets/overlay/ZeroOffsetter.java b/src/client/java/modchest/assets/overlay/ZeroOffsetter.java new file mode 100644 index 0000000..801f366 --- /dev/null +++ b/src/client/java/modchest/assets/overlay/ZeroOffsetter.java @@ -0,0 +1,35 @@ +package modchest.assets.overlay; + +import modchest.util.Float4; +import modchest.util.ToOptional; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.util.Identifier; + +@Environment(EnvType.CLIENT) +public class ZeroOffsetter implements Offsetter, ToOptional.Some { + private final Identifier id; + + public ZeroOffsetter(final Identifier id) { + this.id = id; + } + + @Override + public Float4 offset(final Float4 original) { + final float min = original.min(); + final float max = original.max(); + final float delta = max - min; + + if (original.a == min) { + return Float4.of(0, delta, delta, 0); + } else { + return Float4.of(delta, 0, 0, delta); + } + } + + @Override + public Identifier getId() { + return id; + } + +} diff --git a/src/client/java/modchest/block/custom/gridCodecs.java b/src/client/java/modchest/block/custom/gridCodecs.java new file mode 100644 index 0000000..109b7c1 --- /dev/null +++ b/src/client/java/modchest/block/custom/gridCodecs.java @@ -0,0 +1,68 @@ +package modchest.block.custom; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.jetbrains.annotations.Nullable; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.DataResult; +import com.mojang.serialization.codecs.RecordCodecBuilder; + +import modchest.assets.overlay.Offsetter; +import modchest.assets.overlay.OffsetterRegistry; +import modchest.util.Identifiable; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.util.Identifier; +import net.minecraft.util.Pair; +import net.minecraft.util.math.Direction; + +@Environment(EnvType.CLIENT) +public class gridCodecs { + public final Codec DIRECTION = Codec.STRING.flatXmap( + name -> { + Direction result = Direction.byName(name); + if (result != null) { + return DataResult.success(result); + } else { + return DataResult.error("Invalid direction:" + name); + } + }, + d -> DataResult.success(d.toString())); + + public final Codec OFFSETTER = Identifier.CODEC + .flatXmap( + id -> { + final @Nullable Identifiable> codec = OffsetterRegistry.get(id); + if (codec != null) { + return DataResult.success(codec); + } else { + return DataResult.error("Invalid offsetter type:" + id); + } + }, + codec -> DataResult.success(codec.id()) + ) + .dispatch( + o -> OffsetterRegistry.get(o.getId()), + codec -> RecordCodecBuilder.create(inst -> inst.group( + codec.value().fieldOf("value").forGetter(c -> c) + ).apply(inst, c -> c)) + ); + + public Codec> sideMapOf(final Codec valueCodec) { + final Codec, V>> itemCodec = RecordCodecBuilder.create(inst -> inst.group( + DIRECTION.listOf().fieldOf("sides").forGetter(Pair::getFirst), + valueCodec.fieldOf("value").forGetter(Pair::getSecond) + .apply(inst, Pair::new)); + + return itemCodec.listOf().xmap( + pairs -> pairs.stream().flatMap(pair -> pair.getFirst().stream().map(dir -> new Pair<>(dir, pair.getSecond()))).collect(Pair.toMap()), + map -> map.entrySet().stream().collect(Collectors.groupingBy(Map.Entry::getValue)) + .entrySet().stream() + .map(e -> new Pair<>(e.getValue().stream().map(Map.Entry::getKey).collect(Collectors.toList()), e.getKey())) + .collect(Collectors.toList())); + ) + } +} diff --git a/src/client/java/modchest/block/custom/gridConfig.java b/src/client/java/modchest/block/custom/gridConfig.java new file mode 100644 index 0000000..b930cc7 --- /dev/null +++ b/src/client/java/modchest/block/custom/gridConfig.java @@ -0,0 +1,20 @@ +package modchest.block.custom; + +import org.jetbrains.annotations.NotNull; +import org.spongepowered.asm.mixin.transformer.Config; + +public class gridConfig extends Config { + public static final ValueKey SHOW_PLACEMENT_PREVIEW = builder(true) + .with((oldValue, newValue) -> gridPreviewOutline.enabled = newValue) + .build(); + + @Override + public @NotNull ConfigSerializer getSerializer() { + return FlatOwenSerializer.INSTANCE; + } + + @Override + public @NotNull SaveType getSafeType() { + return SaveType.ROOT; + } +} diff --git a/src/client/java/modchest/block/custom/gridModelChange.java b/src/client/java/modchest/block/custom/gridModelChange.java new file mode 100644 index 0000000..0fbf6df --- /dev/null +++ b/src/client/java/modchest/block/custom/gridModelChange.java @@ -0,0 +1,168 @@ +/*package modchest.block.custom; + +import java.util.Collection; +import java.util.List; +import java.util.Set; +import java.util.function.Function; +import java.util.function.Supplier; + +import javax.swing.Renderer; + +import com.mojang.datafixers.util.Pair; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.renderer.v1.RendererAccess; +import net.fabricmc.fabric.api.renderer.v1.mesh.Mesh; +import net.fabricmc.fabric.api.renderer.v1.mesh.MeshBuilder; +import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView; +import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter; +import net.fabricmc.fabric.api.renderer.v1.model.FabricBakedModel; +import net.fabricmc.fabric.api.renderer.v1.render.RenderContext; +import net.minecraft.block.BlockState; +import net.minecraft.client.render.model.BakedModel; +import net.minecraft.client.render.model.BakedQuad; +import net.minecraft.client.render.model.ModelBakeSettings; +import net.minecraft.client.render.model.ModelLoader; +import net.minecraft.client.render.model.UnbakedModel; +import net.minecraft.client.render.model.json.ModelOverrideList; +import net.minecraft.client.render.model.json.ModelTransformation; +import net.minecraft.client.texture.Sprite; +import net.minecraft.client.texture.SpriteAtlasTexture; +import net.minecraft.client.util.SpriteIdentifier; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Identifier; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import net.minecraft.util.math.random.Random; +import net.minecraft.world.BlockRenderView; + +@Environment(EnvType.CLIENT) +public class gridModelChange implements UnbakedModel, BakedModel, FabricBakedModel { + + @Override + public boolean isVanillaAdapter() { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'isVanillaAdapter'"); + } + + @Override + public void emitBlockQuads(BlockRenderView blockView, BlockState state, BlockPos pos, + Supplier randomSupplier, RenderContext context) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'emitBlockQuads'"); + } + + @Override + public void emitItemQuads(ItemStack stack, Supplier randomSupplier, RenderContext context) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'emitItemQuads'"); + } + + @Override + public ModelOverrideList getOverrides() { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'getOverrides'"); + } + + @Override + public Sprite getParticleSprite() { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'getParticleSprite'"); + } + + @Override + public List getQuads(BlockState arg0, Direction arg1, Random arg2) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'getQuads'"); + } + + @Override + public ModelTransformation getTransformation() { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'getTransformation'"); + } + + @Override + public boolean hasDepth() { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'hasDepth'"); + } + + @Override + public boolean isBuiltin() { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'isBuiltin'"); + } + + @Override + public boolean isSideLit() { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'isSideLit'"); + } + + @Override + public boolean useAmbientOcclusion() { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'useAmbientOcclusion'"); + } + + @Override + public BakedModel bake(ModelLoader loader, Function textureGetter, ModelBakeSettings rotationContainer, Identifier modelId) { + + Get the sprites + for (int i = 0; i < SPRITE_IDS.length; ++i) { + sprites[i] = textureGetter.apply(SPRITE_IDS[i]); + } + // Build the mesh using the Renderer API + Renderer renderer = RendererAccess.INSTANCE.getRenderer(); + MeshBuilder builder = renderer.meshBuilder(); + QuadEmitter emitter = builder.getEmitter(); + + for (Direction direction : Direction.values()) { + // UP and DOWN share the Y axis + int spriteIdx = direction == Direction.UP || direction == Direction.DOWN ? SPRITE_TOP : SPRITE_SIDE; + // Add a new face to the mesh + emitter.square(direction, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f); + // Set the sprite of the face, must be called after .square() + // We haven't specified any UV coordinates, so we want to use the whole texture. + // BAKE_LOCK_UV does exactly that. + emitter.spriteBake(sprites[spriteIdx], MutableQuadView.BAKE_LOCK_UV); + // Enable texture usage + emitter.color(-1, -1, -1, -1); + // Add the quad to the mesh + emitter.emit(); + } + mesh = builder.build(); + + return this; + } + + @Override + public Collection getModelDependencies() { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'getModelDependencies'"); + } + + @Override + public Collection getTextureDependencies(Function unbakedModelGetter, + Set> unresolvedTextureReferences) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'getTextureDependencies'"); + } + + /*@SuppressWarnings("deprecation") + private static final SpriteIdentifier[] SPRITE_IDS = new SpriteIdentifier[] { + new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE, + new Identifier("minecraft:block/furnace_front_on")), + new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE, new Identifier("minecraft:block/furnace_top")) + }; + private final Sprite[] sprites = new Sprite[SPRITE_IDS.length]; + + // Some constants to avoid magic numbers, these need to match the SPRITE_IDS + private static final int SPRITE_SIDE = 0; + private static final int SPRITE_TOP = 1; + + private Mesh mesh; + +} */ \ No newline at end of file diff --git a/src/client/java/modchest/block/custom/gridPreviewOutline.java b/src/client/java/modchest/block/custom/gridPreviewOutline.java new file mode 100644 index 0000000..2318b3c --- /dev/null +++ b/src/client/java/modchest/block/custom/gridPreviewOutline.java @@ -0,0 +1,203 @@ +package modchest.block.custom; + +import static net.minecraft.block.Block.field_31022; + +import java.nio.ByteBuffer; +import java.nio.IntBuffer; +import java.util.Properties; + +import org.lwjgl.system.MemoryStack; + +import modchest.event.playerAfterRespawnEvent; +import modchest.grid.gridBlock; +import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext; +import net.fabricmc.fabric.api.renderer.v1.model.ModelHelper; +import net.fabricmc.tinyremapper.extension.mixin.hard.util.CamelPrefixString; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.enums.DoubleBlockHalf; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.client.render.Camera; +import net.minecraft.client.render.OverlayTexture; +import net.minecraft.client.render.TexturedRenderLayers; +import net.minecraft.client.render.VertexConsumer; +import net.minecraft.client.render.VertexFormats; +import net.minecraft.client.render.WorldRenderer; +import net.minecraft.client.render.model.BakedModel; +import net.minecraft.client.render.model.BakedQuad; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.client.util.math.Vector3d; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.item.BlockItem; +import net.minecraft.item.ItemPlacementContext; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Hand; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.hit.HitResult; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Matrix4f; +import net.minecraft.util.math.Vec3i; +import net.minecraft.util.math.Vector4f; + +public class gridPreviewOutline { + public static boolean enanbled = true; + + public static void renderPreviewOutline(final WorldRenderContext context) { + if (!enanbled) { + return; + } + + final MinecraftClient client = MinecraftClient.getInstance(); + + final ClientPlayerEntity player = client.player; + if (player == null) { + return; + } + + final ItemStack stack = player.getStackInHand(Hand.MAIN_HAND); + if (!(stack.getItem() instanceof BlockItem)) { + return; + } + + final Block block = ((BlockItem) stack.getItem()).getBlock(); + if (!(block instanceof gridBlock)) { + return; + } + + if (!(client.crosshairTarget instanceof BlockHitResult) + || client.crosshairTarget.getType() == HitResult.Type.MISS || client.world == null) { + return; + } + + final BlockHitResult hitResult = (BlockHitResult) client.crosshairTarget; + final ItemPlacementContext placementContext = new ItemPlacementContext(player, Hand.MAIN_HAND, stack, + hitResult); + final BlockState blockState = ((BlockItemAccess) player.getMainHandStack().getItem()) + .getPlacementStateProxy(placementContext); + + if (blockState == null) { + return; + } + + final BlockPos pos = placementContext.getBlockPos(); + final BakedModel model = client.getBlockRenderManager().getModel(blockState); + final boolean valid; + + if (block == Blocks.GRID_DOOR) { + final BlockPos upPos = pos.up(); + final BlockState upState = blockState.with(Properties.DOUBLE_BLOCK_HALF, DoubleBlockHalf.UPPER); + final BakedModel upModel = client.getBlockRenderManager().getModel(upState); + final boolean upValid = new ItemPlacementContext(player, Hand.MAIN_HAND, stack, + hitResult.withBlockPos(upPos)).canReplaceExisting() || client.world.getBlockState(upPos).isAir(); + final boolean downValid = blockState.canPlaceAt(client.world, pos) + && (placementContext.canPlace() || client.world.getBlockState(pos).isAir()); + if (!upValid) { + valid = false; + } else { + valid = downValid; + } + + renderPreview(context, client.world, upState, upPos, upModel, upValid && downValid); + + } else { + valid = blockState.canPlaceAt(client.world, pos) + && (placementContext.canPlace() || client.world.getBlockState(pos).isAir()); + } + + renderPreview(context, client.world, blockState, pos, model, valid); + } + + private static void renderPreview(final WorldRenderContext context, final ClientWorld world, + final BlockState blockState, final BlockPos pos, final BakedModel model, final boolean valid) { + final MatrixStack matrixStack = context.matrixStack(); + final Camera camera = context.camera(); + final int ticks = ((WorldRendererAccess) context.worldRenderer()).ticks(); + final float tickDelta = context.tickDelta(); + + for (int directionId = 0; directionId <= 6; directionId++) { + final List quads = model.getQuads(blockState, ModelHelper.faceFromIndex(directionId), + world.random); + + matrixStack.push(); + matrixStack.translate(-camera.getPos().x, -camera.getPos().y, -camera.getPos().z); + matrixStack.translate(pos.getX(), pos.getY(), pos.getZ()); + + if (blockState.contains(Properties.HORIZONTAL_FACING)) { + matrixStack.translate(0.5, 0.5, 0.5); + matrixStack.translate(-0.5, -0.5, -0.5); + } + + final float scale = 1F - (1F / 60) + ((float) Math.sin((ticks + tickDelta) / 4.5F) / 60); + matrixStack.translate(-0.5 * scale, -0.5 * scale, -0.5 * scale); + matrixStack.translate(scale, scale, scale); + matrixStack.translate(0.5 / scale, 0.5 / scale, 0.5 / scale); + + final int c = 0; + final int r = valid ? c : 255; + final int g = valid ? 255 : c; + final int b = valid ? 64 : 0; + final int a = valid ? 191 : 63; + + final MatrixStack.Entry entry = matrixStack.peek(); + + final VertexConsumer faces = context.consumers() + .getBuffer(TexturedRenderLayers.getItemEntityTranslucentCull()); + for (final BakedQuad quad : quads) { + render(quad, entry, faces, r, g, b, a); + } + matrixStack.pop(); + } + } + + private static void render(final BakedQuad quad, final MatrixStack.Entry entry, final VertexConsumer consumer, + final float r, final float g, final float b, final float a) { + final int[] vertexData = quad.getVertexData(); + final Vec3i vector = quad.getFace().getVector(); + final Vector3f newVector = new Vector3f((float) vec3i.getX(), (float) vec3i.getY(), (float) vec3i.getZ()); + final Matrix4f model = entry.getModel(); + newVector.transform(entry.getNormal()); + + final int j = vertexData.length / 8; + final MemoryStack memoryStack = MemoryStack.stackPush(); + Throwable var17 = null; + + try { + final ByteBuffer byteBuffer = memoryStack + .malloc(VertexFormats.POSITION_COLOR_TEXTURE_LIGHT_NORMAL.getVertexSize()); + final IntBuffer intBuffer = byteBuffer.asIntBuffer(); + + for (int k = 0; k < j; ++k) { + intBuffer.clear(); + intBuffer.put(vertexData, k * 8, 8); + final float x = byteBuffer.getFloat(0); + final float y = byteBuffer.getFloat(4); + final float z = byteBuffer.getFloat(8); + final float v; + final float w; + + final int u = 0x00F000F0; + v = byteBuffer.getFloat(16); + w = byteBuffer.getFloat(20); + final Vector4f vector4f = new Vector4f(x, y, z, 1.0F); + vector4f.transform(model); + consumer.vertex(vector4f.getX(), vector4f.getY(), vector4f.getZ(), r / 255F, g / 255F, b / 255F, + a / 255F, v, w, OverlayTexture.DEFAULT_UV, u, newVector.getX(), newVector.getY(), + newVector.getZ()); + } + } catch (final Throwable var38) { + var17 = var38; + throw var38; + } finally { + if (var17 != null) { + try { + memoryStack.close(); + } catch (final Throwable var37) { + var17.addSuppressed(var37); + } + } else { + memoryStack.close(); + } + } + } +} diff --git a/src/client/java/modchest/gui/gridScreen.java b/src/client/java/modchest/gui/gridScreen.java new file mode 100644 index 0000000..b36d478 --- /dev/null +++ b/src/client/java/modchest/gui/gridScreen.java @@ -0,0 +1,18 @@ +package modchest.gui; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.client.screenhandler.v1.ScreenRegistry; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.text.Text; + +@Environment(EnvType.CLIENT) +public class gridScreen extends CottonInventoryScreen{ + @SuppressWarnings("deprecation") + public static final ScreenRegistry.Factory FACTORY = (desc, playerInventory, title) -> + new gridScreen(desc, playerInventory.player, title); + + public gridScreen(final gridGuiDescription description, final PlayerEntity player, final Text title) { + super(description, player, title); + } +} diff --git a/src/client/java/modchest/networking/packet/gridRenderRequestS2CPacket.java b/src/client/java/modchest/networking/packet/gridRenderRequestS2CPacket.java index c4e8627..96ad1c5 100644 --- a/src/client/java/modchest/networking/packet/gridRenderRequestS2CPacket.java +++ b/src/client/java/modchest/networking/packet/gridRenderRequestS2CPacket.java @@ -1,66 +1,230 @@ -package modchest.networking.packet; +/* + * package modchest.networking.packet; + * + * import static net.minecraft.block.Block.getBlockFromItem; + * + * import java.util.Random; + * + * import modchest.block.custom.grid.gridBlock; + * import modchest.rendering.gridBlockTexture; + * import net.fabricmc.fabric.api.networking.v1.PacketSender; + * import net.minecraft.block.Block; + * import net.minecraft.block.BlockState; + * import net.minecraft.block.Blocks; + * import net.minecraft.block.entity.BlockEntity; + * import net.minecraft.client.MinecraftClient; + * import net.minecraft.client.color.block.BlockColors; + * import net.minecraft.client.network.ClientPlayNetworkHandler; + * import net.minecraft.client.render.BufferBuilder; + * import net.minecraft.client.render.OverlayTexture; + * import net.minecraft.client.render.RenderLayer; + * import net.minecraft.client.render.Tessellator; + * import net.minecraft.client.render.VertexConsumer; + * import net.minecraft.client.render.VertexConsumerProvider; + * import net.minecraft.client.render.VertexFormat; + * import net.minecraft.client.render.VertexFormats; + * import net.minecraft.client.render.WorldRenderer; + * import net.minecraft.client.render.block.BlockModelRenderer; + * import net.minecraft.client.render.entity.ItemFrameEntityRenderer; + * import net.minecraft.client.render.model.BakedModel; + * import net.minecraft.client.util.ModelIdentifier; + * import net.minecraft.client.util.SpriteIdentifier; + * import net.minecraft.client.util.math.MatrixStack; + * import net.minecraft.entity.decoration.ItemFrameEntity; + * import net.minecraft.entity.player.PlayerEntity; + * import net.minecraft.nbt.NbtCompound; + * import net.minecraft.network.PacketByteBuf; + * import net.minecraft.text.Text; + * import net.minecraft.util.Identifier; + * import net.minecraft.util.math.BlockPos; + * import net.minecraft.util.math.Matrix3f; + * import net.minecraft.util.math.Matrix4f; + * import net.minecraft.world.BlockRenderView; + * + * public class gridRenderRequestS2CPacket extends BlockModelRenderer { + * + * public gridRenderRequestS2CPacket(BlockColors colors) { + * super(colors); + * // TODO Auto-generated constructor stub + * } + * + * + * + * public static void receive(MinecraftClient minecraftClient, + * ClientPlayNetworkHandler clientPlayNetworkHandler, + * PacketByteBuf buffer, PacketSender PacketSender) { + * + * NbtCompound nbtgrid = buffer.readNbt(); + * int[] gridPostitionAr = nbtgrid.getIntArray("gridBlockPos"); + * int x = gridPostitionAr[0]; + * int y = gridPostitionAr[1]; + * int z = gridPostitionAr[2]; + * BlockPos gridBlockPos = new BlockPos(x, y, z); + * + * + * /*PlayerEntity playerEntity = minecraftClient.player; + * playerEntity.sendMessage(Text.of("gridRenderRequestS2CPacket.receive")); + * BlockRenderView world = minecraftClient.world; + * + * NbtCompound nbtgrid = buffer.readNbt(); + * int[] gridPostitionAr = nbtgrid.getIntArray("gridBlockPos"); + * int x = gridPostitionAr[0]; + * int y = gridPostitionAr[1]; + * int z = gridPostitionAr[2]; + * BlockPos gridBlockPos = new BlockPos(x, y, z); + * + * /* + * long seed = nbtgrid.getLong("WorldSeed"); + * Random randomGrid = new Random(seed); + * BlockState gridBlockState = world.getBlockState(gridBlockPos); + * //playerEntity.sendMessage(Text.of(gridBlockState.toString())); // + * {minecraft:spruce_planks} + * Block BlockInHand = + * getBlockFromItem(playerEntity.getMainHandStack().getItem()); + * String inHandData = BlockInHand.getDefaultState().toString(); + * //playerEntity.sendMessage(Text.of(inHandData)); // Bsp: + * {minecraft:warped_planks} + * BlockState stateInHand = BlockInHand.getDefaultState(); + * Object obj = inHandData.split("minecraft:"); + * //playerEntity.sendMessage(Text.of(obj.toString())); // Bsp: + * java.lang.string;@4f4001c7 + * Identifier gridBlockId = new Identifier("modchest", "block/grid_block"); // + * Mod-ID + Blockpfad + * //playerEntity.sendMessage(Text.of(gridBlockId.toString())); + * // minecraftClient.getBakedModelManager().getBlockModels(); + * // minecraftClient.getSpriteAtlas(gridBlockTexture.getBlockInHandId(null)); + * playerEntity.sendMessage(Text.of("before bracket")); + * + * //ModelIdentifier gridModelId = (ModelIdentifier) gridBlockId; -> geht nicht, + * gridBlockId nicht instance of ModelIdentifier + * // playerEntity.sendMessage(Text.of(gridModelId.toString())); + * //BakedModel gridModel = + * MinecraftClient.getInstance().getBakedModelManager().getModel(gridModelId); + * //int overlay = OverlayTexture.DEFAULT_UV; + * //MatrixStack matrix = new MatrixStack(); + * //MatrixStack.Entry matrix; + * //Tessellator tessellator = Tessellator.getInstance(); + * //Matrix4f positionMatrix = + * drawContext.getMatrices().peek().getPositionMatrix(); + * //BufferBuilder builder = tessellator.getBuffer(); + * /*builder.begin(VertexFormat.DrawMode.QUADS, + * VertexFormats.POSITION_COLOR_TEXTURE); + * builder.vertex(positionMatrix, 20, 20, 0).color(1f, 1f, 1f, 1f).texture(0f, + * 0f).next(); + * builder.vertex(positionMatrix, 20, 60, 0).color(1f, 0f, 0f, 1f).texture(0f, + * 1f).next(); + * builder.vertex(positionMatrix, 60, 60, 0).color(0f, 1f, 0f, 1f).texture(1f, + * 1f).next(); + * builder.vertex(positionMatrix, 60, 20, 0).color(0f, 0f, 1f, 1f).texture(1f, + * 0f).next(); + * // RenderSystem.setShader(null); + * // RenderSystem.setShaderTexture(0, new Identifier("REServerMod", + * // "block/grid_block_texture.png")); + * // RenderSystem.setShaderColor(1f, 1f, 1f, 1f); + * tessellator.draw(); + * builder.begin(VertexFormat.DrawMode.QUADS, + * VertexFormats.POSITION_COLOR_TEXTURE_OVERLAY_LIGHT_NORMAL); //kaputt + * builder.vertex(1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1); //kaputt + * builder.popState(); //funktioniert ohne Zwei Zeilen davor + */ +// drawContext.getMatrices().peek().getPositionMatrix(): Matrix4f positionMatrix +// = drawContext.getMatrices().peek().getPositionMatrix(); -import static net.minecraft.block.Block.getBlockFromItem; - -/*import modchest.rendering.gridBlockRender; -import modchest.rendering.gridBlockTexture;*/ -import net.fabricmc.fabric.api.networking.v1.PacketSender; -import net.minecraft.block.Block; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.color.block.BlockColors; -import net.minecraft.client.network.ClientPlayNetworkHandler; -import net.minecraft.client.network.ClientPlayerEntity; -import net.minecraft.client.render.block.BlockModelRenderer; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.network.PacketByteBuf; -import net.minecraft.text.Text; -import net.minecraft.util.math.BlockPos; - -public class gridRenderRequestS2CPacket extends BlockModelRenderer { - - public gridRenderRequestS2CPacket(BlockColors colors) { - super(colors); - // TODO Auto-generated constructor stub - } - - public static void receive(MinecraftClient minecraftClient, ClientPlayNetworkHandler clientPlayNetworkHandler, - PacketByteBuf buffer, PacketSender PacketSender) { - // clientPlayNetworkHandler.getWorld(); - NbtCompound nbtgrid = buffer.readNbt(); - int[] positionarray = nbtgrid.getIntArray("BlockPosition"); - Integer h = positionarray[0]; - Integer i = positionarray[1]; - Integer j = positionarray[2]; - - BlockPos gridBlockPos = new BlockPos(h, i, j); - - // minecraftClient.getBakedModelManager().getBlockModels(); - // minecraftClient.getSpriteAtlas(gridBlockTexture.getBlockInHandId(null)); - - //BlockRenderView world = minecraftClient.world; - - /*@Nullable - BlockState gridBlockState = getStateFromRawId(FORCE_STATE); - MatrixStack matrix = new MatrixStack(); - MatrixStack.Entry entry; - Random randomGrid = new Random(); - long seed = 7756495;*/ - - PlayerEntity playerEntity = minecraftClient.player; - Block BlockInHand = getBlockFromItem(playerEntity.getMainHandStack().getItem()); - String inHandData = BlockInHand.getDefaultState().toString(); - playerEntity.sendMessage(Text.of(inHandData)); - - //Identifier testBlockId = new Identifier("modchest", "block/test_block"); // Mod-ID + Blockpfad - //ModelIdentifier testModelId = new ModelIdentifier(testBlockId, "all"); // Verwende "normal" als Variante - //BakedModel gridModel = MinecraftClient.getInstance().getBakedModelManager().getModel(testModelId); - - /* - * gridBlockRender.render(world, BakedModel model, gridBlockState, gridBlockPos, - * matrix, gridConsumer, true, randomGrid, seed, overlay); - */ - - } - -} +/* + * Tessellator tessellator = Tessellator.getInstance(); + * BufferBuilder bufferBuilder = tessellator.getBuffer(); + * + * MatrixStack matrices = new MatrixStack(); + * BlockState defaultState = Blocks.STONE.getDefaultState(); + * playerEntity.sendMessage(Text.of(defaultState.toString())); + * VertexConsumerProvider consumers = + * VertexConsumerProvider.immediate(bufferBuilder); + * playerEntity.sendMessage(Text.of(consumers.toString())); + * Identifier TEXTURE = new Identifier("modchest", + * "textures/block/texture_test.png"); + * playerEntity.sendMessage(Text.of(TEXTURE.toString())); + * //SpriteIdentifier SPRITE = ; + * //SpriteIdentifier#getVertexConsumer( consumers, LAYER_SUPPLIER ) // to use a + * sprite as a texture + * //VertexConsumer consumer = consumers.getBuffer(RenderLayer.getCutout()); + * //VertexConsumer consumer = + * consumers.getBuffer(RenderLayer.getEntityCutout(TEXTURE)); + * //playerEntity.sendMessage(Text.of(consumer.toString())); + * /*MatrixStack.Entry matrix = matrices.peek(); + * matrices.push(); + * matrices.translate(0.5, 0.5, 0.5); + * Matrix4f model = matrix.getPositionMatrix(); + * Matrix3f normal = matrix.getNormalMatrix(); + * int r = 225; + * int g = 255; + * int b = 255; + * int a = 200; + * + * //int light = gridBlockState.getLuminance(); + * int light = WorldRenderer.getLightmapCoordinates(world, gridBlockPos); + * int overlay = OverlayTexture.DEFAULT_UV; + * + * consumer.vertex(model, -0.5f, -0.5f, -0.5f).color(r, g, b, a).texture(0, + * 0).overlay(overlay).light(light).normal(normal, 0.0F, 1.0F, 0.0F).next(); + * consumer.vertex(model, 0.5f, -0.5f, -0.5f).color(r, g, b, a).texture(1, + * 0).overlay(overlay).light(light).normal(normal, 0.0F, 1.0F, 0.0F).next(); + * consumer.vertex(model, 0.5f, -0.5f, 0.5f).color(r, g, b, a).texture(1, + * 1).overlay(overlay).light(light).normal(normal, 0.0F, 1.0F, 0.0F).next(); + * consumer.vertex(model, -0.5f, -0.5f, 0.5f).color(r, g, b, a).texture(0, + * 1).overlay(overlay).light(light).normal(normal, 0.0F, 1.0F, 0.0F).next(); + * matrices.pop(); + * + * MinecraftClient.getInstance().getBlockRenderManager().renderBlockAsEntity( + * defaultState, matrices, consumers, light, overlay); + * + * /* + * + * SpriteIdentifier SPRITE =; + * // solid layer, no texture + * VertexConsumer consumer = consumers.getBuffer(RenderLayer.getSolid()); + * // cutout layer, textured + * VertexConsumer consumer = + * consumers.getBuffer(RenderLayer.getEntityCutout(TEXTURE)); + * // cutout layer, textured (sprite) + * VertexConsumer consumer = SPRITE.getVertexConsumer(consumers, + * RenderLayer::getEntityCutout); + * Identifier texture = new Identifier("textures/block/texture_test.png"); + * // set texture and enable transparency + * VertexConsumer consumer = + * consumers.getBuffer(RenderLayer.getEntityTranslucentCull(texture)); + * MatrixStack.Entry matrix = matrices.peek(); + * // translate to the middle of the block + * matrices.push(); + * matrices.translate(0.5, 0.5, 0.5); + * Matrix4f model = matrix.getModel(); + * Matrix3f normal = matrix.getNormal(); + * int r = 255; + * int g = 255; + * int b = 255; + * int a = 200; + * // use the value provided (in block entity renderer) for breaking animation, + * or + * // use 'OverlayTexture.DEFAULT_UV' to disable breaking animation + * int overlay = OverlayTexture.DEFAULT_UV; + * // provided by block entity renderer, or queried from WorldRenderer: + * // (use only to query light at positions different than provided) + * int light = WorldRenderer.getLightmapCoordinates(world, gridBlockPos); + * // emit 4 vertices - one quad + * consumer.vertex(model, -0.5f, -0.5f, -0.5f).color(r, g, b, a).texture(0, + * 0).overlay(overlay).light(light).normal(normal, 0.0F, 1.0F, 0.0F).next(); + * consumer.vertex(model, 0.5f, -0.5f, -0.5f).color(r, g, b, a).texture(1, + * 0).overlay(overlay).light(light).normal(normal, 0.0F, 1.0F, 0.0F).next(); + * consumer.vertex(model, 0.5f, -0.5f, 0.5f).color(r, g, b, a).texture(1, + * 1).overlay(overlay).light(light).normal(normal, 0.0F, 1.0F, 0.0F).next(); + * consumer.vertex(model, -0.5f, -0.5f, 0.5f).color(r, g, b, a).texture(0, + * 1).overlay(overlay).light(light).normal(normal, 0.0F, 1.0F, 0.0F).next(); + * matrices.pop(); + * + * + * // gridBlockRender.render(world, gridModel, gridBlockState, gridBlockPos, + * // matrix, gridConsumer, true, randomGrid, seed, overlay); + * + * } + * + * } + */ diff --git a/src/client/java/modchest/rendering/gridBlockRender.java b/src/client/java/modchest/rendering/gridBlockRender.java deleted file mode 100644 index 404969a..0000000 --- a/src/client/java/modchest/rendering/gridBlockRender.java +++ /dev/null @@ -1,24 +0,0 @@ -package modchest.rendering; - -import net.minecraft.block.BlockState; -import net.minecraft.client.color.block.BlockColors; -import net.minecraft.client.render.VertexConsumer; -import net.minecraft.client.render.block.BlockModelRenderer; -import net.minecraft.client.render.model.BakedModel; -import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.random.Random; -import net.minecraft.world.BlockRenderView; - -public class gridBlockRender extends BlockModelRenderer{ - - public gridBlockRender(BlockColors colors) { - super(colors); - } - - @Override - public void render(BlockRenderView world, BakedModel model, BlockState state, BlockPos pos, - MatrixStack matrices, VertexConsumer vertexConsumer, boolean cull, Random random, long seed, int overlay) { - - } -} diff --git a/src/client/java/modchest/transform/BaseApplier.java b/src/client/java/modchest/transform/BaseApplier.java new file mode 100644 index 0000000..ed234d9 --- /dev/null +++ b/src/client/java/modchest/transform/BaseApplier.java @@ -0,0 +1,96 @@ +package modchest.transform; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import java.util.function.Function; +import java.util.function.Supplier; + +import it.unimi.dsi.fastutil.objects.Object2IntMap; +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +import modchest.util.Float4; +import modchest.util.ToOptional; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView; +import net.fabricmc.fabric.api.renderer.v1.model.ModelHelper; +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.Direction; +import net.minecraft.util.math.random.Random; + +@Environment(EnvType.CLIENT) +public abstract class BaseApplier implements ToOptional { + public abstract TransformResult apply(MutableQuadView mqv, Direction dir, int index, Float4 vs, int color); + + public static final BaseApplier NONE = new BaseApplier() { + @Override + public TransformResult apply(MutableQuadView mqv, Direction dir, int index, Float4 vs, int color) { + return TransformResult.NOTHING_TO_DO; + } + + @Override + public Optional toOptional() { + return Optional.empty(); + } + + @Override + public T match(final Function some, final Supplier none) { + return none.get(); + } + }; + + public static class Some extends BaseApplier implements ToOptional.Some { + private final BlockState state; + private final Object2IntMap sizes = new Object2IntOpenHashMap<>(7); + private final Map spriteAppliers = new HashMap<>(7); + private final Map materialAppliers = new HashMap<>(7); + private final Map colorAppliers = new HashMap<>(7); + + public Some(final BlockState state, final BakedModel model, final Random r) { + this.state= state; + for (int i = 0; i<= 6; i++) { + final Direction dir = ModelHelper.faceFromIndex(i); + final List quads = model.getQuads(state, dir, r); + final int size = quads.size(); + sizes.put(dir, size); + final SpriteApplier[] spriteAppliers = this.spriteAppliers.computeIfAbsent(dir, x -> new SpriteAppliers[size]); + final MaterialApplier[] materialAppliers = this.materialAppliers.computeIfAbsent(dir, x -> new MaterialApplier[size]); + final LazyColorApplier[] colorAppliers = this.colorAppliers.computeIfAbsent(dir, x -> new LazyColorApplier[size]); + + for(int j = 0; j < size; j++) { + final BakedQuad quad = quads.get(j); + final Sprite sprite = ((BakedQuadAccess) quad).sprite(); + spriteAppliers[j] = new SpriteApplier.Some(sprite); + materialAppliers[j] = new MaterialApplier,ofSpriteAndBlockState(sprite, state); + + if (quad.hasColor()) { + colorAppliers[j] = new LazyColorApplier.Some(); + } else { + colorAppliers[j] = LazyColorApplier.NONE; + } + + } + + } + } + + @Override + public TransformResult apply(MutableQuadView mqv, Direction dir, int quadIndex, Float4 vs, int color) { + int size = sizes.getInt(dir); + if (size == 0) { + return TransformResult.failed(String.format("No %s quads in model for %s", dir, state)); + } + final int index = quadIndex % size; + materialAppliers.get(dir)[index].apply(mqv); + colorAppliers.get(dir)[index].apply(mqv, color); + return spriteAppliers.get(dir)[index].apply(mqv, us, vs); + } + + } + +} \ No newline at end of file diff --git a/src/client/java/modchest/transform/ColorApplier.java b/src/client/java/modchest/transform/ColorApplier.java new file mode 100644 index 0000000..343fb33 --- /dev/null +++ b/src/client/java/modchest/transform/ColorApplier.java @@ -0,0 +1,56 @@ +package modchest.transform; + +import java.util.Optional; +import java.util.OptionalInt; +import java.util.function.Function; +import java.util.function.Supplier; + +import modchest.util.ToOptional; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView; + +@Environment(EnvType.CLIENT) +public abstract class ColorApplier implements ToOptional { + @SuppressWarnings("OptionalUsedAsFieldOrParameterType") + public static ColorApplier ofOptional(final OptionalInt optional) { + if (optional.isPresent()) { + return new Some(optional.getAsInt()); + } else { + return NONE; + } + } + + public abstract void apply(MutableQuadView mqv); + + @SuppressWarnings("java:S1186") + public static final ColorApplier NONE = new ColorApplier() { + @Override + public void apply(final MutableQuadView mqv) { + } + + @Override + public Optional toOptional() { + return Optional.empty(); + } + + @Override + public T match(final Function some, final Supplier none) { + return none.get(); + } + }; + + public static class Some extends ColorApplier implements ToOptional.Some { + private final int color; + + public Some(final int color) { + this.color = color; + } + + @Override + public void apply(final MutableQuadView mqv) { + mqv.spriteColor(0, color, color, color, color); + } + + } +} diff --git a/src/client/java/modchest/transform/LazyColorApplier.java b/src/client/java/modchest/transform/LazyColorApplier.java new file mode 100644 index 0000000..a4804fb --- /dev/null +++ b/src/client/java/modchest/transform/LazyColorApplier.java @@ -0,0 +1,26 @@ +package modchest.transform; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView; + +@Environment(EnvType.CLIENT) +public abstract class LazyColorApplier { + @SuppressWarnings("java:S1186") + public static final LazyColorApplier NONE = new LazyColorApplier() { + @Override + public void apply(final MutableQuadView mqv, final int color) { + } + }; + + public abstract void apply(MutableQuadView mqv, int color); + + public static class Some extends LazyColorApplier { + @Override + public void apply(final MutableQuadView mqv, final int color) { + mqv.spriteColor(0, color, color, color, color); + } + + } + +} diff --git a/src/client/java/modchest/transform/MaterialApplier.java b/src/client/java/modchest/transform/MaterialApplier.java new file mode 100644 index 0000000..3d2f028 --- /dev/null +++ b/src/client/java/modchest/transform/MaterialApplier.java @@ -0,0 +1,62 @@ +package modchest.transform; + +import java.util.Optional; + +import javax.swing.text.html.Option; + +import org.jetbrains.annotations.NotNull; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.renderer.v1.material.RenderMaterial; +import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView; +import net.minecraft.block.BlockState; +import net.minecraft.client.texture.Sprite; +import net.minecraft.util.Identifier; +import net.minecraft.util.registry.Registry; + +@Environment(EnvType.CLIENT) +public abstract class MaterialApplier { + public static MaterialApplier ofSpriteAndBlockState(@NotNull final Sprite sprite, @NotNull final BlockState blockState) { + if (blockState == null) { + return NONE; + } + final RenderMaterial material = MaterialMap.get(blockState).getMapped(sprite); + final Identifier id = Registry.BLOCK.getId(blockState.getBlock()); + return MaterialApplier.ofNullable(id, material); + } + + public static final MaterialApplier NONE = new MaterialApplier() { + @Override + public void apply(final MutableQuadView mqv) {} + + @Override + public Optional id() { + return Optional.empty(); + } + }; + + public abstract void apply(MutableQuadView mqv); + public abstract Optional id(); + + public static class Some extends MaterialApplier { + private final @NotNull Identifier id; + private final @NotNull RenderMaterial toApply; + + public Some(final @NotNull Identifier id, final @NotNull RenderMaterial toApply) { + this.toApply = toApply; + this.id = id; + } + + @Override + public void apply(final MutableQuadView mqv) { + mqv.material(toApply); + } + + @Override + public Optional id() { + return Optional.of(id); + } + } + +} diff --git a/src/client/java/modchest/transform/SpriteApplier.java b/src/client/java/modchest/transform/SpriteApplier.java new file mode 100644 index 0000000..f7192fc --- /dev/null +++ b/src/client/java/modchest/transform/SpriteApplier.java @@ -0,0 +1,66 @@ +package modchest.transform; + +import org.jetbrains.annotations.Nullable; + +import modchest.util.Float4; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView; +import net.minecraft.client.texture.MissingSprite; +import net.minecraft.client.texture.Sprite; +import net.minecraft.util.Identifier; +import net.minecraft.util.math.MathHelper; + +@Environment(EnvType.CLIENT) +public abstract class SpriteApplier { + public static SpriteApplier ofNullable(@Nullable final Sprite toApply) { + if (toApply != null) { + return new Some(toApply); + } else { + return NONE; + } + } + + public abstract TransformResult apply(MutableQuadView mqv, Float4 us, Float4 vs); + + public abstract Identifier id(); + + public static final SpriteApplier NONE = new SpriteApplier() { + @Override + public TransformResult apply(final MutableQuadView mqv, final Float4 us, final Float4 vs) { + return TransformResult.NOTHING_TO_DO; + } + + @Override + public Identifier id() { + return MissingSprite.getMissingSpriteId(); + } + }; + + public static class Some extends SpriteApplier { + private final Sprite toApply; + + public Some(final Sprite toApply) { + this.toApply = toApply; + } + + @Override + public TransformResult apply(final MutableQuadView mqv, final Float4 us, final Float4 vs) { + mqv.sprite(0, 0, MathHelper.lerp(us.a, toApply.getMinU(), toApply.getMaxU()), + MathHelper.lerp(vs.a, toApply.getMinV(), toApply.getMaxV())); + mqv.sprite(1, 0, MathHelper.lerp(us.b, toApply.getMinU(), toApply.getMaxU()), + MathHelper.lerp(vs.b, toApply.getMinV(), toApply.getMaxV())); + mqv.sprite(2, 0, MathHelper.lerp(us.c, toApply.getMinU(), toApply.getMaxU()), + MathHelper.lerp(vs.c, toApply.getMinV(), toApply.getMaxV())); + mqv.sprite(3, 0, MathHelper.lerp(us.d, toApply.getMinU(), toApply.getMaxU()), + MathHelper.lerp(vs.d, toApply.getMinV(), toApply.getMaxV())); + return TransformResult.DID_SOMETHING; + } + + @Override + public Identifier id() { + return toApply.getId(); + } + + } +} diff --git a/src/client/java/modchest/transform/TransformResult.java b/src/client/java/modchest/transform/TransformResult.java new file mode 100644 index 0000000..cccbe97 --- /dev/null +++ b/src/client/java/modchest/transform/TransformResult.java @@ -0,0 +1,31 @@ +package modchest.transform; + +import org.jetbrains.annotations.Nullable; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +@Environment(EnvType.CLIENT) +public class TransformResult { + public enum Status { + DID_SOMETHING, + NOTHING_TO_DO, + FAILED,; + } + + public static final TransformResult DID_SOMETHING = new TransformResult(Status.DID_SOMETHING, null); + public static final TransformResult NOTHING_TO_DO = new TransformResult(Status.NOTHING_TO_DO, null); + + public final Status status; + public final @Nullable String message; + + private TransformResult(Status status, @Nullable String message) { + this.status = status; + this.message = message; + } + + public static TransformResult failed(String message) { + return new TransformResult(Status.FAILED, message); + } + +} diff --git a/src/client/java/modchest/transform/gridTransform.java b/src/client/java/modchest/transform/gridTransform.java new file mode 100644 index 0000000..a198457 --- /dev/null +++ b/src/client/java/modchest/transform/gridTransform.java @@ -0,0 +1,207 @@ +package modchest.transform; + +import java.util.EnumMap; +import java.util.List; +import java.util.Optional; +import java.util.OptionalInt; +import java.util.function.Supplier; +import java.util.stream.IntStream; + +import modchest.block.custom.grid.gridSlotInfo; +import modchest.grid.data.gridData; +import modchest.util.Float4; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.client.rendering.v1.ColorProviderRegistry; +import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView; +import net.fabricmc.fabric.api.renderer.v1.render.RenderContext; +import net.fabricmc.fabric.api.rendering.data.v1.RenderAttachedBlockView; +import net.minecraft.block.BlockState; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.screen.Overlay; +import net.minecraft.client.texture.SpriteAtlasTexture.Data; +import net.minecraft.item.BlockItem; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Identifier; +import net.minecraft.util.Pair; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; +import net.minecraft.util.math.random.Random; +import net.minecraft.world.BlockRenderView; + +@Environment(EnvType.CLIENT) +public final class gridTransform implements RenderContext.QuadTransform { + public static final QuadTransformRegistry.QuadTransformSource SOURCE = new QuadTransformRegistry.QuadTransformSource() { + + @Override + public RenderContext.QuadTransform getForBlock(final BlockRenderView brv, final BlockState state, + final BlockPos pos, final Supplier randomSupplier) { + return new gridTransform(brv, state, pos, randomSupplier); + } + + @Override + public RenderContext.QuadTransform getForItem(final ItemStack stack, final Supplier randomSupplier) { + final gridSlotInfo slotInfo = (gridSlotInfo) ((BlockItem) stack.getItem()).getBlock(); + if (!stack.hasTag()) { + return new gridTransform(slotInfo, new gridData(slotInfo.sections()), randomSupplier); + } else { + return new gridTransform(slotInfo, + gridData.fromTag(stack.getSubTag("BlockEntityTag").getCompound("gridData")), randomSupplier); + } + } + }; + + private final EnumMap transformCount = new EnumMap<>(Direction.class); + + @Override + public boolean transform(MutableQuadView mqv) { + if (mqv.tag() == 0) { + return true; + } + final Direction dir = mqv.lightFace(); + final int quadIndex = transformedCount.computeIfAbsent(dir, d-> 0); + transformedCount.put(dir, quadIndex + 1); + final int partIndex = getPartIndex(mqv, dir); + final Data data = this.data[partIndex]; + final Pair origUvs = getUvs(mqv, dir); + + if (mqv.tag() == 1) { + TransformResult result = data.baseApplier.apply(mqv, dir, quadIndex, origUvs.getFirst(), origUvs.getSecond(), data.baseColor); + switch (result.status) { + case DID_SOMETHING: + case NOTHING_TO_DO: + return true; + case FAILED: + META:LOGGER.warn("An error occured with a gridEntity:" + result.message); + return false; + } + } else if (mqv.tag() == 2) { + TransformResult result = data.overlay.match(overlay -> { + data.overlayColorApplier.apply(mqv); + return overlay.apply(mqv, dir, quadIndex, origUvs.getFirst(), origUvs.getSecond(), data.baseColor) + }, + () -> data.baseApplier.apply(mqv, dir, quadIndex, origUvs.getFirst(), origUvs.getSecond(), data.baseColor) + ); + + switch (result.status) { + case DID_SOMETHING: + return true; + case NOTHING_TO_DO: + return false; + case FAILED: + META:LOGGER.warn("An error occured with a gridEntity:" + result.message); + } + } else { + return false; + } + + META.LOGGER.warn("Somehow gridTransform::transform didn't return a valid value"); + return false; + } + + @SuppressWarnings("OptionalUsedAsFieldOrParameterType") + private static class Data { + public final BaseApplier baseApplier; + public final Overlay overlay; + public final ColorApplier overlayColorApplier; + public final int baseColor; + + public Data(final BaseApplier baseApplier, final Overlay overlay, final OverlayInt maybeCachedOverlayColor, + final int baseColor) { + this.baseApplier = baseApplier; + this.overlay = overlay; + this.overlayColorApplier = ColorApplier.ofOptional(maybeCachedOverlayColor); + this.baseColor = baseColor; + } + + } + + private final gridSlotInfo slotInfo; + private final Data[] data; + + private gridTransform(final gridSlotInfo slotInfo, final BlockRenderView brv, final BlockPos pos, + final Supplier ranSupplier, + final List, Optional>> attachment) { + this.slotInfo = slotInfo; + data = attachment.stream().map(pair -> { + final Optional maybeBaseState = pair.getFirst(); + final int color; + final BaseApplier baseApplier; + if (maybeBaseState.isPresent()) { + final BlockState baseState = maybeBaseState.get(); + color = Optional.ofNullable(ColorProviderRegistry.BLOCK.get(baseState.getBlock())) + .map(prov -> prov.getColor(baseState, brv, pos, 1) | 0xFF000000).orElse(0xFFFFFFFF); + baseApplier = new BaseApplier.Some(baseState, + MinecraftClient.getInstance().getBlockRenderManager().getModel(baseState), + randomSupplier.get()); + } else { + color = 0xFFFFFFFF; + baseApplier = BaseApplier.NONE; + } + + final Overlay overlay = pair.getSecond().map(CLIENT_OVERLAYS::getOverlayFor).orElse(Overlay.NONE); + final OptionalInt cachedOverlayColor = flatMapToInt(overlay.coloredLike(), coloredLike -> mapToInt( + Optional.ofNullable(ColorProviderRegistry.BLOCK.get(coloredLike.colorSource().getBlock())), + prov -> prov.getColor(coloredLike.colorSource(), brv, pos, 1) | 0xFF000000)); + return new Data(baseApplier, overlay, cachedOverlayColor, color); + }).toArray(Data[]::new); + + } + + private gridTransform(final gridSlotInfo slotInfo, final gridData gridData, final Supplier randomSupplier) { + this(slotInfo, MinecraftClient.getInstance().player.clientWorld, + MinecraftClient.getInstance().player.getBlockPos(), randomSupplier, gridData.toRenderAttachment()); + } + + private gridTransform(final BlockRenderView brv, final BlockState state, final BlockPos pos, + final Supplier randomSupplier) { + this( + (gridSlotInfo) state.getBlock(), + brv, + pos, + randomSupplier, + (List, Optional>>) ((RenderAttachedBlockView) brv) + .getBlockEntityRenderAttachment(pos)); + } + + protected int getPartIndex(final MutableQuadView mqv, final Direction dir) { + return slotInfo.getRelativeSlotAt( + new Vec3d(calcCenter(mqv::x), calcCenter(mqv::y), calcCenter(mqv::z)), dir); + } + + protected Pair getUvs(final MutableQuadView mqv, final Direction dir) { + final IntStream us = IntStream.rangeClosed(0, 3); + final IntStream vs = IntStream.rangeClosed(0, 3); + switch (dir) { + case DOWN: + return Pair.of( + Float4.fromIterator(us.mapToDouble(i -> MathHelper.clamp(mqv.x(i), 0, 1)).iterator()), + Float4.fromIterator(vs.mapToDouble(i -> 1 - MathHelper.clamp(mqv.z(i), 0, 1)).iterator())); + case UP: + return Pair.of( + Float4.fromIterator(us.mapToDouble(i -> MathHelper.clamp(mqv.x(i), 0, 1)).iterator()), + Float4.fromIterator(vs.mapToDouble(i -> MathHelper.clamp(mqv.z(i), 0, 1)).iterator())); + case NORTH: + return Pair.of( + Float4.fromIterator(us.mapToDouble(i -> 1 - MathHelper.clamp(mqv.x(i), 0f, 1f)).iterator()), + Float4.fromIterator(vs.mapToDouble(i -> 1 - MathHelper.clamp(mqv.y(i), 0f, 1f)).iterator())); + case SOUTH: + return Pair.of( + Float4.fromIterator(us.mapToDouble(i -> MathHelper.clamp(mqv.x(i), 0f, 1f)).iterator()), + Float4.fromIterator(vs.mapToDouble(i -> 1 - MathHelper.clamp(mqv.y(i), 0f, 1f)).iterator())); + case EAST: + return Pair.of( + Float4.fromIterator(us.mapToDouble(i -> 1 - MathHelper.clamp(mqv.z(i), 0f, 1f)).iterator()), + Float4.fromIterator(vs.mapToDouble(i -> 1 - MathHelper.clamp(mqv.y(i), 0f, 1f)).iterator())); + case WEST: + return Pair.of( + Float4.fromIterator(us.mapToDouble(i -> MathHelper.clamp(mqv.z(i), 0f, 1f)).iterator()), + Float4.fromIterator(vs.mapToDouble(i -> 1 - MathHelper.clamp(mqv.y(i), 0f, 1f)).iterator())); + default: + throw new IllegalArgumentException("Invalid direction:" + dir); + } + } + +} diff --git a/src/client/java/modchest/util/QuadUtil.java b/src/client/java/modchest/util/QuadUtil.java new file mode 100644 index 0000000..c5af6c9 --- /dev/null +++ b/src/client/java/modchest/util/QuadUtil.java @@ -0,0 +1,27 @@ +package modchest.util; + +import it.unimi.dsi.fastutil.ints.Int2FloatFunction; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +@Environment(EnvType.CLIENT) +public class QuadUtil { + private QuadUtil() { + throw new IllegalStateException("Should not instantiate utility class."); + } + + public static float calcCenter(final Int2FloatFunction key) { + float min = Float.POSITIVE_INFINITY; + float max = Float.NEGATIVE_INFINITY; + + for ( int i = 0; i <= 3; i++) { + final float cur = key.get(i); + if (cur > max) { + max = cur; + } else if (cur < min) { + min = cur; + } + } + return (min +max) / 2; + } +} diff --git a/src/client/java/modchest/util/ToOptional.java b/src/client/java/modchest/util/ToOptional.java new file mode 100644 index 0000000..beda72e --- /dev/null +++ b/src/client/java/modchest/util/ToOptional.java @@ -0,0 +1,27 @@ +package modchest.util; + +import java.util.Optional; +import java.util.function.Supplier; + +import java.util.function.Function; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +@Environment(EnvType.CLIENT) +public interface ToOptional> { + Optional toOptional(); + + T match(Function some, Supplier none); + + interface Some> extends ToOptional { + default Optional toOptional() { + return Optional.of((O) this); + } + + @Override + default T match(final Function some, final Supplier none) { + return some.apply((O) this); + } + } +} diff --git a/src/main/java/modchest/REServerMod.java b/src/main/java/modchest/REServerMod.java index fe7cbcc..d790df0 100644 --- a/src/main/java/modchest/REServerMod.java +++ b/src/main/java/modchest/REServerMod.java @@ -2,8 +2,18 @@ package modchest; import net.fabricmc.api.ModInitializer; +import net.fabricmc.fabric.api.resource.ResourceManagerHelper; +import net.minecraft.resource.ResourceType; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; + +import modchest.data.OverlayDataListener; +import modchest.grid.gridBlockEntityTypes; +import modchest.grid.gridBlocks; +import modchest.grid.gridItems; +import modchest.grid.gridMeta; +import modchest.item.custom.SpecialItems; import modchest.util.initializer; //Main file; Hier wird alles aufgesetzt @@ -11,6 +21,16 @@ public class REServerMod implements ModInitializer { public static final String MOD_ID = "modchest"; public static final Logger LOGGER = LoggerFactory.getLogger("modchest"); // Erster Error Logger + public static REServerModProperties PROPERTIES; + public static SpecialItems SPECIAL_ITEMS; + + public static gridMeta META; + public static gridBlocks BLOCKS; + public static gridItems ITEMS; + public static gridBlockEntityTypes BLOCK_ENTITY_TYPES; + + public static OverlayDataListener OVERLAYS; + @Override public void onInitialize() { //Der uebersicht halber sind jetzt alle initializer in Klassen in util in initializer initializer.itemGroups(); @@ -18,6 +38,17 @@ public class REServerMod implements ModInitializer { initializer.events(); initializer.networking(); + PROPERTIES = new GridProperties(); + SPECIAL_ITEMS = new SpecialItems(); + + META = new gridMeta() + BLOCKS = new gridBlocks(); + ITEMS = new gridItems(); + BLOCK_ENTITY_TYPES = new gridBlockEntityTypes(); + + OVERLAYS = new OverlayDataListener(); + ResourceManagerHelper.get(ResourceType.SERVER_DATA).registerReloadListener(OVERLAYS); + LOGGER.info("Modchest successfully loaded!"); } } \ No newline at end of file diff --git a/src/main/java/modchest/block/custom/grid.java b/src/main/java/modchest/block/custom/grid.java deleted file mode 100644 index 11dd620..0000000 --- a/src/main/java/modchest/block/custom/grid.java +++ /dev/null @@ -1,5 +0,0 @@ -package modchest.block.custom; - -public class grid { - -} diff --git a/src/main/java/modchest/block/custom/grid/grid.java b/src/main/java/modchest/block/custom/grid/grid.java new file mode 100644 index 0000000..59a03bf --- /dev/null +++ b/src/main/java/modchest/block/custom/grid/grid.java @@ -0,0 +1,40 @@ +package modchest.block.custom.grid; + +public interface grid { + + /* + * public static PacketByteBuf writeBufferEntity(EntityHitResult hitResult, + * ServerWorld serverWorld) { + * long seed = serverWorld.getSeed(); + * Vec3d gridEntityPos = hitResult.getPos(); + * NbtCompound Nbtgrid = new NbtCompound(); + * double gridX = gridEntityPos.getX(); + * Nbtgrid.putDouble("gridX", gridX); + * double gridY = gridEntityPos.getY(); + * Nbtgrid.putDouble("gridY", gridY); + * double gridZ = gridEntityPos.getZ(); + * Nbtgrid.putDouble("gridZ", gridZ); + * Nbtgrid.putLong("WorldSeed", seed); + * PacketByteBuf gridBuffer = PacketByteBufs.create(); + * gridBuffer.writeNbt(Nbtgrid); + * return gridBuffer; + * } + * + * + * public static PacketByteBuf writeBufferBlock(BlockHitResult hitResult, + * ServerWorld serverWorld){ + * long seed = serverWorld.getSeed(); + * BlockPos gridBlockPos = hitResult.getBlockPos(); + * int[] gridBlockPosAr = new int[3]; + * gridBlockPosAr [0] = gridBlockPos.getX(); + * gridBlockPosAr [1] = gridBlockPos.getY(); + * gridBlockPosAr [2] = gridBlockPos.getZ(); + * NbtCompound Nbtgrid = new NbtCompound(); + * Nbtgrid.putIntArray("gridBlockPos", gridBlockPosAr); + * Nbtgrid.putLong("WorldSeed", seed); + * PacketByteBuf gridBlockBuffer = PacketByteBufs.create(); + * return gridBlockBuffer; + * + * } + */ +} diff --git a/src/main/java/modchest/block/custom/grid/gridBlock.java b/src/main/java/modchest/block/custom/grid/gridBlock.java new file mode 100644 index 0000000..c977f24 --- /dev/null +++ b/src/main/java/modchest/block/custom/grid/gridBlock.java @@ -0,0 +1,151 @@ +package modchest.block.custom.grid; + +import net.minecraft.block.Block; +import net.minecraft.util.math.Direction; +import net.minecraft.block.BlockState; + +public class gridBlock extends Block { + + public gridBlock(final Settings settings) { + super(settings); + } + + @SuppressWarnings("deprecation") + @Override + public boolean isSideInvisible(BlockState state, BlockState stateFrom, Direction direction) { + return super.isSideInvisible(state, stateFrom, direction) || (state == stateFrom); + } + +} + +/* + * public gridBlock(Settings settings) { + * super(settings); + * } + * + * @SuppressWarnings("deprecation") + * + * @Override + * public boolean isSideInvisible(BlockState state, BlockState stateFrom, + * Direction direction) { + * return super.isSideInvisible(state, stateFrom, direction) || (state == + * stateFrom); + * } + * + * /* BLOCK ENTITY + */ + +/* + * @Override + * public BlockRenderType getRenderType(BlockState state) { // sonst Block + * unsichtbar + * return BlockRenderType.MODEL; + * } + * + * @Override + * public BlockEntity createBlockEntity(BlockPos arg0, BlockState arg1) { + * // TODO Auto-generated method stub + * throw new + * UnsupportedOperationException("Unimplemented method 'createBlockEntity'"); + * } + * + * /*@SuppressWarnings("deprecation") + * + * @Override + * public void onStateReplaced(BlockState state, World world, BlockPos pos, + * BlockState newState, boolean moved) { // wenn Block zerstört wird Inventar + * Inhalt in die Welt gespawnt + * if (state.getBlock() != newState.getBlock()) { + * BlockEntity blockEntity = world.getBlockEntity(pos); + * if (blockEntity instanceof gridBlockEntity) { + * ItemScatterer.spawn(world, pos, (gridBlockEntity) blockEntity); + * world.updateComparators(pos, this); + * } + * super.onStateReplaced(state, world, pos, newState, moved); + * } + * } + */ + +/* + * @SuppressWarnings("deprecation") + * + * @Override + * public ActionResult onUse(BlockState state, World world, BlockPos pos, + * PlayerEntity player, Hand hand, + * BlockHitResult hitResult) { + * + * if (!world.isClient) { + * NamedScreenHandlerFactory screenHandlerFactory = + * state.createScreenHandlerFactory(world, pos); + * + * if (screenHandlerFactory != null) { + * player.openHandledScreen(screenHandlerFactory); + * } + * } + * player.sendMessage(Text.literal("onUse")); + * return ActionResult.SUCCESS; + * /* + * if (!world.isClient) { + * Block BlockInHand = getBlockFromItem(player.getMainHandStack().getItem()); + * BlockState StateInHand = BlockInHand.getDefaultState(); + * BlockPos gridBlockPos = hitResult.getBlockPos(); + * if + * (world.getBlockState(hitResult.getBlockPos()).getBlock().toString().equals( + * "Block{modchest:grid_block}") + * && player.isSpectator() == false) { + * if (BlockInHand instanceof gridBlock) { + * return ActionResult.PASS; + * } else { + * player.sendMessage(Text.of("gridBlock benutzt")); + * // world.setBlockState(gridBlockPos, StateInHand); // tauscht den "benutzten" + * // gridBlock mit dem + * // Blocks in der Hand, wie platzieren, nur cooler + * player.getMainHandStack().decrement(1); + * player.jump(); + * // player.onLanding(player.playSoundIfNotSilent()); + * if (player instanceof ServerPlayerEntity && world instanceof ServerWorld) { + * // nötig, um + * // sicherzustellen, dass + * // eine + * // ServerPlayerEntity + * // fürs networking übergeben wird und nicht eine + * // PlayerEntity, da sonst Absturz; gleiches für ServerWorld + * ServerWorld serverWorld = (ServerWorld) world; + * ServerPlayerEntity serverPlayer = (ServerPlayerEntity) player; + * ServerPlayNetworking.send(serverPlayer, + * modNetworkingServer.grid_block_networking, + * grid.writeBufferBlock(hitResult, serverWorld)); + * } + * } + * } else { + * return ActionResult.PASS; + * } + * + * } + * return ActionResult.SUCCESS; + */ +/* + * } + * + * @Override + * public BlockEntity createBlockEntity(BlockPos arg0, BlockState arg1) { + * // TODO Auto-generated method stub + * throw new + * UnsupportedOperationException("Unimplemented method 'createBlockEntity'"); + * } + */ + +/* + * @Override + * public BlockEntity createBlockEntity(BlockPos pos, BlockState state) { + * return new gridBlockEntity(pos, state); + * } + * + * @Override + * public BlockEntityTicker getTicker(World world, + * BlockState state, BlockEntityType type) { + * return checkType(type, modBlockEntities.grid_block_entity, + * gridBlockEntity::tick); + * } + * } + */ \ No newline at end of file diff --git a/src/main/java/modchest/block/custom/grid/gridCarpet.java b/src/main/java/modchest/block/custom/grid/gridCarpet.java new file mode 100644 index 0000000..5cbbfb3 --- /dev/null +++ b/src/main/java/modchest/block/custom/grid/gridCarpet.java @@ -0,0 +1,10 @@ +package modchest.block.custom.grid; + +import net.minecraft.block.CarpetBlock; + +public class gridCarpet extends CarpetBlock { + + public gridCarpet(Settings settings) { + super(settings); + } +} diff --git a/src/main/java/modchest/block/custom/grid/gridDoor.java b/src/main/java/modchest/block/custom/grid/gridDoor.java new file mode 100644 index 0000000..5d98cb3 --- /dev/null +++ b/src/main/java/modchest/block/custom/grid/gridDoor.java @@ -0,0 +1,10 @@ +package modchest.block.custom.grid; + +import net.minecraft.block.DoorBlock; + +public class gridDoor extends DoorBlock { + + public gridDoor(Settings settings) { + super(settings); + } +} diff --git a/src/main/java/modchest/block/custom/grid/gridFence.java b/src/main/java/modchest/block/custom/grid/gridFence.java new file mode 100644 index 0000000..7976d45 --- /dev/null +++ b/src/main/java/modchest/block/custom/grid/gridFence.java @@ -0,0 +1,10 @@ +package modchest.block.custom.grid; + +import net.minecraft.block.FenceBlock; + +public class gridFence extends FenceBlock{ + + public gridFence(Settings settings) { + super(settings); + } +} diff --git a/src/main/java/modchest/block/custom/grid/gridFenceGate.java b/src/main/java/modchest/block/custom/grid/gridFenceGate.java new file mode 100644 index 0000000..fd76088 --- /dev/null +++ b/src/main/java/modchest/block/custom/grid/gridFenceGate.java @@ -0,0 +1,11 @@ +package modchest.block.custom.grid; + +import net.minecraft.block.FenceGateBlock; + +public class gridFenceGate extends FenceGateBlock{ + + public gridFenceGate(Settings settings) { + super(settings); + } + +} diff --git a/src/main/java/modchest/block/custom/grid/gridLayer.java b/src/main/java/modchest/block/custom/grid/gridLayer.java new file mode 100644 index 0000000..65cfc4d --- /dev/null +++ b/src/main/java/modchest/block/custom/grid/gridLayer.java @@ -0,0 +1,11 @@ +package modchest.block.custom.grid; + +import net.minecraft.block.SnowBlock; + +public class gridLayer extends SnowBlock{ + + public gridLayer(Settings settings) { + super(settings); + } + +} diff --git a/src/main/java/modchest/block/custom/grid/gridPane.java b/src/main/java/modchest/block/custom/grid/gridPane.java new file mode 100644 index 0000000..5423138 --- /dev/null +++ b/src/main/java/modchest/block/custom/grid/gridPane.java @@ -0,0 +1,11 @@ +package modchest.block.custom.grid; + +import net.minecraft.block.PaneBlock; + +public class gridPane extends PaneBlock{ + + public gridPane(Settings settings) { + super(settings); + } + +} diff --git a/src/main/java/modchest/block/custom/grid/gridPath.java b/src/main/java/modchest/block/custom/grid/gridPath.java new file mode 100644 index 0000000..303a77c --- /dev/null +++ b/src/main/java/modchest/block/custom/grid/gridPath.java @@ -0,0 +1,17 @@ +package modchest.block.custom.grid; + +import net.minecraft.block.AbstractBlock.Settings; +import net.minecraft.block.BlockState; +import net.minecraft.util.math.Direction; + +public class gridPath extends PathBlock { + public gridPath(final Settings settings) { + super(settings); + } + + @SuppressWarnings("deprecation") + @Override + public boolean isSideInvisible(BlockState state, BlockState stateFrom, Direction direction) { + return super.isSideInvisible(state, stateFrom, direction) || (state == stateFrom); + } +} diff --git a/src/main/java/modchest/block/custom/grid/gridPressurePlate.java b/src/main/java/modchest/block/custom/grid/gridPressurePlate.java new file mode 100644 index 0000000..d93de9b --- /dev/null +++ b/src/main/java/modchest/block/custom/grid/gridPressurePlate.java @@ -0,0 +1,11 @@ +package modchest.block.custom.grid; + +import net.minecraft.block.PressurePlateBlock; + +public class gridPressurePlate extends PressurePlateBlock{ + + public gridPressurePlate(ActivationRule type, Settings settings) { + super(ActivationRule.MOBS, settings); + } + +} diff --git a/src/main/java/modchest/block/custom/grid/gridSlab.java b/src/main/java/modchest/block/custom/grid/gridSlab.java new file mode 100644 index 0000000..93d6e13 --- /dev/null +++ b/src/main/java/modchest/block/custom/grid/gridSlab.java @@ -0,0 +1,87 @@ +package modchest.block.custom.grid; + +import java.util.Properties; + +import javax.swing.text.html.BlockView; + +import modchest.block.entity.gridEntity; +import modchest.grid.data.Sections; +import net.minecraft.block.BlockEntityProvider; +import net.minecraft.block.BlockState; +import net.minecraft.block.SlabBlock; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import net.minecraft.util.math.Vec3d; + +public class gridSlab extends SlabBlock implements gridSlotInfo, BlockEntityProvider { + + public gridSlab(Settings settings) { + super(settings); + } + + public static final int LOWER_SLOT = 0; + public static final int UPPER_SLOT = 1; + + @Override + public Sections sections() { + return META.GRID_SLAB_SECTIONS; + } + + @Override + public int getRelativeSlotAt(final Vec3d posInBlock, final Direction side) { + switch (side) { + case UP: + return posInBlock.y == 0.5 ? LOWER_SLOT : UPPER_SLOT; + case DOWN: + return posInBlock.y == 0.5 ? UPPER_SLOT : LOWER_SLOT; + default: + return posInBlock.y < 0.5 ? LOWER_SLOT : UPPER_SLOT; + } + } + + @Override + public boolean absoluteSlotIsValid(final gridEntity grid, final BlockState state, final int slot) { + final int wantedSlot; + switch (state.get(Properties.SLAB_TYPE)) { + case DOUBLE: + return true; + case TOP: + wantedSlot = UPPER_SLOT; + break; + case BOTTOM: + wantedSlot = LOWER_SLOT; + break; + default: + throw new IllegalStateException("unreachable"); + } + switch (grid.sections().findSectionIndexOf(slot)) { + case Sections.BASE_INDEX: + return grid.sections().base().makeAbsolute(slot) == wantedSlot; + case Sections.OVERLAY_INDEX: + return grid.sections().overlay().makeAbsolute(slot) == wantedSlot; + case Sections.SPECIAL_INDEX: + return true; + default: + throw new IllegalArgumentException("Invalid slot for grid slab:" + slot); + } + } + + @SuppressWarnings("deprecation") + @Override + public boolean isSideInvisible(BlockState state, BlockState stateFrom, Direction direction) { + return super.isSideInvisible(state, stateFrom, direction) || (state == stateFrom); + } + + @Override + public BlockEntity createBlockEntity(final BlockView world) { + return new gridEntity(BLOCK_ENTITY_TYPES.GRID_SLAB, META.GRID_SLAB_SECTIONS); + } + + @Override + public BlockEntity createBlockEntity(BlockPos arg0, BlockState arg1) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'createBlockEntity'"); + } + +} diff --git a/src/main/java/modchest/block/custom/grid/gridSlotInfo.java b/src/main/java/modchest/block/custom/grid/gridSlotInfo.java new file mode 100644 index 0000000..3e55b8e --- /dev/null +++ b/src/main/java/modchest/block/custom/grid/gridSlotInfo.java @@ -0,0 +1,13 @@ +package modchest.block.custom.grid; + +import modchest.block.entity.gridEntity; +import modchest.grid.data.Sections; +import net.minecraft.block.BlockState; +import net.minecraft.util.math.Direction; +import net.minecraft.util.math.Vec3d; + +public interface gridSlotInfo { + Sections sections(); + int getRelativeSlotAt(Vec3d posInBlock, Direction side); + boolean absoluteSlotIsValid(gridEntity entity, BlockState state, int slot); +} diff --git a/src/main/java/modchest/block/custom/grid/gridStairs.java b/src/main/java/modchest/block/custom/grid/gridStairs.java new file mode 100644 index 0000000..85a7261 --- /dev/null +++ b/src/main/java/modchest/block/custom/grid/gridStairs.java @@ -0,0 +1,12 @@ +package modchest.block.custom.grid; + +import net.minecraft.block.BlockState; +import net.minecraft.block.StairsBlock; + +public class gridStairs extends StairsBlock{ + + public gridStairs(BlockState baseBlockState, Settings settings) { + super(baseBlockState, settings); + } + +} diff --git a/src/main/java/modchest/block/custom/grid/gridTorch.java b/src/main/java/modchest/block/custom/grid/gridTorch.java new file mode 100644 index 0000000..835c615 --- /dev/null +++ b/src/main/java/modchest/block/custom/grid/gridTorch.java @@ -0,0 +1,13 @@ +package modchest.block.custom.grid; + +import net.minecraft.block.TorchBlock; +import net.minecraft.particle.ParticleEffect; +import net.minecraft.particle.ParticleTypes; + +public class gridTorch extends TorchBlock{ + + public gridTorch(Settings settings, ParticleEffect particle) { + super(settings, ParticleTypes.FLAME); + } + +} diff --git a/src/main/java/modchest/block/custom/grid/gridTrapdoor.java b/src/main/java/modchest/block/custom/grid/gridTrapdoor.java new file mode 100644 index 0000000..d3398b5 --- /dev/null +++ b/src/main/java/modchest/block/custom/grid/gridTrapdoor.java @@ -0,0 +1,11 @@ +package modchest.block.custom.grid; + +import net.minecraft.block.TrapdoorBlock; + +public class gridTrapdoor extends TrapdoorBlock{ + + public gridTrapdoor(Settings settings) { + super(settings); + } + +} diff --git a/src/main/java/modchest/block/custom/grid/gridWall.java b/src/main/java/modchest/block/custom/grid/gridWall.java new file mode 100644 index 0000000..54882ee --- /dev/null +++ b/src/main/java/modchest/block/custom/grid/gridWall.java @@ -0,0 +1,11 @@ +package modchest.block.custom.grid; + +import net.minecraft.block.WallBlock; + +public class gridWall extends WallBlock{ + + public gridWall(Settings settings) { + super(settings); + } + +} diff --git a/src/main/java/modchest/block/custom/grid/gridWallTorch.java b/src/main/java/modchest/block/custom/grid/gridWallTorch.java new file mode 100644 index 0000000..cad9be4 --- /dev/null +++ b/src/main/java/modchest/block/custom/grid/gridWallTorch.java @@ -0,0 +1,13 @@ +package modchest.block.custom.grid; + +import net.minecraft.block.WallTorchBlock; +import net.minecraft.particle.ParticleEffect; +import net.minecraft.particle.ParticleTypes; + +public class gridWallTorch extends WallTorchBlock { + + public gridWallTorch(Settings settings, ParticleEffect particleEffect) { + super(settings, ParticleTypes.FLAME); + } + +} diff --git a/src/main/java/modchest/block/custom/gridBlock.java b/src/main/java/modchest/block/custom/gridBlock.java deleted file mode 100644 index ade0e7e..0000000 --- a/src/main/java/modchest/block/custom/gridBlock.java +++ /dev/null @@ -1,50 +0,0 @@ -package modchest.block.custom; - -import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; -import net.minecraft.block.Block; -import net.minecraft.util.hit.BlockHitResult; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.minecraft.block.BlockRenderType; -import net.minecraft.block.BlockState; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.network.PacketByteBuf; - -public class gridBlock extends Block { - - public static final String ServerPlayNetworking = null; - - public gridBlock(Settings settings) { - super(settings); - } - - @Override - public BlockRenderType getRenderType(BlockState state) { - return BlockRenderType.MODEL; - } - - @SuppressWarnings("deprecation") - @Override - public boolean isSideInvisible(BlockState state, BlockState stateFrom, Direction direction) { - return super.isSideInvisible(state, stateFrom, direction) || (state == stateFrom); - } - - public static PacketByteBuf writeBuffer(BlockHitResult hitResult) { - BlockPos gridBlockPos = hitResult.getBlockPos(); - int[] gridPos = new int[3]; - gridPos[0] = gridBlockPos.getX(); - gridPos[1] = gridBlockPos.getY(); - gridPos[2] = gridBlockPos.getZ(); - - NbtCompound Nbtgrid = new NbtCompound(); - Nbtgrid.putIntArray("BlockPosition", gridPos); - - PacketByteBuf gridBlockBuffer = PacketByteBufs.create(); - gridBlockBuffer.writeNbt(Nbtgrid); - - // gridBlockBuffer.writeBlockHitResult(hitResult); - // gridBlockBuffer.writeBlockPos(gridBlockPos); - - return gridBlockBuffer; - } -} diff --git a/src/main/java/modchest/block/entity/gridEntity.java b/src/main/java/modchest/block/entity/gridEntity.java new file mode 100644 index 0000000..ee677c7 --- /dev/null +++ b/src/main/java/modchest/block/entity/gridEntity.java @@ -0,0 +1,370 @@ +package modchest.block.entity; + +import java.util.Arrays; +import java.util.List; +import java.util.Optional; + +import javax.swing.text.html.Option; + +import org.spongepowered.asm.mixin.transformer.ClassInfo.FrameData; + +import com.ibm.icu.impl.Pair; + +import modchest.item.modItems; +import net.fabricmc.fabric.api.networking.v1.PlayerLookup; +import net.fabricmc.fabric.api.rendering.data.v1.RenderAttachedBlockView; +import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.block.entity.BlockEntityType; +import net.minecraft.block.entity.LockableContainerBlockEntity; +import net.minecraft.client.MinecraftClient; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.inventory.Inventories; +import net.minecraft.inventory.SimpleInventory; +import net.minecraft.item.BlockItem; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.network.PacketByteBuf; +import net.minecraft.screen.NamedScreenHandlerFactory; +import net.minecraft.screen.PropertyDelegate; +import net.minecraft.screen.ScreenHandler; +import net.minecraft.screen.ScreenHandlerContext; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.text.Text; +import net.minecraft.text.TranslatableTextContent; +import net.minecraft.util.Identifier; +import net.minecraft.util.collection.DefaultedList; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import net.minecraft.world.World; + +public class gridEntity extends LockableContainerBlockEntity implements ExtendedScreenHandlerFactory, RenderAttachedBlockEntity, BlockEntityClientSerializable { + private gridData data; + //private final DefaultedList inventory = DefaultedList.ofSize(1, ItemStack.EMPTY); + + //protected final PropertyDelegate propertyDelegate; // synchronisieren zwischen client und server + //private int progress = 0; + //private int maxProgress = 72; + + public gridEntity(final BlockEntityType type, final Sections sections) { + super type; + + data = new gridData(sections); + } + + public gridData data() { + return data; + } + + public Sections sections() { + return data.sections(); + } + + public Optional[] items() { + return data.items(); + } + + public List> baseItems() { + return data.baseItems(); + } + + public List> overlayItems() { + return data.overlayItems(); + } + + public List> specialItems() { + return data.specialItems(); + } + + public Optional[] baseStates() { + return data.baseStates(); + } + + public void copyFrom(final int slot, final ItemStack stack, final int count, final boolean take) { + final ItemStack newStack = stack.copy(); + final int realCount = Math.min(count, stack.getCount()); + + newStack.setCount(realCount); + + if (take) { + stack.setCount(stack.getCount() - realCount); + } + this.setStack(slot, newStack); + } + + @Override + public int getMaxCountPerStack() { + return 1; + } + + @Override + public boolean isValid(final int slot, final ItemStack stack) { + switch (sections().findSectionIndexOf(slot)) { + case Sections.BASE_INDEX: return checkIf(stack).isValidForBase(s -> Optional.of(s.getBlock().getDefaultState()), world, pos).isPresent(); + case Sections.OVERLAY_INDEX: return checkIf(stack).isValidForOverlay(); + case Sections.SPECIAL_INDEX: return checkIf(stack).isValidForSpecial(); + default: return false; + } + } + + private void beforeRemove(final int slot) { + switch (sections().findSectionIndexOf(slot)) { + case Sections.BASE_INDEX: baseStates()[sections().base().makeRelative(slot)] = Optional.empty(); + break; + case Sections.OVERLAY_INDEX: + break; + case Sections.SPECIAL_INDEX: + SPECIAL_ITEMS.Map.get(getItemBeforeEmpty(getStack(slot))).onRemove(world, this); + break; + + default: + throw new IllegalArgumentException("Invalid slot:" + slot); + } + } + + @Override + public ItemStack removeStack(final int slot, final int amount) { + beforeRemove(slot); + + return Optional.of(slot).filter(s -> sections().itemIndices().contains(s)).filter(s -> amount > 0).flatMap(s -> items()[s]) + .map(orig -> new Pair<>(orig, orig.split(amount))).map(pair -> { + markDirty(); + if (pair.getFirst().isEmpty()) { + items() [slot] = Optional.empty(); + } + return pair.getSecond(); + }).orElse(ItemStack.EMPTY); + } + + @Override + public ItemStack removeStack(int slot) { + beforeRemove(slot); + markDirty(); + final Optional result = items()[slot]; + items()[slot] = Optional.empty(); + return result.orElse(ItemStack.EMPTY); + } + + @Override + public ItemStack getStack(int slot) { + return items()[slot].orElse(ItemStack.EMPTY); + } + + @Override + public int size() { + return items().length; + } + + @Override + public boolean isEmpty() { + return Arrays.stream(items()).noneMatch(Optional::isPresent); + } + + @Override + public boolean canPlayerUse(PlayerEntity player) { + return true; + } + + @Override + public void clear() { + for (int i = 0; size = size(); i < size; i++) { + items()[i] = Optional.empty(); + } + } + + @Override + public void setStack(int slot, ItemStack stack) { + final int sectionIndex = sections().findSectionIndexOf(slot); + final Runnable setStack = () -> { + items()[slot] = Optional.of(stack); + stack.setCount(Math.min(stack.getCount(), getMaxCountPerStack())); + markDirty(); + }; + + switch (sectionIndex) { + case Sections.BASE_INDEX: setStack.run(); + final int baseSlot = sections().base().makeRelative(slot); + baseStates()[baseSlot] = baseItems().get(baseSlot).map(ItemStack::getItem).filter(i -> i instanceof BlockItem).map(i -> ((BlockItem) i).getBlock().getDefaultState()); + break; + case Sections.SPECIAL_INDEX: + final SpecialItems.SpecialItem old = SPECIAL_ITEMS.Map.get(getItemBeforeEmpty(getStack(slot))); + if (old != null && world != null) { + old.onRemove(world, this); + } + setStack.run(); + + final SpecialItems.SpecialItems _new = SPECIAL_ITEMS.Map.get(getStack(slot).getItem()); + if (_new != null && world != null) { + _new.onAdd(world,this); + } + + break; + + default: setStack.run();; + break; + } + } + + @Override + public void markDirty() { + super.markDirty(); + + final World world = this.world; + if (world != null) { + final BlockState state = world.getBlockState(pos); + final Block block = state.getBlock(); + + if (world.isClient) { + MinecraftClient.getInstance().worldRenderer.updateBlock(world, pos, getCachedState(), state, 1); + } else { + sync(); + PlayerLookup.tracking(this).forEach(p -> p.networkHandler.sendPacket(this.toUpdatePacket())); + world.updateNeighborsAlways(pos.offset(Direction.UP), block); + } + } + } + + @Override + public List, Optional>> getRenderAttachmentData() { + return data.toRenderAttachment(); + } + + @Override + public CompoundTag toTag(final CompoundTag tag) { + toClientTag(tag); + return super.toTag(tag); + } + + @Override + public void fromTag(BlockState state, CompoundTag tag) { + fromClientTag(tag); + super.fromTag(state, tag); + } + + @Override + public CompoundTag toClientTag(CompoundTag tag) { + tag.put("gridData", data.toTag()); + return tag; + } + + @Override + public CompoundTag fromClientTag (final CompoundTag tag) { + data = gridData.fromTag(compoundTag.getCompound("gridData")); + this.markDirty(); + } + + @Override + protected ScreenHandler createScreenHandler(final int syncId, final PlayerInventory playerInventory) { + return new gridGuiDescription(syncId, playerInventory, ScreenHandlerContext.create(world, pos)); + } + + @Override + public void writeScreenopeningData(final ServerPlayerEntity serverPlayerEntity, final PacketByteBuf packetByteBuf) { + packetByteBuf.writeBlockPos(pos); + } + + @Override + protected Text getContainerName() { + return new TranslatableText(getCachedState().getBlock().getTranslationKey()); + } + + + + /*@Override + public DefaultedList getItems() { + return this.inventory; + } + + @Override + public Text getDisplayName() { + return Text.literal("gridBlock"); + } + + + @Override + protected void writeNbt(NbtCompound nbt) { + Inventories.writeNbt(nbt, inventory); + super.writeNbt(nbt); + nbt.putInt("grid_block_entity_progress", progress); + } + + @Override + public void readNbt(NbtCompound nbt) { + Inventories.readNbt(nbt, inventory); + progress = nbt.getInt("grid_block_entity_progress"); + super.readNbt(nbt); + } + + public static void tick(World world, BlockPos pos, BlockState state, gridBlockEntity entity) { + if (world.isClient()) { + return; + } + + if(hasRecipe(entity)) { + entity.progress++; + markDirty(world, pos, state); //reloads blockPosition/chunk -> synchronize server and client + if (entity.progress >= entity.maxProgress) { + craftItem(entity); + } + } else { + entity.resetProgress(); + markDirty(world, pos, state); + } + } + + private void resetProgress() { + this.progress = 0; + } + + private static void craftItem(gridBlockEntity entity) { + SimpleInventory inventory = new SimpleInventory(entity.size()); + for (int i = 0; i < entity.size(); i++) { + inventory.setStack(i, entity.getStack(i)); + } + + if (hasRecipe(entity)) { + entity.removeStack(1,1); + + entity.setStack(2, new ItemStack(modItems.pirates_coin, entity.getStack(2).getCount() + 1)); + } + } + + private static boolean hasRecipe(gridBlockEntity entity) { + SimpleInventory inventory = new SimpleInventory(entity.size()); + for (int i = 0; i< entity.size(); i++) { + inventory.setStack(i, entity.getStack(i)); + } + + boolean hasRawGemInFirstSlot = entity.getStack(1).getItem() == modItems.pirates_coin; + + return hasRawGemInFirstSlot && canInsertAmountIntoOutputSlot(inventory, 1) && canInsertItemIntoOutputSlot(inventory, modItems.pirates_coin); + } + + private static boolean canInsertItemIntoOutputSlot(SimpleInventory inventory, Item output) { + return inventory.getStack(2).getItem() == output || inventory.getStack(2).isEmpty(); + } + + private static boolean canInsertAmountIntoOutputSlot(SimpleInventory inventory, int count) { + return inventory.getStack(2).getMaxCount() > inventory.getStack(2).getCount() + count; + } + + @Override + public ScreenHandler createMenu(int arg0, PlayerInventory arg1, PlayerEntity arg2) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'createMenu'"); + } + + public ItemStack getRenderStack() { + if (this.getStack(2).isEmpty()) { + return this.getStack(1); + } else { + return this.getStack(2); + } + }*/ + + +} diff --git a/src/main/java/modchest/block/entity/modBlockEntities.java b/src/main/java/modchest/block/entity/modBlockEntities.java index 27f4323..68ab289 100644 --- a/src/main/java/modchest/block/entity/modBlockEntities.java +++ b/src/main/java/modchest/block/entity/modBlockEntities.java @@ -10,10 +10,16 @@ import net.minecraft.util.registry.Registry; //rendert letztendlich die Interaktionsmenüs der Blöcke public class modBlockEntities { public static BlockEntityType steering_wheel_interface; // Interaktionsmenü wird erstellt + // public static BlockEntityType grid_block_entity; public static void registerBlockEntities() { steering_wheel_interface = Registry.register(Registry.BLOCK_ENTITY_TYPE, new Identifier(REServerMod.MOD_ID, "steering_wheel_interface"), // Interkationsmenü wird gerendert FabricBlockEntityTypeBuilder.create(steeringWheelEntity::new, modBlocks.steering_wheel).build(null)); + + /*grid_block_entity = Registry.register(Registry.BLOCK_ENTITY_TYPE, + new Identifier(REServerMod.MOD_ID, "grid_block_entity"), + FabricBlockEntityTypeBuilder.create(gridBlockEntity::new, modBlocks.grid_block).build(null));*/ } + } diff --git a/src/main/java/modchest/block/modBlocks.java b/src/main/java/modchest/block/modBlocks.java index 9c9a786..eb12fb0 100644 --- a/src/main/java/modchest/block/modBlocks.java +++ b/src/main/java/modchest/block/modBlocks.java @@ -1,7 +1,7 @@ package modchest.block; -import modchest.block.custom.gridBlock; import modchest.block.custom.steeringWheelBlock; +import modchest.block.custom.grid.gridBlock; import modchest.item.modItemGroup; import modchest.REServerMod; import net.fabricmc.fabric.api.item.v1.FabricItemSettings; diff --git a/src/main/java/modchest/data/OverlayDataListener.java b/src/main/java/modchest/data/OverlayDataListener.java new file mode 100644 index 0000000..544a02f --- /dev/null +++ b/src/main/java/modchest/data/OverlayDataListener.java @@ -0,0 +1,77 @@ +package modchest.data; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; + +import org.spongepowered.include.com.google.gson.Gson; +import org.spongepowered.include.com.google.gson.JsonParseException; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; + +import net.fabricmc.fabric.api.resource.SimpleResourceReloadListener; +import net.minecraft.item.ItemStack; +import net.minecraft.recipe.Ingredient; +import net.minecraft.resource.ResourceManager; +import net.minecraft.util.Identifier; +import net.minecraft.util.profiler.Profiler; + +public class OverlayDataListener implements SimpleResourceReloadListener> { + private final Map triggers = new HashMap<>(); + + public Optional getOverlayId(final ItemStack stack) { + return triggers.entrySet().stream().filter(e -> e.getKey().test(stack)).map(Map.Entry::getValue).findFirst(); + } + + public boolean hasOverlay(final ItemStack stack) { + return getOverlayId(stack).isPresent(); + } + + @Override + public CompletableFuture> load(final ResourceManager manager, final Profiler profiler, + final Executor executor) { + return CompletableFuture.supplyAsync(() -> { + triggers.clear(); + return ResourceManager.findResources("grid/overlays", s -> s.endsWith(".json")); + }, executor); + } + + @Override + public CompletableFuture apply(final Collection data, final ResourceManager manager, final Profiler profiler, + final Executor executor) { + return CompletableFuture.runAsync(() -> { + for (final Identifier id : identifiers) { + try { + final JsonElement element = new Gson().fromJson(new BufferedReader(new InputStreamReader(resourceManager.getResource(id).getInputStream())), JsonElement.class); + + if (!element.isJsonObject()) { + throw new JsonParseException("Invalid JSON: expected an object."); + } + + final JsonObject obj = element.getAsJsonObject(); + if (!obj.has("trigger")) { + throw new JsonParseException("Invalid JSON: expected the key 'triger'."); + } + + triggers.put(Ingredient.fromJson(.get("trigger")), id); + } catch (final Exception e) { + META.LOGGER.warn("Exception while parsing overlay:" + e); + } + } + }, executor); +} + + private final Identifier id = META.id("data/overlay"); + + @Override + public Identifier getFabricId() { + return id; + } + +} diff --git a/src/main/java/modchest/event/useBlockCallback.java b/src/main/java/modchest/event/useBlockCallback.java index b35f176..56b9fe3 100644 --- a/src/main/java/modchest/event/useBlockCallback.java +++ b/src/main/java/modchest/event/useBlockCallback.java @@ -1,10 +1,9 @@ -package modchest.event; +/*package modchest.event; import static net.minecraft.block.Block.getBlockFromItem; import modchest.block.custom.gridBlock; import modchest.networking.modNetworkingServer; -import modchest.networking.packet.gridBlockS2CPacket; import net.fabricmc.fabric.api.event.player.UseBlockCallback; import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; import net.minecraft.block.Block; @@ -12,11 +11,13 @@ import net.minecraft.block.BlockState; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.server.MinecraftServer; import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.server.world.ServerWorld; import net.minecraft.text.Text; import net.minecraft.util.ActionResult; import net.minecraft.util.Hand; import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.registry.RegistryKey; import net.minecraft.world.World; public class useBlockCallback implements UseBlockCallback { @@ -26,7 +27,7 @@ public class useBlockCallback implements UseBlockCallback { Block BlockInHand = getBlockFromItem(player.getMainHandStack().getItem()); BlockState StateInHand = BlockInHand.getDefaultState(); BlockPos gridBlockPos = hitResult.getBlockPos(); - + //MinecraftServer server = player.getServer(); //funktioniert // PlayerPublicKey playerPublicKey = player.getPublicKey(); if (world.getBlockState(hitResult.getBlockPos()).getBlock().toString().equals("Block{modchest:grid_block}") && player.isSpectator() == false) { @@ -34,17 +35,18 @@ public class useBlockCallback implements UseBlockCallback { return ActionResult.PASS; } else { player.sendMessage(Text.of("gridBlock benutzt")); - world.setBlockState(gridBlockPos, StateInHand); // tauscht die Textur des "benutzten" gridBlocks mit der - // des Blocks in der Hand + //world.setBlockState(gridBlockPos, StateInHand); // tauscht den "benutzten" gridBlock mit dem + // Blocks in der Hand, wie platzieren, nur cooler player.getMainHandStack().decrement(1); player.jump(); // player.onLanding(player.playSoundIfNotSilent()); - if (player instanceof ServerPlayerEntity) { // nötig, um sicherzustellen, dass eine ServerPlayerEntity + if (player instanceof ServerPlayerEntity && world instanceof ServerWorld) { // nötig, um sicherzustellen, dass eine ServerPlayerEntity // fürs networking übergeben wird und nicht eine - // PlayerEntity, da sonst Absturz + // PlayerEntity, da sonst Absturz; gleiches für ServerWorld + ServerWorld serverWorld = (ServerWorld) world; ServerPlayerEntity serverPlayer = (ServerPlayerEntity) player; ServerPlayNetworking.send(serverPlayer, modNetworkingServer.grid_block_networking, - gridBlock.writeBuffer(hitResult)); + gridBlock.writeBuffer(hitResult, serverWorld)); } } } else { @@ -52,4 +54,4 @@ public class useBlockCallback implements UseBlockCallback { } return ActionResult.SUCCESS; } -} +}*/ \ No newline at end of file diff --git a/src/main/java/modchest/event/useEntityCallback.java b/src/main/java/modchest/event/useEntityCallback.java new file mode 100644 index 0000000..e6cc385 --- /dev/null +++ b/src/main/java/modchest/event/useEntityCallback.java @@ -0,0 +1,62 @@ +/*package modchest.event; + +import static net.minecraft.block.Block.getBlockFromItem; + +import org.jetbrains.annotations.Nullable; + +import modchest.block.custom.grid.gridBlock; +import modchest.networking.modNetworkingServer; +import net.fabricmc.fabric.api.event.player.UseEntityCallback; +import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.text.Text; +import net.minecraft.util.ActionResult; +import net.minecraft.util.Hand; +import net.minecraft.util.hit.EntityHitResult; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; + +public class useEntityCallback implements UseEntityCallback { + + @Override + public ActionResult interact(PlayerEntity player, World world, Hand hand, Entity entity, + @Nullable EntityHitResult hitResult) { + Block BlockInHand = getBlockFromItem(player.getMainHandStack().getItem()); + BlockState StateInHand = BlockInHand.getDefaultState(); + Vec3d gridBlockPos = hitResult.getPos(); + if (hitResult.getEntity().toString().equals("Block{modchest:grid_block_entity}") + && player.isSpectator() == false) { + if (BlockInHand instanceof gridBlock) { + return ActionResult.PASS; + } else { + player.sendMessage(Text.of("gridBlock benutzt")); + // world.setBlockState(gridBlockPos, StateInHand); // tauscht den "benutzten" + // gridBlock mit dem + // Blocks in der Hand, wie platzieren, nur cooler + player.getMainHandStack().decrement(1); + player.jump(); + // player.onLanding(player.playSoundIfNotSilent()); + if (player instanceof ServerPlayerEntity && world instanceof ServerWorld) { // nötig, um + // sicherzustellen, dass + // eine ServerPlayerEntity + // fürs networking übergeben wird und nicht eine + // PlayerEntity, da sonst Absturz; gleiches für ServerWorld + ServerWorld serverWorld = (ServerWorld) world; + ServerPlayerEntity serverPlayer = (ServerPlayerEntity) player; + /*ServerPlayNetworking.send(serverPlayer, modNetworkingServer.grid_block_networking, + grid.writeEntityBuffer(hitResult, serverWorld)); + } + } + } else { + return ActionResult.PASS; + } + return ActionResult.SUCCESS; + } +} +*/ \ No newline at end of file diff --git a/src/main/java/modchest/grid/Registrar.java b/src/main/java/modchest/grid/Registrar.java new file mode 100644 index 0000000..0f0549f --- /dev/null +++ b/src/main/java/modchest/grid/Registrar.java @@ -0,0 +1,16 @@ +package modchest.grid; + +import net.minecraft.util.Identifier; +import net.minecraft.util.registry.Registry; + +public class Registrar { + private final Registry target; + + protected Registrar(final Registry target) { + this.target = target; + } + + protected U register(final U value, final Identifier id) { + return Registry.register(target, id, value); + } +} diff --git a/src/main/java/modchest/grid/data/Sections.java b/src/main/java/modchest/grid/data/Sections.java new file mode 100644 index 0000000..fca65e0 --- /dev/null +++ b/src/main/java/modchest/grid/data/Sections.java @@ -0,0 +1,110 @@ +package modchest.grid.data; + +import java.util.Arrays; +import java.util.Optional; +import java.util.stream.IntStream; + +import org.spongepowered.asm.util.perf.Profiler.Section; + +import net.minecraft.block.BlockState; +import net.minecraft.item.ItemStack; + +public class Sections { + public static final int BASE_INDEX = 0; + public static final int OVERLAY_INDEX = 1; + public static final int SPECIAL_INDEX = 2; + + public static Sections fromTag(ListTag tag) { + return new Sections(makesections(tag.stream().mapToInt(t -> ((IntTag) t).getInt()))); + } + + private static Section[] makSections(final IntStream sizes) { + int start = 0; + final int[] sizeArr = sizes.toArray(); + final Section[] sections = new Section[sizeArr.length]; + for (int i = 0, sizeArrLength = sizeArr.length; i < sizeArrLength; i++) { + final int size = sizeArr[i]; + sections[i] = Section.exclusive(start, start + size); + start += size; + } + return sections; + } + + private final Section[] sections; + + public Sections(final Section[] sections) { + this.sections = sections; + } + + public Sections(final int partCount, final int... otherSizes) { + this(makSections(IntStream.concat(IntStream.of(partCount, partCount, SPECIAL_ITEMS.Map.size()), Arrays.stream(otherSizes)))); + } + + public Section get(final int index) { + return sections[index]; + } + + public Section base() { + return get(BASE_INDEX); + } + + public Section overlay() { + return get(OVERLAY_INDEX); + } + + public Section special() { + return get(SPECIAL_INDEX); + } + + public Section itemIndices() { + return Section.exclusive(0, sections[sections.length -1].end()); + } + + public boolean containsSlot(final int slot) { + return 0 <= slot && slot < sections[sections.length -1].end(); + } + + public int findSectionIndexOf(final int absoluteIndex) { + for (int i = 0; i < sections.length; i++) { + if (absoluteIndex < sections[i].end()) { + return i; + } + } + return -1; + } + + public Optional[] makeItems() { + final Optional[] items = new Optional[sections[sections.length -1].end()]; + Arrays.fill(items, Optional.empty()); + return items; + } + + public Optional[] makeBaseStates() { + final Optional[] baseStates = new Optional[base().size()]; + Arrays.fill(baseStates, Optional.empty()); + return baseStates; + } + + public ListTag toTag() { + final ListTag tag = new ListTag(); + + for (final Section section : sections) { + tag.add(IntTag.of(section.size())); + } + return tag; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + final Sections sections1 = (Sections) o; + return Arrays.equals(sections, sections1.sections); + } + + @Override + public int hashCode() { + return Arrays.hashCode(sections); + } + +} diff --git a/src/main/java/modchest/grid/data/gridData.java b/src/main/java/modchest/grid/data/gridData.java new file mode 100644 index 0000000..3fade2e --- /dev/null +++ b/src/main/java/modchest/grid/data/gridData.java @@ -0,0 +1,129 @@ +package modchest.grid.data; + +import java.util.Arrays; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +import javax.swing.text.html.Option; + +import org.jetbrains.annotations.NotNull; + +import com.google.common.collect.Streams; + +import net.minecraft.block.BlockState; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NbtOps; +import net.minecraft.util.Identifier; +import net.minecraft.util.Pair; + +public class gridData { + private static Optional[] itemsFromTag(final Sections sections, final ListTag tag) { + final Optional[] items = sections.makeItems(); + + for (int i = 0, size = tag.size(); i< size; i++) { + final CompoundTag stackTag = tag.getCompound(i); + final int slot = stackTag.getByte("Slot") & 255; + if (sections.containsSlot(slot)) { + items[slot] = Optional.of(ItemStack.fromTag(stackTag)); + } + } + return items; + } + + private static optional[] baseStatesFromTag(final Sections sections, final ListTag tag) { + final Optional[] baseStates = sections.makeBaseStates(); + + for (int i = 0, size = tag.size(); i < size; i++) { + final CompoundTag stateTag = tag.getCompound(i); + final int realIndex = stateTag.getInt("i"); + baseStates[realIndex] = BlockState.CODEC.decode(new Dynamic<>(NbtOps.INSTANCE, stateTag)).result().map(Pair::getFirst); + } + return baseStates; + } + + public static gridData fromTag(final CompoundTag tag) { + final Sections sections = Sections.fromTag(tag.getList("format", 3)); + + return new gridData(sections, itemsFromTag(sections, tag.getList("Items", 10)), baseStatesFromTag(sections, tag.getList("states", 10))); + } + + private final Sections sections; + private final Optional[] items; + private final Optional[] baseStates; + + public gridData(final Sections sections, final Optional[] items, final Optional[] baseStates) { + this.sections = sections; + this.items = items; + this.baseStates = baseStates; + } + + public gridData(@NotNull final Sections sections) { + this(sections, sections.makeItems(), sections.makeBaseStates()); + } + + public Sections sections() { + return sections; + } + + public Optional[] items() { + return items; + } + + public List> baseItems() { + return Arrays.asList(items).subList(sections.base().start(), sections.base().end()); + } + + public List> overlayItems() { + return Arrays.asList(items).subList(sections.overlay().start(), sections.overlay().end()); + } + + public List> specialItems() { + return Arrays.asList(items).subList(sections.special().start(), sections.special().end()); + } + + public Optional[] baseStates() { + return baseStates; + } + + public CompoundTag toTag() { + final CompoundTag tag = new CompoundTag(); + + tag.put("format", sections.toTag()); + + final ListTag itemsTag = new ListTag(); + for (int i = 0, size = items.length; i < size; i++) { + final int i2 = i; + items[i].ifPresent(stack -> { + final CompoundTag stackTag = new CompoundTag(); + stack.toTag(stackTag); + stackTag.putByte("Slot", (byte)i2); + itemsTag.add(stackTag); + }); + } + if (!itemsTag.isEmpty()) { + tag.put("Items", itemsTag); + } + + final ListTag baseStatesTag = new ListTag(); + for (int i = 0, size = baseStates.length; i < size; i++) { + final int i2 = i; + baseStates[i].ifPresent(baseState -> { + final CompoundTag baseStateTag = new CompoundTag(); + baseStateTag.putInt("i", i2); + baseStateTag.add( + BlockState.CODEC.encode(baseState, NbtOps.INSTANCE, baseStateTag).get().left().get() + ); + }); + } + if (!baseStatesTag.isEmpty()) { + tag.put("states", baseStatesTag); + } + return tag; + } + + public List, Optional>> toRenderAttachment() { + return Streams.zip(Arrays.stream(baseStates), overlayItems().stream().map(i -> i.flatMap(OVERLAYS::getOverlayId)), Pair::new).collect(Collectors.toList()); + } + +} diff --git a/src/main/java/modchest/grid/gridBlock.java b/src/main/java/modchest/grid/gridBlock.java new file mode 100644 index 0000000..0144b9a --- /dev/null +++ b/src/main/java/modchest/grid/gridBlock.java @@ -0,0 +1,18 @@ +/*package modchest.grid; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.util.math.Direction; + +public class gridBlock extends Block{ + + public gridBlock(Settings settings) { + super(settings); + } + + @SuppressWarnings("deprecation") + @Override + public boolean isSideInvisible(BlockState state, BlockState stateFrom, Direction direction) { + return super.isSideInvisible(state, stateFrom, direction) || (state == stateFrom); + } +}*/ diff --git a/src/main/java/modchest/grid/gridBlockEntityTypes.java b/src/main/java/modchest/grid/gridBlockEntityTypes.java new file mode 100644 index 0000000..ed0b2d9 --- /dev/null +++ b/src/main/java/modchest/grid/gridBlockEntityTypes.java @@ -0,0 +1,36 @@ +package modchest.grid; + +import modchest.block.entity.gridEntity; +import net.minecraft.block.entity.BlockEntityType; +import net.minecraft.util.registry.Registry; + +public class gridBlockEntityTypes extends Registrar> { + public gridBlockEntityTypes() { + super(Registry.BLOCK_ENTITY_TYPE); + } + + public final BlockEntityType GRID = register( + BlockEntityType.Builder.create( + () -> new gridEntity(this.GRID, META.GRID_SECTIONS), + BLOCKS.GRID_BLOCK, + BLOCK.GRID_STAIRS, + BLOCK.GRID_FENCE, + BLOCK.GRID_FENCE_GATE, + BLOCKS.GRID_TRAPDOOR, + BLOCKS.GRID_DOOR, + BLOCKS.GRID_PATH, + BLOCKS.GRID_TORCH, + BLOCKS.GRID_WALL_TORCH, + BLOCKS.GRID_PRESSURE_PLATE, + BLOCKS.GRID_WALL, + BLOCKS.GRID_LAYER, + BLOCKS.GRID_CARPET, + BLOCKS.GRID_PANE).build(null), + META.id("frame")); + + public final BlockEntityType GRID_SLAB = register( + BlockEntityType.Builder.create( + () -> new gridEntity(this.GRID_SLAB, META.GRID_SLAB_SECTIONS), + BLOCKS.GRID_SLAB).build(null), + META.id("grid_slab")); +} diff --git a/src/main/java/modchest/grid/gridBlocks.java b/src/main/java/modchest/grid/gridBlocks.java new file mode 100644 index 0000000..c69cb4e --- /dev/null +++ b/src/main/java/modchest/grid/gridBlocks.java @@ -0,0 +1,93 @@ +package modchest.grid; + +import java.util.Properties; +import java.util.function.Function; + +import modchest.block.custom.grid.gridBlock; +import modchest.block.custom.grid.gridCarpet; +import modchest.block.custom.grid.gridDoor; +import modchest.block.custom.grid.gridFence; +import modchest.block.custom.grid.gridFenceGate; +import modchest.block.custom.grid.gridLayer; +import modchest.block.custom.grid.gridPane; +import modchest.block.custom.grid.gridPath; +import modchest.block.custom.grid.gridPressurePlate; +import modchest.block.custom.grid.gridSlab; +import modchest.block.custom.grid.gridStairs; +import modchest.block.custom.grid.gridTorch; +import modchest.block.custom.grid.gridTrapdoor; +import modchest.block.custom.grid.gridWall; +import modchest.block.custom.grid.gridWallTorch; +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; +import net.minecraft.block.AbstractBlock; +import net.minecraft.block.Block; +import net.minecraft.block.Material; +import net.minecraft.item.BlockItem; +import net.minecraft.item.Item; +import net.minecraft.sound.BlockSoundGroup; +import net.minecraft.state.property.Property; +import net.minecraft.util.Identifier; +import net.minecraft.util.registry.Registry; + +public class gridBlocks extends Registrar { + public final gridBlock GRID_BLOCK; + public final gridSlab GRID_SLAB; + public final gridStairs GRID_STAIRS; + public final gridFence GRID_FENCE; + public final gridFenceGate GRID_FENCE_GATE; + public final gridTrapdoor GRID_TRAPDOOR; + public final gridDoor GRID_DOOR; + public final gridPath GRID_PATH; + public final gridTorch GRID_TORCH; + public final gridWallTorch GRID_WALL_TORCH; + public final gridPressurePlate GRID_PRESSURE_PLATE; + public final gridWall GRID_WALL; + public final gridLayer GRID_LAYER; + public final gridCarpet GRID_CARPET; + public final gridPane GRID_PANE; + + private A registerWithItem(final A block, final Identifier id, final Item.Settings settings) { + Registry.register(Registry.ITEM, id, new BlockItem(block, settings)); + return register(block, id); + } + + public gridBlocks() { + super(Registry.BLOCK); + + final Function makeSettings = material -> FabricBlockSettings + .of(material) + .hardness(0.33f) + .sounds(BlockSoundGroup.WOOD) + .nonOpaque() + .solidBlock((a, b, c) -> false) + .luminance(state -> Boolean.TRUE.equals(state.get(Properties.LIT)) ? 15 : 0); + + final AbstractBlock.Settings gridSettings = makeSettings.apply(Material.WOOD); + final AbstractBlock.Settings gridTorchSettings = makeSettings.apply(Material.SUPPORTED).noCollision() + .breakInstantly() + .luminance(state -> Boolean.TRUE.equals(state.get(Properties.LIT)) ? 15 : 14); + + final Item.Settings itemSettings = new Item.Settings().group(META.MAIN_ITEM_GROUP); + + GRID_BLOCK = registerWithItem(new gridBlock(gridSettings), META.id("grid_block"), itemSettings); + GRID_SLAB = registerWithItem(new gridSlab(gridSettings), META.id("grid_slab"), itemSettings); + GRID_STAIRS = registerWithItem(new gridStairs(GRID_BLOCK.getDefaultState(), gridSettings), + META.id("grid_stairs"), itemSettings); + GRID_FENCE = registerWithItem(new gridFence(gridSettings), META.id("grid_fence"), itemSettings); + GRID_FENCE_GATE = registerWithItem(new gridFenceGate(gridSettings), META.id("grid_fence_gate"), itemSettings); + GRID_TRAPDOOR = registerWithItem(new gridTrapdoor(gridSettings.allowsSpawning((a, b, c, d) -> false)), + META.id("grid_trapdoor"), itemSettings); + GRID_DOOR = registerWithItem(new gridDoor(gridSettings), META.id("grid_door"), itemSettings); + GRID_PATH = registerWithItem(new gridPath(gridSettings), META.id("grid_path"), itemSettings); + GRID_PRESSURE_PLATE = registerWithItem(new gridPressurePlate(gridSettings), META.id("grid_pressure_plate"), + itemSettings); + GRID_WALL = registerWithItem(new gridWall(gridSettings), META.id("grid_wall"), itemSettings); + GRID_LAYER = registerWithItem(new gridLayer(gridSettings), META.id("grid_layer"), itemSettings); + GRID_CARPET = registerWithItem(new gridCarpet(gridSettings), META.id("grid_carpet"), itemSettings); + GRID_PANE = registerWithItem(new gridPane(gridSettings), META.id("grid_pane"), itemSettings); + + GRID_TORCH = registerWithItem(new gridTorch(gridTorchSettings), META.id("grid_torch")); + GRID_WALL_TORCH = registerWithItem(new gridWallTorch(gridTorchSettings), META.id("grid_wall_torch")); + } + +} diff --git a/src/main/java/modchest/grid/gridItems.java b/src/main/java/modchest/grid/gridItems.java new file mode 100644 index 0000000..90ac676 --- /dev/null +++ b/src/main/java/modchest/grid/gridItems.java @@ -0,0 +1,20 @@ +package modchest.grid; + +import modchest.item.custom.Hammer; +import net.minecraft.item.Item; +import net.minecraft.item.WallStandingBlockItem; +import net.minecraft.util.registry.Registry; + +public class gridItems extends Registrar { + public gridItems() { + super(Registry.ITEM); + } + + public final Hammer HAMMER = register(new Hammer(new Item.Settings().maxCount(1).group(META.MAIN_ITEM_GROUP)), META.id("hammer")); + + public final WallStandingBlockItem GRID_TORCH = register( + new WallStandingBlockItem(BLOCKS.GRID_TORCH, BLOCKS.GRID_WALL_TORCH, new Item.Settings().group(META.MAIN_ITEM_GROUP)), + META.id("grid_torch") + ); + +} diff --git a/src/main/java/modchest/grid/gridMeta.java b/src/main/java/modchest/grid/gridMeta.java new file mode 100644 index 0000000..4488e2d --- /dev/null +++ b/src/main/java/modchest/grid/gridMeta.java @@ -0,0 +1,37 @@ +package modchest.grid; + +import java.util.logging.LogManager; +import java.util.logging.Logger; + +import modchest.grid.data.Sections; +import modchest.gui.gridGuiDescription; +import net.fabricmc.fabric.api.client.itemgroup.FabricItemGroupBuilder; +import net.fabricmc.fabric.api.screenhandler.v1.ScreenHandlerRegistry; +import net.minecraft.item.ItemGroup; +import net.minecraft.item.ItemStack; +import net.minecraft.screen.ScreenHandlerContext; +import net.minecraft.screen.ScreenHandlerType; +import net.minecraft.util.Identifier; + +public class gridMeta { + public final String NAMESPACE = "grid"; + + public Identifier id(final String path) { + return new Identifier(NAMESPACE, path); + } + + public final Logger LOGGER = LogManager.getLogger("grid"); + + @SuppressWarnings("deprecation") + public final ScreenHandlerType GRID_SCREEN_HANDLER_TYPE = ScreenHandlerRegistry + .registerExtended(id("grid"), + (syncId, inventory, buf) -> new gridGuiDescription(syncId, inventory, + ScreenHandlerContext.create(inventory.player.world, buf.readBlockPos()))); + + public final Sections GRID_SECTIONS = new Sections(1); + public final Sections GRID_SLAB_SECTIONS = new Sections(2); + + public final ItemGroup MAIN_ITEM_GROUP = FabricItemGroupBuilder.create(id("grid")) + .icon(() -> new ItemStack(ITEMS.HAMMER)).build(); + +} diff --git a/src/main/java/modchest/grid/gridProperties.java b/src/main/java/modchest/grid/gridProperties.java new file mode 100644 index 0000000..ab5220b --- /dev/null +++ b/src/main/java/modchest/grid/gridProperties.java @@ -0,0 +1,7 @@ +package modchest.grid; + +import net.minecraft.state.property.BooleanProperty; + +public class gridProperties { + public final BooleanProperty HAS_REDSTONE = BooleanProperty.of("has_redstone"); +} diff --git a/src/main/java/modchest/gui/SingleItemSlots.java b/src/main/java/modchest/gui/SingleItemSlots.java new file mode 100644 index 0000000..328fb9c --- /dev/null +++ b/src/main/java/modchest/gui/SingleItemSlots.java @@ -0,0 +1,14 @@ +package modchest.gui; + +import net.minecraft.inventory.Inventory; + +public class SingleItemSlots extends WItemSlot { + public SingleItemSlots(final Inventory inventory, final int startIndex, final int slotsWide, final int slotsHigh, final boolean big) { + super(inventory, startIndex, slotsWide, slotsHigh, big); + } + + @Override + protected ValidatedSlot createSlotPeer(final Inventory inventory, final int index, final int x, final int y) { + return new ValidatedSingleItemSlot(inventory, index, x, y); + } +} diff --git a/src/main/java/modchest/gui/ValidatedSingleItemSlot.java b/src/main/java/modchest/gui/ValidatedSingleItemSlot.java new file mode 100644 index 0000000..3676bc9 --- /dev/null +++ b/src/main/java/modchest/gui/ValidatedSingleItemSlot.java @@ -0,0 +1,20 @@ +package modchest.gui; + +import net.minecraft.inventory.Inventory; +import net.minecraft.item.ItemStack; + +public class ValidatedSingleItemSlot extends ValidatedSlot { + public ValidatedSingleItemSlot(final Inventory inventory, final int index, final int x, final int y) { + super(inventory, index, x, y); + } + + @Override + public int getMaxItemCount() { + return 1; + } + + @Override + public int getMaxItemCount(final ItemStack stack) { + return 1; + } +} diff --git a/src/main/java/modchest/gui/gridGuiDescription.java b/src/main/java/modchest/gui/gridGuiDescription.java new file mode 100644 index 0000000..c2a776f --- /dev/null +++ b/src/main/java/modchest/gui/gridGuiDescription.java @@ -0,0 +1,32 @@ +package modchest.gui; + +import modchest.block.entity.gridEntity; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.screen.ScreenHandlerContext; + +public class gridGuiDescription extends SyncedGuiDescription { + public gridGuiDescription(final int syncId, final PlayerInventory playerInventory, final ScreenHandlerContext context) { + this (syncId, playerInventory, context, context.run((world, pos) -> (gridEntity) world.getBlockEntity(pos)) + .orElseThrow(() -> new IllegalArgumentException("gridGuiDescription can only be used with gridEntity")) + ); + } + + private gridGuiDescription(final int syncId, final PlayerInventory playerInventory, final ScreenHandlerContext context, final gridEntity grid) { + super(META.GRID_SCREEN_HANDLER_TYPE, syncId, playerInventory, SyncedGuiDescription.getBlockInventory(context, frame.size()), SyncedGuiDescription.getBlockPropertyDelegate(context)); + final WGridPanel root = new GridPanel(9); + root.add(centered(label("gui.framed.frame.base_label")), 1, 2, 8, 2); + root.add( + slotRow(SingleItemSlots::new, blockInventory, frame.sections().overlay()), + 13 - gridBlock.sections().overlay().size(), 4 //gridBlock ersetzt in diesem Fall frame also nochmal TODO + ); + root.add(centered(label("gui.framed.frame.special_label")), 0, 6, 18, 2); + + SPECIAL_ITEMS.Map.forEach((item, specialItem) -> root.add( + new SingleItemSlots(blockInventory, grid.sections().special().makeAbsolute(specialItem.offset()), 1, 1, false), + 9 - grid.sections().special().size() + specialItem.offset() *2, 8 + )); + root.add(createPlayerInventoryPanel(), 0, 11); + root.validate(this); + rootPanel = root; + } +} diff --git a/src/main/java/modchest/item/custom/Hammer.java b/src/main/java/modchest/item/custom/Hammer.java new file mode 100644 index 0000000..e8e497b --- /dev/null +++ b/src/main/java/modchest/item/custom/Hammer.java @@ -0,0 +1,225 @@ +package modchest.item.custom; + +import java.util.Arrays; +import java.util.Map; +import java.util.Optional; +import java.util.stream.IntStream; +import java.util.stream.Stream; + +import org.jetbrains.annotations.Nullable; + +import modchest.block.custom.grid.gridSlotInfo; +import modchest.block.entity.gridEntity; +import modchest.grid.data.gridData; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.item.ItemUsageContext; +import net.minecraft.text.TranslatableTextContent; +import net.minecraft.util.ActionResult; +import net.minecraft.util.Hand; +import net.minecraft.util.Pair; +import net.minecraft.util.TypedActionResult; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +public class Hammer extends Item { + + public Hammer(Settings settings) { + super(settings); + } + + public enum CopyMode { + NONE(0, "none"), ANY(1, "any"), REQUIRE_ALL(2, "require_all"); + + public final int id; + public final String translationKey; + + CopyMode(final int id, final String translationKey) { + this.translationKey = translationKey; + this.id = id; + } + + public CopyMode next() { + return CopyMode.values()[(id + 1) % CopyMode.values().length]; + } + + public static final CopyMode DEFAULT = NONE; + + public static Optional fromString(final String string) { + return Arrays.stream(values()).filter(s -> s.translationKey.equals(string)).findFirst(); + } + + public static CopyMode fromStringOrDefault(final String string) { + return fromString(string).orElse(DEFAULT); + } + } + + public static class Data { + public static Data fromTag(final CompoundTag tag) { + return new Data( + tag.contains("storedData") ? gridData.fromTag(tag.getCompound("storedData")) : null, + (tag.contains("mode") ? CopyMode.fromString(tag.getString("mode")) : Optional.empty()) + .orElse(CopyMode.DEFAULT)); + } + + private final @Nullable gridData storedData; + private final CopyMode mode; + + public Data(@Nullable final gridData storedData, final CopyMode mode) { + this.storedData = storedData; + this.mode = mode; + } + + public boolean applySettings(final gridSlotInfo slotInfo, final BlockState state, final gridEntity entity, final PlayerEntity player, final World world) { + final gridData storedData = this.storedData; + if (storedData == null) { + return false; + } + + if (!storedData.sections().equals(grid.sections())) { + player.sendMessage(new TranslatableText("gui.framers_hammer.different_format"), true); + return false; + } + + if (player.isCreative()) { + if (mode == CopyMode.NONE) { + return false; + } + + if (!world.isClient) { + IntStream.range(0, storedData.items().length) + .boxed() + .map(i -> new Pair<>(storedData.items()[i], i)) + .flatMap(pair -> pair.getFirst().map(itemStack -> Stream.of(new Pair<>(itemStack, pair.getSecond()))).orElseGet(Stream::empty)) + .forEach(pair -> grid.setStack(pair.getSecond(), pair.getFirst().copy())); + } + } else { + final boolean requireAllItems; + switch (mode) { + case NONE: + return false; + case ANY: + requireAllItems = false; + break; + case REQUIRE_ALL: + requireAllItems = true; + break; + default: + throw new IllegalStateException("Unreachable."); + } + + final Map itemSlotToGridSlot = IntStream.range(0, storedData.items().length).boxed() + .map(i -> new Pair<>(storedData.items()[i], i)) + .flatMap(pair -> { + if (pair.getFirst().isPresent()) { + return Stream.of(pair.mapFirst(stack -> stack.get().getItem())); + } else { + return Stream.empty(); + } + }).collect(Pair.toMap()); + + final Map playerSlotToGridSlot = IntStream.range(0, player.getInventory().size()).boxed() + .map(i -> new Pair<>(Optional.of(player.getInventory().getStack(i)).filter(s -> !s.isEmpty()), i)) + .flatMap(pair -> { + final Item item = maybeStack.get().getItem(); + if (itemSlotToGridSlot.containsKey(item)) { + return Stream.of(new Pair(pair.getSecond(), itemSlotToGridSlot.get(item))); + } else { + return Stream.empty(); + } else { + return Stream.empty(); + } + + }).collect(Pair.toMap()); + + if (!world.isClient) { + for (final Map.Entry entry : playerSlotToGridSlot.entrySet()) { + final int playerSlot = entry.getKey(); + final int gridSlot = entry.getValue(); + + if (grid.getStack(gridSlot).getItem() != player.getInventory().getStack(playerSlot).getItem() && slotInfo.absoluteSlotIsValid(grid, state, gridSlot)) { + if (!grid.getStack(gridSlot).isEmpty()) { + player.getInventory().offerOrDrop(world, grid.removeStack(gridSlot)); + } + grid.setStack(gridSlot, player.getInventory().removeStack(playerSlot, 1)); + } + } + } + } + + player.sendMessage(new TranslatableText("gui.framed.framers_hammer.apply_settings"), true); + return true; + } + + } + + private CompoundTag getTagOrAssignDefault (final ItemStack stack) { + if (stack.getTag() == null) { + final CompoundTag tag = new CompoundTag(); + tag.putString("mode", CopyMode.DEFAULT.toString()); + stack.setTag(tag); + } + return stack.getTag(); + } + + @Override + public ActionResult useOnBlock(final ItemUsageContext context) { + final CompoundTag tag = getTagOrAssignDefault(context.getStack()); + final Data data = Data.fromTag(tag); + + final BlockPos pos = context.getBlockPos(); + final World world = context.getWorld(); + final BlockState state = world.getBlockState(pos); + + final Block block = state.getBlock(); + if (!(block instanceof gridSlotInfo)) { + return super.useOnBlock(context); + } + + final gridSlotInfo slotInfo = (gridSlotInfo) block; + + final BlockEntity blockEntity = world.getBlockEntity(pos); + if (!(blockEntity instanceof gridEntity)) { + return super.useOnBlock(context); + } + final gridEntity grid = (gridEntity) blockEntity; + + final PlayerEntity player = context.getPlayer(); + if (player == null) { + return super.useOnBlock(context); + } + + if (player.isSneaking()) { + player.sendMessage(new TranslatableText("gui.framers_hammer.copy_settings"), true); + tag.put("storedData", grid.data().toTag()); + return ActionResult.SUCCESS; + } else { + if (data.applySettings(slotInfo, state, grid, player, world)) { + return ActionResult.SUCCESS; + } else { + return super.useOnBlock(context); + } + } + } + + @Override + public TypedActionResult use(final World world, final PlayerEntity user, final Hand hand) { + if (!user.isSneaking()) { + return super.use(world, user, hand); + } + + final ItemStack stack = user.getStackInHand(hand); + final CompoundTag tag = getTagOrAssignDefault(stack); + final CopyMode mode = CopyMode.fromStringOrDefault(tag.getString("mode")); + + final CopyMode newMode = mode.next(); + tag.putString("mode", newMode.toString()); + user.sendMessage(new TranslatableText("gui.framed.framers_hammer" + newMode.translationKey), true); + return TypedActionResult.success(stack); + } + +} diff --git a/src/main/java/modchest/item/custom/SpecialItems.java b/src/main/java/modchest/item/custom/SpecialItems.java new file mode 100644 index 0000000..baa8d99 --- /dev/null +++ b/src/main/java/modchest/item/custom/SpecialItems.java @@ -0,0 +1,53 @@ +package modchest.item.custom; + +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.stream.IntStream; + +import com.google.common.collect.Lists; +import com.google.common.collect.Streams; + +import modchest.block.entity.gridEntity; +import net.minecraft.item.Item; +import net.minecraft.item.Items; +import net.minecraft.state.property.BooleanProperty; +import net.minecraft.util.Pair; +import net.minecraft.world.World; + +public class SpecialItems { + public static class SpecialItem { + private final int offset; + private final BooleanProperty property; + + public SpecialItem(final int offset, final BooleanProperty property) { + this.offset = offset; + this.property = property; + } + + public int offset() { + return offset; + } + + public void onAdd(final World world, final gridEntity grid) { + world.setBlockState(grid.getPos(), world.getBlockState(grid.getPos()).with(property, true)); + } + + public void onRemove(final World world, final gridEntity grid) { + world.setBlockState(grid.getPos(), world.getBlockState(frame.getPos()).with(property, false)); + } + + } + + public final Map MAP; + + public SpecialItems() { + final List> pairs = Lists.newArrayList( + Pair.of(Items.GLOWSTONE_DUST, Properties.LIT), Pair.of(Items.REDSTONE, PROPERTIES.HAS_REDSTONE) + ); + + MAP = Streams.zip(IntStream.range(0, pairs.size()).boxed(), pairs.stream(), Pair::new) + .map(pair -> new Pair<>(pair.getSecond().getFirst(), new SpecialItem(pair.getFirst(), pair.getSecond().getSecond())) + ).collect(Pair.toMap()); + } +} diff --git a/src/main/java/modchest/mixin/local/SinglePartGridBlock.java b/src/main/java/modchest/mixin/local/SinglePartGridBlock.java new file mode 100644 index 0000000..9bcd119 --- /dev/null +++ b/src/main/java/modchest/mixin/local/SinglePartGridBlock.java @@ -0,0 +1,63 @@ +package modchest.mixin.local; + +import org.spongepowered.asm.mixin.Mixin; + +import modchest.block.custom.grid.gridBlock; +import modchest.block.custom.grid.gridCarpet; +import modchest.block.custom.grid.gridDoor; +import modchest.block.custom.grid.gridFence; +import modchest.block.custom.grid.gridFenceGate; +import modchest.block.custom.grid.gridLayer; +import modchest.block.custom.grid.gridPane; +import modchest.block.custom.grid.gridPath; +import modchest.block.custom.grid.gridPressurePlate; +import modchest.block.custom.grid.gridSlab; +import modchest.block.custom.grid.gridSlotInfo; +import modchest.block.custom.grid.gridStairs; +import modchest.block.custom.grid.gridTorch; +import modchest.block.custom.grid.gridTrapdoor; +import modchest.block.custom.grid.gridWall; +import modchest.block.custom.grid.gridWallTorch; +import modchest.block.entity.gridEntity; +import modchest.grid.data.Sections; +import net.minecraft.block.BlockState; +import net.minecraft.util.math.Direction; +import net.minecraft.util.math.Vec3d; + +@Mixin({ + gridBlock.class, + gridSlab.class, + gridStairs.class, + gridFence.class, + gridFenceGate.class, + gridTrapdoor.class, + gridDoor.class, + gridPath.class, + gridTorch.class, + gridWallTorch.class, + gridPressurePlate.class, + gridWall.class, + gridLayer.class, + gridCarpet.class, + gridPane.class +}) +public class SinglePartGridBlock implements gridSlotInfo { + private SinglePartGridBlock() { + throw new IllegalStateException("Mixin constructor should not run"); + } + + @Override + public Sections sections() { + return META.GRID_SECTIONS; + } + + @Override + public int getRelativeSlotAt(final Vec3d posInBlock, final Direction side) { + return 0; + } + + @Override + public boolean absoluteSlotIsValid(final gridEntity grid, final BlockState state, final int slot) { + return grid.sections().containsSlot(slot); + } +} diff --git a/src/main/java/modchest/mixin/local/gridBehaviour.java b/src/main/java/modchest/mixin/local/gridBehaviour.java new file mode 100644 index 0000000..8991a93 --- /dev/null +++ b/src/main/java/modchest/mixin/local/gridBehaviour.java @@ -0,0 +1,330 @@ +package modchest.mixin.local; + +import java.util.List; +import java.util.Optional; +import java.util.Properties; +import java.util.function.Supplier; + +import javax.swing.text.html.BlockView; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.lwjgl.system.NonnullDefault; +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.callback.CallbackInfo; + +import com.mojang.datafixers.util.Function3; + +import modchest.block.custom.grid.grid; +import modchest.block.custom.grid.gridBlock; +import modchest.block.custom.grid.gridCarpet; +import modchest.block.custom.grid.gridDoor; +import modchest.block.custom.grid.gridFence; +import modchest.block.custom.grid.gridFenceGate; +import modchest.block.custom.grid.gridLayer; +import modchest.block.custom.grid.gridPane; +import modchest.block.custom.grid.gridPath; +import modchest.block.custom.grid.gridPressurePlate; +import modchest.block.custom.grid.gridSlab; +import modchest.block.custom.grid.gridSlotInfo; +import modchest.block.custom.grid.gridStairs; +import modchest.block.custom.grid.gridTorch; +import modchest.block.custom.grid.gridTrapdoor; +import modchest.block.custom.grid.gridWall; +import modchest.block.custom.grid.gridWallTorch; +import modchest.block.entity.gridEntity; +import modchest.event.playerAfterRespawnEvent; +import modchest.item.custom.Hammer; +import modchest.item.custom.SpecialItems; +import modchest.item.custom.SpecialItems.SpecialItem; +import modchest.util.ValidQuery; +import net.minecraft.block.Block; +import net.minecraft.block.BlockEntityProvider; +import net.minecraft.block.BlockState; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.block.entity.StructureBlockBlockEntity.Action; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.inventory.Inventory; +import net.minecraft.item.Item; +import net.minecraft.item.ItemPlacementContext; +import net.minecraft.item.ItemStack; +import net.minecraft.item.ItemUsageContext; +import net.minecraft.screen.NamedScreenHandlerFactory; +import net.minecraft.sound.SoundCategory; +import net.minecraft.sound.SoundEvents; +import net.minecraft.state.StateManager; +import net.minecraft.state.StateManager.Builder; +import net.minecraft.util.ActionResult; +import net.minecraft.util.Hand; +import net.minecraft.util.ItemScatterer; +import net.minecraft.util.Unit; +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.world.World; + +@Mixin({ + gridBlock.class, + gridSlab.class, + gridStairs.class, + gridFence.class, + gridFenceGate.class, + gridTrapdoor.class, + gridDoor.class, + gridPath.class, + gridTorch.class, + gridWallTorch.class, + gridPressurePlate.class, + gridWall.class, + gridLayer.class, + gridCarpet.class, + gridPane.class +}) +public abstract class gridBehaviour extends Block implements BlockEntityProvider, grid, gridSlotInfo { + + public gridBehaviour(Settings settings) { + super(settings); + throw new IllegalStateException("Mixin constructor should never run"); + } + + @Inject(method = "*", at = @At("TAIL")) + void setGridPropertiesDefaultState(CallbackInfo ci) { + setDefaultState(getDefaultState().with(Properties.LIT, false).with(Properties.HAS_REDSTONE, false)); + } + + @Unique + @Nullable + private PlayerEntity breaker; + + @Override + protected void appendProperties(final StateManager.Builder builder) { + super.appendProperties(builder); + builder.add(Properties.LIT, Properties.HAS_REDSTONE); + } + + @SuppressWarnings("deprecation") + @Override + public boolean emitsRedstonePower(final BlockState state) { + return super.emitsRedstonePower(state) || state.get(PROPERTIES.HAS_REDSTONE); + } + + @SuppressWarnings("deprecation") + @Override + public int getWeakRedstonePower(BlockState state, net.minecraft.world.BlockView world, BlockPos pos, + Direction direction) { + if (state.get(PROPERTIES.HAS_REDSTONE)) { + return 15 - super.getWeakRedstonePower(state, world, pos, direction) + } else { + return super.getWeakRedstonePower(state, world, pos, direction); + } + } + + @SuppressWarnings("deprecation") + @Override + public boolean onSyncedBlockEvent(BlockState state, World world, BlockPos pos, int type, int data) { + super.onSyncedBlockEvent(state, world, pos, type, data); + final @Nullable BlockEntity blockEntity = world.getBlockEntity(pos); + if (blockEntity == null) { + return false; + } + return blockEntity.onSyncedBlockEvent(type, data); + } + + @SuppressWarnings("deprecation") + @Nullable + @Override + public NamedScreenHandlerFactory createScreenHandlerFactory(BlockState state, World world, BlockPos pos) { + return (NamedScreenHandlerFactory) world.getBlockEntity(pos); + } + + private void removeStack(final World world, final gridEntity from, final PlayerEntity to, final int slot, + final boolean giveItem) { + final ItemStack stack = from.removeStack(slot); + if (!stack.isEmpty() && giveItem) { + to.getInventory().offerOrDrop(stack); + world.playSound(null, from.getPos(), SoundEvents.ENTITY_ITEM_PICKUP, SoundCategory.PLAYERS, 0.2f, + (float) (Math.random() - Math.random()) * 1.4f + 2f); + } + } + + private void onHammerRemoved(final World world, final gridEntity grid, final BlockState state, + final PlayerEntity player, final boolean giveItem) { + world.setBlockState(grid.getPos(), state); + + if (player.isSneaking()) { + for (final int i : grid.sections().itemIndices()) { + removeStack(world, grid, player, i, giveItem); + } + } else { + int slot = -1; + for (int i = grid.size() - 1; i >= 0; i--) { + if (grid.items()[i].isPresent()) { + slot = i; + break; + } + + } + if (slot != -1) { + removeStack(world, grid, player, slot, giveItem); + } + } + + } + + @SuppressWarnings("deprecation") + @Override + public void onStateReplaced(BlockState oldState, World world, BlockPos pos, BlockState newState, boolean moved) { + if (world.isClient || oldState.getBlock() == newState.getBlock()) { + return; + } + + final @Nullable BlockEntity blockEntity = world.getBlockEntity(pos); + final @Nullable PlayerEntity player = breaker; + + if (player != null) { + if (player.getStackInHand(player.getActiveHand()).getItem() == ITEMS.GRID_HAMMER) { + onHammerRemoved(world, (gridEntity) blockEntity, oldState, player, false); + } else { + super.onStateReplaced(oldState, world, pos, newState, moved); + } + } else { + if (blockEntity instanceof Inventory) { + ItemScatterer.spawn(world, pos, (Inventory) blockEntity); + } + super.onStateReplaced(state, world, pos, newState, moved); + } + + } + + @SuppressWarnings("deprecation") + @Override + public void onBlockBreakStart(BlockState state, World world, BlockPos pos, PlayerEntity player) { + super.onBlockBreakStart(state, world, pos, player); + if (world.isClient) { + return; + } + + if (player.getStackInHand(player.getActiveHand()).getItem() == ITEMS.GRID_HAMMER) { + final @Nullable BlockEntity blockEntity = world.getBlockEntity(pos); + + if (blockEntity instanceof gridEntity) { + onHammerRemoved(world, (gridEntity) blockEntity, state, player, true); + } + } + } + + @Override + public void onBreak(World world, BlockPos pos, BlockState state, PlayerEntity player) { + super.onBreak(world, pos, state, player); + if (world.isClient || !player.isCreative()) { + return; + } + breaker = player; + } + + @SuppressWarnings("deprecation") + @Override + public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, + BlockHitResult hit) { + final @Nullable BlockEntity blockEntity = world.getBlockEntity(pos); + if (!(blockEntity instanceof gridEntity)) { + return ActionResult.CONSUME; + } + + final @NotNull gridEntity grid = (gridEntity) blockEntity; + final @Nullable ItemStack playerStack = player.getMainHandStack(); + + if (playerStack != null) { + final Vec3d posInBlock = hit.getPos().subtract(Vec3d.of(hit.getBlockPos())); + final int relativeSlot = getRelativeSlotAt(posInBlock, hit.getSide()); + + final Function3>, Integer, Supplier, ActionResult> swapItems = (slots, + absoluteSlot, onSuccess) -> { + final Optional maybeStack = slots.get(relativeSlot); + if (playerStack.getItem() != maybeStack.orElse(ItemStack.EMPTY).getItem()) { + if (!world.isClient) { + if (!player.isCreative() && maybeStack.isPresent()) { + player.getInventory().offerOrDrop(maybeStack.get()); + } + grid.copyFrom(absoluteSlot, playerStack, 1, !player.isCreative()); + onSuccess.get(); + } + return ActionResult.SUCCESS; + } else { + return ActionResult.CONSUME; + } + }; + + final ValidQuery.ItemStackValidQuery query = checkIf(playerStack); + + if (query.isValidForOverlay()) { + final int absoluteSlot = grid.sections().overlay().makeAbsolute(relativeSlot); + return swapItems.apply(grid.overlayItems(), absoluteSlot, () -> Unit.INSTANCE); + } + + final Optional maybeBaseState = query.isValidForBase( + i -> Optional.ofNullable(i.getBlock() + .getPlacementState(new ItemPlacementContext(new ItemUsageContext(player, hand, hit)))), + world, pos); + if (maybeBaseState.isPresent()) { + final int absoluteSlot = grid.sections().base().makeAbsolute(relativeSlot); + return swapItems.apply(grid.baseItems(), absoluteSlot, () -> { + grid.baseStates()[relativeSlot] = maybeBaseState; + return Unit.INSTANCE; + }); + } + + if (query.isValidForSpecial()) { + final SpecialItems.SpecialItem specialItem = SPECIAL_ITEM.Map.get(playerStack.getItem()); + final int slot = grid.sections().special().makeAbsolute(specialItem.offset()); + + if (grid.getStack(slot).isEmpty()) { + if (!world.isClient) { + grid.copyFrom(slot, playerStack, 1, !player.isCreative()); + specialItem.onAdd(world, grid); + } + return ActionResult.SUCCESS; + } else { + return ActionResult.CONSUME; + } + } + if (playerStack.isEmpty() && player.isSneaking()) { + player.openHandledScreen(state.createScreenHandlerFactory(world, pos)); + return ActionResult.SUCCESS; + } + } + return super.onUse(state, world, pos, player, hand, hit); + } + + @Override + public void onPlaced(World world, BlockPos pos, BlockState state, LivingEntity placer, ItemStack itemStack) { + final boolean tryCopy; + + if (placer instanceof PlayerEntity) { + final PlayerEntity player = (PlayerEntity) placer; + if (player.getOffHandStack().getItem() != ITEMS.GRID_HAMMER || player.getOffHandStack().getTag() == null) { + tryCopy = false; + } else { + final BlockEntity blockEntity = world.getBlockEntity(pos); + if (blockEntity instanceof gridEntity) { + tryCopy = Hammer.Data.fromTag(player.getOffHandStack().getTag()).applySettings(this, + (gridEntity) blockEntity, player, world); + } else { + tryCopy = false; + } + } + } else { + tryCopy = false; + } + if (!tryCopy) { + super.onPlaced(world, pos, state, placer, itemStack); + } + + } + +} diff --git a/src/main/java/modchest/mixin/local/gridEntityProvider.java b/src/main/java/modchest/mixin/local/gridEntityProvider.java new file mode 100644 index 0000000..b0d6a9f --- /dev/null +++ b/src/main/java/modchest/mixin/local/gridEntityProvider.java @@ -0,0 +1,55 @@ +package modchest.mixin.local; + +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; + +import modchest.block.custom.grid.gridBlock; +import modchest.block.custom.grid.gridCarpet; +import modchest.block.custom.grid.gridDoor; +import modchest.block.custom.grid.gridFence; +import modchest.block.custom.grid.gridFenceGate; +import modchest.block.custom.grid.gridLayer; +import modchest.block.custom.grid.gridPane; +import modchest.block.custom.grid.gridPath; +import modchest.block.custom.grid.gridPressurePlate; +import modchest.block.custom.grid.gridSlab; +import modchest.block.custom.grid.gridStairs; +import modchest.block.custom.grid.gridTorch; +import modchest.block.custom.grid.gridTrapdoor; +import modchest.block.custom.grid.gridWall; +import modchest.block.custom.grid.gridWallTorch; +import modchest.block.entity.gridEntity; +import net.minecraft.block.BlockEntityProvider; +import net.minecraft.block.BlockState; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.BlockView; + +@Mixin({ + gridBlock.class, + gridSlab.class, + gridStairs.class, + gridFence.class, + gridFenceGate.class, + gridTrapdoor.class, + gridDoor.class, + gridPath.class, + gridTorch.class, + gridWallTorch.class, + gridPressurePlate.class, + gridWall.class, + gridLayer.class, + gridCarpet.class, + gridPane.class +}) +public class gridEntityProvider implements BlockEntityProvider { + private gridEntityProvider() { + throw new IllegalStateException("Mixin constructor should not run"); + } + + @Override + public BlockEntity createBlockEntity(BlockPos pos, BlockState state) { + return new gridEntity(BLOCK_ENTITY_TYPES.GRID, META.FRAME_SECTIONS); + } + +} diff --git a/src/main/java/modchest/mixin/mc/BakedQuadAccess.java b/src/main/java/modchest/mixin/mc/BakedQuadAccess.java new file mode 100644 index 0000000..7307b8d --- /dev/null +++ b/src/main/java/modchest/mixin/mc/BakedQuadAccess.java @@ -0,0 +1,13 @@ +package modchest.mixin.mc; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import net.minecraft.client.render.model.BakedQuad; +import net.minecraft.client.texture.Sprite; + +@Mixin(BakedQuad.class) +public interface BakedQuadAccess { + @Accessor("sprite") + Sprite sprite; +} diff --git a/src/main/java/modchest/mixin/mc/BlockItemAccess.java b/src/main/java/modchest/mixin/mc/BlockItemAccess.java new file mode 100644 index 0000000..a864489 --- /dev/null +++ b/src/main/java/modchest/mixin/mc/BlockItemAccess.java @@ -0,0 +1,15 @@ +package modchest.mixin.mc; + +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +import net.minecraft.block.BlockState; +import net.minecraft.item.BlockItem; +import net.minecraft.item.ItemPlacementContext; + +@Mixin(BlockItem.class) +public interface BlockItemAccess { + @Invoker("getPlacementState") + @Nullable BlockState getPlacementStateProxy(ItemPlacementContext context); +} diff --git a/src/main/java/modchest/mixin/mc/FenceBlockMixin.java b/src/main/java/modchest/mixin/mc/FenceBlockMixin.java new file mode 100644 index 0000000..7b5abba --- /dev/null +++ b/src/main/java/modchest/mixin/mc/FenceBlockMixin.java @@ -0,0 +1,27 @@ +package modchest.mixin.mc; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import modchest.REServerMod; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.block.FenceBlock; +import net.minecraft.util.math.Direction; + +@Mixin(FenceBlock.class) +public class FenceBlockMixin { + @Inject(method = "canConnect", at = @At("HEAD"), cancellable = true) + void connectToGridFence(final BlockState state, final boolean neighborIsFullSquare, final Direction dir, + final CallbackInfoReturnable cir) { + if (state.isOf(modchest.REServerMod.BLOCKS.GRID_FENCE)) { + cir.setReturnValue(true); + } + + if ((Object) this == REServerMod.BLOCKS.GRID_FENCE && state.getBlock() instanceof FenceBlock) { + cir.setReturnValue(true); + } + } +} diff --git a/src/main/java/modchest/mixin/mc/GetItemBeforeEmpty.java b/src/main/java/modchest/mixin/mc/GetItemBeforeEmpty.java new file mode 100644 index 0000000..c2a6723 --- /dev/null +++ b/src/main/java/modchest/mixin/mc/GetItemBeforeEmpty.java @@ -0,0 +1,13 @@ +package modchest.mixin.mc; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; + +@Mixin(ItemStack.class) +public interface GetItemBeforeEmpty { + @Accessor("item") + Item getItemBeforeEmpty(); +} diff --git a/src/main/java/modchest/mixin/mc/ItemRendererMixin.java b/src/main/java/modchest/mixin/mc/ItemRendererMixin.java new file mode 100644 index 0000000..e7e212d --- /dev/null +++ b/src/main/java/modchest/mixin/mc/ItemRendererMixin.java @@ -0,0 +1,53 @@ +package modchest.mixin.mc; + +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 modchest.util.initializer; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.render.item.ItemModels; +import net.minecraft.client.render.item.ItemRenderer; +import net.minecraft.client.render.model.BakedModel; +import net.minecraft.client.util.ModelIdentifier; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.entity.LivingEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.world.World; + +@Environment(EnvType.CLIENT) +@Mixin(ItemRenderer.class) +public abstract class ItemRendererMixin { + @Final + @Shadow + private ItemModels models; + + @Shadow + public abstract BakedModel getHeldItemModel(ItemStack stack, World world, LivingEntity entity); + + @Redirect(method = "getHeldItemModel", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/item/ItemModels;getModel(Lnet/minecraft/item/ItemStack;)Lnet/minecraft/client/render/model/BakedModel;")) + BakedModel getModelProxy(final ItemModels itemModels, final ItemStack stack) { + if (stack.getItem() == ITEMS.HAMMER) { + return itemModels.getModelManager().getModel(new ModelIdentifier(META.id("hammer_none"), "inventory")); + } + return itemModels.getModel(stack); + } + + @Redirect(method = "innerRenderInGui", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/item/ItemRenderer;getHeldItemModel(Lnet/minecraft/item/ItemStack;Lnet/minecraft/world/World;Lnet/minecraft/entity/LivingEntity;)Lnet/minecraft/client/render/model/BakedModel;")) + BakedModel getHeldItemModelProxy(final ItemRenderer itemRenderer, final ItemStack stack, final World world, + final LivingEntity entity) { + if (stack.getItem() == ITEMS.HAMMER) { + final ClientWorld clientWorld = world instanceof ClientWorld ? (ClientWorld) world : null; + final BakedModel model = models.getModelManager() + .getModel(new ModelIdentifier(META.id("hammer"), "inventory")); + final BakedModel model2 = model.getOverrides().apply(model, stack, clientWorld, entity, 0); + return model2 == null ? models.getModelManager().getMissingModel() : model2; + } + return this.getHeldItemModel(stack, world, entity); + } + +} diff --git a/src/main/java/modchest/mixin/mc/WallBlockMixin.java b/src/main/java/modchest/mixin/mc/WallBlockMixin.java new file mode 100644 index 0000000..7f6beee --- /dev/null +++ b/src/main/java/modchest/mixin/mc/WallBlockMixin.java @@ -0,0 +1,90 @@ +package modchest.mixin.mc; + +import java.util.Map; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import com.google.common.collect.ImmutableMap; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.WallBlock; +import net.minecraft.block.enums.WallShape; +import net.minecraft.state.property.BooleanProperty; +import net.minecraft.state.property.EnumProperty; +import net.minecraft.util.shape.VoxelShape; +import net.minecraft.util.shape.VoxelShapes; + +@Mixin(WallBlock.class) +public class WallBlockMixin extends Block { + @Shadow + @Final + public static BooleanProperty UP; + @Shadow + @Final + public static EnumProperty EAST_SHAPE; + @Shadow + @Final + public static EnumProperty WEST_SHAPE; + @Shadow + @Final + public static EnumProperty SOUTH_SHAPE; + @Shadow + @Final + public static EnumProperty NORTH_SHAPE; + + @SuppressWarnings("unused") + public WallBlockMixin(Settings settings) { + super(settings); + throw new IllegalStateException("Mixin constructor should not run"); + } + + @SuppressWarnings("unused") + @Shadow + private static VoxelShape method_24426(VoxelShape voxelShape, WallShape wallShape, VoxelShape voxelShape2, VoxelShape voxelShape3) { + throw new IllegalStateException("Shadow method should not run."); + } + + @SuppressWarnings("DuplicatedCode") + @Override + private Map getShapeMap(float f, float g, float h, float i, float j, float k) { + float l = 8.0F - f; + float m = 8.0F + f; + float n = 8.0F - g; + float o = 8.0F + g; + VoxelShape voxelShape = Block.createCuboidShape(l, 0.0D, l, m, h, m); + VoxelShape voxelShape2 = Block.createCuboidShape(n, i, 0.0D, o, j, o); + VoxelShape voxelShape3 = Block.createCuboidShape(n, i, n, o, j, 16.0D); + VoxelShape voxelShape4 = Block.createCuboidShape(0.0D, i, n, o, j, o); + VoxelShape voxelShape5 = Block.createCuboidShape(n, i, n, 16.0D, j, o); + VoxelShape voxelShape6 = Block.createCuboidShape(n, i, 0.0D, o, k, o); + VoxelShape voxelShape7 = Block.createCuboidShape(n, i, n, o, k, 16.0D); + VoxelShape voxelShape8 = Block.createCuboidShape(0.0D, i, n, o, k, o); + VoxelShape voxelShape9 = Block.createCuboidShape(n, i, n, 16.0D, k, o); + ImmutableMap.Builder builder = ImmutableMap.builder(); + + for (BlockState state : stateManager.getStates()) { + Boolean boolean_ = state.get(UP); + WallShape wallShape = state.get(EAST_SHAPE); + WallShape wallShape2 = state.get(NORTH_SHAPE); + WallShape wallShape3 = state.get(WEST_SHAPE); + WallShape wallShape4 = state.get(SOUTH_SHAPE); + + VoxelShape voxelShape10 = VoxelShapes.empty(); + voxelShape10 = method_24426(voxelShape10, wallShape, voxelShape5, voxelShape9); + voxelShape10 = method_24426(voxelShape10, wallShape3, voxelShape4, voxelShape8); + voxelShape10 = method_24426(voxelShape10, wallShape2, voxelShape2, voxelShape6); + voxelShape10 = method_24426(voxelShape10, wallShape4, voxelShape3, voxelShape7); + if (Boolean.TRUE.equals(boolean_)) { + voxelShape10 = VoxelShapes.union(voxelShape10, voxelShape); + } + builder.put(state, voxelShape10); + + } + return builder.build(); + + } + +} diff --git a/src/main/java/modchest/mixin/mc/WorldRendererAccess.java b/src/main/java/modchest/mixin/mc/WorldRendererAccess.java new file mode 100644 index 0000000..9ec426c --- /dev/null +++ b/src/main/java/modchest/mixin/mc/WorldRendererAccess.java @@ -0,0 +1,15 @@ +package modchest.mixin.mc; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.render.WorldRenderer; + +@Mixin(WorldRenderer.class) +@Environment(EnvType.CLIENT) +public interface WorldRendererAccess { + @Accessor("ticks") + int ticks(); +} diff --git a/src/main/java/modchest/util/Float4.java b/src/main/java/modchest/util/Float4.java new file mode 100644 index 0000000..ee7480f --- /dev/null +++ b/src/main/java/modchest/util/Float4.java @@ -0,0 +1,35 @@ +package modchest.util; + +import java.util.PrimitiveIterator; + +public class Float4 { + public final float a; + public final float b; + public final float c; + public final float d; + + public Float4(final float a, final float b, final float c, final float d) { + this.a = a; + this.b = b; + this.c = c; + this.d = d; + } + + public static Float4 of(final float a, final float b, final float c, final float d) { + return new Float4(a, b, c, d); + } + + public float min() { + return Math.min(Math.min(Math.min(a, b), c), d); + } + + public float max() { + return Math.max(Math.max(Math.max(a, b), c), d); + } + + public static Float4 fromIterator(final PrimitiveIterator.OfDouble doubles) { + return new Float4((float) doubles.nextDouble(), (float) doubles.nextDouble(), (float) doubles.nextDouble(), (float) doubles.nextDouble()); + } + + +} diff --git a/src/main/java/modchest/util/FunctionalUtil.java b/src/main/java/modchest/util/FunctionalUtil.java new file mode 100644 index 0000000..a90d2cc --- /dev/null +++ b/src/main/java/modchest/util/FunctionalUtil.java @@ -0,0 +1,22 @@ +package modchest.util; + +import java.util.Optional; +import java.util.OptionalInt; +import java.util.function.Function; +import java.util.function.ToIntFunction; + +@SuppressWarnings("OptionalUsedAsFieldOrParameterType") +public class FunctionalUtil { + private FunctionalUtil() { + throw new IllegalStateException("Should not instantiate utility class."); + } + + public static OptionalInt mapToInt(final Optional optional, final ToIntFunction f) { + return optional.map(a -> OptionalInt.of(f.applyAsInt(a))).orElseGet(OptionalInt::empty); + } + + public static OptionalInt flatMapToInt(final Optional optional, final Function f) { + return optional.isPresent() ? f.apply(optional.get()) : OptionalInt.empty(); + } + +} diff --git a/src/main/java/modchest/util/GetItemBeforeEmptyUtil.java b/src/main/java/modchest/util/GetItemBeforeEmptyUtil.java new file mode 100644 index 0000000..a793206 --- /dev/null +++ b/src/main/java/modchest/util/GetItemBeforeEmptyUtil.java @@ -0,0 +1,16 @@ +package modchest.util; + +import modchest.mixin.mc.GetItemBeforeEmpty; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; + +public class GetItemBeforeEmptyUtil { + private GetItemBeforeEmptyUtil(){ + throw new IllegalStateException("Should not instantiate utility class."); + } + + public static Item getItemBeforeEmpty(final ItemStack stack) { + return ((GetItemBeforeEmpty) (Object) stack).getItemBeforeEmpty(); + } + +} diff --git a/src/main/java/modchest/util/GuiUtil.java b/src/main/java/modchest/util/GuiUtil.java new file mode 100644 index 0000000..328dc55 --- /dev/null +++ b/src/main/java/modchest/util/GuiUtil.java @@ -0,0 +1,29 @@ +package modchest.util; + +import org.intellij.lang.annotations.JdkConstants.HorizontalAlignment; +import org.spongepowered.asm.util.perf.Profiler.Section; + +import com.mojang.datafixers.util.Function5; + +import net.minecraft.inventory.Inventory; + +public enum GuiUtil { + ; + + public static WLabel label(final String translationKey) { + return new WLabel(new TranslatableText(translationKey)); + } + + @SuppressWarnings("deprecation") + public static L centered(final L label) { + label.setHorizontalAlignment(HorizontalAlignment.CENTER); + label.setVerticalAlignment(VerticalAlignment.CENTER); + return label; + } + + public static S slotRow( + final Function5 constructor, final Inventory inventory, + final Section section) { + return constructor.apply(inventory, section.start(), section.size(), 1, false); + } +} diff --git a/src/main/java/modchest/util/Identifiable.java b/src/main/java/modchest/util/Identifiable.java new file mode 100644 index 0000000..b78ffa0 --- /dev/null +++ b/src/main/java/modchest/util/Identifiable.java @@ -0,0 +1,21 @@ +package modchest.util; + +import net.minecraft.util.Identifier; + +public class Identifiable { + private final A value; + private final Identifier id; + + public Identifiable (final A value, final Identifier id) { + this.value = value; + this.id = id; + } + + public A value() { + return value; + } + + public Identifier id() { + return id; + } +} diff --git a/src/main/java/modchest/util/Section.java b/src/main/java/modchest/util/Section.java new file mode 100644 index 0000000..9f47814 --- /dev/null +++ b/src/main/java/modchest/util/Section.java @@ -0,0 +1,86 @@ +package modchest.util; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +public class Section implements Iterable { + private final int start; + private final int end; + + public Section(final int start, final int end) { + this.start = start; + this.end = end; + } + + public static Section exclusive(final int start, final int end) { + return new Section(start, end); + } + + public int start() { + return start; + } + + public int end() { + return end; + } + + public int size() { + return end - start; + } + + public int makeRelative(final int absolute) { + return absolute - start; + } + + public int makeAbsolute(final int relative) { + return relative + start; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + final Section section = (Section) o; + if (start != section.start) + return false; + return end == section.end; + } + + @Override + public int hashCode() { + int result = start; + result = 31 * result + end; + return result; + } + + public boolean contains(final int i) { + return start <= i && i < end; + } + + @Override + public Iterator iterator() { + return new SectionIterator(); + } + + private class SectionIterator implements Iterator { + int current = start; + + @Override + public boolean hasNext() { + return current < end; + } + + @Override + public Integer next() { + if (current >= end) { + throw new NoSuchElementException(); + } + return current++; + + } + + } +} diff --git a/src/main/java/modchest/util/ValidQuery.java b/src/main/java/modchest/util/ValidQuery.java new file mode 100644 index 0000000..5d3938e --- /dev/null +++ b/src/main/java/modchest/util/ValidQuery.java @@ -0,0 +1,75 @@ +package modchest.util; + +import java.util.Optional; +import java.util.function.Function; + +import net.minecraft.block.BlockEntityProvider; +import net.minecraft.block.BlockRenderType; +import net.minecraft.block.BlockState; +import net.minecraft.item.BlockItem; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.shape.VoxelShapes; +import net.minecraft.world.World; + +public class ValidQuery { + private ValidQuery() {} + + public static class ItemStackValidQuery { + private final ItemStack stack; + + public ItemStackValidQuery(final ItemStack stack) { + this.stack = stack; + } + + public Optional isValidForBase (final Function> toState, final World world, final BlockPos pos) { + final Item item = stack.getItem(); + + if (item instanceof BlockItem) { + final BlockItem blockItem = (BlockItem) item; + if (blockItem.getBlock() instanceof grid) { + return Optional.empty(); + } else { + return toState.apply(blockItem).filter(b -> checkIf(b).isValidForBase(world, pos)); + } + } else { + return Optional.empty(); + } + } + + public boolean isValidForOverlay () { + return OVERLAYS.hasOverlay(stack); + } + + public boolean isValidForSpecial() { + return SPECIAL_ITEMS.Map.containsKey(stack.getItem()); + } + + } + + public static class BlockStateValidQuery { + private final BlockState state; + + public BlockStateValidQuery(final BlockState state) { + this.state = state; + } + + public boolean isValidForBase(final World world, final BlockPos pos) { + if (state.getBlock() instanceof BlockEntityProvider && state.getRenderType() != BlockRenderType.MODEL) { + return false; + } + return state.getOutlineShape(world, pos).getBoundingBoxes().equals(VoxelShapes.fullCube().getBoundingBoxes()); + } + + } + + public static ItemStackValidQuery checkIf(final ItemStack stack) { + return new ItemStackValidQuery(stack); + } + + public static BlockStateValidQuery checkIf(final BlockState state) { + return new BlockStateValidQuery(state); + } + +} diff --git a/src/main/java/modchest/util/initializer.java b/src/main/java/modchest/util/initializer.java index 5d21799..0a377f8 100644 --- a/src/main/java/modchest/util/initializer.java +++ b/src/main/java/modchest/util/initializer.java @@ -3,7 +3,6 @@ package modchest.util; import modchest.block.entity.modBlockEntities; import modchest.block.modBlocks; import modchest.event.playerAfterRespawnEvent; -import modchest.event.useBlockCallback; import modchest.item.modItemGroup; import modchest.item.modItems; import modchest.networking.modNetworkingServer; @@ -23,10 +22,11 @@ public class initializer { public static void events() { //Events, bei denen custom Code ausgefuehrt wird, werden eingefuehrt ServerPlayerEvents.AFTER_RESPAWN.register(new playerAfterRespawnEvent()); - useBlockCallback.EVENT.register(new useBlockCallback()); + //useBlockCallback.EVENT.register(new useBlockCallback()); + //useEntityCallback.EVENT.register(new useEntityCallback()); } public static void networking() { //Identifier unter denen der Server zuhoert werden registriert modNetworkingServer.registerS2CPackets(); } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/modchest/textures/block/texture_test.png b/src/main/resources/assets/modchest/textures/block/texture_test.png new file mode 100644 index 0000000000000000000000000000000000000000..f054cc6499b03b9a80e969e7d154b38e2219163b GIT binary patch literal 769 zcmV+c1OEJpP)5sMMH9ll~?Ltpilsz!2)7yf6Y-@ z9FYWdAvr84NGPbZIA@uio7v;$&HDC+`6QR)cJ{IFeecbiUswCQHv0zzmR>)nnB&E} zJ0$y;t8Ym5k^JFcCB?#4oc%4cuodUpWhQ1GSv~yf^bi0rGhMf`KRxRK02b$Gt?b)J zCw&1#U~+J}K!pgV_Hkrr{vE8OSgsxC1{z#8gNs@s?HX%sr?Qu+fW3SbJfYBj)#05(BYWjJ)60b)oLFCae(2%+Mnh3;+x zhZi4RyD$>Y1Q<07yvzVyp%cQ$v%xA+$~?f74W_9wC#6kTw?+IpT!1YDo*kBZm{qW<2WlUrW{f&knOa1#XJc7U580Jj6& z1Od1m;3f#b?Ep7H0B#4ki2&t%--0Tv>TLN7-GK{DxWTLR00000NkvXXu0mjf