Skip to content

Commit

Permalink
feat: ✨ Added advanced jukebox upgrade
Browse files Browse the repository at this point in the history
  • Loading branch information
P3pp3rF1y committed Jan 8, 2025
1 parent 84dc604 commit 9c5d711
Show file tree
Hide file tree
Showing 17 changed files with 665 additions and 204 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ loader_version_range=[4,)
mod_id=sophisticatedcore
mod_name=Sophisticated Core
mod_license=GNU General Public License v3.0
mod_version=1.0.13
mod_version=1.1.0
mod_group_id=sophisticatedcore
mod_authors=P3pp3rF1y
mod_description=A library / shared functionality mod for Sophisticated Storage and Backpacks
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

public abstract class SettingsTabBase<T extends AbstractContainerScreen<?>> extends Tab {
private static final int RIGHT_BORDER_WIDTH = 6;
private static final int BOTTOM_BORDER_HEIGHT = 7;
private static final int BOTTOM_BORDER_HEIGHT = 6;

protected final T screen;
protected Dimension openTabDimension = new Dimension(0, 0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,10 @@ public Optional<Rect2i> getTabRectangle() {
@Override
protected void renderBg(GuiGraphics guiGraphics, Minecraft minecraft, int mouseX, int mouseY) {
int halfHeight = height / 2;
int oddHeightAddition = height % 2;
int secondHalfHeight = halfHeight + oddHeightAddition;
guiGraphics.blit(GuiHelper.GUI_CONTROLS, x, y, (float) TEXTURE_WIDTH - width, 0, width, halfHeight, TEXTURE_WIDTH, TEXTURE_HEIGHT);
guiGraphics.blit(GuiHelper.GUI_CONTROLS, x, y + halfHeight, (float) TEXTURE_WIDTH - width, (float) TEXTURE_HEIGHT - halfHeight, width, halfHeight, TEXTURE_WIDTH, TEXTURE_HEIGHT);
guiGraphics.blit(GuiHelper.GUI_CONTROLS, x, y + halfHeight, (float) TEXTURE_WIDTH - width, (float) TEXTURE_HEIGHT - secondHalfHeight, width, secondHalfHeight, TEXTURE_WIDTH, TEXTURE_HEIGHT);
guiGraphics.blit(GuiHelper.GUI_CONTROLS, x - 3, y, TEXTURE_WIDTH / 2, TEXTURE_HEIGHT - height, 3, height);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import net.p3pp3rf1y.sophisticatedcore.upgrades.FilterAttributes;
import net.p3pp3rf1y.sophisticatedcore.upgrades.feeding.HungerLevel;
import net.p3pp3rf1y.sophisticatedcore.upgrades.filter.Direction;
import net.p3pp3rf1y.sophisticatedcore.upgrades.jukebox.RepeatMode;
import net.p3pp3rf1y.sophisticatedcore.upgrades.xppump.AutomationDirection;
import net.p3pp3rf1y.sophisticatedcore.util.SimpleItemContent;

Expand Down Expand Up @@ -152,6 +153,18 @@ public class ModCoreDataComponents {
public static final Supplier<DataComponentType<Boolean>> ENABLED = DATA_COMPONENT_TYPES.register("enabled",
() -> new DataComponentType.Builder<Boolean>().persistent(Codec.BOOL).networkSynchronized(ByteBufCodecs.BOOL).build());

public static final Supplier<DataComponentType<RepeatMode>> REPEAT_MODE = DATA_COMPONENT_TYPES.register("repeat_mode",
() -> new DataComponentType.Builder<RepeatMode>().persistent(RepeatMode.CODEC).networkSynchronized(RepeatMode.STREAM_CODEC).build());

public static final Supplier<DataComponentType<Boolean>> SHUFFLE = DATA_COMPONENT_TYPES.register("shuffle",
() -> new DataComponentType.Builder<Boolean>().persistent(Codec.BOOL).networkSynchronized(ByteBufCodecs.BOOL).build());

public static final Supplier<DataComponentType<Integer>> DISC_SLOT_ACTIVE = DATA_COMPONENT_TYPES.register("disc_slot_active",
() -> new DataComponentType.Builder<Integer>().persistent(Codec.INT).networkSynchronized(ByteBufCodecs.INT).build());

public static final Supplier<DataComponentType<Long>> DISC_FINISH_TIME = DATA_COMPONENT_TYPES.register("disc_finish_time",
() -> new DataComponentType.Builder<Long>().persistent(Codec.LONG).networkSynchronized(ByteBufCodecs.VAR_LONG).build());

public static void register(IEventBus modBus) {
DATA_COMPONENT_TYPES.register(modBus);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import net.p3pp3rf1y.sophisticatedcore.SophisticatedCore;
import net.p3pp3rf1y.sophisticatedcore.network.*;
import net.p3pp3rf1y.sophisticatedcore.upgrades.jukebox.PlayDiscPayload;
import net.p3pp3rf1y.sophisticatedcore.upgrades.jukebox.SoundStopNotificationPayload;
import net.p3pp3rf1y.sophisticatedcore.upgrades.jukebox.SoundFinishedNotificationPayload;
import net.p3pp3rf1y.sophisticatedcore.upgrades.jukebox.StopDiscPlaybackPayload;
import net.p3pp3rf1y.sophisticatedcore.upgrades.tank.TankClickPayload;

Expand All @@ -21,7 +21,7 @@ public static void registerPayloads(final RegisterPayloadHandlersEvent event) {
registrar.playToClient(SyncPlayerSettingsPayload.TYPE, SyncPlayerSettingsPayload.STREAM_CODEC, SyncPlayerSettingsPayload::handlePayload);
registrar.playToClient(PlayDiscPayload.TYPE, PlayDiscPayload.STREAM_CODEC, PlayDiscPayload::handlePayload);
registrar.playToClient(StopDiscPlaybackPayload.TYPE, StopDiscPlaybackPayload.STREAM_CODEC, StopDiscPlaybackPayload::handlePayload);
registrar.playToServer(SoundStopNotificationPayload.TYPE, SoundStopNotificationPayload.STREAM_CODEC, SoundStopNotificationPayload::handlePayload);
registrar.playToServer(SoundFinishedNotificationPayload.TYPE, SoundFinishedNotificationPayload.STREAM_CODEC, SoundFinishedNotificationPayload::handlePayload);
registrar.playToServer(TankClickPayload.TYPE, TankClickPayload.STREAM_CODEC, TankClickPayload::handlePayload);
registrar.playToServer(TransferItemsPayload.TYPE, TransferItemsPayload.STREAM_CODEC, TransferItemsPayload::handlePayload);
registrar.playToClient(SyncTemplateSettingsPayload.TYPE, SyncTemplateSettingsPayload.STREAM_CODEC, SyncTemplateSettingsPayload::handlePayload);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package net.p3pp3rf1y.sophisticatedcore.upgrades.jukebox;

import net.neoforged.neoforge.common.ModConfigSpec;

public class JukeboxUpgradeConfig {
public final ModConfigSpec.IntValue numberOfSlots;
public final ModConfigSpec.IntValue slotsInRow;

public JukeboxUpgradeConfig(ModConfigSpec.Builder builder, String upgradeName, String path, int defaultNumberOfSlots) {
builder.comment(upgradeName + " Settings").push(path);
numberOfSlots = builder.comment("Number of slots for discs in jukebox upgrade").defineInRange("numberOfSlots", defaultNumberOfSlots, 1, 16);
slotsInRow = builder.comment("Number of lots displayed in a row").defineInRange("slotsInRow", 4, 1, 6);

builder.pop();
}
}
Original file line number Diff line number Diff line change
@@ -1,42 +1,60 @@
package net.p3pp3rf1y.sophisticatedcore.upgrades.jukebox;

import net.minecraft.core.Holder;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.Slot;
import net.minecraft.world.item.JukeboxSong;
import net.minecraft.world.level.Level;
import net.neoforged.neoforge.items.SlotItemHandler;
import net.p3pp3rf1y.sophisticatedcore.common.gui.StorageContainerMenuBase;
import net.p3pp3rf1y.sophisticatedcore.common.gui.UpgradeContainerBase;
import net.p3pp3rf1y.sophisticatedcore.common.gui.UpgradeContainerType;
import net.p3pp3rf1y.sophisticatedcore.util.NBTHelper;

public class JukeboxUpgradeContainer extends UpgradeContainerBase<JukeboxUpgradeItem.Wrapper, JukeboxUpgradeContainer> {
import java.util.Optional;

public class JukeboxUpgradeContainer extends UpgradeContainerBase<JukeboxUpgradeWrapper, JukeboxUpgradeContainer> {

private static final String ACTION_DATA = "action";

public JukeboxUpgradeContainer(Player player, int upgradeContainerId, JukeboxUpgradeItem.Wrapper upgradeWrapper, UpgradeContainerType<JukeboxUpgradeItem.Wrapper, JukeboxUpgradeContainer> type) {
public JukeboxUpgradeContainer(Player player, int upgradeContainerId, JukeboxUpgradeWrapper upgradeWrapper, UpgradeContainerType<JukeboxUpgradeWrapper, JukeboxUpgradeContainer> type) {
super(player, upgradeContainerId, upgradeWrapper, type);
slots.add(new SlotItemHandler(upgradeWrapper.getDiscInventory(), 0, -100, -100) {
@Override
public void setChanged() {
super.setChanged();
if (upgradeWrapper.isPlaying()) {
upgradeWrapper.stop(player);
for (int slot = 0; slot < upgradeWrapper.getDiscInventory().getSlots(); slot++) {
slots.add(new SlotItemHandler(upgradeWrapper.getDiscInventory(), slot, -100, -100) {
@Override
public void setChanged() {
super.setChanged();
if (upgradeWrapper.isPlaying() && getSlotIndex() == upgradeWrapper.getDiscSlotActive()) {
upgradeWrapper.stop(player);
}
}
}
});
});
}
}

@Override
public void handlePacket(CompoundTag data) {
if (data.contains(ACTION_DATA)) {
String actionName = data.getString(ACTION_DATA);
if (actionName.equals("play")) {
if (player.containerMenu instanceof StorageContainerMenuBase<?> storageContainerMenu) {
storageContainerMenu.getBlockPosition().ifPresentOrElse(pos -> upgradeWrapper.play(player.level(), pos), () -> upgradeWrapper.play(storageContainerMenu.getEntity().orElse(player)));
switch (actionName) {
case "play" -> {
if (player.containerMenu instanceof StorageContainerMenuBase<?> storageContainerMenu) {
storageContainerMenu.getBlockPosition().ifPresentOrElse(pos -> upgradeWrapper.play(player.level(), pos), () -> upgradeWrapper.play(storageContainerMenu.getEntity().orElse(player)));
}
}
} else if (actionName.equals("stop")) {
upgradeWrapper.stop(player);
case "stop" -> upgradeWrapper.stop(player);
case "next" -> upgradeWrapper.next();
case "previous" -> upgradeWrapper.previous();
}
}
if (data.contains("shuffle")) {
upgradeWrapper.setShuffleEnabled(data.getBoolean("shuffle"));
}

if (data.contains("repeat")) {
NBTHelper.getEnumConstant(data, "repeat", RepeatMode::fromName).ifPresent(upgradeWrapper::setRepeatMode);
}
}

public void play() {
Expand All @@ -46,4 +64,45 @@ public void play() {
public void stop() {
sendDataToServer(() -> NBTHelper.putString(new CompoundTag(), ACTION_DATA, "stop"));
}

public void next() {
sendDataToServer(() -> NBTHelper.putString(new CompoundTag(), ACTION_DATA, "next"));
}

public void previous() {
sendDataToServer(() -> NBTHelper.putString(new CompoundTag(), ACTION_DATA, "previous"));
}

public boolean isShuffleEnabled() {
return upgradeWrapper.isShuffleEnabled();
}

public void toggleShuffle() {
boolean newValue = !upgradeWrapper.isShuffleEnabled();
upgradeWrapper.setShuffleEnabled(newValue);
sendBooleanToServer("shuffle", newValue);
}

public RepeatMode getRepeatMode() {
return upgradeWrapper.getRepeatMode();
}

public void toggleRepeat() {
RepeatMode newValue = upgradeWrapper.getRepeatMode().next();
upgradeWrapper.setRepeatMode(newValue);
sendDataToServer(() -> NBTHelper.putEnumConstant(new CompoundTag(), "repeat", newValue));
}

public Optional<Slot> getDiscSlotActive() {
int discSlotActive = upgradeWrapper.getDiscSlotActive();
return discSlotActive > -1 ? Optional.of(slots.get(discSlotActive)) : Optional.empty();
}

public long getDiscFinishTime() {
return upgradeWrapper.getDiscFinishTime();
}

public Optional<Holder<JukeboxSong>> getJukeboxSong(Level level) {
return upgradeWrapper.getJukeboxSongHolder(level);
}
}
Original file line number Diff line number Diff line change
@@ -1,35 +1,28 @@
package net.p3pp3rf1y.sophisticatedcore.upgrades.jukebox;

import net.minecraft.core.BlockPos;
import net.minecraft.core.component.DataComponents;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.JukeboxSong;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.Vec3;
import net.neoforged.neoforge.items.ComponentItemHandler;
import net.neoforged.neoforge.items.IItemHandler;
import net.p3pp3rf1y.sophisticatedcore.api.IStorageWrapper;
import net.p3pp3rf1y.sophisticatedcore.init.ModCoreDataComponents;
import net.p3pp3rf1y.sophisticatedcore.upgrades.*;
import net.p3pp3rf1y.sophisticatedcore.client.gui.utils.TranslationHelper;
import net.p3pp3rf1y.sophisticatedcore.upgrades.IUpgradeCountLimitConfig;
import net.p3pp3rf1y.sophisticatedcore.upgrades.UpgradeGroup;
import net.p3pp3rf1y.sophisticatedcore.upgrades.UpgradeItemBase;
import net.p3pp3rf1y.sophisticatedcore.upgrades.UpgradeType;

import javax.annotation.Nullable;
import java.util.List;
import java.util.UUID;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.IntSupplier;

public class JukeboxUpgradeItem extends UpgradeItemBase<JukeboxUpgradeItem.Wrapper> {
public static final UpgradeType<Wrapper> TYPE = new UpgradeType<>(Wrapper::new);
public class JukeboxUpgradeItem extends UpgradeItemBase<JukeboxUpgradeWrapper> {
public static final UpgradeGroup UPGRADE_GROUP = new UpgradeGroup("jukebox_upgrades", TranslationHelper.INSTANCE.translUpgradeGroup("jukebox_upgrades"));
public static final UpgradeType<JukeboxUpgradeWrapper> TYPE = new UpgradeType<>(JukeboxUpgradeWrapper::new);
private final IntSupplier numberOfSlots;
private final IntSupplier slotsInRow;

public JukeboxUpgradeItem(IUpgradeCountLimitConfig upgradeTypeLimitConfig) {
public JukeboxUpgradeItem(IUpgradeCountLimitConfig upgradeTypeLimitConfig, IntSupplier numberOfSlots, IntSupplier slotsInRow) {
super(upgradeTypeLimitConfig);
this.numberOfSlots = numberOfSlots;
this.slotsInRow = slotsInRow;
}

@Override
public UpgradeType<Wrapper> getType() {
public UpgradeType<JukeboxUpgradeWrapper> getType() {
return TYPE;
}

Expand All @@ -38,101 +31,17 @@ public List<UpgradeConflictDefinition> getUpgradeConflicts() {
return List.of();
}

public static class Wrapper extends UpgradeWrapperBase<Wrapper, JukeboxUpgradeItem> implements ITickableUpgrade {
private static final int KEEP_ALIVE_SEND_INTERVAL = 5;
private final ComponentItemHandler discInventory;
private long lastKeepAliveSendTime = 0;
private boolean isPlaying;

protected Wrapper(IStorageWrapper storageWrapper, ItemStack upgrade, Consumer<ItemStack> upgradeSaveHandler) {
super(storageWrapper, upgrade, upgradeSaveHandler);
discInventory = new ComponentItemHandler(upgrade, DataComponents.CONTAINER, 1) {
@Override
protected void onContentsChanged(int slot, ItemStack oldStack, ItemStack newStack) {
super.onContentsChanged(slot, oldStack, newStack);
save();
}

@Override
public boolean isItemValid(int slot, ItemStack stack) {
return stack.isEmpty() || stack.has(DataComponents.JUKEBOX_PLAYABLE);
}
};
isPlaying = upgrade.getOrDefault(ModCoreDataComponents.IS_PLAYING, false);
}

public void setDisc(ItemStack disc) {
discInventory.setStackInSlot(0, disc);
}

public ItemStack getDisc() {
return discInventory.getStackInSlot(0);
}

public void play(Level level, BlockPos pos) {
play(level, (serverLevel, storageUuid) -> JukeboxSong.fromStack(level.registryAccess(), getDisc())
.ifPresent(song -> ServerStorageSoundHandler.startPlayingDisc(serverLevel, pos, storageUuid, song, () -> setIsPlaying(false))));
}

public void play(Entity entity) {
play(entity.level(), (world, storageUuid) -> JukeboxSong.fromStack(entity.level().registryAccess(), getDisc())
.ifPresent(song -> ServerStorageSoundHandler.startPlayingDisc(world, entity.position(), storageUuid, entity.getId(), song, () -> setIsPlaying(false))));
}

private void play(Level level, BiConsumer<ServerLevel, UUID> play) {
if (!(level instanceof ServerLevel) || getDisc().isEmpty()) {
return;
}
storageWrapper.getContentsUuid().ifPresent(storageUuid -> play.accept((ServerLevel) level, storageUuid));
setIsPlaying(true);
}

private void setIsPlaying(boolean playing) {
isPlaying = playing;
upgrade.set(ModCoreDataComponents.IS_PLAYING, playing);
if (isPlaying) {
storageWrapper.getRenderInfo().setUpgradeRenderData(JukeboxUpgradeRenderData.TYPE, new JukeboxUpgradeRenderData(true));
} else {
removeRenderData();
}
save();
}

private void removeRenderData() {
storageWrapper.getRenderInfo().removeUpgradeRenderData(JukeboxUpgradeRenderData.TYPE);
}

public void stop(LivingEntity entity) {
if (!(entity.level() instanceof ServerLevel)) {
return;
}
storageWrapper.getContentsUuid().ifPresent(storageUuid ->
ServerStorageSoundHandler.stopPlayingDisc(entity.level(), entity.position(), storageUuid)
);
setIsPlaying(false);
}

public IItemHandler getDiscInventory() {
return discInventory;
}

@Override
public void tick(@Nullable Entity entity, Level level, BlockPos pos) {
if (isPlaying && lastKeepAliveSendTime < level.getGameTime() - KEEP_ALIVE_SEND_INTERVAL) {
storageWrapper.getContentsUuid().ifPresent(storageUuid ->
ServerStorageSoundHandler.updateKeepAlive(storageUuid, level, entity != null ? entity.position() : Vec3.atCenterOf(pos), () -> setIsPlaying(false))
);
lastKeepAliveSendTime = level.getGameTime();
}
}
@Override
public UpgradeGroup getUpgradeGroup() {
return UPGRADE_GROUP;
}

public boolean isPlaying() {
return isPlaying;
}
public int getNumberOfSlots() {
return numberOfSlots.getAsInt();
}

@Override
public void onBeforeRemoved() {
removeRenderData();
}
public int getSlotsInRow() {
return slotsInRow.getAsInt();
}

}
Loading

0 comments on commit 9c5d711

Please sign in to comment.