tweak the card take animation
This commit is contained in:
@@ -48,9 +48,11 @@ public class DuelTableBlockEntity extends BlockEntity {
|
|||||||
private static final int CAPTURE_DURATION = 10;
|
private static final int CAPTURE_DURATION = 10;
|
||||||
private static final int OVERVIEW_SWEEP_DURATION = 18;
|
private static final int OVERVIEW_SWEEP_DURATION = 18;
|
||||||
private static final int CLEAR_WAVE_DURATION = 10;
|
private static final int CLEAR_WAVE_DURATION = 10;
|
||||||
|
private static final int REWARD_TAKE_DURATION = 14;
|
||||||
|
|
||||||
private final NonNullList<ItemStack> boardCards = NonNullList.withSize(SLOT_COUNT, ItemStack.EMPTY);
|
private final NonNullList<ItemStack> boardCards = NonNullList.withSize(SLOT_COUNT, ItemStack.EMPTY);
|
||||||
private final NonNullList<ItemStack> rewardCards = NonNullList.withSize(REWARD_SLOT_COUNT, ItemStack.EMPTY);
|
private final NonNullList<ItemStack> rewardCards = NonNullList.withSize(REWARD_SLOT_COUNT, ItemStack.EMPTY);
|
||||||
|
private final List<RewardTakeAnimation> rewardTakeAnimations = new ArrayList<>();
|
||||||
private final int[] ownerSlots = new int[SLOT_COUNT];
|
private final int[] ownerSlots = new int[SLOT_COUNT];
|
||||||
private final int[] slotAges = new int[SLOT_COUNT];
|
private final int[] slotAges = new int[SLOT_COUNT];
|
||||||
private final ArrayDeque<AnimationStep> pendingAnimations = new ArrayDeque<>();
|
private final ArrayDeque<AnimationStep> pendingAnimations = new ArrayDeque<>();
|
||||||
@@ -88,6 +90,10 @@ public class DuelTableBlockEntity extends BlockEntity {
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<RewardTakeAnimation> rewardTakeAnimations() {
|
||||||
|
return List.copyOf(rewardTakeAnimations);
|
||||||
|
}
|
||||||
|
|
||||||
public int ownerAt(int slot) {
|
public int ownerAt(int slot) {
|
||||||
return ownerSlots[slot];
|
return ownerSlots[slot];
|
||||||
}
|
}
|
||||||
@@ -253,6 +259,15 @@ public class DuelTableBlockEntity extends BlockEntity {
|
|||||||
if (taken.isEmpty()) {
|
if (taken.isEmpty()) {
|
||||||
return ItemStack.EMPTY;
|
return ItemStack.EMPTY;
|
||||||
}
|
}
|
||||||
|
int visibleIndex = visibleRewardIndex(slot);
|
||||||
|
int rewardCountBeforeTake = rewardCardCount();
|
||||||
|
if (visibleIndex >= 0 && rewardCountBeforeTake > 0) {
|
||||||
|
BoardLocalSpace.SlotCenter center = BoardLocalSpace.rewardCenter(
|
||||||
|
visibleIndex,
|
||||||
|
getBlockState().getValue(DuelTableBlock.FACING),
|
||||||
|
rewardCountBeforeTake);
|
||||||
|
rewardTakeAnimations.add(new RewardTakeAnimation(taken.copyWithCount(1), center.x(), center.z(), 0, REWARD_TAKE_DURATION));
|
||||||
|
}
|
||||||
rewardCards.set(slot, ItemStack.EMPTY);
|
rewardCards.set(slot, ItemStack.EMPTY);
|
||||||
refreshRewardInteractions();
|
refreshRewardInteractions();
|
||||||
sync();
|
sync();
|
||||||
@@ -263,6 +278,7 @@ public class DuelTableBlockEntity extends BlockEntity {
|
|||||||
for (int index = 0; index < rewardCards.size(); index++) {
|
for (int index = 0; index < rewardCards.size(); index++) {
|
||||||
rewardCards.set(index, ItemStack.EMPTY);
|
rewardCards.set(index, ItemStack.EMPTY);
|
||||||
}
|
}
|
||||||
|
rewardTakeAnimations.clear();
|
||||||
removeRewardInteractions();
|
removeRewardInteractions();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -274,6 +290,7 @@ public class DuelTableBlockEntity extends BlockEntity {
|
|||||||
rewardCards.set(slot, ItemStack.EMPTY);
|
rewardCards.set(slot, ItemStack.EMPTY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
rewardTakeAnimations.clear();
|
||||||
removeRewardInteractions();
|
removeRewardInteractions();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -431,6 +448,21 @@ public class DuelTableBlockEntity extends BlockEntity {
|
|||||||
blockEntity.slotAges[slot] = 0;
|
blockEntity.slotAges[slot] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!blockEntity.rewardTakeAnimations.isEmpty()) {
|
||||||
|
boolean changed = false;
|
||||||
|
for (int index = blockEntity.rewardTakeAnimations.size() - 1; index >= 0; index--) {
|
||||||
|
RewardTakeAnimation animation = blockEntity.rewardTakeAnimations.get(index);
|
||||||
|
animation.age++;
|
||||||
|
if (animation.age >= animation.duration) {
|
||||||
|
blockEntity.rewardTakeAnimations.remove(index);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!level.isClientSide && changed) {
|
||||||
|
blockEntity.sync();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -440,6 +472,7 @@ public class DuelTableBlockEntity extends BlockEntity {
|
|||||||
CompoundTag rewardTag = new CompoundTag();
|
CompoundTag rewardTag = new CompoundTag();
|
||||||
ContainerHelper.saveAllItems(rewardTag, rewardCards, registries);
|
ContainerHelper.saveAllItems(rewardTag, rewardCards, registries);
|
||||||
tag.put("RewardCards", rewardTag);
|
tag.put("RewardCards", rewardTag);
|
||||||
|
saveRewardTakeAnimations(tag, registries);
|
||||||
tag.putIntArray("OwnerSlots", ownerSlots);
|
tag.putIntArray("OwnerSlots", ownerSlots);
|
||||||
tag.putIntArray("SlotAges", slotAges);
|
tag.putIntArray("SlotAges", slotAges);
|
||||||
saveAnimation(tag);
|
saveAnimation(tag);
|
||||||
@@ -460,6 +493,7 @@ public class DuelTableBlockEntity extends BlockEntity {
|
|||||||
if (tag.contains("RewardCards", Tag.TAG_COMPOUND)) {
|
if (tag.contains("RewardCards", Tag.TAG_COMPOUND)) {
|
||||||
ContainerHelper.loadAllItems(tag.getCompound("RewardCards"), rewardCards, registries);
|
ContainerHelper.loadAllItems(tag.getCompound("RewardCards"), rewardCards, registries);
|
||||||
}
|
}
|
||||||
|
loadRewardTakeAnimations(tag, registries);
|
||||||
loadOwnerData(tag);
|
loadOwnerData(tag);
|
||||||
loadAnimation(tag);
|
loadAnimation(tag);
|
||||||
loadTableAnimation(tag);
|
loadTableAnimation(tag);
|
||||||
@@ -472,6 +506,7 @@ public class DuelTableBlockEntity extends BlockEntity {
|
|||||||
CompoundTag rewardTag = new CompoundTag();
|
CompoundTag rewardTag = new CompoundTag();
|
||||||
ContainerHelper.saveAllItems(rewardTag, rewardCards, registries);
|
ContainerHelper.saveAllItems(rewardTag, rewardCards, registries);
|
||||||
tag.put("RewardCards", rewardTag);
|
tag.put("RewardCards", rewardTag);
|
||||||
|
saveRewardTakeAnimations(tag, registries);
|
||||||
tag.putIntArray("OwnerSlots", ownerSlots);
|
tag.putIntArray("OwnerSlots", ownerSlots);
|
||||||
tag.putIntArray("SlotAges", slotAges);
|
tag.putIntArray("SlotAges", slotAges);
|
||||||
saveAnimation(tag);
|
saveAnimation(tag);
|
||||||
@@ -499,6 +534,7 @@ public class DuelTableBlockEntity extends BlockEntity {
|
|||||||
if (tag.contains("RewardCards", Tag.TAG_COMPOUND)) {
|
if (tag.contains("RewardCards", Tag.TAG_COMPOUND)) {
|
||||||
ContainerHelper.loadAllItems(tag.getCompound("RewardCards"), rewardCards, registries);
|
ContainerHelper.loadAllItems(tag.getCompound("RewardCards"), rewardCards, registries);
|
||||||
}
|
}
|
||||||
|
loadRewardTakeAnimations(tag, registries);
|
||||||
loadOwnerData(tag);
|
loadOwnerData(tag);
|
||||||
loadAnimation(tag);
|
loadAnimation(tag);
|
||||||
loadTableAnimation(tag);
|
loadTableAnimation(tag);
|
||||||
@@ -531,6 +567,44 @@ public class DuelTableBlockEntity extends BlockEntity {
|
|||||||
secondParticipantId = tag.hasUUID("SecondParticipantId") ? tag.getUUID("SecondParticipantId") : null;
|
secondParticipantId = tag.hasUUID("SecondParticipantId") ? tag.getUUID("SecondParticipantId") : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void saveRewardTakeAnimations(CompoundTag tag, HolderLookup.Provider registries) {
|
||||||
|
CompoundTag animationsTag = new CompoundTag();
|
||||||
|
for (int index = 0; index < rewardTakeAnimations.size(); index++) {
|
||||||
|
RewardTakeAnimation animation = rewardTakeAnimations.get(index);
|
||||||
|
CompoundTag animationTag = new CompoundTag();
|
||||||
|
animationTag.put("Stack", animation.stack.saveOptional(registries));
|
||||||
|
animationTag.putFloat("LocalX", animation.localX);
|
||||||
|
animationTag.putFloat("LocalZ", animation.localZ);
|
||||||
|
animationTag.putInt("Age", animation.age);
|
||||||
|
animationTag.putInt("Duration", animation.duration);
|
||||||
|
animationsTag.put("Animation" + index, animationTag);
|
||||||
|
}
|
||||||
|
animationsTag.putInt("Count", rewardTakeAnimations.size());
|
||||||
|
tag.put("RewardTakeAnimations", animationsTag);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadRewardTakeAnimations(CompoundTag tag, HolderLookup.Provider registries) {
|
||||||
|
rewardTakeAnimations.clear();
|
||||||
|
if (!tag.contains("RewardTakeAnimations", Tag.TAG_COMPOUND)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
CompoundTag animationsTag = tag.getCompound("RewardTakeAnimations");
|
||||||
|
int count = animationsTag.getInt("Count");
|
||||||
|
for (int index = 0; index < count; index++) {
|
||||||
|
CompoundTag animationTag = animationsTag.getCompound("Animation" + index);
|
||||||
|
ItemStack stack = ItemStack.parseOptional(registries, animationTag.getCompound("Stack"));
|
||||||
|
if (stack.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
rewardTakeAnimations.add(new RewardTakeAnimation(
|
||||||
|
stack,
|
||||||
|
animationTag.getFloat("LocalX"),
|
||||||
|
animationTag.getFloat("LocalZ"),
|
||||||
|
animationTag.getInt("Age"),
|
||||||
|
animationTag.getInt("Duration")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void saveAnimation(CompoundTag tag) {
|
private void saveAnimation(CompoundTag tag) {
|
||||||
tag.putString("AnimationType", animationType.name());
|
tag.putString("AnimationType", animationType.name());
|
||||||
tag.putIntArray("AnimationSlots", animationSlots);
|
tag.putIntArray("AnimationSlots", animationSlots);
|
||||||
@@ -672,4 +746,54 @@ public class DuelTableBlockEntity extends BlockEntity {
|
|||||||
|
|
||||||
private record AnimationStep(AnimationType type, int[] slots, int targetOwner) {
|
private record AnimationStep(AnimationType type, int[] slots, int targetOwner) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static final class RewardTakeAnimation {
|
||||||
|
private final ItemStack stack;
|
||||||
|
private final float localX;
|
||||||
|
private final float localZ;
|
||||||
|
private int age;
|
||||||
|
private final int duration;
|
||||||
|
|
||||||
|
private RewardTakeAnimation(ItemStack stack, float localX, float localZ, int age, int duration) {
|
||||||
|
this.stack = stack;
|
||||||
|
this.localX = localX;
|
||||||
|
this.localZ = localZ;
|
||||||
|
this.age = age;
|
||||||
|
this.duration = duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemStack stack() {
|
||||||
|
return stack;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float localX() {
|
||||||
|
return localX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float localZ() {
|
||||||
|
return localZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int age() {
|
||||||
|
return age;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int duration() {
|
||||||
|
return duration;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int visibleRewardIndex(int slot) {
|
||||||
|
int visibleIndex = 0;
|
||||||
|
for (int index = 0; index < rewardCards.size(); index++) {
|
||||||
|
if (rewardCards.get(index).isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (index == slot) {
|
||||||
|
return visibleIndex;
|
||||||
|
}
|
||||||
|
visibleIndex++;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ public class DuelTableBlockEntityRenderer implements BlockEntityRenderer<DuelTab
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderRewardCards(blockEntity, partialTick, poseStack, buffer);
|
renderRewardCards(blockEntity, partialTick, poseStack, buffer);
|
||||||
|
renderRewardTakeAnimations(blockEntity, partialTick, poseStack, buffer);
|
||||||
renderRewardProxyDebug(blockEntity, poseStack, buffer);
|
renderRewardProxyDebug(blockEntity, poseStack, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,6 +129,33 @@ public class DuelTableBlockEntityRenderer implements BlockEntityRenderer<DuelTab
|
|||||||
return Math.floorMod(blockEntity.getBlockPos().hashCode() * 31 + slot * 17, 97);
|
return Math.floorMod(blockEntity.getBlockPos().hashCode() * 31 + slot * 17, 97);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void renderRewardTakeAnimations(DuelTableBlockEntity blockEntity, float partialTick, PoseStack poseStack, MultiBufferSource buffer) {
|
||||||
|
var facing = blockEntity.getBlockState().getValue(DuelTableBlock.FACING);
|
||||||
|
float forwardX = facing.getStepX() * 0.33F;
|
||||||
|
float forwardZ = facing.getStepZ() * 0.33F;
|
||||||
|
for (DuelTableBlockEntity.RewardTakeAnimation animation : blockEntity.rewardTakeAnimations()) {
|
||||||
|
float progress = Math.clamp((animation.age() + partialTick) / animation.duration(), 0.0F, 1.0F);
|
||||||
|
float riseProgress = Math.min(1.0F, progress / 0.45F);
|
||||||
|
float arcProgress = progress <= 0.45F ? 0.0F : (progress - 0.45F) / 0.55F;
|
||||||
|
|
||||||
|
float x = animation.localX() + forwardX * arcProgress;
|
||||||
|
float y = REWARD_CARD_Y
|
||||||
|
+ riseProgress * 0.26F
|
||||||
|
+ (float) Math.sin(arcProgress * Math.PI) * 0.08F
|
||||||
|
- arcProgress * 0.26F;
|
||||||
|
float z = animation.localZ() + forwardZ * arcProgress;
|
||||||
|
float spin = progress * 720.0F;
|
||||||
|
|
||||||
|
poseStack.pushPose();
|
||||||
|
poseStack.translate(x, y, z);
|
||||||
|
poseStack.mulPose(Axis.YP.rotationDegrees(facing.toYRot()));
|
||||||
|
poseStack.mulPose(Axis.YP.rotationDegrees(spin));
|
||||||
|
poseStack.scale(0.3F, 0.3F, 0.3F);
|
||||||
|
TriadCardItemRenderer.renderCard(animation.stack(), poseStack, buffer, perspectivePalette(blockEntity, DuelTableBlockEntity.OWNER_SECOND));
|
||||||
|
poseStack.popPose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void renderRewardProxyDebug(DuelTableBlockEntity blockEntity, PoseStack poseStack, MultiBufferSource buffer) {
|
private static void renderRewardProxyDebug(DuelTableBlockEntity blockEntity, PoseStack poseStack, MultiBufferSource buffer) {
|
||||||
if (Minecraft.getInstance().level == null) {
|
if (Minecraft.getInstance().level == null) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
Reference in New Issue
Block a user