activeSounds = new ArrayList<>();
private DynamicSoundManager() {
// private constructor to make sure that the normal
// instantiation of that object is not used externally
}
- /**
- * This "Singleton Design Pattern" makes sure that, at runtime,
- * only one instance of this class can exist.
- *
- * If this class has been used once already, it keeps its instance stored
- * in the static instance variable and return it.
- * Otherwise, the instance variable is not initialized yet (null).
- * It will create a new instance, use it
- * and store it in the static variable for next uses.
- */
+ // when accessing this class for the first time a new instance
+ // is created and stored. If this is called again only the already
+ // existing instance will be returned, instead of creating a new instance
public static DynamicSoundManager getInstance() {
- if (instance == null) return new DynamicSoundManager();
+ if (instance == null) {
+ instance = new DynamicSoundManager();
+ }
return instance;
}
+ // :::1
+
+ // :::2
+ // Plays a sound instance, if it doesn't already exist in the list
+ public void play(T soundInstance) {
+ if (this.activeSounds.contains(soundInstance)) return;
+
+ client.getSoundManager().play(soundInstance);
+ this.activeSounds.add(soundInstance);
+ }
+
+ // Stops a sound immediately. in most cases it is preferred to use
+ // the sound's ending phase, which will clean it up after completion
+ public void stop(T soundInstance) {
+ client.getSoundManager().stop(soundInstance);
+ this.activeSounds.remove(soundInstance);
+ }
- public void play(AbstractDynamicSoundInstance sound) {
- client.getSoundManager().play(sound);
+ // Finds a SoundInstance from a SoundEvent, if it exists and is currently playing
+ public Optional getPlayingSoundInstance(SoundEvent soundEvent) {
+ for (var activeSound : this.activeSounds) {
+ // SoundInstances use their SoundEvent's id by default
+ if (activeSound.getId().equals(soundEvent.getId())) {
+ return Optional.of(activeSound);
+ }
+ }
+ return Optional.empty();
}
+ // :::2
- public void stop(AbstractDynamicSoundInstance sound) {
+ // :::1
+ // This is where the callback signal of a finished custom SoundInstance will arrive.
+ // For now, we can just stop and remove the sound from the list, but you can add
+ // your own functionality too
+ @Override
+ public void onFinished(T soundInstance) {
+ this.stop(soundInstance);
}
}
+// :::1
diff --git a/reference/latest/src/client/java/com/example/docs/sound/TransitionState.java b/reference/latest/src/client/java/com/example/docs/sound/TransitionState.java
deleted file mode 100644
index 1a87ac688..000000000
--- a/reference/latest/src/client/java/com/example/docs/sound/TransitionState.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.example.docs.sound;
-
-public enum TransitionState {
- STARTING, RUNNING, ENDING
-}
diff --git a/reference/latest/src/client/java/com/example/docs/sound/instance/CustomSoundInstance.java b/reference/latest/src/client/java/com/example/docs/sound/instance/CustomSoundInstance.java
index e24da9602..de321b2c5 100644
--- a/reference/latest/src/client/java/com/example/docs/sound/instance/CustomSoundInstance.java
+++ b/reference/latest/src/client/java/com/example/docs/sound/instance/CustomSoundInstance.java
@@ -13,14 +13,15 @@ public class CustomSoundInstance extends MovingSoundInstance {
private final LivingEntity entity;
- // Here we pass over the sound source of the SoundInstance and store it in the instance.
+
public CustomSoundInstance(LivingEntity entity, SoundEvent soundEvent, SoundCategory soundCategory) {
super(soundEvent, soundCategory, SoundInstance.createRandom());
-
- // here we can set up values when the sound is about to start.
- this.repeat = true;
+ // In this constructor we also add the sound source (LivingEntity) of
+ // the SoundInstance and store it in the current object
this.entity = entity;
- setPositionToEntity();
+ // set up default values when the sound is about to start
+ this.repeat = true;
+ this.setPositionToEntity();
}
@Override
@@ -31,15 +32,22 @@ public void tick() {
return;
}
// move sound position over to the new position for every tick
- setPositionToEntity();
+ this.setPositionToEntity();
+ }
+
+ @Override
+ public boolean shouldAlwaysPlay() {
+ // override to true, so that the SoundInstance can start
+ // or add your own condition to the SoundInstance, if necessary
+ return true;
}
// small utility method to move the sound instance position
// to the sound source's position
private void setPositionToEntity() {
- this.x = entity.getX();
- this.y = entity.getY();
- this.z = entity.getZ();
+ this.x = this.entity.getX();
+ this.y = this.entity.getY();
+ this.z = this.entity.getZ();
}
}
// :::1
\ No newline at end of file
diff --git a/reference/latest/src/client/java/com/example/docs/sound/instance/EngineSoundInstance.java b/reference/latest/src/client/java/com/example/docs/sound/instance/EngineSoundInstance.java
index 1c728856c..777d5203e 100644
--- a/reference/latest/src/client/java/com/example/docs/sound/instance/EngineSoundInstance.java
+++ b/reference/latest/src/client/java/com/example/docs/sound/instance/EngineSoundInstance.java
@@ -1,17 +1,41 @@
package com.example.docs.sound.instance;
-import com.example.docs.sound.AbstractDynamicSoundInstance;
-
-import com.example.docs.sound.DynamicSoundSource;
-
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvent;
-import net.minecraft.util.math.random.Random;
+import com.example.docs.block.entity.custom.EngineBlockEntity;
+import com.example.docs.sound.AbstractDynamicSoundInstance;
+import com.example.docs.sound.DynamicSoundSource;
+
+// :::1
public class EngineSoundInstance extends AbstractDynamicSoundInstance {
- protected EngineSoundInstance(DynamicSoundSource source, SoundEvent soundEvent, SoundCategory soundCategory, Random random) {
- super(source, soundEvent, soundCategory);
+
+ // Here we just use the default constructor parameters.
+ // If you want to specifically set values here already,
+ // you can clean up the constructor parameters a bit
+ public EngineSoundInstance(DynamicSoundSource soundSource, SoundEvent soundEvent, SoundCategory soundCategory,
+ int startTransitionTicks, int endTransitionTicks, float maxVolume, float minPitch, float maxPitch,
+ SoundInstanceCallback callback) {
+ super(soundSource, soundEvent, soundCategory, startTransitionTicks, endTransitionTicks, maxVolume, minPitch, maxPitch, callback);
}
+ @Override
+ public void tick() {
+ // check conditions which set this sound automatically into the ending phase
+ if (soundSource instanceof EngineBlockEntity blockEntity && blockEntity.isRemoved()) {
+ this.end();
+ }
+
+ // apply the default tick behaviour from the parent class
+ super.tick();
+
+ // modulate volume and pitch of the SoundInstance
+ this.modulateSoundForTransition();
+ this.modulateSoundForStress();
+ }
+ // you can also add sound modulation methods here,
+ // which should be only accessible to this
+ // specific SoundInstance
}
+// :::1
\ No newline at end of file
diff --git a/reference/latest/src/client/java/com/example/docs/sound/instance/SoundInstanceCallback.java b/reference/latest/src/client/java/com/example/docs/sound/instance/SoundInstanceCallback.java
new file mode 100644
index 000000000..e25e73627
--- /dev/null
+++ b/reference/latest/src/client/java/com/example/docs/sound/instance/SoundInstanceCallback.java
@@ -0,0 +1,11 @@
+package com.example.docs.sound.instance;
+
+import com.example.docs.sound.AbstractDynamicSoundInstance;
+
+// :::1
+public interface SoundInstanceCallback {
+ // deliver the custom SoundInstance, from which this signal originates,
+ // using the method parameters
+ void onFinished(T soundInstance);
+}
+// :::1
\ No newline at end of file
diff --git a/reference/latest/src/main/java/com/example/docs/block/custom/EngineBlock.java b/reference/latest/src/main/java/com/example/docs/block/custom/EngineBlock.java
index 62e3042b0..1b0c16164 100644
--- a/reference/latest/src/main/java/com/example/docs/block/custom/EngineBlock.java
+++ b/reference/latest/src/main/java/com/example/docs/block/custom/EngineBlock.java
@@ -1,12 +1,17 @@
package com.example.docs.block.custom;
import com.mojang.serialization.MapCodec;
+import net.minecraft.block.BlockRenderType;
import net.minecraft.block.BlockState;
import net.minecraft.block.BlockWithEntity;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.entity.BlockEntityTicker;
import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.entity.player.PlayerEntity;
+import net.minecraft.registry.tag.ItemTags;
+import net.minecraft.sound.SoundCategory;
+import net.minecraft.sound.SoundEvent;
+import net.minecraft.sound.SoundEvents;
import net.minecraft.util.ActionResult;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
@@ -42,11 +47,37 @@ public BlockEntityTicker getTicker(World world, Block
@Override
protected ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, BlockHitResult hit) {
- if (!(world.getBlockEntity(pos) instanceof EngineBlockEntity blockEntity))
+ if (!(world.getBlockEntity(pos) instanceof EngineBlockEntity engineBlockEntity))
return super.onUse(state, world, pos, player, hit);
- if (blockEntity.isTicking()) return super.onUse(state, world, pos, player, hit);
- blockEntity.setTick(0); // starts ticking
- return ActionResult.SUCCESS;
+ if (player.getMainHandStack().isIn(ItemTags.COALS)) {
+ if (engineBlockEntity.setFuelIfPossible(engineBlockEntity.getFuel() + 40)) {
+ player.getMainHandStack().decrementUnlessCreative(1, player);
+ playSound(world, SoundEvents.ITEM_AXE_STRIP, pos);
+ return ActionResult.SUCCESS;
+ }
+ return ActionResult.PASS;
+ }
+ else {
+ if (engineBlockEntity.isRunning()) {
+ engineBlockEntity.setNormalizedStress(engineBlockEntity.getNormalizedStress() + 0.2f);
+ return ActionResult.SUCCESS;
+ } else if (engineBlockEntity.getFuel() > 0) {
+ playSound(world, SoundEvents.BLOCK_LEVER_CLICK, pos);
+ engineBlockEntity.turnOn();
+ return ActionResult.SUCCESS;
+ }
+ }
+ return ActionResult.PASS;
+ }
+
+ @Override
+ protected BlockRenderType getRenderType(BlockState state) {
+ return BlockRenderType.MODEL;
+ }
+
+ private static void playSound(World world, SoundEvent soundEvent, BlockPos pos) {
+ if (world.isClient()) return;
+ world.playSound(null, pos, soundEvent, SoundCategory.BLOCKS, 0.8f, 1f);
}
}
diff --git a/reference/latest/src/main/java/com/example/docs/block/entity/custom/EngineBlockEntity.java b/reference/latest/src/main/java/com/example/docs/block/entity/custom/EngineBlockEntity.java
index 4e64d401b..263313558 100644
--- a/reference/latest/src/main/java/com/example/docs/block/entity/custom/EngineBlockEntity.java
+++ b/reference/latest/src/main/java/com/example/docs/block/entity/custom/EngineBlockEntity.java
@@ -1,60 +1,132 @@
package com.example.docs.block.entity.custom;
-import com.example.docs.sound.DynamicSoundSource;
-
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntity;
+import net.minecraft.nbt.NbtCompound;
+import net.minecraft.network.listener.ClientPlayPacketListener;
+import net.minecraft.network.packet.CustomPayload;
+import net.minecraft.network.packet.Packet;
+import net.minecraft.network.packet.s2c.play.BlockEntityUpdateS2CPacket;
+import net.minecraft.registry.RegistryWrapper;
import net.minecraft.server.world.ServerWorld;
+import net.minecraft.text.Text;
import net.minecraft.util.math.BlockPos;
+import net.minecraft.util.math.MathHelper;
+import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
+import org.jetbrains.annotations.Nullable;
+import net.fabricmc.fabric.api.networking.v1.PlayerLookup;
+import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
import com.example.docs.block.entity.ModBlockEntities;
+import com.example.docs.networking.payload.EngineSoundInstancePacket;
+import com.example.docs.sound.DynamicSoundSource;
public class EngineBlockEntity extends BlockEntity implements DynamicSoundSource {
- public static final int MAX_TICK_AMOUNT = 120; // can represent something like fuel capacity
-
- private int tick = -1; // -1 is turned off, it will only tick if its 0 or bigger
+ public static final int MAX_FUEL = 200;
+ private int tick = -1; // starts turned off
+ private int fuel = 0;
private float normalizedStress = 0;
public EngineBlockEntity(BlockPos pos, BlockState state) {
super(ModBlockEntities.ENGINE_BLOCK_ENTITY, pos, state);
}
+ public void setTick(int tick) {
+ this.tick = tick;
+ }
+
+ @Override
public int getTick() {
- return tick;
+ return this.tick;
}
- public void setTick(int tick) {
- this.tick = tick;
+ public static void tick(World world, BlockPos pos, BlockState state, EngineBlockEntity engineBlockEntity) {
+ if (engineBlockEntity.getTick() < 0) return;
+
+ engineBlockEntity.setTick(engineBlockEntity.getTick() + 1);
+ engineBlockEntity.setFuelIfPossible(engineBlockEntity.getFuel() - 1);
+ engineBlockEntity.setNormalizedStress(engineBlockEntity.getNormalizedStress() - 0.02f);
+
+ if (!world.isClient() && engineBlockEntity.getFuel() > 0) {
+ PlayerLookup.tracking(engineBlockEntity).forEach(player -> {
+ String engineState = "Engine Fuel: %s | Stress: %s".formatted(
+ engineBlockEntity.getFuel(),
+ String.format("%.02f", engineBlockEntity.getNormalizedStress())
+ );
+ player.sendMessage(Text.literal(engineState), true);
+ });
+ }
+
+ if (engineBlockEntity.getFuel() <= 0) {
+ engineBlockEntity.turnOff();
+ engineBlockEntity.setFuelIfPossible(0);
+ }
}
- public boolean isTicking() {
- return this.getTick() > -1;
+ @Override
+ public float getNormalizedStress() {
+ return MathHelper.clamp(normalizedStress, 0, 1);
}
public void setNormalizedStress(float normalizedStress) {
this.normalizedStress = Math.clamp(normalizedStress, 0, 1);
}
- public static void tick(World world, BlockPos pos, BlockState state, EngineBlockEntity blockEntity) {
- if (blockEntity.getTick() < 0) return;
- blockEntity.setTick(blockEntity.getTick() + 1);
- if (blockEntity.getTick() >= MAX_TICK_AMOUNT) blockEntity.setTick(-1);
+ public int getFuel() {
+ return MathHelper.clamp(this.fuel, 0, MAX_FUEL);
+ }
+
+ public boolean setFuelIfPossible(int fuel) {
+ boolean consumeItem = this.getFuel() != MAX_FUEL;
+ this.fuel = MathHelper.clamp(fuel, 0, MAX_FUEL);
+ return consumeItem;
}
@Override
- public int getTicks() {
- return getTick();
+ public Vec3d getPosition() {
+ return this.getPos().toCenterPos();
+ }
+
+ public void turnOn() {
+ if (this.getFuel() > 0) {
+ this.setTick(0);
+ this.setNormalizedStress(0);
+ this.sendPacketToTrackingClients(new EngineSoundInstancePacket(true, this.getPos()));
+ this.syncToChunk();
+ }
+ }
+
+ public void turnOff() {
+ this.tick = -1;
+ this.sendPacketToTrackingClients(new EngineSoundInstancePacket(false, this.getPos()));
+ this.syncToChunk();
}
+ public boolean isRunning() {
+ return this.getTick() > -1;
+ }
+
+ private void sendPacketToTrackingClients(CustomPayload payload) {
+ if (payload == null || !(this.getWorld() instanceof ServerWorld)) return;
+ PlayerLookup.tracking(this).forEach(player -> ServerPlayNetworking.send(player, payload));
+ }
+
+ // S2C BlockEntity sync boilerplate
+ public void syncToChunk() {
+ if (!(getWorld() instanceof ServerWorld serverWorld)) return;
+ serverWorld.getChunkManager().markForUpdate(this.getPos());
+ }
+
+ @Nullable
@Override
- public BlockPos getPosition() {
- return this.getPos();
+ public Packet toUpdatePacket() {
+ return BlockEntityUpdateS2CPacket.create(this);
}
@Override
- public float getNormalizedStress() {
- return normalizedStress;
+ public NbtCompound toInitialChunkDataNbt(RegistryWrapper.WrapperLookup registryLookup) {
+ return createNbt(registryLookup);
}
}
diff --git a/reference/latest/src/main/java/com/example/docs/item/custom/CustomSoundItem.java b/reference/latest/src/main/java/com/example/docs/item/custom/CustomSoundItem.java
index 7d15908e8..d786c1e93 100644
--- a/reference/latest/src/main/java/com/example/docs/item/custom/CustomSoundItem.java
+++ b/reference/latest/src/main/java/com/example/docs/item/custom/CustomSoundItem.java
@@ -19,7 +19,7 @@ public CustomSoundItem(Settings settings) {
@Override
public ActionResult useOnEntity(ItemStack stack, PlayerEntity user, LivingEntity entity, Hand hand) {
// As stated above, don't use the playSound() method on the client side
- // ... it wont work!
+ // ... it won't work!
if (!entity.getWorld().isClient()) {
// Play the sound as if it was coming from the entity.
entity.playSound(SoundEvents.ENTITY_PILLAGER_AMBIENT, 2f, 0.7f);
diff --git a/reference/latest/src/main/java/com/example/docs/networking/FabricDocsReferenceNetworking.java b/reference/latest/src/main/java/com/example/docs/networking/FabricDocsReferenceNetworking.java
new file mode 100644
index 000000000..b55378b25
--- /dev/null
+++ b/reference/latest/src/main/java/com/example/docs/networking/FabricDocsReferenceNetworking.java
@@ -0,0 +1,19 @@
+package com.example.docs.networking;
+
+import com.example.docs.FabricDocsReference;
+import net.fabricmc.api.ModInitializer;
+
+import net.minecraft.util.Identifier;
+
+public class FabricDocsReferenceNetworking implements ModInitializer {
+ public static final String MOD_ID = FabricDocsReference.MOD_ID;
+
+ @Override
+ public void onInitialize() {
+ NetworkPayloads.initialize();
+ }
+
+ public static Identifier getId(String input) {
+ return Identifier.of(MOD_ID, input);
+ }
+}
diff --git a/reference/latest/src/main/java/com/example/docs/networking/NetworkPayloads.java b/reference/latest/src/main/java/com/example/docs/networking/NetworkPayloads.java
new file mode 100644
index 000000000..7a23884a9
--- /dev/null
+++ b/reference/latest/src/main/java/com/example/docs/networking/NetworkPayloads.java
@@ -0,0 +1,28 @@
+package com.example.docs.networking;
+
+
+import com.example.docs.networking.payload.EngineSoundInstancePacket;
+
+import net.minecraft.network.RegistryByteBuf;
+import net.minecraft.network.codec.PacketCodec;
+import net.minecraft.network.packet.CustomPayload;
+
+import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry;
+
+@SuppressWarnings("SameParameterValue")
+public class NetworkPayloads {
+ static {
+ registerS2C(EngineSoundInstancePacket.IDENTIFIER, EngineSoundInstancePacket.CODEC);
+ }
+
+ private static void registerS2C(CustomPayload.Id packetIdentifier, PacketCodec codec) {
+ PayloadTypeRegistry.playS2C().register(packetIdentifier, codec);
+ }
+
+ private static void registerC2S(CustomPayload.Id packetIdentifier, PacketCodec codec) {
+ PayloadTypeRegistry.playC2S().register(packetIdentifier, codec);
+ }
+
+ public static void initialize() {
+ }
+}
diff --git a/reference/latest/src/main/java/com/example/docs/networking/payload/EngineSoundInstancePacket.java b/reference/latest/src/main/java/com/example/docs/networking/payload/EngineSoundInstancePacket.java
new file mode 100644
index 000000000..eef649505
--- /dev/null
+++ b/reference/latest/src/main/java/com/example/docs/networking/payload/EngineSoundInstancePacket.java
@@ -0,0 +1,27 @@
+package com.example.docs.networking.payload;
+
+import net.minecraft.network.RegistryByteBuf;
+import net.minecraft.network.codec.PacketCodec;
+import net.minecraft.network.codec.PacketCodecs;
+import net.minecraft.network.packet.CustomPayload;
+import net.minecraft.util.math.BlockPos;
+
+import com.example.docs.sound.FabricDocsReferenceSounds;
+
+public record EngineSoundInstancePacket(boolean shouldStart, BlockPos blockEntityPos) implements CustomPayload {
+
+
+ public static final CustomPayload.Id IDENTIFIER =
+ new CustomPayload.Id<>(FabricDocsReferenceSounds.identifierOf("sound_instance"));
+
+ @Override
+ public Id extends CustomPayload> getId() {
+ return IDENTIFIER;
+ }
+
+ public static final PacketCodec CODEC = PacketCodec.tuple(
+ PacketCodecs.BOOL, EngineSoundInstancePacket::shouldStart,
+ BlockPos.PACKET_CODEC, EngineSoundInstancePacket::blockEntityPos,
+ EngineSoundInstancePacket::new
+ );
+}
diff --git a/reference/latest/src/main/java/com/example/docs/sound/DynamicSoundSource.java b/reference/latest/src/main/java/com/example/docs/sound/DynamicSoundSource.java
index f75dad692..e723478f9 100644
--- a/reference/latest/src/main/java/com/example/docs/sound/DynamicSoundSource.java
+++ b/reference/latest/src/main/java/com/example/docs/sound/DynamicSoundSource.java
@@ -1,17 +1,18 @@
package com.example.docs.sound;
-import net.minecraft.util.math.BlockPos;
+import net.minecraft.util.math.Vec3d;
+import org.jetbrains.annotations.Nullable;
// :::1
public interface DynamicSoundSource {
- // gets access to how many ticks have passed for that instance
- int getTicks();
+ // gets access to how many ticks have passed for e.g. a BlockEntity instance
+ int getTick();
- // gets access to where this instance is placed in the world
- BlockPos getPosition();
+ // gets access to where currently this instance is placed in the world
+ Vec3d getPosition();
- // holds a normalized value (range of 0-1) showing, how much stress this instance is experiencing
- // Tt is more or less just an arbitrary value, which will cause the sound to change its pitch while playing.
+ // holds a normalized (range of 0-1) value, showing how much stress this instance is currently experiencing
+ // It is more or less just an arbitrary value, which will cause the sound to change its pitch while playing.
float getNormalizedStress();
}
// :::1
diff --git a/reference/latest/src/main/java/com/example/docs/sound/FabricDocsReferenceSounds.java b/reference/latest/src/main/java/com/example/docs/sound/FabricDocsReferenceSounds.java
index dbb925e9f..cfb84ee73 100644
--- a/reference/latest/src/main/java/com/example/docs/sound/FabricDocsReferenceSounds.java
+++ b/reference/latest/src/main/java/com/example/docs/sound/FabricDocsReferenceSounds.java
@@ -20,11 +20,15 @@ public class FabricDocsReferenceSounds implements ModInitializer {
public void onInitialize() {
// This is the basic registering. Use a new class for registering sounds
// instead, to keep the ModInitializer implementing class clean!
- Registry.register(Registries.SOUND_EVENT, Identifier.of(MOD_ID, "metal_whistle"),
- SoundEvent.of(Identifier.of(MOD_ID, "metal_whistle")));
+ Registry.register(Registries.SOUND_EVENT, Identifier.of(MOD_ID, "metal_whistle_simple"),
+ SoundEvent.of(Identifier.of(MOD_ID, "metal_whistle_simple")));
// ... the cleaner approach. // [!code focus]
- // CustomSounds.initialize(); // [!code focus]
+ CustomSounds.initialize(); // [!code focus]
+ }
+
+ public static Identifier identifierOf(String path) {
+ return Identifier.of(FabricDocsReference.MOD_ID, path);
}
}
// :::2
diff --git a/reference/latest/src/main/java/com/example/docs/sound/TransitionState.java b/reference/latest/src/main/java/com/example/docs/sound/TransitionState.java
new file mode 100644
index 000000000..5e81f1e04
--- /dev/null
+++ b/reference/latest/src/main/java/com/example/docs/sound/TransitionState.java
@@ -0,0 +1,23 @@
+package com.example.docs.sound;
+
+import com.example.docs.FabricDocsReference;
+
+import net.minecraft.util.Identifier;
+
+// :::1
+public enum TransitionState {
+ STARTING("starting_phase"),
+ RUNNING("idle_phase"),
+ ENDING("ending_phase");
+
+ private final Identifier identifier;
+
+ TransitionState(String name) {
+ this.identifier = Identifier.of(FabricDocsReference.MOD_ID, name);
+ }
+
+ public Identifier getIdentifier() {
+ return identifier;
+ }
+}
+// :::1
diff --git a/reference/latest/src/main/resources/fabric.mod.json b/reference/latest/src/main/resources/fabric.mod.json
index 6dc596cbd..e1c4bbee3 100644
--- a/reference/latest/src/main/resources/fabric.mod.json
+++ b/reference/latest/src/main/resources/fabric.mod.json
@@ -17,7 +17,8 @@
"com.example.docs.item.FabricDocsReferenceItems",
"com.example.docs.block.FabricDocsReferenceBlocks",
"com.example.docs.block.entity.FabricDocsReferenceBlockEntities",
- "com.example.docs.component.FabricDocsReferenceComponents"
+ "com.example.docs.component.FabricDocsReferenceComponents",
+ "com.example.docs.networking.FabricDocsReferenceNetworking"
],
"client": [
"com.example.docs.FabricDocsReferenceClient",