Skip to content

Commit

Permalink
party hats
Browse files Browse the repository at this point in the history
  • Loading branch information
LeoLezury committed Jul 26, 2024
1 parent caec313 commit d74271f
Show file tree
Hide file tree
Showing 21 changed files with 509 additions and 27 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// 1.21 2024-07-26T13:49:02.5727059 Loot Tables
// 1.21 2024-07-26T18:16:26.7838952 Loot Tables
f16854500c1fe7c108a688f323b1d43ec314c7f0 data/celebrations/loot_table/blocks/chinese_styled_bamboo_lantern.json
60535fb769799b40c4ad680dd775157ca407c7b3 data/celebrations/loot_table/blocks/chinese_styled_paper_lantern.json
14e52a830878533cee7bb9e1f7ffb84503fd8f53 data/celebrations/loot_table/blocks/chinese_styled_red_lantern.json
Expand All @@ -11,4 +11,4 @@ fb43c8227c2caaeb32bd595007ca5dbc85a20b13 data/celebrations/loot_table/blocks/gol
e1e48f5b29801955968898e511e4dd098c069f22 data/celebrations/loot_table/blocks/inverted_golden_fu_sticker.json
f615d7c82e77b608ba0a3b8e87b4cc2b895d2446 data/celebrations/loot_table/blocks/japanese_styled_paper_lantern.json
7b5266b8253cdeddf9c4f7ebbffd74c2ad5826bb data/celebrations/loot_table/blocks/japanese_styled_red_lantern.json
4825ea7177de3c39d11e36f43b29342952d79f82 data/celebrations/loot_table/gameplay/villager_gift.json
960e8fd76f6ff7f261b2103a5c2c9fe81e18f38a data/celebrations/loot_table/gameplay/villager_gift.json
Original file line number Diff line number Diff line change
Expand Up @@ -202,11 +202,23 @@
"entries": [
{
"type": "minecraft:item",
"conditions": [
{
"chance": 0.5,
"condition": "minecraft:random_chance"
}
],
"name": "minecraft:emerald",
"weight": 50
},
{
"type": "minecraft:item",
"conditions": [
{
"chance": 0.3,
"condition": "minecraft:random_chance"
}
],
"name": "minecraft:diamond",
"weight": 20
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,37 +15,40 @@
public class PartyHatRenderer {
public static final ResourceLocation PARTY_HAT = Celebrations.id("textures/entity/party_hat.png");

public static void render(ResourceLocation texture, boolean overlay, PoseStack poseStack, MultiBufferSource buffer, int color, int packedLight) {
public static void render(ResourceLocation texture, float scale, boolean overlay, PoseStack poseStack, MultiBufferSource buffer, int color, int packedLight) {
VertexConsumer consumer = buffer.getBuffer(CRenderType.entityCutoutNoCullTriangles(texture));

float hatRadius = overlay ? 3f / 16f + 0.001f : 3f / 16f;
float hatBottom = overlay ? -0.001f : 0;
float hatHeight = overlay ? 0.501f : 0.5f;
float cubeRadius = overlay ? 0.0635f : 0.0625f;

poseStack.pushPose();
poseStack.scale(scale, scale, scale);
PoseStack.Pose pose = poseStack.last();
float hatRadius = overlay ? 3.0001f / 16f : 3f / 16f;
float hatHeight = 0.5f;
float cubeRadius = overlay ? 0.0626f : 0.0625f;

vertex(consumer, pose, hatRadius, 0, hatRadius, 0, 11f / 17f, color, packedLight);
vertex(consumer, pose, -hatRadius, 0, hatRadius, 1, 11f / 17f, color, packedLight);
vertex(consumer, pose, hatRadius, hatBottom, hatRadius, 0, 11f / 17f, color, packedLight);
vertex(consumer, pose, -hatRadius, hatBottom, hatRadius, 1, 11f / 17f, color, packedLight);
vertex(consumer, pose, 0, hatHeight, 0, 0.5f, 2.5f / 17f, color, packedLight);

vertex(consumer, pose, hatRadius, 0, -hatRadius, 0, 11f / 17f, color, packedLight);
vertex(consumer, pose, -hatRadius, 0, -hatRadius, 1, 11f / 17f, color, packedLight);
vertex(consumer, pose, hatRadius, hatBottom, -hatRadius, 0, 11f / 17f, color, packedLight);
vertex(consumer, pose, -hatRadius, hatBottom, -hatRadius, 1, 11f / 17f, color, packedLight);
vertex(consumer, pose, 0, hatHeight, 0, 0.5f, 2.5f / 17f, color, packedLight);

vertex(consumer, pose, hatRadius, 0, hatRadius, 0, 11f / 17f, color, packedLight);
vertex(consumer, pose, hatRadius, 0, -hatRadius, 1, 11f / 17f, color, packedLight);
vertex(consumer, pose, hatRadius, hatBottom, hatRadius, 0, 11f / 17f, color, packedLight);
vertex(consumer, pose, hatRadius, hatBottom, -hatRadius, 1, 11f / 17f, color, packedLight);
vertex(consumer, pose, 0, hatHeight, 0, 0.5f, 2.5f / 17f, color, packedLight);

vertex(consumer, pose, -hatRadius, 0, hatRadius, 0, 11f / 17f, color, packedLight);
vertex(consumer, pose, -hatRadius, 0, -hatRadius, 1, 11f / 17f, color, packedLight);
vertex(consumer, pose, -hatRadius, hatBottom, hatRadius, 0, 11f / 17f, color, packedLight);
vertex(consumer, pose, -hatRadius, hatBottom, -hatRadius, 1, 11f / 17f, color, packedLight);
vertex(consumer, pose, 0, hatHeight, 0, 0.5f, 2.5f / 17f, color, packedLight);

poseStack.pushPose();
VertexConsumer quadsConsumer = buffer.getBuffer(RenderType.entityCutoutNoCull(texture));

vertex(quadsConsumer, pose, hatRadius, 0, hatRadius, 0, 11f / 17f, color, packedLight);
vertex(quadsConsumer, pose, hatRadius, 0, -hatRadius, 0, 1, color, packedLight);
vertex(quadsConsumer, pose, -hatRadius, 0, -hatRadius, 1, 1, color, packedLight);
vertex(quadsConsumer, pose, -hatRadius, 0, hatRadius, 1, 11f / 17f, color, packedLight);
vertex(quadsConsumer, pose, hatRadius, hatBottom, hatRadius, 0, 11f / 17f, color, packedLight);
vertex(quadsConsumer, pose, hatRadius, hatBottom, -hatRadius, 0, 1, color, packedLight);
vertex(quadsConsumer, pose, -hatRadius, hatBottom, -hatRadius, 1, 1, color, packedLight);
vertex(quadsConsumer, pose, -hatRadius, hatBottom, hatRadius, 1, 11f / 17f, color, packedLight);

poseStack.translate(0, 0.5f, 0);
pose = poseStack.last();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package team.leomc.celebrations.client.renderer.layer;

import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.model.EntityModel;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.entity.RenderLayerParent;
import net.minecraft.client.renderer.entity.layers.RenderLayer;
import net.minecraft.util.FastColor;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.entity.Mob;
import net.minecraft.world.item.ItemStack;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.api.distmarker.OnlyIn;
import team.leomc.celebrations.client.renderer.PartyHatRenderer;
import team.leomc.celebrations.entity.PartyHatWearer;
import team.leomc.celebrations.item.component.PartyHat;
import team.leomc.celebrations.registry.CDataComponents;
import team.leomc.celebrations.registry.CItems;
import team.leomc.celebrations.util.PartyHatUtils;

@OnlyIn(Dist.CLIENT)
public class PartyHatLayer<T extends Mob, M extends EntityModel<T> & PartyHatParent> extends RenderLayer<T, M> {
public PartyHatLayer(RenderLayerParent<T, M> renderer) {
super(renderer);
}

@Override
public void render(PoseStack poseStack, MultiBufferSource buffer, int packedLight, T mob, float limbSwing, float limbSwingAmount, float partialTicks, float ageInTicks, float netHeadYaw, float headPitch) {
poseStack.pushPose();
getParentModel().translate(poseStack);
ItemStack stack = mob.getItemBySlot(EquipmentSlot.HEAD);
if (mob instanceof PartyHatWearer wearer && wearer.isWearingPartyHat() && !stack.is(CItems.PARTY_HAT.get())) {
stack = PartyHatUtils.getMobPartyHatItem(mob);
}
if (stack.is(CItems.PARTY_HAT.get())) {
poseStack.pushPose();
poseStack.translate(0, 0.375f, 0);
PartyHatRenderer.render(PartyHatRenderer.PARTY_HAT, 1, false, poseStack, buffer, FastColor.ARGB32.colorFromFloat(1, 1, 1, 1), packedLight);
PartyHat hat = stack.get(CDataComponents.PART_HAT.get());
if (hat != null) {
PartyHatRenderer.render(hat.getTextureLocation(), 1, true, poseStack, buffer, hat.color().getTextureDiffuseColor(), packedLight);
}
poseStack.popPose();
}
poseStack.popPose();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package team.leomc.celebrations.client.renderer.layer;

import com.mojang.blaze3d.vertex.PoseStack;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.api.distmarker.OnlyIn;

@OnlyIn(Dist.CLIENT)
public interface PartyHatParent {
void translate(PoseStack stack);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package team.leomc.celebrations.entity;

public interface PartyHatWearer {
void beforeClientGetItem();

void afterClientGetItem();

boolean isWearingPartyHat();
}
92 changes: 88 additions & 4 deletions src/main/java/team/leomc/celebrations/event/CEvents.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,49 @@
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.RandomSource;
import net.minecraft.world.entity.Mob;
import net.minecraft.world.entity.animal.allay.Allay;
import net.minecraft.world.entity.monster.*;
import net.minecraft.world.entity.monster.piglin.Piglin;
import net.minecraft.world.entity.monster.piglin.PiglinBrute;
import net.minecraft.world.entity.npc.Villager;
import net.minecraft.world.entity.npc.VillagerProfession;
import net.minecraft.world.entity.npc.WanderingTrader;
import net.minecraft.world.item.Item;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.neoforge.event.RegisterCommandsEvent;
import net.neoforged.neoforge.event.level.LevelEvent;
import net.neoforged.neoforge.event.tick.EntityTickEvent;
import net.neoforged.neoforge.event.tick.LevelTickEvent;
import net.neoforged.neoforge.network.PacketDistributor;
import team.leomc.celebrations.Celebrations;
import team.leomc.celebrations.ai.VillagerCelebrationAI;
import team.leomc.celebrations.block.entity.LanternBlockEntity;
import team.leomc.celebrations.command.CelebrationsCommand;
import team.leomc.celebrations.network.UpdateMobPartyHatPayload;
import team.leomc.celebrations.registry.CItems;
import team.leomc.celebrations.util.CelebrationUtils;
import team.leomc.celebrations.util.LanternUtils;
import team.leomc.celebrations.world.CelebrationSavedData;

import java.util.Calendar;
import java.util.List;

@EventBusSubscriber(modid = Celebrations.ID)
public class CEvents {
public static final String TAG_PARTY_HAT = Celebrations.id("party_hat").toString();
public static final String TAG_RAID_WON_CELEBRATION_TICKS_LEFT = Celebrations.id("raid_won_celebration_ticks_left").toString();
public static final String TAG_PLACE_CANDLE_CELEBRATION_TICKS_LEFT = Celebrations.id("place_candle_celebration_ticks_left").toString();

@SubscribeEvent
public static void onRegisterCommands(RegisterCommandsEvent event) {
private static void onRegisterCommands(RegisterCommandsEvent event) {
CelebrationsCommand.register(event.getDispatcher());
}

@SubscribeEvent
public static void onLevelLoad(LevelEvent.Load event) {
private static void onLevelLoad(LevelEvent.Load event) {
if (event.getLevel() instanceof ServerLevel serverLevel) {
CelebrationSavedData celebrationSavedData = CelebrationUtils.getCelebrationData(serverLevel);
if (celebrationSavedData == null) {
Expand All @@ -40,7 +55,7 @@ public static void onLevelLoad(LevelEvent.Load event) {
}

@SubscribeEvent
public static void onPostLevelTick(LevelTickEvent.Post event) {
private static void onPostLevelTick(LevelTickEvent.Post event) {
if (event.getLevel() instanceof ServerLevel serverLevel) {
CelebrationSavedData celebrationSavedData = CelebrationUtils.getCelebrationData(serverLevel);
if (celebrationSavedData != null) {
Expand All @@ -50,7 +65,76 @@ public static void onPostLevelTick(LevelTickEvent.Post event) {
}

@SubscribeEvent
public static void onPostEntityTick(EntityTickEvent.Post event) {
private static void onPostEntityTick(EntityTickEvent.Post event) {
if (event.getEntity() instanceof Mob mob && !mob.level().isClientSide && mob.tickCount % 15 == 0) {
mob.getPersistentData().putBoolean(TAG_PARTY_HAT, false);
int month = Calendar.getInstance().get(Calendar.MONTH);
int day = Calendar.getInstance().get(Calendar.DAY_OF_MONTH);
// all mobs
if (month == Calendar.MAY && day >= 15 && day <= 30) {
mob.getPersistentData().putBoolean(TAG_PARTY_HAT, true);
}
// all villagers
if (mob instanceof Villager villager) {
int ticks = mob.getPersistentData().getInt(TAG_RAID_WON_CELEBRATION_TICKS_LEFT);
mob.getPersistentData().putInt(TAG_RAID_WON_CELEBRATION_TICKS_LEFT, Math.max(ticks - 40, 0));
if (month == Calendar.SEPTEMBER && day == 22
|| month == Calendar.DECEMBER && day == 12
|| month == Calendar.APRIL && day == 23
|| mob.getPersistentData().getInt(TAG_RAID_WON_CELEBRATION_TICKS_LEFT) > 0) {
mob.getPersistentData().putBoolean(TAG_PARTY_HAT, true);
}
if (villager.getVillagerData().getProfession() == VillagerProfession.NITWIT && month == Calendar.AUGUST && day == 11) {
mob.getPersistentData().putBoolean(TAG_PARTY_HAT, true);
}
}
// zombie villager
if (mob instanceof ZombieVillager
&& (month == Calendar.SEPTEMBER && day == 22
|| month == Calendar.DECEMBER && day == 12
|| month == Calendar.APRIL && day == 23) && RandomSource.create(mob.getId()).nextInt(3) == 0) {
mob.getPersistentData().putBoolean(TAG_PARTY_HAT, true);
}
// wandering trader
if (mob instanceof WanderingTrader && (month == Calendar.JANUARY && day == 30 || month == Calendar.APRIL && day == 23)) {
mob.getPersistentData().putBoolean(TAG_PARTY_HAT, true);
}
// all illagers
if (mob instanceof AbstractIllager
&& (month == Calendar.MARCH && day == 25
|| month == Calendar.APRIL && day == 23
|| month == Calendar.MAY && day == 26)) {
mob.getPersistentData().putBoolean(TAG_PARTY_HAT, true);
}
// evoker, vex, vindicator
if ((mob instanceof Evoker || mob instanceof Vex || mob instanceof Vindicator) && (month == Calendar.SEPTEMBER && day == 28 || month == Calendar.NOVEMBER && day == 14)) {
mob.getPersistentData().putBoolean(TAG_PARTY_HAT, true);
}
// pillager
if (mob instanceof Pillager && month == Calendar.OCTOBER && day == 24) {
mob.getPersistentData().putBoolean(TAG_PARTY_HAT, true);
}
// piglin
if (mob instanceof Piglin && (month == Calendar.FEBRUARY && day == 14 || month == Calendar.JUNE && day == 23)) {
mob.getPersistentData().putBoolean(TAG_PARTY_HAT, true);
}
// piglin brute
if (mob instanceof PiglinBrute
&& (month == Calendar.FEBRUARY && day == 13
|| month == Calendar.JUNE && day == 23
|| month == Calendar.JULY && day == 1)) {
mob.getPersistentData().putBoolean(TAG_PARTY_HAT, true);
}
// allay
if (mob instanceof Allay) {
int ticks = mob.getPersistentData().getInt(TAG_PLACE_CANDLE_CELEBRATION_TICKS_LEFT);
mob.getPersistentData().putInt(TAG_PLACE_CANDLE_CELEBRATION_TICKS_LEFT, Math.max(ticks - 40, 0));
if (mob.getPersistentData().getInt(TAG_PLACE_CANDLE_CELEBRATION_TICKS_LEFT) > 0) {
mob.getPersistentData().putBoolean(TAG_PARTY_HAT, true);
}
}
PacketDistributor.sendToAllPlayers(new UpdateMobPartyHatPayload(mob.getId(), mob.getPersistentData().getBoolean(TAG_PARTY_HAT)));
}
if (event.getEntity() instanceof Villager villager && !villager.level().isClientSide) {
if (villager.tickCount % 100 == 0) {
if (LanternUtils.getVillagerLanternBlock(villager).defaultBlockState().isAir()) {
Expand Down
15 changes: 15 additions & 0 deletions src/main/java/team/leomc/celebrations/item/component/PartyHat.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.core.HolderLookup;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtOps;
import net.minecraft.nbt.Tag;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.codec.ByteBufCodecs;
import net.minecraft.network.codec.StreamCodec;
Expand All @@ -19,10 +23,21 @@ public record PartyHat(PartyHatType type, DyeColor color) {

public static final StreamCodec<RegistryFriendlyByteBuf, PartyHat> STREAM_CODEC = ByteBufCodecs.fromCodecWithRegistries(CODEC);

public static final PartyHat DEFAULT = new PartyHat(PartyHatType.STRIPES, DyeColor.RED);

public ResourceLocation getTextureLocation() {
return Celebrations.id("textures/entity/party_hat_" + type().getSerializedName() + ".png");
}

public static PartyHat fromTag(Tag tag, HolderLookup.Provider provider) {
return CODEC.parse(provider.createSerializationContext(NbtOps.INSTANCE), tag).resultOrPartial().orElse(DEFAULT);
}

public Tag toTag(HolderLookup.Provider provider) {
return CODEC.encodeStart(provider.createSerializationContext(NbtOps.INSTANCE), this).resultOrPartial().orElseGet(CompoundTag::new);
}


@Override
public boolean equals(Object o) {
if (this == o) return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public PartyHatRecipe(CraftingBookCategory category) {

@Override
public boolean matches(CraftingInput craftingInput, Level level) {
if (craftingInput.items().stream().anyMatch(stack -> !stack.is(CItems.PARTY_HAT.get()) && !stack.is(CTags.Items.PARTY_HAT_PATTERN_INGREDIENTS) && !(stack.getItem() instanceof DyeItem))) {
if (craftingInput.items().stream().anyMatch(stack -> !stack.isEmpty() && !stack.is(CItems.PARTY_HAT.get()) && !stack.is(CTags.Items.PARTY_HAT_PATTERN_INGREDIENTS) && !(stack.getItem() instanceof DyeItem))) {
return false;
}
if (craftingInput.items().stream().filter(stack -> stack.is(CTags.Items.PARTY_HAT_PATTERN_INGREDIENTS)).count() != 1) {
Expand Down
32 changes: 32 additions & 0 deletions src/main/java/team/leomc/celebrations/mixin/AllayModelMixin.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package team.leomc.celebrations.mixin;

import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Axis;
import net.minecraft.client.model.AllayModel;
import net.minecraft.client.model.geom.ModelPart;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.api.distmarker.OnlyIn;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import team.leomc.celebrations.client.renderer.layer.PartyHatParent;

@OnlyIn(Dist.CLIENT)
@Mixin(AllayModel.class)
public abstract class AllayModelMixin implements PartyHatParent {
@Shadow
@Final
private ModelPart head;

@Shadow
public abstract ModelPart root();

@Override
public void translate(PoseStack stack) {
this.root().translateAndRotate(stack);
this.head.translateAndRotate(stack);
stack.mulPose(Axis.YP.rotationDegrees(180.0F));
stack.scale(1, -1, -1);
stack.translate(0, -0.125, 0);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package team.leomc.celebrations.mixin;

import net.minecraft.client.renderer.entity.AllayRenderer;
import net.minecraft.client.renderer.entity.EntityRendererProvider;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.api.distmarker.OnlyIn;
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 team.leomc.celebrations.client.renderer.layer.PartyHatLayer;

@OnlyIn(Dist.CLIENT)
@Mixin(AllayRenderer.class)
public abstract class AllayRendererMixin {
@Inject(method = "<init>", at = @At("RETURN"))
protected void init(EntityRendererProvider.Context context, CallbackInfo ci) {
AllayRenderer renderer = ((AllayRenderer) (Object) this);
renderer.addLayer(new PartyHatLayer(renderer));
}
}
Loading

0 comments on commit d74271f

Please sign in to comment.