diff --git a/gradle.properties b/gradle.properties index 9c5f5fd..56d07eb 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,7 @@ minecraft_version=1.20.1 yarn_mappings=1.20.1+build.10 loader_version=0.18.3 # Mod Properties -mod_version=26.3.5 +mod_version=26.3.7 maven_group=dev.tggamesyt archives_base_name=szar # Dependencies diff --git a/src/client/java/dev/tggamesyt/szar/client/SzarClient.java b/src/client/java/dev/tggamesyt/szar/client/SzarClient.java index 8bc5dc5..3a54327 100644 --- a/src/client/java/dev/tggamesyt/szar/client/SzarClient.java +++ b/src/client/java/dev/tggamesyt/szar/client/SzarClient.java @@ -96,6 +96,7 @@ public class SzarClient implements ClientModInitializer { }); }); + VideoManager.init(); ClientTickEvents.END_CLIENT_TICK.register(client -> { VideoManager.tick(); }); @@ -441,7 +442,7 @@ public class SzarClient implements ClientModInitializer { (dispatcher, registryAccess) -> PanoramaClientCommand.register(dispatcher) ); } - ClientTickEvents.END_CLIENT_TICK.register(client -> { + /*ClientTickEvents.END_CLIENT_TICK.register(client -> { if (addedFeature) return; // only run once MinecraftClient mc = MinecraftClient.getInstance(); if (mc.getEntityRenderDispatcher() == null) return; @@ -453,7 +454,7 @@ public class SzarClient implements ClientModInitializer { } addedFeature = true; // prevent running again - }); + });*/ } private boolean isDebugEnabled() { diff --git a/src/client/java/dev/tggamesyt/szar/client/VideoHeadFeature.java b/src/client/java/dev/tggamesyt/szar/client/VideoHeadFeature.java index a2db890..f51a35c 100644 --- a/src/client/java/dev/tggamesyt/szar/client/VideoHeadFeature.java +++ b/src/client/java/dev/tggamesyt/szar/client/VideoHeadFeature.java @@ -2,6 +2,7 @@ package dev.tggamesyt.szar.client; import com.mojang.blaze3d.systems.RenderSystem; import net.minecraft.client.network.AbstractClientPlayerEntity; +import net.minecraft.client.render.OverlayTexture; import net.minecraft.client.render.VertexConsumer; import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.RenderLayer; @@ -26,7 +27,6 @@ public class VideoHeadFeature extends FeatureRenderer activeVideos = new HashMap<>(); - + private static final Map activeSounds = new HashMap<>(); private static final List FRAMES = new ArrayList<>(); - - /* - * Load frames (call once during client init) - */ + /* Load frames (call once during client init) */ public static void init() { - if (!FRAMES.isEmpty()) return; - for (int i = 0; i < TOTAL_FRAMES; i++) { + for (int i = 1; i <= TOTAL_FRAMES; i++) { String frame = String.format("textures/video/frame_%03d.png", i); FRAMES.add(new Identifier(MOD_ID, frame)); } } - - /* - * Start playing the video on a player - */ + /* Start or restart video for a player */ public static void startVideo(String playerUuid) { - if (client.world == null) return; UUID uuid = UUID.fromString(playerUuid); - activeVideos.put(uuid, new VideoInstance(uuid)); - - playSound(uuid); - } - - - /* - * Tick method (call every client tick) - */ - public static void tick() { - - if (activeVideos.isEmpty()) return; - - Iterator> iterator = activeVideos.entrySet().iterator(); - - while (iterator.hasNext()) { - - VideoInstance instance = iterator.next().getValue(); - - instance.tick(); - - if (instance.finished()) { - iterator.remove(); - } - + // Stop existing video and sound if playing + if (activeVideos.containsKey(uuid)) { + stopVideo(uuid); } + // Start new video with sound delay + VideoInstance instance = new VideoInstance(uuid, SOUND_DELAY_TICKS); + activeVideos.put(uuid, instance); } + /* Tick method (call every client tick) */ + public static void tick() { + if (activeVideos.isEmpty()) return; + + List finishedVideos = new ArrayList<>(); + + for (Map.Entry entry : activeVideos.entrySet()) { + VideoInstance instance = entry.getValue(); + instance.tick(); + + // Start sound after delay + if (!activeSounds.containsKey(entry.getKey()) && instance.shouldPlaySound()) { + playSound(entry.getKey()); + } + + if (instance.finished()) { + finishedVideos.add(entry.getKey()); + } + } + + // Stop finished videos and their sounds + for (UUID uuid : finishedVideos) { + stopVideo(uuid); + } + } - /* - * Check if a player currently has a video playing - */ public static boolean isPlaying(UUID player) { return activeVideos.containsKey(player); } - - /* - * Get current frame texture for player - */ public static Identifier getCurrentFrame(UUID player) { - VideoInstance instance = activeVideos.get(player); - if (instance == null) return null; int frameIndex = instance.frame; - if (frameIndex >= FRAMES.size()) return null; return FRAMES.get(frameIndex); } + private static void stopVideo(UUID playerUuid) { + activeVideos.remove(playerUuid); + + SoundInstance sound = activeSounds.remove(playerUuid); + if (sound != null) { + client.getSoundManager().stop(sound); + } + } - /* - * Play sound from the player's location - */ private static void playSound(UUID playerUuid) { + if (activeSounds.containsKey(playerUuid)) return; ClientWorld world = client.world; - if (world == null) return; - var player = world.getPlayerByUuid(playerUuid); - + ClientPlayerEntity player = (ClientPlayerEntity) world.getPlayerByUuid(playerUuid); if (player == null) return; Identifier soundId = new Identifier(MOD_ID, "firtana"); SoundEvent soundEvent = SoundEvent.of(soundId); - client.getSoundManager().play( - new PositionedSoundInstance( - soundEvent, - SoundCategory.PLAYERS, - 1.0f, // volume - 1.0f, // pitch - player.getRandom(), - player.getX(), - player.getY(), - player.getZ() - ) + PositionedSoundInstance soundInstance = new PositionedSoundInstance( + soundEvent, + SoundCategory.PLAYERS, + 1.0f, + 1.0f, + player.getRandom(), + player.getX(), + player.getY(), + player.getZ() ); + + client.getSoundManager().play(soundInstance); + activeSounds.put(playerUuid, soundInstance); } - - /* - * Video instance for each player - */ + /* Video instance with sound delay support */ private static class VideoInstance { - UUID player; int frame = 0; int tickCounter = 0; + int soundDelay; - VideoInstance(UUID player) { + VideoInstance(UUID player, int soundDelayTicks) { this.player = player; + this.soundDelay = soundDelayTicks; } void tick() { - tickCounter++; - if (tickCounter >= TICKS_PER_FRAME) { - frame++; tickCounter = 0; - } + if (soundDelay > 0) { + soundDelay--; + } + } + + boolean shouldPlaySound() { + return soundDelay <= 0; } boolean finished() { return frame >= TOTAL_FRAMES; } - } - } \ No newline at end of file diff --git a/src/client/java/dev/tggamesyt/szar/client/mixin/PlayerEntityRendererMixin.java b/src/client/java/dev/tggamesyt/szar/client/mixin/PlayerEntityRendererMixin.java new file mode 100644 index 0000000..c8ccda8 --- /dev/null +++ b/src/client/java/dev/tggamesyt/szar/client/mixin/PlayerEntityRendererMixin.java @@ -0,0 +1,21 @@ +package dev.tggamesyt.szar.client.mixin; + +import dev.tggamesyt.szar.client.VideoHeadFeature; +import net.minecraft.client.render.entity.EntityRendererFactory; +import net.minecraft.client.render.entity.PlayerEntityRenderer; +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; + +@Mixin(PlayerEntityRenderer.class) +public abstract class PlayerEntityRendererMixin { + + @Inject(method = "", at = @At("RETURN")) + private void addVideoFeature(EntityRendererFactory.Context ctx, boolean slim, CallbackInfo ci) { + + PlayerEntityRenderer renderer = (PlayerEntityRenderer)(Object)this; + + renderer.addFeature(new VideoHeadFeature(renderer)); + } +} \ No newline at end of file diff --git a/src/client/resources/szar.client.mixins.json b/src/client/resources/szar.client.mixins.json index 59f88c0..5d03136 100644 --- a/src/client/resources/szar.client.mixins.json +++ b/src/client/resources/szar.client.mixins.json @@ -6,6 +6,7 @@ "client": [ "ItemRendererMixin", "MouseMixin", + "PlayerEntityRendererMixin", "PlayerModelMixin", "RadiatedItemRendererMixin", "RadiationHeartMixin", diff --git a/src/main/generated/.cache/0dcec3edc46b99b91b10474633480b6842e700fc b/src/main/generated/.cache/0dcec3edc46b99b91b10474633480b6842e700fc index 8a7f7a5..4899d6a 100644 --- a/src/main/generated/.cache/0dcec3edc46b99b91b10474633480b6842e700fc +++ b/src/main/generated/.cache/0dcec3edc46b99b91b10474633480b6842e700fc @@ -1,3 +1,3 @@ -// 1.20.1 2026-02-22T17:34:09.3606501 szar/World Gen +// 1.20.1 2026-03-07T14:06:37.8445606 szar/World Gen 1d26b5da3b0a2ea6b23d456d1f0b82455a788ca1 data\szar\worldgen\configured_feature\uranium_ore.json 32864170bdb41310f9ee5d06f5720dfdb3badb6d data\szar\worldgen\placed_feature\uranium_ore_placed.json diff --git a/src/main/generated/.cache/79d6404f7b0803346bb38c848032926817f10037 b/src/main/generated/.cache/79d6404f7b0803346bb38c848032926817f10037 index 470de3f..520e7c2 100644 --- a/src/main/generated/.cache/79d6404f7b0803346bb38c848032926817f10037 +++ b/src/main/generated/.cache/79d6404f7b0803346bb38c848032926817f10037 @@ -1,2 +1,2 @@ -// 1.20.1 2026-02-22T17:34:09.3606501 szar/Tags for minecraft:point_of_interest_type +// 1.20.1 2026-03-07T14:06:37.8455587 szar/Tags for minecraft:point_of_interest_type eba137b51c50a7143a3668876f41adaa1447b1d1 data\minecraft\tags\point_of_interest_type\acquirable_job_site.json diff --git a/src/main/generated/.cache/e8da7d0da6535b734ad1b062d141fd76f701db77 b/src/main/generated/.cache/e8da7d0da6535b734ad1b062d141fd76f701db77 index 2acc7aa..7b86b67 100644 --- a/src/main/generated/.cache/e8da7d0da6535b734ad1b062d141fd76f701db77 +++ b/src/main/generated/.cache/e8da7d0da6535b734ad1b062d141fd76f701db77 @@ -1,2 +1,2 @@ -// 1.20.1 2026-02-22T17:34:09.3596499 szar/Tags for minecraft:item -15754f2ee2c60320aae8a09679ed422fea29a705 data\minecraft\tags\items\music_discs.json +// 1.20.1 2026-03-07T14:06:37.8432546 szar/Tags for minecraft:item +935692b1c49ef3164e01f8a993f3ce8002919afe data\minecraft\tags\items\music_discs.json diff --git a/src/main/generated/data/minecraft/tags/items/music_discs.json b/src/main/generated/data/minecraft/tags/items/music_discs.json index ccd54f0..1aa7631 100644 --- a/src/main/generated/data/minecraft/tags/items/music_discs.json +++ b/src/main/generated/data/minecraft/tags/items/music_discs.json @@ -3,6 +3,7 @@ "values": [ "szar:pop_tart", "szar:baiter", - "szar:efn" + "szar:efn", + "szar:hello" ] } \ No newline at end of file diff --git a/src/main/java/dev/tggamesyt/szar/ModItemTagProvider.java b/src/main/java/dev/tggamesyt/szar/ModItemTagProvider.java index 301b6d4..4ec182a 100644 --- a/src/main/java/dev/tggamesyt/szar/ModItemTagProvider.java +++ b/src/main/java/dev/tggamesyt/szar/ModItemTagProvider.java @@ -2,16 +2,8 @@ package dev.tggamesyt.szar; import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput; import net.fabricmc.fabric.api.datagen.v1.provider.FabricTagProvider; -import net.minecraft.data.DataOutput; -import net.minecraft.data.server.tag.TagProvider; -import net.minecraft.registry.Registry; -import net.minecraft.registry.RegistryKey; -import net.minecraft.registry.RegistryKeys; import net.minecraft.registry.RegistryWrapper; import net.minecraft.registry.tag.ItemTags; -import net.minecraft.registry.tag.PointOfInterestTypeTags; -import net.minecraft.util.Identifier; -import net.minecraft.world.poi.PointOfInterestType; import java.util.concurrent.CompletableFuture; @@ -24,7 +16,8 @@ public class ModItemTagProvider extends FabricTagProvider.ItemTagProvider { @Override protected void configure(RegistryWrapper.WrapperLookup lookup) { getOrCreateTagBuilder(ItemTags.MUSIC_DISCS).add(Szar.POPTART); - getOrCreateTagBuilder(ItemTags.MUSIC_DISCS).add(Szar.BAITER_DISK); + getOrCreateTagBuilder(ItemTags.MUSIC_DISCS).add(Szar.BAITER_DISC); getOrCreateTagBuilder(ItemTags.MUSIC_DISCS).add(Szar.EFN_DISK); + getOrCreateTagBuilder(ItemTags.MUSIC_DISCS).add(Szar.HELLO_DISC); } } \ No newline at end of file diff --git a/src/main/java/dev/tggamesyt/szar/Szar.java b/src/main/java/dev/tggamesyt/szar/Szar.java index 70cfe5c..618fa7b 100644 --- a/src/main/java/dev/tggamesyt/szar/Szar.java +++ b/src/main/java/dev/tggamesyt/szar/Szar.java @@ -1,7 +1,6 @@ package dev.tggamesyt.szar; import com.google.common.collect.ImmutableSet; -import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.builder.LiteralArgumentBuilder; import net.fabricmc.api.ModInitializer; import net.fabricmc.fabric.api.biome.v1.BiomeModifications; @@ -75,13 +74,11 @@ import net.minecraft.world.gen.structure.StructureType; import net.minecraft.world.poi.PointOfInterestType; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.jetbrains.annotations.UnknownNullability; import java.util.*; import java.util.concurrent.CompletableFuture; import java.util.regex.Pattern; -import static com.mojang.brigadier.builder.LiteralArgumentBuilder.literal; import static dev.tggamesyt.szar.ServerCosmetics.USERS; import static dev.tggamesyt.szar.ServerCosmetics.sync; @@ -317,12 +314,13 @@ public class Szar implements ModInitializer { entries.add(Szar.NYAN_SPAWNEGG); entries.add(Szar.EPSTEIN_FILES); entries.add(Szar.EPSTEIN_SPAWNEGG); - entries.add(Szar.BAITER_DISK); + entries.add(Szar.BAITER_DISC); entries.add(Szar.MERL_SPAWNEGG); entries.add(Szar.EFN_DISK); entries.add(Szar.SLOT_MACHINE); entries.add(Szar.ROULETTE); entries.add(Szar.FIRTANA); + entries.add(Szar.HELLO_DISC); // nsfw entries.add(Szar.FASZITEM); entries.add(Szar.CNDM); @@ -1226,11 +1224,19 @@ public class Szar implements ModInitializer { ); public static final SoundEvent BAITER = SoundEvent.of(new Identifier(MOD_ID, "baiter")); - public static final Item BAITER_DISK = Registry.register( + public static final Item BAITER_DISC = Registry.register( Registries.ITEM, new Identifier(MOD_ID, "baiter"), new MusicDiscItem(12, BAITER, new Item.Settings().maxCount(1).rarity(Rarity.RARE), 172) ); + + public static final SoundEvent HELLO = + SoundEvent.of(new Identifier(MOD_ID, "firtana")); + public static final Item HELLO_DISC = Registry.register( + Registries.ITEM, + new Identifier(MOD_ID, "hello"), + new MusicDiscItem(10, HELLO, new Item.Settings().maxCount(1).rarity(Rarity.RARE), 239) + ); public static final SoundEvent EFN = SoundEvent.of(new Identifier(MOD_ID, "efn")); public static final Item EFN_DISK = Registry.register( diff --git a/src/main/resources/assets/szar/lang/en_us.json b/src/main/resources/assets/szar/lang/en_us.json index 837d8ab..67d74af 100644 --- a/src/main/resources/assets/szar/lang/en_us.json +++ b/src/main/resources/assets/szar/lang/en_us.json @@ -83,5 +83,7 @@ "block.szar.slot_machine": "Slot Machine", "block.szar.casino": "Casino Title", "block.szar.roulette": "Roulette", - "item.szar.firtana": "Firtana" + "item.szar.firtana": "Firtana", + "item.szar.hello": "Music Disc", + "item.szar.hello.desc": "Alex Savage - OMFG - Hello (Dark Remix)" } diff --git a/src/main/resources/assets/szar/models/item/hello.json b/src/main/resources/assets/szar/models/item/hello.json new file mode 100644 index 0000000..2a2a490 --- /dev/null +++ b/src/main/resources/assets/szar/models/item/hello.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "szar:item/hello" + } +} diff --git a/src/main/resources/assets/szar/sounds.json b/src/main/resources/assets/szar/sounds.json index b69bf6b..754d100 100644 --- a/src/main/resources/assets/szar/sounds.json +++ b/src/main/resources/assets/szar/sounds.json @@ -107,6 +107,14 @@ } ] }, + "firtana_og": { + "sounds": [ + { + "name": "szar:firtana_og", + "stream": true + } + ] + }, "firtana": { "sounds": [ { diff --git a/src/main/resources/assets/szar/sounds/firtana.ogg b/src/main/resources/assets/szar/sounds/firtana.ogg index 95ec639..fae401a 100644 Binary files a/src/main/resources/assets/szar/sounds/firtana.ogg and b/src/main/resources/assets/szar/sounds/firtana.ogg differ diff --git a/src/main/resources/assets/szar/sounds/firtana_og.ogg b/src/main/resources/assets/szar/sounds/firtana_og.ogg new file mode 100644 index 0000000..95ec639 Binary files /dev/null and b/src/main/resources/assets/szar/sounds/firtana_og.ogg differ diff --git a/src/main/resources/assets/szar/textures/item/hello.png b/src/main/resources/assets/szar/textures/item/hello.png new file mode 100644 index 0000000..1bc8c26 Binary files /dev/null and b/src/main/resources/assets/szar/textures/item/hello.png differ diff --git a/src/main/resources/data/szar/recipes/firtana.json b/src/main/resources/data/szar/recipes/firtana.json new file mode 100644 index 0000000..166cc46 --- /dev/null +++ b/src/main/resources/data/szar/recipes/firtana.json @@ -0,0 +1,17 @@ +{ + "type": "minecraft:crafting_shapeless", + "ingredients": [ + { + "item": "minecraft:diamond" + }, + { + "item": "minecraft:dried_kelp" + }, + { + "item": "minecraft:stick" + } + ], + "result": { + "item": "szar:firtana" + } +} \ No newline at end of file diff --git a/src/main/resources/data/szar/recipes/hello.json b/src/main/resources/data/szar/recipes/hello.json new file mode 100644 index 0000000..8985e0f --- /dev/null +++ b/src/main/resources/data/szar/recipes/hello.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:crafting_shapeless", + "ingredients": [ + { + "tag": "minecraft:music_discs" + }, + { + "item": "szar:firtana" + } + ], + "result": { + "item": "szar:hello" + } +} \ No newline at end of file