Initial commit

This commit is contained in:
tibs 2022-01-04 12:23:14 -05:00
commit 5bd7750177
Signed by untrusted user who does not match committer: tibs
GPG key ID: 047833989F50F88F
24 changed files with 1627 additions and 0 deletions

View file

@ -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());
}
}

View file

@ -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;
};
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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());
}
}
}

View file

@ -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));
}
}

View file

@ -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);
}
}
}

View file

@ -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();
}
}

View file

@ -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);
}
}