This commit is contained in:
KäseToatz
2025-08-23 02:27:04 +02:00
parent 1403d6dbed
commit 4b3a2add69
9 changed files with 132 additions and 41 deletions

View File

@@ -6,7 +6,7 @@ minecraft_version=1.21.8
yarn_mappings=1.21.8+build.1
loader_version=0.17.2
# Mod Properties
mod_version=1.0
mod_version=1.1
maven_group=com.kasetoatz
archives_base_name=JukeboxBoat
# Dependencies

View File

@@ -8,6 +8,6 @@ public interface IAbstractBoatEntity
boolean jukeboxBoat$isJukeboxBoat();
void jukeboxBoat$setJukeboxBoat(boolean value);
ItemStack jukeboxBoat$getStoredDisc();
DisplayEntity.BlockDisplayEntity jukeboxBoat$getJukebox();
void jukeboxBoat$setJukebox(DisplayEntity.BlockDisplayEntity jukebox);
String jukeboxBoat$getJukebox();
void jukeboxBoat$setJukebox(String uuid);
}

View File

@@ -0,0 +1,9 @@
package com.kasetoatz.jukeboxboat.interfaces;
import java.util.UUID;
public interface IBlockDisplayEntity
{
String jukeboxBoat$getUUID();
void jukeboxBoat$setUUID(String uuid);
}

View File

@@ -10,12 +10,16 @@ import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.vehicle.AbstractBoatEntity;
import net.minecraft.entity.vehicle.BoatEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.network.packet.s2c.play.PlaySoundFromEntityS2CPacket;
import net.minecraft.network.packet.s2c.play.PositionFlag;
import net.minecraft.registry.Registries;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvent;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.math.random.Random;
import net.minecraft.world.WorldEvents;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
@@ -24,7 +28,6 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.EnumSet;
import java.util.UUID;
import static com.kasetoatz.jukeboxboat.util.Util.*;
@@ -98,32 +101,21 @@ public abstract class AbstractBoatEntityMixin implements IAbstractBoatEntity
}
@Override
public DisplayEntity.BlockDisplayEntity jukeboxBoat$getJukebox()
public String jukeboxBoat$getJukebox()
{
if ((Object)this instanceof BoatEntity boat)
{
String uuid = boat.get(DataComponentTypes.CUSTOM_DATA).copyNbt().getString("jukebox", "");
if (boat.getWorld().getEntity(UUID.fromString(uuid)) instanceof DisplayEntity.BlockDisplayEntity entity)
{
return entity;
}
return boat.get(DataComponentTypes.CUSTOM_DATA).copyNbt().getString("jukebox", "");
}
return null;
}
@Override
public void jukeboxBoat$setJukebox(DisplayEntity.BlockDisplayEntity jukebox)
public void jukeboxBoat$setJukebox(String uuid)
{
if ((Object)this instanceof BoatEntity boat)
{
if (jukebox == null)
{
boat.setComponent(DataComponentTypes.CUSTOM_DATA, boat.get(DataComponentTypes.CUSTOM_DATA).apply(nbtCompound -> nbtCompound.remove("jukebox")));
}
else
{
boat.setComponent(DataComponentTypes.CUSTOM_DATA, boat.get(DataComponentTypes.CUSTOM_DATA).apply(nbtCompound -> nbtCompound.putString("jukebox", jukebox.getUuidAsString())));
}
boat.setComponent(DataComponentTypes.CUSTOM_DATA, boat.get(DataComponentTypes.CUSTOM_DATA).apply(nbtCompound -> nbtCompound.putString("jukebox", uuid)));
}
}
@@ -162,19 +154,19 @@ public abstract class AbstractBoatEntityMixin implements IAbstractBoatEntity
return ActionResult.PASS;
}
stack.splitUnlessCreative(1, player);
DisplayEntity.BlockDisplayEntity jukebox = jukeboxBoat$getJukebox();
DisplayEntity.BlockDisplayEntity jukebox = findJukebox(boat, jukeboxBoat$getJukebox());
if (jukebox == null)
{
jukebox = createJukebox(boat);
}
player.getWorld().playSoundFromEntity(
null,
jukebox,
sound,
SoundCategory.RECORDS,
1.0f,
1.0f
);
boat.getServer().getPlayerManager().sendToAll(new PlaySoundFromEntityS2CPacket(
Registries.SOUND_EVENT.getEntry(sound),
SoundCategory.RECORDS,
jukebox,
1.f,
1.f,
0L
));
setPlaying(boat, true);
setStoredDisc(storedDisc);
setLastStateChange();
@@ -190,7 +182,7 @@ public abstract class AbstractBoatEntityMixin implements IAbstractBoatEntity
if ((Object)this instanceof BoatEntity boat)
{
IAbstractBoatEntity accessor = (IAbstractBoatEntity)boat;
DisplayEntity.BlockDisplayEntity jukebox = jukeboxBoat$getJukebox();
DisplayEntity.BlockDisplayEntity jukebox = findJukebox(boat, jukeboxBoat$getJukebox());
if (!accessor.jukeboxBoat$isJukeboxBoat() || jukebox == null)
{
return;

View File

@@ -0,0 +1,35 @@
package com.kasetoatz.jukeboxboat.mixin;
import com.kasetoatz.jukeboxboat.interfaces.IBlockDisplayEntity;
import net.minecraft.component.DataComponentTypes;
import net.minecraft.component.type.NbtComponent;
import net.minecraft.entity.Entity;
import net.minecraft.entity.decoration.DisplayEntity;
import org.spongepowered.asm.mixin.Mixin;
@Mixin(DisplayEntity.BlockDisplayEntity.class)
public class BlockDisplayEntityMixin implements IBlockDisplayEntity
{
@Override
public String jukeboxBoat$getUUID()
{
NbtComponent nbt = ((Entity)(Object)this).get(DataComponentTypes.CUSTOM_DATA);
if (nbt != null)
{
return nbt.copyNbt().getString("uuid").orElse("");
}
return "";
}
@Override
public void jukeboxBoat$setUUID(String uuid)
{
Entity entity = ((Entity)(Object)this);
NbtComponent nbt = entity.get(DataComponentTypes.CUSTOM_DATA);
if (nbt != null)
{
nbt.apply(nbtCompound -> nbtCompound.putString("uuid", uuid));
}
entity.setComponent(DataComponentTypes.CUSTOM_DATA, nbt);
}
}

View File

@@ -31,14 +31,13 @@ public class BoatItemMixin
{
isJukeboxBoat = name.getString().equals("Boat with Jukebox");
}
IAbstractBoatEntity accessor = (IAbstractBoatEntity)boat;
accessor.jukeboxBoat$setJukeboxBoat(isJukeboxBoat);
((IAbstractBoatEntity)boat).jukeboxBoat$setJukeboxBoat(isJukeboxBoat);
if (!isJukeboxBoat)
{
return;
}
spawnPlaceholder(boat);
accessor.jukeboxBoat$setJukebox(createJukebox(boat));
createJukebox(boat);
}
}
}

View File

@@ -3,6 +3,7 @@ package com.kasetoatz.jukeboxboat.mixin;
import com.kasetoatz.jukeboxboat.interfaces.IAbstractBoatEntity;
import com.llamalad7.mixinextras.sugar.Local;
import net.minecraft.component.DataComponentTypes;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.decoration.DisplayEntity;
import net.minecraft.entity.vehicle.BoatEntity;
import net.minecraft.entity.vehicle.VehicleEntity;
@@ -10,31 +11,46 @@ import net.minecraft.item.ItemStack;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.text.Text;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import static com.kasetoatz.jukeboxboat.util.Util.findJukebox;
import static com.kasetoatz.jukeboxboat.util.Util.removePlaceholder;
@Mixin(VehicleEntity.class)
public abstract class VehicleEntityMixin
{
@Inject(method="killAndDropItem", at=@At("HEAD"))
public void preKill(CallbackInfo ci)
@Unique
private void delete()
{
if ((Object)this instanceof BoatEntity boat)
{
IAbstractBoatEntity accessor = (IAbstractBoatEntity)boat;
DisplayEntity.BlockDisplayEntity jukebox = accessor.jukeboxBoat$getJukebox();
DisplayEntity.BlockDisplayEntity jukebox = findJukebox(boat, accessor.jukeboxBoat$getJukebox());
if (jukebox != null)
{
jukebox.discard();
accessor.jukeboxBoat$setJukebox(null);
accessor.jukeboxBoat$setJukebox("");
}
removePlaceholder(boat);
}
}
@Inject(method="damage", at=@At(value = "INVOKE", target = "Lnet/minecraft/entity/vehicle/VehicleEntity;discard()V"))
public void discard(CallbackInfoReturnable<Boolean> cir)
{
delete();
}
@Inject(method="damage", at= @At(value = "INVOKE", target = "Lnet/minecraft/entity/vehicle/VehicleEntity;killAndDropSelf(Lnet/minecraft/server/world/ServerWorld;Lnet/minecraft/entity/damage/DamageSource;)V"))
public void preKill(CallbackInfoReturnable<Boolean> cir)
{
delete();
}
@Inject(method="killAndDropItem", at=@At(value="INVOKE", target="Lnet/minecraft/entity/vehicle/VehicleEntity;dropStack(Lnet/minecraft/server/world/ServerWorld;Lnet/minecraft/item/ItemStack;)Lnet/minecraft/entity/ItemEntity;"))
public void killAndDropItem(CallbackInfo ci, @Local(argsOnly=true) ServerWorld world, @Local ItemStack stack)
{

View File

@@ -2,11 +2,13 @@ package com.kasetoatz.jukeboxboat.util;
import com.kasetoatz.jukeboxboat.interfaces.IAbstractBoatEntity;
import com.kasetoatz.jukeboxboat.interfaces.IArmorStandEntity;
import com.kasetoatz.jukeboxboat.interfaces.IBlockDisplayEntity;
import net.minecraft.block.Blocks;
import net.minecraft.block.JukeboxBlock;
import net.minecraft.block.jukebox.JukeboxSong;
import net.minecraft.component.DataComponentTypes;
import net.minecraft.component.type.JukeboxPlayableComponent;
import net.minecraft.component.type.NbtComponent;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.decoration.ArmorStandEntity;
@@ -16,12 +18,14 @@ import net.minecraft.entity.vehicle.BoatEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.registry.Registry;
import net.minecraft.registry.RegistryKeys;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.sound.SoundEvent;
import net.minecraft.util.math.AffineTransformation;
import org.joml.Quaternionf;
import org.joml.Vector3f;
import java.util.Optional;
import java.util.UUID;
public class Util
{
@@ -38,7 +42,7 @@ public class Util
public static void setPlaying(BoatEntity boat, boolean playing)
{
DisplayEntity.BlockDisplayEntity jukebox = ((IAbstractBoatEntity)boat).jukeboxBoat$getJukebox();
DisplayEntity.BlockDisplayEntity jukebox = findJukebox(boat, ((IAbstractBoatEntity)boat).jukeboxBoat$getJukebox());
if (jukebox != null)
{
if (playing)
@@ -63,6 +67,8 @@ public class Util
new Quaternionf()
));
boat.getWorld().spawnEntity(jukebox);
((IBlockDisplayEntity)jukebox).jukeboxBoat$setUUID(jukebox.getUuidAsString());
((IAbstractBoatEntity)boat).jukeboxBoat$setJukebox(jukebox.getUuidAsString());
return jukebox;
}
@@ -92,13 +98,46 @@ public class Util
public static void replaceJukebox(BoatEntity boat)
{
IAbstractBoatEntity accessor = (IAbstractBoatEntity)boat;
DisplayEntity.BlockDisplayEntity old = accessor.jukeboxBoat$getJukebox();
DisplayEntity.BlockDisplayEntity old = findJukebox(boat, ((IAbstractBoatEntity)boat).jukeboxBoat$getJukebox());
if (old != null)
{
old.discard();
}
DisplayEntity.BlockDisplayEntity jukebox = createJukebox(boat);
accessor.jukeboxBoat$setJukebox(jukebox);
createJukebox(boat);
}
private static DisplayEntity.BlockDisplayEntity iterateJukeboxes(BoatEntity boat, String uuid)
{
if (boat.getWorld() instanceof ServerWorld world)
{
for (Entity entity : world.iterateEntities())
{
if (entity instanceof DisplayEntity.BlockDisplayEntity jukebox)
{
IBlockDisplayEntity accessor = (IBlockDisplayEntity)jukebox;
if (accessor.jukeboxBoat$getUUID().equals(uuid))
{
((IAbstractBoatEntity)accessor).jukeboxBoat$setJukebox(jukebox.getUuidAsString());
accessor.jukeboxBoat$setUUID(jukebox.getUuidAsString());
return jukebox;
}
}
}
}
return null;
}
public static DisplayEntity.BlockDisplayEntity findJukebox(BoatEntity boat, String uuid)
{
if (uuid.isEmpty())
{
return null;
}
Entity possible = boat.getWorld().getEntity(UUID.fromString(uuid));
if (possible instanceof DisplayEntity.BlockDisplayEntity jukebox)
{
return jukebox;
}
return iterateJukeboxes(boat, uuid);
}
}

View File

@@ -6,6 +6,7 @@
"mixins": [
"AbstractBoatEntityMixin",
"ArmorStandEntityMixin",
"BlockDisplayEntityMixin",
"BoatItemMixin",
"ShapelessRecipeMixin",
"VehicleEntityMixin"