-
-
Notifications
You must be signed in to change notification settings - Fork 132
/
JackInTheBoxItem.java
128 lines (114 loc) · 5.36 KB
/
JackInTheBoxItem.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package software.bernie.example.item;
import net.minecraft.client.Minecraft;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.client.renderer.BlockEntityWithoutLevelRenderer;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResultHolder;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraftforge.client.extensions.common.IClientItemExtensions;
import net.minecraftforge.network.PacketDistributor;
import software.bernie.example.GeckoLibMod;
import software.bernie.example.client.renderer.item.JackInTheBoxRenderer;
import software.bernie.example.registry.SoundRegistry;
import software.bernie.geckolib3.core.AnimationState;
import software.bernie.geckolib3.core.IAnimatable;
import software.bernie.geckolib3.core.PlayState;
import software.bernie.geckolib3.core.builder.AnimationBuilder;
import software.bernie.geckolib3.core.builder.ILoopType.EDefaultLoopTypes;
import software.bernie.geckolib3.core.controller.AnimationController;
import software.bernie.geckolib3.core.event.SoundKeyframeEvent;
import software.bernie.geckolib3.core.event.predicate.AnimationEvent;
import software.bernie.geckolib3.core.manager.AnimationData;
import software.bernie.geckolib3.core.manager.AnimationFactory;
import software.bernie.geckolib3.network.GeckoLibNetwork;
import software.bernie.geckolib3.network.ISyncable;
import software.bernie.geckolib3.util.GeckoLibUtil;
import java.util.function.Consumer;
public class JackInTheBoxItem extends Item implements IAnimatable, ISyncable {
private static final String CONTROLLER_NAME = "popupController";
private static final int ANIM_OPEN = 0;
public AnimationFactory factory = GeckoLibUtil.createFactory(this);
public JackInTheBoxItem(Properties properties) {
super(properties.tab(GeckoLibMod.geckolibItemGroup));
GeckoLibNetwork.registerSyncable(this);
}
@Override
public void initializeClient(Consumer<IClientItemExtensions> consumer) {
super.initializeClient(consumer);
consumer.accept(new IClientItemExtensions() {
private final BlockEntityWithoutLevelRenderer renderer = new JackInTheBoxRenderer();
@Override
public BlockEntityWithoutLevelRenderer getCustomRenderer() {
return renderer;
}
});
}
private <P extends Item & IAnimatable> PlayState predicate(AnimationEvent<P> event) {
// Not setting an animation here as that's handled below
return PlayState.CONTINUE;
}
@Override
public void registerControllers(AnimationData data) {
AnimationController controller = new AnimationController(this, CONTROLLER_NAME, 20, this::predicate);
// Registering a sound listener just makes it so when any sound keyframe is hit
// the method will be called.
// To register a particle listener or custom event listener you do the exact
// same thing, just with registerParticleListener and
// registerCustomInstructionListener, respectively.
controller.registerSoundListener(this::soundListener);
data.addAnimationController(controller);
}
private <ENTITY extends IAnimatable> void soundListener(SoundKeyframeEvent<ENTITY> event) {
// The animation for the JackInTheBoxItem has a sound keyframe at time 0:00.
// As soon as that keyframe gets hit this method fires and it starts playing the
// sound to the current player.
// The music is synced with the animation so the box opens as soon as the music
// plays the box opening sound
LocalPlayer player = Minecraft.getInstance().player;
if (player != null) {
player.playSound(SoundRegistry.JACK_MUSIC.get(), 1, 1);
}
}
@Override
public AnimationFactory getFactory() {
return this.factory;
}
@Override
public InteractionResultHolder<ItemStack> use(Level world, Player player, InteractionHand hand) {
if (!world.isClientSide) {
// Gets the item that the player is holding, should be a JackInTheBoxItem
final ItemStack stack = player.getItemInHand(hand);
final int id = GeckoLibUtil.guaranteeIDForStack(stack, (ServerLevel) world);
// Tell all nearby clients to trigger this JackInTheBoxItem
final PacketDistributor.PacketTarget target = PacketDistributor.TRACKING_ENTITY_AND_SELF.with(() -> player);
GeckoLibNetwork.syncAnimation(target, this, id, ANIM_OPEN);
}
return super.use(world, player, hand);
}
@Override
public void onAnimationSync(int id, int state) {
if (state == ANIM_OPEN) {
// Always use GeckoLibUtil to get AnimationControllers when you don't have
// access to an AnimationEvent
final AnimationController controller = GeckoLibUtil.getControllerForID(this.factory, id, CONTROLLER_NAME);
if (controller.getAnimationState() == AnimationState.Stopped) {
final LocalPlayer player = Minecraft.getInstance().player;
if (player != null) {
player.displayClientMessage(Component.literal("Opening the jack in the box!"), true);
}
// If you don't do this, the popup animation will only play once because the
// animation will be cached.
controller.markNeedsReload();
// Set the animation to open the JackInTheBoxItem which will start playing music
// and
// eventually do the actual animation. Also sets it to not loop
controller.setAnimation(new AnimationBuilder().addAnimation("Soaryn_chest_popup", EDefaultLoopTypes.PLAY_ONCE));
}
}
}
}