OiOiOiAEyeEye

This commit is contained in:
2026-03-07 14:28:02 +01:00
parent a7aa7d36f9
commit 76803eb460
20 changed files with 196 additions and 106 deletions

View File

@@ -6,7 +6,7 @@ minecraft_version=1.20.1
yarn_mappings=1.20.1+build.10 yarn_mappings=1.20.1+build.10
loader_version=0.18.3 loader_version=0.18.3
# Mod Properties # Mod Properties
mod_version=26.3.5 mod_version=26.3.7
maven_group=dev.tggamesyt maven_group=dev.tggamesyt
archives_base_name=szar archives_base_name=szar
# Dependencies # Dependencies

View File

@@ -96,6 +96,7 @@ public class SzarClient implements ClientModInitializer {
}); });
}); });
VideoManager.init();
ClientTickEvents.END_CLIENT_TICK.register(client -> { ClientTickEvents.END_CLIENT_TICK.register(client -> {
VideoManager.tick(); VideoManager.tick();
}); });
@@ -441,7 +442,7 @@ public class SzarClient implements ClientModInitializer {
(dispatcher, registryAccess) -> PanoramaClientCommand.register(dispatcher) (dispatcher, registryAccess) -> PanoramaClientCommand.register(dispatcher)
); );
} }
ClientTickEvents.END_CLIENT_TICK.register(client -> { /*ClientTickEvents.END_CLIENT_TICK.register(client -> {
if (addedFeature) return; // only run once if (addedFeature) return; // only run once
MinecraftClient mc = MinecraftClient.getInstance(); MinecraftClient mc = MinecraftClient.getInstance();
if (mc.getEntityRenderDispatcher() == null) return; if (mc.getEntityRenderDispatcher() == null) return;
@@ -453,7 +454,7 @@ public class SzarClient implements ClientModInitializer {
} }
addedFeature = true; // prevent running again addedFeature = true; // prevent running again
}); });*/
} }
private boolean isDebugEnabled() { private boolean isDebugEnabled() {

View File

@@ -2,6 +2,7 @@ package dev.tggamesyt.szar.client;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.network.AbstractClientPlayerEntity; import net.minecraft.client.network.AbstractClientPlayerEntity;
import net.minecraft.client.render.OverlayTexture;
import net.minecraft.client.render.VertexConsumer; import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.RenderLayer; import net.minecraft.client.render.RenderLayer;
@@ -26,7 +27,6 @@ public class VideoHeadFeature extends FeatureRenderer<AbstractClientPlayerEntity
public void render(MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, public void render(MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light,
AbstractClientPlayerEntity player, float limbAngle, float limbDistance, AbstractClientPlayerEntity player, float limbAngle, float limbDistance,
float tickDelta, float animationProgress, float headYaw, float headPitch) { float tickDelta, float animationProgress, float headYaw, float headPitch) {
// Only render if the player is playing a video // Only render if the player is playing a video
if (!VideoManager.isPlaying(player.getUuid())) return; if (!VideoManager.isPlaying(player.getUuid())) return;
@@ -40,16 +40,43 @@ public class VideoHeadFeature extends FeatureRenderer<AbstractClientPlayerEntity
// Position quad slightly in front of the face // Position quad slightly in front of the face
float size = 0.5f; float size = 0.5f;
matrices.translate(-size / 2f, -size / 2f, -0.25f); matrices.translate(-size / 2f, -size / 2f - 0.24f, -0.30f);
// Render the video frame // Render the video frame
VertexConsumer vc = vertexConsumers.getBuffer(RenderLayer.getEntityCutoutNoCull(frame)); VertexConsumer vc = vertexConsumers.getBuffer(RenderLayer.getEntityCutoutNoCull(frame));
Matrix4f matrix = matrices.peek().getPositionMatrix(); Matrix4f matrix = matrices.peek().getPositionMatrix();
vc.vertex(matrix, 0, 0, 0).texture(0, 1).light(light).next(); vc.vertex(matrix, 0, 0, 0)
vc.vertex(matrix, size, 0, 0).texture(1, 1).light(light).next(); .color(255,255,255,255)
vc.vertex(matrix, size, size, 0).texture(1, 0).light(light).next(); .texture(0,0)
vc.vertex(matrix, 0, size, 0).texture(0, 0).light(light).next(); .overlay(OverlayTexture.DEFAULT_UV)
.light(light)
.normal(0,0,1)
.next();
vc.vertex(matrix, size, 0, 0)
.color(255,255,255,255)
.texture(1,0)
.overlay(OverlayTexture.DEFAULT_UV)
.light(light)
.normal(0,0,1)
.next();
vc.vertex(matrix, size, size, 0)
.color(255,255,255,255)
.texture(1,1)
.overlay(OverlayTexture.DEFAULT_UV)
.light(light)
.normal(0,0,1)
.next();
vc.vertex(matrix, 0, size, 0)
.color(255,255,255,255)
.texture(0,1)
.overlay(OverlayTexture.DEFAULT_UV)
.light(light)
.normal(0,0,1)
.next();
matrices.pop(); matrices.pop();
} }

View File

@@ -4,9 +4,9 @@ import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.client.world.ClientWorld; import net.minecraft.client.world.ClientWorld;
import net.minecraft.client.sound.PositionedSoundInstance; import net.minecraft.client.sound.PositionedSoundInstance;
import net.minecraft.client.sound.SoundInstance;
import net.minecraft.sound.SoundCategory; import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvent; import net.minecraft.sound.SoundEvent;
import net.minecraft.sound.SoundEvents;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import java.util.*; import java.util.*;
@@ -19,151 +19,144 @@ public class VideoManager {
private static final int TOTAL_FRAMES = 193; private static final int TOTAL_FRAMES = 193;
private static final int TICKS_PER_FRAME = 1; private static final int TICKS_PER_FRAME = 1;
private static final int SOUND_DELAY_TICKS = 4;
private static final Map<UUID, VideoInstance> activeVideos = new HashMap<>(); private static final Map<UUID, VideoInstance> activeVideos = new HashMap<>();
private static final Map<UUID, SoundInstance> activeSounds = new HashMap<>();
private static final List<Identifier> FRAMES = new ArrayList<>(); private static final List<Identifier> FRAMES = new ArrayList<>();
/* Load frames (call once during client init) */
/*
* Load frames (call once during client init)
*/
public static void init() { public static void init() {
if (!FRAMES.isEmpty()) return; 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); String frame = String.format("textures/video/frame_%03d.png", i);
FRAMES.add(new Identifier(MOD_ID, frame)); FRAMES.add(new Identifier(MOD_ID, frame));
} }
} }
/* Start or restart video for a player */
/*
* Start playing the video on a player
*/
public static void startVideo(String playerUuid) { public static void startVideo(String playerUuid) {
if (client.world == null) return; if (client.world == null) return;
UUID uuid = UUID.fromString(playerUuid); UUID uuid = UUID.fromString(playerUuid);
activeVideos.put(uuid, new VideoInstance(uuid)); // Stop existing video and sound if playing
if (activeVideos.containsKey(uuid)) {
playSound(uuid); stopVideo(uuid);
}
/*
* Tick method (call every client tick)
*/
public static void tick() {
if (activeVideos.isEmpty()) return;
Iterator<Map.Entry<UUID, VideoInstance>> iterator = activeVideos.entrySet().iterator();
while (iterator.hasNext()) {
VideoInstance instance = iterator.next().getValue();
instance.tick();
if (instance.finished()) {
iterator.remove();
}
} }
// 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<UUID> finishedVideos = new ArrayList<>();
for (Map.Entry<UUID, VideoInstance> 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) { public static boolean isPlaying(UUID player) {
return activeVideos.containsKey(player); return activeVideos.containsKey(player);
} }
/*
* Get current frame texture for player
*/
public static Identifier getCurrentFrame(UUID player) { public static Identifier getCurrentFrame(UUID player) {
VideoInstance instance = activeVideos.get(player); VideoInstance instance = activeVideos.get(player);
if (instance == null) return null; if (instance == null) return null;
int frameIndex = instance.frame; int frameIndex = instance.frame;
if (frameIndex >= FRAMES.size()) return null; if (frameIndex >= FRAMES.size()) return null;
return FRAMES.get(frameIndex); 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) { private static void playSound(UUID playerUuid) {
if (activeSounds.containsKey(playerUuid)) return;
ClientWorld world = client.world; ClientWorld world = client.world;
if (world == null) return; if (world == null) return;
var player = world.getPlayerByUuid(playerUuid); ClientPlayerEntity player = (ClientPlayerEntity) world.getPlayerByUuid(playerUuid);
if (player == null) return; if (player == null) return;
Identifier soundId = new Identifier(MOD_ID, "firtana"); Identifier soundId = new Identifier(MOD_ID, "firtana");
SoundEvent soundEvent = SoundEvent.of(soundId); SoundEvent soundEvent = SoundEvent.of(soundId);
client.getSoundManager().play( PositionedSoundInstance soundInstance = new PositionedSoundInstance(
new PositionedSoundInstance( soundEvent,
soundEvent, SoundCategory.PLAYERS,
SoundCategory.PLAYERS, 1.0f,
1.0f, // volume 1.0f,
1.0f, // pitch player.getRandom(),
player.getRandom(), player.getX(),
player.getX(), player.getY(),
player.getY(), player.getZ()
player.getZ()
)
); );
client.getSoundManager().play(soundInstance);
activeSounds.put(playerUuid, soundInstance);
} }
/* Video instance with sound delay support */
/*
* Video instance for each player
*/
private static class VideoInstance { private static class VideoInstance {
UUID player; UUID player;
int frame = 0; int frame = 0;
int tickCounter = 0; int tickCounter = 0;
int soundDelay;
VideoInstance(UUID player) { VideoInstance(UUID player, int soundDelayTicks) {
this.player = player; this.player = player;
this.soundDelay = soundDelayTicks;
} }
void tick() { void tick() {
tickCounter++; tickCounter++;
if (tickCounter >= TICKS_PER_FRAME) { if (tickCounter >= TICKS_PER_FRAME) {
frame++; frame++;
tickCounter = 0; tickCounter = 0;
} }
if (soundDelay > 0) {
soundDelay--;
}
}
boolean shouldPlaySound() {
return soundDelay <= 0;
} }
boolean finished() { boolean finished() {
return frame >= TOTAL_FRAMES; return frame >= TOTAL_FRAMES;
} }
} }
} }

View File

@@ -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 = "<init>", at = @At("RETURN"))
private void addVideoFeature(EntityRendererFactory.Context ctx, boolean slim, CallbackInfo ci) {
PlayerEntityRenderer renderer = (PlayerEntityRenderer)(Object)this;
renderer.addFeature(new VideoHeadFeature(renderer));
}
}

View File

@@ -6,6 +6,7 @@
"client": [ "client": [
"ItemRendererMixin", "ItemRendererMixin",
"MouseMixin", "MouseMixin",
"PlayerEntityRendererMixin",
"PlayerModelMixin", "PlayerModelMixin",
"RadiatedItemRendererMixin", "RadiatedItemRendererMixin",
"RadiationHeartMixin", "RadiationHeartMixin",

View File

@@ -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 1d26b5da3b0a2ea6b23d456d1f0b82455a788ca1 data\szar\worldgen\configured_feature\uranium_ore.json
32864170bdb41310f9ee5d06f5720dfdb3badb6d data\szar\worldgen\placed_feature\uranium_ore_placed.json 32864170bdb41310f9ee5d06f5720dfdb3badb6d data\szar\worldgen\placed_feature\uranium_ore_placed.json

View File

@@ -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 eba137b51c50a7143a3668876f41adaa1447b1d1 data\minecraft\tags\point_of_interest_type\acquirable_job_site.json

View File

@@ -1,2 +1,2 @@
// 1.20.1 2026-02-22T17:34:09.3596499 szar/Tags for minecraft:item // 1.20.1 2026-03-07T14:06:37.8432546 szar/Tags for minecraft:item
15754f2ee2c60320aae8a09679ed422fea29a705 data\minecraft\tags\items\music_discs.json 935692b1c49ef3164e01f8a993f3ce8002919afe data\minecraft\tags\items\music_discs.json

View File

@@ -3,6 +3,7 @@
"values": [ "values": [
"szar:pop_tart", "szar:pop_tart",
"szar:baiter", "szar:baiter",
"szar:efn" "szar:efn",
"szar:hello"
] ]
} }

View File

@@ -2,16 +2,8 @@ package dev.tggamesyt.szar;
import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput; import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput;
import net.fabricmc.fabric.api.datagen.v1.provider.FabricTagProvider; 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.RegistryWrapper;
import net.minecraft.registry.tag.ItemTags; 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; import java.util.concurrent.CompletableFuture;
@@ -24,7 +16,8 @@ public class ModItemTagProvider extends FabricTagProvider.ItemTagProvider {
@Override @Override
protected void configure(RegistryWrapper.WrapperLookup lookup) { protected void configure(RegistryWrapper.WrapperLookup lookup) {
getOrCreateTagBuilder(ItemTags.MUSIC_DISCS).add(Szar.POPTART); 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.EFN_DISK);
getOrCreateTagBuilder(ItemTags.MUSIC_DISCS).add(Szar.HELLO_DISC);
} }
} }

View File

@@ -1,7 +1,6 @@
package dev.tggamesyt.szar; package dev.tggamesyt.szar;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import net.fabricmc.api.ModInitializer; import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.biome.v1.BiomeModifications; 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 net.minecraft.world.poi.PointOfInterestType;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.jetbrains.annotations.UnknownNullability;
import java.util.*; import java.util.*;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.regex.Pattern; 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.USERS;
import static dev.tggamesyt.szar.ServerCosmetics.sync; import static dev.tggamesyt.szar.ServerCosmetics.sync;
@@ -317,12 +314,13 @@ public class Szar implements ModInitializer {
entries.add(Szar.NYAN_SPAWNEGG); entries.add(Szar.NYAN_SPAWNEGG);
entries.add(Szar.EPSTEIN_FILES); entries.add(Szar.EPSTEIN_FILES);
entries.add(Szar.EPSTEIN_SPAWNEGG); entries.add(Szar.EPSTEIN_SPAWNEGG);
entries.add(Szar.BAITER_DISK); entries.add(Szar.BAITER_DISC);
entries.add(Szar.MERL_SPAWNEGG); entries.add(Szar.MERL_SPAWNEGG);
entries.add(Szar.EFN_DISK); entries.add(Szar.EFN_DISK);
entries.add(Szar.SLOT_MACHINE); entries.add(Szar.SLOT_MACHINE);
entries.add(Szar.ROULETTE); entries.add(Szar.ROULETTE);
entries.add(Szar.FIRTANA); entries.add(Szar.FIRTANA);
entries.add(Szar.HELLO_DISC);
// nsfw // nsfw
entries.add(Szar.FASZITEM); entries.add(Szar.FASZITEM);
entries.add(Szar.CNDM); entries.add(Szar.CNDM);
@@ -1226,11 +1224,19 @@ public class Szar implements ModInitializer {
); );
public static final SoundEvent BAITER = public static final SoundEvent BAITER =
SoundEvent.of(new Identifier(MOD_ID, "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, Registries.ITEM,
new Identifier(MOD_ID, "baiter"), new Identifier(MOD_ID, "baiter"),
new MusicDiscItem(12, BAITER, new Item.Settings().maxCount(1).rarity(Rarity.RARE), 172) 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 = public static final SoundEvent EFN =
SoundEvent.of(new Identifier(MOD_ID, "efn")); SoundEvent.of(new Identifier(MOD_ID, "efn"));
public static final Item EFN_DISK = Registry.register( public static final Item EFN_DISK = Registry.register(

View File

@@ -83,5 +83,7 @@
"block.szar.slot_machine": "Slot Machine", "block.szar.slot_machine": "Slot Machine",
"block.szar.casino": "Casino Title", "block.szar.casino": "Casino Title",
"block.szar.roulette": "Roulette", "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)"
} }

View File

@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "szar:item/hello"
}
}

View File

@@ -107,6 +107,14 @@
} }
] ]
}, },
"firtana_og": {
"sounds": [
{
"name": "szar:firtana_og",
"stream": true
}
]
},
"firtana": { "firtana": {
"sounds": [ "sounds": [
{ {

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

View File

@@ -0,0 +1,17 @@
{
"type": "minecraft:crafting_shapeless",
"ingredients": [
{
"item": "minecraft:diamond"
},
{
"item": "minecraft:dried_kelp"
},
{
"item": "minecraft:stick"
}
],
"result": {
"item": "szar:firtana"
}
}

View File

@@ -0,0 +1,14 @@
{
"type": "minecraft:crafting_shapeless",
"ingredients": [
{
"tag": "minecraft:music_discs"
},
{
"item": "szar:firtana"
}
],
"result": {
"item": "szar:hello"
}
}