mirror of
https://github.com/TibiNonEst/cauldron-dyeing.git
synced 2025-04-29 13:04:08 -05:00
Initial commit
This commit is contained in:
commit
5bd7750177
24 changed files with 1627 additions and 0 deletions
|
@ -0,0 +1,33 @@
|
|||
package me.tibinonest.mods.cauldron_dyeing;
|
||||
|
||||
import me.tibinonest.mods.cauldron_dyeing.block.WaterCauldronBlockEntity;
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
import net.fabricmc.fabric.api.object.builder.v1.block.entity.FabricBlockEntityTypeBuilder;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.block.entity.BlockEntityType;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
|
||||
public class CauldronDyeing implements ModInitializer {
|
||||
public static final String MOD_ID = "cauldron_dyeing";
|
||||
|
||||
public static BlockEntityType<WaterCauldronBlockEntity> WATER_CAULDRON_BLOCK_ENTITY;
|
||||
|
||||
static {
|
||||
WATER_CAULDRON_BLOCK_ENTITY = FabricBlockEntityTypeBuilder.create(WaterCauldronBlockEntity::new, Blocks.WATER_CAULDRON).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInitialize() {
|
||||
Registry.register(Registry.BLOCK_ENTITY_TYPE, new Identifier(MOD_ID, "water_cauldron_entity"), WATER_CAULDRON_BLOCK_ENTITY);
|
||||
}
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public static void rebuildBlock(BlockPos pos) {
|
||||
MinecraftClient.getInstance().worldRenderer.scheduleBlockRenders(pos.getX(), pos.getY(), pos.getZ(), pos.getX(), pos.getY(), pos.getZ());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package me.tibinonest.mods.cauldron_dyeing.block;
|
||||
|
||||
import net.minecraft.block.cauldron.CauldronBehavior;
|
||||
import net.minecraft.item.DyeItem;
|
||||
import net.minecraft.util.ActionResult;
|
||||
|
||||
public interface CauldronBehaviorExtended {
|
||||
CauldronBehavior DYE_WATER = (state, world, pos, player, hand, stack) -> {
|
||||
var blockEntity = world.getBlockEntity(pos);
|
||||
var item = stack.getItem();
|
||||
|
||||
if (item instanceof DyeItem dyeItem && blockEntity instanceof WaterCauldronBlockEntity waterCauldron) {
|
||||
waterCauldron.setColor(dyeItem.getColor());
|
||||
return ActionResult.success(world.isClient);
|
||||
}
|
||||
|
||||
return ActionResult.PASS;
|
||||
};
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package me.tibinonest.mods.cauldron_dyeing.block;
|
||||
|
||||
import net.minecraft.block.BlockEntityProvider;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.LeveledCauldronBlock;
|
||||
import net.minecraft.block.cauldron.CauldronBehavior;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.biome.Biome;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class WaterCauldronBlock extends LeveledCauldronBlock implements BlockEntityProvider {
|
||||
public WaterCauldronBlock(Settings settings, Predicate<Biome.Precipitation> precipitationPredicate, Map<Item, CauldronBehavior> behaviorMap) {
|
||||
super(settings, precipitationPredicate, behaviorMap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockEntity createBlockEntity(BlockPos pos, BlockState state) {
|
||||
return new WaterCauldronBlockEntity(pos, state);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
package me.tibinonest.mods.cauldron_dyeing.block;
|
||||
|
||||
import com.google.common.primitives.Ints;
|
||||
import me.tibinonest.mods.cauldron_dyeing.CauldronDyeing;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.network.Packet;
|
||||
import net.minecraft.network.listener.ClientPlayPacketListener;
|
||||
import net.minecraft.network.packet.s2c.play.BlockEntityUpdateS2CPacket;
|
||||
import net.minecraft.util.DyeColor;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class WaterCauldronBlockEntity extends BlockEntity {
|
||||
private int[] color;
|
||||
|
||||
public WaterCauldronBlockEntity(BlockPos pos, BlockState state) {
|
||||
super(CauldronDyeing.WATER_CAULDRON_BLOCK_ENTITY, pos, state);
|
||||
color = new int[]{-1, -1, -1};
|
||||
}
|
||||
|
||||
// Formula taken from https://minecraft.fandom.com/wiki/Dye#Dyeing_armor and DyeableItem#blendAndSetColor
|
||||
public void setColor(DyeColor dyeColor) {
|
||||
var colorComponents = dyeColor.getColorComponents();
|
||||
|
||||
var newColor = new int[3];
|
||||
newColor[0] = (int) (colorComponents[0] * 255.0f);
|
||||
newColor[1] = (int) (colorComponents[1] * 255.0f);
|
||||
newColor[2] = (int) (colorComponents[2] * 255.0f);
|
||||
|
||||
var workingColor = hasColor() ? color : new int[]{0, 0, 0};
|
||||
|
||||
var avgColor = new int[3];
|
||||
avgColor[0] = (workingColor[0] + newColor[0]) / 2;
|
||||
avgColor[1] = (workingColor[1] + newColor[1]) / 2;
|
||||
avgColor[2] = (workingColor[2] + newColor[2]) / 2;
|
||||
|
||||
var avgMax = (Ints.max(workingColor) + Ints.max(newColor)) / 2.0f;
|
||||
|
||||
var maxOfAvg = (float) Ints.max(avgColor);
|
||||
var gainFactor = avgMax / maxOfAvg;
|
||||
|
||||
color[0] = (int) (avgColor[0] * gainFactor);
|
||||
color[1] = (int) (avgColor[1] * gainFactor);
|
||||
color[2] = (int) (avgColor[2] * gainFactor);
|
||||
|
||||
markDirty();
|
||||
rebuildBlock();
|
||||
}
|
||||
|
||||
public boolean hasColor() {
|
||||
return color[0] != -1 && color[1] != -1 && color[2] != -1;
|
||||
}
|
||||
|
||||
public int getColor() {
|
||||
return hasColor() ? (color[0] << 16) + (color[1] << 8) + color[2] : -1;
|
||||
}
|
||||
|
||||
public void resetColor() {
|
||||
color = new int[]{-1, -1, -1};
|
||||
rebuildBlock();
|
||||
}
|
||||
|
||||
public void rebuildBlock() {
|
||||
if (world != null && world.isClient) {
|
||||
CauldronDyeing.rebuildBlock(pos);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeNbt(NbtCompound tag) {
|
||||
super.writeNbt(tag);
|
||||
tag.putIntArray("color", color);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readNbt(NbtCompound tag) {
|
||||
super.readNbt(tag);
|
||||
color = tag.getIntArray("color");
|
||||
}
|
||||
|
||||
@Override
|
||||
public NbtCompound toInitialChunkDataNbt() {
|
||||
var nbt = new NbtCompound();
|
||||
nbt.putIntArray("color", color);
|
||||
return nbt;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Packet<ClientPlayPacketListener> toUpdatePacket() {
|
||||
return BlockEntityUpdateS2CPacket.create(this);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package me.tibinonest.mods.cauldron_dyeing.mixin;
|
||||
|
||||
import me.tibinonest.mods.cauldron_dyeing.block.WaterCauldronBlockEntity;
|
||||
import net.minecraft.client.color.world.BiomeColors;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.BlockRenderView;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
@Mixin(BiomeColors.class)
|
||||
public class BiomeColorsMixin {
|
||||
@Inject(method = "getWaterColor", at = @At("RETURN"), cancellable = true)
|
||||
private static void modifyWaterColor(BlockRenderView world, BlockPos pos, CallbackInfoReturnable<Integer> cir) {
|
||||
var blockEntity = world.getBlockEntity(pos);
|
||||
|
||||
if (blockEntity instanceof WaterCauldronBlockEntity waterCauldron && waterCauldron.getColor() != -1) {
|
||||
cir.setReturnValue(waterCauldron.getColor());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package me.tibinonest.mods.cauldron_dyeing.mixin;
|
||||
|
||||
import me.tibinonest.mods.cauldron_dyeing.block.WaterCauldronBlock;
|
||||
import net.minecraft.block.AbstractBlock;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.block.cauldron.CauldronBehavior;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
@Mixin(Blocks.class)
|
||||
public class BlocksMixin {
|
||||
@Redirect(method = "<clinit>", at = @At(value = "INVOKE", target = "Lnet/minecraft/block/Blocks;register(Ljava/lang/String;Lnet/minecraft/block/Block;)Lnet/minecraft/block/Block;", ordinal = 271))
|
||||
private static Block redirectWaterCauldron(String id, Block block) {
|
||||
return Registry.register(Registry.BLOCK, id, new WaterCauldronBlock(AbstractBlock.Settings.copy(Blocks.CAULDRON), WaterCauldronBlock.RAIN_PREDICATE, CauldronBehavior.WATER_CAULDRON_BEHAVIOR));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
package me.tibinonest.mods.cauldron_dyeing.mixin;
|
||||
|
||||
import me.tibinonest.mods.cauldron_dyeing.block.CauldronBehaviorExtended;
|
||||
import me.tibinonest.mods.cauldron_dyeing.block.WaterCauldronBlockEntity;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.LeveledCauldronBlock;
|
||||
import net.minecraft.block.cauldron.CauldronBehavior;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.DyeItem;
|
||||
import net.minecraft.item.DyeableItem;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.stat.Stats;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.DyeColor;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
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.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
import org.spongepowered.tools.obfuscation.SuppressedBy;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Mixin(CauldronBehavior.class)
|
||||
public interface CauldronBehaviorMixin {
|
||||
@Inject(method = "method_32209", at = @At("HEAD"), cancellable = true)
|
||||
private static void injectCleanDyeableItem(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, ItemStack stack, CallbackInfoReturnable<ActionResult> cir) {
|
||||
var blockEntity = world.getBlockEntity(pos);
|
||||
var item = stack.getItem();
|
||||
|
||||
if (item instanceof DyeableItem dyeableItem && blockEntity instanceof WaterCauldronBlockEntity waterCauldron && waterCauldron.getColor() != -1) {
|
||||
dyeableItem.setColor(stack, waterCauldron.getColor());
|
||||
if (!world.isClient) {
|
||||
player.incrementStat(Stats.USE_CAULDRON);
|
||||
LeveledCauldronBlock.decrementFluidLevel(state, world, pos);
|
||||
}
|
||||
|
||||
cir.setReturnValue(ActionResult.success(world.isClient));
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "method_32217", at = @At(value = "TAIL"))
|
||||
private static void injectFillWithWater(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, ItemStack stack, CallbackInfoReturnable<ActionResult> cir) {
|
||||
var blockEntity = world.getBlockEntity(pos);
|
||||
if (blockEntity instanceof WaterCauldronBlockEntity waterCauldron) {
|
||||
waterCauldron.resetColor();
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "registerBehavior", at = @At("TAIL"))
|
||||
private static void injectRegisterBehavior(CallbackInfo ci) {
|
||||
var dyeMap = DyeItemAccessor.getDyeMap();
|
||||
for (Map.Entry<DyeColor, DyeItem> dyeItem : dyeMap.entrySet()) {
|
||||
CauldronBehavior.WATER_CAULDRON_BEHAVIOR.put(dyeItem.getValue(), CauldronBehaviorExtended.DYE_WATER);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package me.tibinonest.mods.cauldron_dyeing.mixin;
|
||||
|
||||
import net.minecraft.item.DyeItem;
|
||||
import net.minecraft.util.DyeColor;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Mixin(DyeItem.class)
|
||||
public interface DyeItemAccessor {
|
||||
@Accessor("DYES")
|
||||
static Map<DyeColor, DyeItem> getDyeMap() {
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package me.tibinonest.mods.cauldron_dyeing.mixin.sodium;
|
||||
|
||||
import me.jellysquid.mods.sodium.client.model.quad.ModelQuadColorProvider;
|
||||
import me.jellysquid.mods.sodium.client.model.quad.ModelQuadView;
|
||||
import me.jellysquid.mods.sodium.client.model.quad.blender.BiomeColorBlender;
|
||||
import me.jellysquid.mods.sodium.client.model.quad.blender.FlatBiomeColorBlender;
|
||||
import me.jellysquid.mods.sodium.client.render.pipeline.BlockRenderer;
|
||||
import me.tibinonest.mods.cauldron_dyeing.block.WaterCauldronBlockEntity;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.BlockRenderView;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
@Mixin(BlockRenderer.class)
|
||||
public class SodiumBlockRendererMixin {
|
||||
@Redirect(method = "renderQuad", at=@At(value = "INVOKE", target="Lme/jellysquid/mods/sodium/client/model/quad/blender/BiomeColorBlender;getColors(Lnet/minecraft/world/BlockRenderView;Lnet/minecraft/util/math/BlockPos;Lme/jellysquid/mods/sodium/client/model/quad/ModelQuadView;Lme/jellysquid/mods/sodium/client/model/quad/ModelQuadColorProvider;Ljava/lang/Object;)[I"))
|
||||
private <T> int[] redirectGetColors(BiomeColorBlender instance, BlockRenderView world, BlockPos pos, ModelQuadView quad, ModelQuadColorProvider<T> handler, T fluidState) {
|
||||
var blockEntity = world.getBlockEntity(pos);
|
||||
|
||||
if (blockEntity instanceof WaterCauldronBlockEntity) {
|
||||
var flatBiomeColorBlender = new FlatBiomeColorBlender();
|
||||
return flatBiomeColorBlender.getColors(world, pos, quad, handler, fluidState);
|
||||
}
|
||||
|
||||
return instance.getColors(world, pos, quad, handler, fluidState);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue