From de845ddffd93f7a5c8b20ee4e413a485e2624b56 Mon Sep 17 00:00:00 2001 From: Zontreck Date: Thu, 15 Feb 2024 02:33:41 -0700 Subject: [PATCH] Adds in the time bottle from time in a bottle. With plans to add an energy variant --- .../zontreck/essentials/AriasEssentials.java | 12 +- .../renderer}/HeartsRenderer.java | 2 +- .../renderer/TimeBoostEntityRenderer.java | 60 +++++++ .../zontreck/essentials/configs/NBTKeys.java | 13 ++ .../configs/server/AEServerConfig.java | 8 + .../configs/server/sections/Bottles.java | 76 +++++++++ .../essentials/entities/ModEntities.java | 27 ++++ .../essentials/entities/TimeBoostEntity.java | 128 +++++++++++++++ .../essentials/items/CreativeModeTabs.java | 39 +++++ .../essentials/items/EventHandlers.java | 11 ++ .../zontreck/essentials/items/ModItems.java | 20 +++ .../items/abstraction/AbstractBottle.java | 148 ++++++++++++++++++ .../items/implementation/TimeBottle.java | 106 +++++++++++++ .../essentials/util/SoundUtilities.java | 47 ++++++ .../zontreck/essentials/util/StylesUtil.java | 10 ++ .../assets/ariasessentials/lang/en_us.json | 5 + .../ariasessentials/models/item/eiab.json | 6 + .../ariasessentials/models/item/tiab.json | 6 + .../ariasessentials/textures/item/eiab.png | Bin 0 -> 2553 bytes .../textures/item/eiab.png.mcmeta | 6 + .../textures/item/tiab.aseprite | Bin 0 -> 4305 bytes .../ariasessentials/textures/item/tiab.png | Bin 0 -> 2561 bytes .../textures/item/tiab.png.mcmeta | 6 + 23 files changed, 734 insertions(+), 2 deletions(-) rename src/main/java/dev/zontreck/essentials/{gui => client/renderer}/HeartsRenderer.java (99%) create mode 100644 src/main/java/dev/zontreck/essentials/client/renderer/TimeBoostEntityRenderer.java create mode 100644 src/main/java/dev/zontreck/essentials/configs/NBTKeys.java create mode 100644 src/main/java/dev/zontreck/essentials/configs/server/sections/Bottles.java create mode 100644 src/main/java/dev/zontreck/essentials/entities/ModEntities.java create mode 100644 src/main/java/dev/zontreck/essentials/entities/TimeBoostEntity.java create mode 100644 src/main/java/dev/zontreck/essentials/items/CreativeModeTabs.java create mode 100644 src/main/java/dev/zontreck/essentials/items/EventHandlers.java create mode 100644 src/main/java/dev/zontreck/essentials/items/ModItems.java create mode 100644 src/main/java/dev/zontreck/essentials/items/abstraction/AbstractBottle.java create mode 100644 src/main/java/dev/zontreck/essentials/items/implementation/TimeBottle.java create mode 100644 src/main/java/dev/zontreck/essentials/util/SoundUtilities.java create mode 100644 src/main/java/dev/zontreck/essentials/util/StylesUtil.java create mode 100644 src/main/resources/assets/ariasessentials/models/item/eiab.json create mode 100644 src/main/resources/assets/ariasessentials/models/item/tiab.json create mode 100644 src/main/resources/assets/ariasessentials/textures/item/eiab.png create mode 100644 src/main/resources/assets/ariasessentials/textures/item/eiab.png.mcmeta create mode 100644 src/main/resources/assets/ariasessentials/textures/item/tiab.aseprite create mode 100644 src/main/resources/assets/ariasessentials/textures/item/tiab.png create mode 100644 src/main/resources/assets/ariasessentials/textures/item/tiab.png.mcmeta diff --git a/src/main/java/dev/zontreck/essentials/AriasEssentials.java b/src/main/java/dev/zontreck/essentials/AriasEssentials.java index 93825ec..16166a6 100644 --- a/src/main/java/dev/zontreck/essentials/AriasEssentials.java +++ b/src/main/java/dev/zontreck/essentials/AriasEssentials.java @@ -8,11 +8,15 @@ import java.util.UUID; import dev.zontreck.ariaslib.util.DelayedExecutorService; import dev.zontreck.essentials.client.Keybindings; +import dev.zontreck.essentials.client.renderer.TimeBoostEntityRenderer; import dev.zontreck.essentials.commands.teleport.TeleportActioner; import dev.zontreck.essentials.configs.client.AEClientConfig; import dev.zontreck.essentials.configs.server.AEServerConfig; +import dev.zontreck.essentials.entities.ModEntities; import dev.zontreck.essentials.events.TeleportEvent; -import dev.zontreck.essentials.gui.HeartsRenderer; +import dev.zontreck.essentials.client.renderer.HeartsRenderer; +import dev.zontreck.essentials.items.CreativeModeTabs; +import dev.zontreck.essentials.items.ModItems; import dev.zontreck.essentials.networking.ModMessages; import dev.zontreck.essentials.rtp.RTPCaches; import dev.zontreck.essentials.rtp.RTPCachesEventHandlers; @@ -21,6 +25,7 @@ import dev.zontreck.essentials.util.CommandCooldowns; import dev.zontreck.libzontreck.util.ChatHelpers; import dev.zontreck.libzontreck.util.ServerUtilities; import dev.zontreck.libzontreck.vectors.WorldPosition; +import net.minecraft.client.renderer.entity.EntityRenderers; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.player.Player; import net.minecraftforge.api.distmarker.Dist; @@ -76,6 +81,10 @@ public class AriasEssentials { MinecraftForge.EVENT_BUS.register(new RTPCachesEventHandlers()); MinecraftForge.EVENT_BUS.register(new CommandCooldowns()); MinecraftForge.EVENT_BUS.register(RTPCachesEventHandlers.class); + + ModItems.register(bus); + ModEntities.register(bus); + CreativeModeTabs.register(bus); } @SubscribeEvent @@ -142,6 +151,7 @@ public class AriasEssentials { LOGGER.info("Client setup"); + EntityRenderers.register(ModEntities.TIAB_ENTITY.get(), TimeBoostEntityRenderer::new); MinecraftForge.EVENT_BUS.register(new HeartsRenderer()); } diff --git a/src/main/java/dev/zontreck/essentials/gui/HeartsRenderer.java b/src/main/java/dev/zontreck/essentials/client/renderer/HeartsRenderer.java similarity index 99% rename from src/main/java/dev/zontreck/essentials/gui/HeartsRenderer.java rename to src/main/java/dev/zontreck/essentials/client/renderer/HeartsRenderer.java index d8df687..5eb2b37 100644 --- a/src/main/java/dev/zontreck/essentials/gui/HeartsRenderer.java +++ b/src/main/java/dev/zontreck/essentials/client/renderer/HeartsRenderer.java @@ -7,7 +7,7 @@ * */ -package dev.zontreck.essentials.gui; +package dev.zontreck.essentials.client.renderer; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; diff --git a/src/main/java/dev/zontreck/essentials/client/renderer/TimeBoostEntityRenderer.java b/src/main/java/dev/zontreck/essentials/client/renderer/TimeBoostEntityRenderer.java new file mode 100644 index 0000000..1ed3bf2 --- /dev/null +++ b/src/main/java/dev/zontreck/essentials/client/renderer/TimeBoostEntityRenderer.java @@ -0,0 +1,60 @@ +package dev.zontreck.essentials.client.renderer; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.math.Axis; +import dev.zontreck.essentials.entities.TimeBoostEntity; +import net.minecraft.ChatFormatting; +import net.minecraft.client.gui.Font; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.entity.EntityRenderer; +import net.minecraft.client.renderer.entity.EntityRendererProvider; +import net.minecraft.resources.ResourceLocation; +import org.joml.Quaternionf; +import org.joml.Vector3f; + +public class TimeBoostEntityRenderer extends EntityRenderer +{ + + public TimeBoostEntityRenderer(EntityRendererProvider.Context erp) { + super(erp); + } + + + + @Override + public void render(TimeBoostEntity entity, float entityYaw, float partialTicks, PoseStack matrixStack, MultiBufferSource bufferIn, int packedLightIn) { + String timeRate = "x" + 2 * entity.getTimeRate(); + float paddingLeftRight = 2 * entity.getTimeRate() < 10 ? 0.11F : 0.19F; + drawText(matrixStack, bufferIn, timeRate, new Vector3f(-paddingLeftRight, 0.064F, 0.51F), Axis.YP.rotationDegrees(0), ChatFormatting.WHITE.getColor()); // Front + drawText(matrixStack, bufferIn, timeRate, new Vector3f(paddingLeftRight, 0.064F, -0.51F), Axis.YP.rotationDegrees(180F), ChatFormatting.WHITE.getColor()); // Back + drawText(matrixStack, bufferIn, timeRate, new Vector3f(0.51F, 0.064F, paddingLeftRight), Axis.YP.rotationDegrees(90F), ChatFormatting.WHITE.getColor()); // Right + drawText(matrixStack, bufferIn, timeRate, new Vector3f(-0.51F, 0.064F, -paddingLeftRight), Axis.YP.rotationDegrees(-90F), ChatFormatting.WHITE.getColor()); // Left + drawText(matrixStack, bufferIn, timeRate, new Vector3f(-paddingLeftRight, 0.51F, -0.064F), Axis.XP.rotationDegrees(90F), ChatFormatting.WHITE.getColor()); // Top + drawText(matrixStack, bufferIn, timeRate, new Vector3f(-paddingLeftRight, -0.51F, 0.064F), Axis.XP.rotationDegrees(-90F), ChatFormatting.WHITE.getColor()); // Bottom + } + + @Override + public ResourceLocation getTextureLocation(TimeBoostEntity entity) { + return null; + } + + private void drawText(PoseStack matrixStack, MultiBufferSource source, String text, Vector3f translateVector, Quaternionf rotate, int color) { + matrixStack.pushPose(); + matrixStack.translate(translateVector.x(), translateVector.y(), translateVector.z()); + matrixStack.scale(0.02F, -0.02F, 0.02F); + matrixStack.mulPose(rotate); + getFont().drawInBatch( + text, + 0, + 0, + -1, + false, + matrixStack.last().pose(), + source, + Font.DisplayMode.NORMAL, + 0, + color + ); + matrixStack.popPose(); + } +} diff --git a/src/main/java/dev/zontreck/essentials/configs/NBTKeys.java b/src/main/java/dev/zontreck/essentials/configs/NBTKeys.java new file mode 100644 index 0000000..6bfc121 --- /dev/null +++ b/src/main/java/dev/zontreck/essentials/configs/NBTKeys.java @@ -0,0 +1,13 @@ +package dev.zontreck.essentials.configs; + + +public class NBTKeys { + // for time in a bottle item + public static final String STORED_TIME = "storedTime"; + public static final String TOTAL_ACCUMULATED_TIME = "totalAccumulatedTime"; + + // for time accelerator entity + public static final String ENTITY_TIME_RATE = "timeRate"; + public static final String ENTITY_REMAINING_TIME = "remainingTime"; + public static final String ENTITY_POS = "position"; +} diff --git a/src/main/java/dev/zontreck/essentials/configs/server/AEServerConfig.java b/src/main/java/dev/zontreck/essentials/configs/server/AEServerConfig.java index 35d0879..686bbb9 100644 --- a/src/main/java/dev/zontreck/essentials/configs/server/AEServerConfig.java +++ b/src/main/java/dev/zontreck/essentials/configs/server/AEServerConfig.java @@ -4,6 +4,7 @@ import dev.zontreck.ariaslib.util.Lists; import dev.zontreck.essentials.configs.server.sections.*; import dev.zontreck.essentials.util.EssentialsDatastore; import dev.zontreck.essentials.util.Maps; +import dev.zontreck.libzontreck.chat.ChatColor; import dev.zontreck.libzontreck.util.SNbtIo; import net.minecraft.nbt.*; @@ -20,6 +21,7 @@ public class AEServerConfig public Back back; public Teleportation teleport; public Messages messages; + public Bottles bottles; @@ -38,6 +40,10 @@ public class AEServerConfig config.back = Back.deserialize(tag.getCompound(Back.TAG_NAME)); config.teleport = Teleportation.deserialize(tag.getCompound(Teleportation.TAG_NAME)); config.messages = Messages.deserialize(tag.getCompound(Messages.TAG_NAME)); + if(tag.contains(Bottles.TAG_NAME)) + { + config.bottles = Bottles.deserialize(tag.getCompound(Bottles.TAG_NAME)); + } else config.bottles = new Bottles(); return config; @@ -88,6 +94,7 @@ public class AEServerConfig "witherstormmod:bowels" ); messages = new Messages(); + bottles = new Bottles(); @@ -116,6 +123,7 @@ public class AEServerConfig tag.put(Back.TAG_NAME, back.serialize()); tag.put(Teleportation.TAG_NAME, teleport.serialize()); tag.put(Messages.TAG_NAME, messages.serialize()); + tag.put(Bottles.TAG_NAME, bottles.serialize()); diff --git a/src/main/java/dev/zontreck/essentials/configs/server/sections/Bottles.java b/src/main/java/dev/zontreck/essentials/configs/server/sections/Bottles.java new file mode 100644 index 0000000..9d96d17 --- /dev/null +++ b/src/main/java/dev/zontreck/essentials/configs/server/sections/Bottles.java @@ -0,0 +1,76 @@ +package dev.zontreck.essentials.configs.server.sections; + +import net.minecraft.nbt.CompoundTag; + +public class Bottles { + public static final String TAG_NAME = "bottles"; + public static final String TAG_DURATION = "durationEachUse"; + public static final String TAG_TICKS = "ticks"; + public static final String TAG_RANDOM_TICKS = "avgRandomTicks"; + public static final String TAG_MAX_TIME_RATE = "maxTimeRate"; + public static final String TAG_STORED_TIME = "maxTime"; + + public static final String TAG_MESSAGE_STORED_TIME = "msg_storedTime"; + public static final String TAG_MESSAGE_ACCUMULATED_TIME = "msg_accumulatedTime"; + + + + + public int eachUseDuration = 30; + public int ticks = 20; + public int avgRandomTicks = 512; + public int maxTimeRate = 8; + public int maxTime = (60 * 60 * 24 * 30); // 30 days is the default + public String storedTimeStr = "!Dark_Green!Stored Time: [0]:[1]:[2]"; + public String accumulatedTimeStr = "!Gray!Total Accumulated Time: [0]:[1]:[2]"; + + + + public CompoundTag serialize() + { + CompoundTag tag = new CompoundTag(); + tag.putInt(TAG_DURATION, eachUseDuration); + tag.putInt(TAG_TICKS, ticks); + tag.putInt(TAG_RANDOM_TICKS, avgRandomTicks); + tag.putInt(TAG_MAX_TIME_RATE, maxTimeRate); + tag.putString(TAG_MESSAGE_STORED_TIME, storedTimeStr); + tag.putString(TAG_MESSAGE_ACCUMULATED_TIME, accumulatedTimeStr); + tag.putInt(TAG_STORED_TIME, maxTime); + + + return tag; + } + + public static Bottles deserialize(CompoundTag tag) + { + Bottles bottles = new Bottles(); + if(tag.contains(TAG_DURATION)) + { + bottles.eachUseDuration = tag.getInt(TAG_DURATION); + } + + if(tag.contains(TAG_TICKS)) + bottles.ticks = tag.getInt(TAG_TICKS); + + if(tag.contains(TAG_RANDOM_TICKS)) + bottles.avgRandomTicks = tag.getInt(TAG_RANDOM_TICKS); + + if(tag.contains(TAG_MAX_TIME_RATE)) + bottles.maxTimeRate = tag.getInt(TAG_MAX_TIME_RATE); + + if(tag.contains(TAG_MESSAGE_STORED_TIME)) + bottles.storedTimeStr = tag.getString(TAG_MESSAGE_STORED_TIME); + + if(tag.contains(TAG_MESSAGE_ACCUMULATED_TIME)) + bottles.accumulatedTimeStr = tag.getString(TAG_MESSAGE_ACCUMULATED_TIME); + + if(tag.contains(TAG_STORED_TIME)) + bottles.maxTime = tag.getInt(TAG_STORED_TIME); + + + + + return bottles; + } + +} diff --git a/src/main/java/dev/zontreck/essentials/entities/ModEntities.java b/src/main/java/dev/zontreck/essentials/entities/ModEntities.java new file mode 100644 index 0000000..394500f --- /dev/null +++ b/src/main/java/dev/zontreck/essentials/entities/ModEntities.java @@ -0,0 +1,27 @@ +package dev.zontreck.essentials.entities; + +import dev.zontreck.essentials.AriasEssentials; +import net.minecraft.core.registries.Registries; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.MobCategory; +import net.minecraftforge.eventbus.api.IEventBus; +import net.minecraftforge.registries.DeferredRegister; +import net.minecraftforge.registries.ForgeRegistries; +import net.minecraftforge.registries.RegistryObject; + +public class ModEntities +{ + public static final DeferredRegister> REGISTER = DeferredRegister.create(ForgeRegistries.ENTITY_TYPES, AriasEssentials.MODID); + + public static RegistryObject> TIAB_ENTITY = REGISTER.register("tiab_entity_type", ()->EntityType.Builder.of(TimeBoostEntity::new, MobCategory.MISC) + .sized(0.1f, 0.1f) + .build(new ResourceLocation(AriasEssentials.MODID, "tiab_entity_type").toString()) + ); + + + public static void register(IEventBus bus) { + REGISTER.register(bus); + } +} diff --git a/src/main/java/dev/zontreck/essentials/entities/TimeBoostEntity.java b/src/main/java/dev/zontreck/essentials/entities/TimeBoostEntity.java new file mode 100644 index 0000000..bd26f43 --- /dev/null +++ b/src/main/java/dev/zontreck/essentials/entities/TimeBoostEntity.java @@ -0,0 +1,128 @@ +package dev.zontreck.essentials.entities; + +import dev.zontreck.essentials.configs.NBTKeys; +import dev.zontreck.essentials.configs.server.AEServerConfig; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtUtils; +import net.minecraft.network.protocol.Packet; +import net.minecraft.network.protocol.game.ClientGamePacketListener; +import net.minecraft.network.syncher.EntityDataAccessor; +import net.minecraft.network.syncher.EntityDataSerializers; +import net.minecraft.network.syncher.SynchedEntityData; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityTicker; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.network.NetworkHooks; + +public class TimeBoostEntity extends Entity +{ + private static final EntityDataAccessor timeRate = SynchedEntityData.defineId(TimeBoostEntity.class, EntityDataSerializers.INT); + + private int remainingTime; + private BlockPos position; + + + public TimeBoostEntity(EntityType entityType, Level worldIn) { + super(entityType, worldIn); + entityData.set(timeRate, 1); + } + + + public TimeBoostEntity(Level worldIn, BlockPos pos, double posX, double posY, double posZ) { + this(ModEntities.TIAB_ENTITY.get(), worldIn); + this.position = pos; + this.setPos(posX, posY, posZ); + } + + @Override + protected void defineSynchedData() { + entityData.define(timeRate, 1); + } + + + + @Override + protected void readAdditionalSaveData(CompoundTag compound) { + entityData.set(timeRate, compound.getInt(NBTKeys.ENTITY_TIME_RATE)); + setRemainingTime(compound.getInt(NBTKeys.ENTITY_REMAINING_TIME)); + this.position = NbtUtils.readBlockPos(compound.getCompound(NBTKeys.ENTITY_POS)); + } + + @Override + protected void addAdditionalSaveData(CompoundTag compound) { + compound.putInt(NBTKeys.ENTITY_TIME_RATE, getTimeRate()); + compound.putInt(NBTKeys.ENTITY_REMAINING_TIME, getRemainingTime()); + compound.put(NBTKeys.ENTITY_POS, NbtUtils.writeBlockPos(this.position)); + } + + @Override + public Packet getAddEntityPacket() { + return NetworkHooks.getEntitySpawningPacket(this); + } + + public int getTimeRate() { + return entityData.get(timeRate); + } + + public void setTimeRate(int rate) { + entityData.set(timeRate, rate); + } + + public int getRemainingTime() { + return this.remainingTime; + } + + public void setRemainingTime(int remainingTime) { + this.remainingTime = remainingTime; + } + + @Override + public void tick() { + super.tick(); + Level level = level(); + + if(position == null) + { + if(!level.isClientSide) + { + remove(RemovalReason.KILLED); + } + return; + } + + BlockState state = level.getBlockState(position); + ServerLevel serverWorld = level.getServer().getLevel(level.dimension()); + BlockEntity targetTE = level.getBlockEntity(position); + + + for (int i = 0; i < getTimeRate(); i++) { + if (targetTE != null) { + // if is TileEntity (furnace, brewing stand, ...) + BlockEntityTicker ticker = targetTE.getBlockState().getTicker(level, (BlockEntityType) targetTE.getType()); + if (ticker != null) { + ticker.tick(level, position, targetTE.getBlockState(), targetTE); + } + } else if (serverWorld != null && state.isRandomlyTicking()) { + // if is random ticket block (grass block, sugar cane, wheat or sapling, ...) + if (level.random.nextInt(AEServerConfig.getInstance().bottles.avgRandomTicks) == 0) { + state.randomTick(serverWorld, position, level.random); + } + } else { + // block entity broken + this.remove(RemovalReason.KILLED); + break; + } + } + + this.remainingTime -= 1; + if (this.remainingTime <= 0 && !level.isClientSide) { + this.remove(RemovalReason.KILLED); + } + } +} diff --git a/src/main/java/dev/zontreck/essentials/items/CreativeModeTabs.java b/src/main/java/dev/zontreck/essentials/items/CreativeModeTabs.java new file mode 100644 index 0000000..c276910 --- /dev/null +++ b/src/main/java/dev/zontreck/essentials/items/CreativeModeTabs.java @@ -0,0 +1,39 @@ +package dev.zontreck.essentials.items; + +import dev.zontreck.essentials.AriasEssentials; +import net.minecraft.core.registries.Registries; +import net.minecraft.network.chat.Component; +import net.minecraft.world.item.CreativeModeTab; +import net.minecraft.world.item.Item; +import net.minecraft.world.level.ItemLike; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.eventbus.api.IEventBus; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.registries.DeferredRegister; +import net.minecraftforge.registries.ForgeRegistries; +import net.minecraftforge.registries.RegistryObject; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Supplier; + +@Mod.EventBusSubscriber(modid = AriasEssentials.MODID, value = Dist.CLIENT) +public class CreativeModeTabs { + public static DeferredRegister REGISTER = DeferredRegister.create(Registries.CREATIVE_MODE_TAB, AriasEssentials.MODID); + + public static void register(IEventBus bus) { + REGISTER.register(bus); + } + public static final List> AE_TAB_ITEMS = new ArrayList<>(); + public static RegistryObject AE_GAME_TAB = REGISTER.register("ariasessentials", ()->CreativeModeTab.builder() + .icon(ModItems.TIME_IN_A_BOTTLE.get()::getDefaultInstance) + .title(Component.translatable("itemGroup.tabs.ariasessentials")) + .displayItems((display, output) -> AE_TAB_ITEMS.forEach(it->output.accept(it.get()))) + .build()); + + public static RegistryObject addToAETab(RegistryObject item) + { + AE_TAB_ITEMS.add(item); + return item; + } +} diff --git a/src/main/java/dev/zontreck/essentials/items/EventHandlers.java b/src/main/java/dev/zontreck/essentials/items/EventHandlers.java new file mode 100644 index 0000000..caa1f21 --- /dev/null +++ b/src/main/java/dev/zontreck/essentials/items/EventHandlers.java @@ -0,0 +1,11 @@ +package dev.zontreck.essentials.items; + +import dev.zontreck.essentials.AriasEssentials; +import net.minecraftforge.event.TickEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; + +@Mod.EventBusSubscriber(modid = AriasEssentials.MODID) +public class EventHandlers +{ +} diff --git a/src/main/java/dev/zontreck/essentials/items/ModItems.java b/src/main/java/dev/zontreck/essentials/items/ModItems.java new file mode 100644 index 0000000..f696837 --- /dev/null +++ b/src/main/java/dev/zontreck/essentials/items/ModItems.java @@ -0,0 +1,20 @@ +package dev.zontreck.essentials.items; + +import dev.zontreck.essentials.AriasEssentials; +import dev.zontreck.essentials.items.implementation.TimeBottle; +import net.minecraft.world.item.Item; +import net.minecraftforge.eventbus.api.IEventBus; +import net.minecraftforge.registries.DeferredRegister; +import net.minecraftforge.registries.ForgeRegistries; +import net.minecraftforge.registries.RegistryObject; + +public class ModItems +{ + public static DeferredRegister REGISTRY = DeferredRegister.create(ForgeRegistries.ITEMS, AriasEssentials.MODID); + + public static void register(IEventBus bus) { + REGISTRY.register(bus); + } + + public static RegistryObject TIME_IN_A_BOTTLE = CreativeModeTabs.addToAETab(REGISTRY.register("tiab", ()->new TimeBottle())); +} diff --git a/src/main/java/dev/zontreck/essentials/items/abstraction/AbstractBottle.java b/src/main/java/dev/zontreck/essentials/items/abstraction/AbstractBottle.java new file mode 100644 index 0000000..5518522 --- /dev/null +++ b/src/main/java/dev/zontreck/essentials/items/abstraction/AbstractBottle.java @@ -0,0 +1,148 @@ +package dev.zontreck.essentials.items.abstraction; + +import dev.zontreck.essentials.configs.server.AEServerConfig; +import dev.zontreck.essentials.entities.TimeBoostEntity; +import dev.zontreck.essentials.util.SoundUtilities; +import net.minecraft.core.BlockPos; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.context.UseOnContext; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.AABB; + +import java.util.Optional; + +public abstract class AbstractBottle extends Item { + private static final String[] NOTES = {"C", "D", "E", "F", "G2", "A2", "B2", "C2", "D2", "E2", "F2"}; + + public AbstractBottle() { + super(new Properties().stacksTo(1)); + } + + @Override + public InteractionResult useOn(UseOnContext context) { + Level level = context.getLevel(); + + if (level.isClientSide) { + return InteractionResult.PASS; + } + + BlockPos pos = context.getClickedPos(); + BlockState blockState = level.getBlockState(pos); + BlockEntity targetTE = level.getBlockEntity(pos); + ItemStack stack = context.getItemInHand(); + Player player = context.getPlayer(); + + if (targetTE == null && !blockState.isRandomlyTicking()) { + return InteractionResult.FAIL; + } + + int nextRate = 1; + int energyRequired = getEnergyCost(nextRate); + boolean isCreativeMode = player != null && player.isCreative(); + + Optional o = level.getEntitiesOfClass(TimeBoostEntity.class, new AABB(pos)).stream().findFirst(); + + if (o.isPresent()) { + TimeBoostEntity entityTA = o.get(); + int currentRate = entityTA.getTimeRate(); + int usedUpTime = getEachUseDuration() - entityTA.getRemainingTime(); + + if (currentRate >= Math.pow(2, AEServerConfig.getInstance().bottles.maxTimeRate - 1)) { + return InteractionResult.SUCCESS; + } + + nextRate = currentRate * 2; + int timeAdded = usedUpTime / 2; + energyRequired = getEnergyCost(nextRate); + + if (!canUse(stack, isCreativeMode, energyRequired)) { + return InteractionResult.SUCCESS; + } + + entityTA.setTimeRate(nextRate); + entityTA.setRemainingTime(entityTA.getRemainingTime() + timeAdded); + } else { + // First use + if (!canUse(stack, isCreativeMode, energyRequired)) { + return InteractionResult.SUCCESS; + } + + TimeBoostEntity entityTA = new TimeBoostEntity(level, pos, pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5); + entityTA.setRemainingTime(getEachUseDuration()); + level.addFreshEntity(entityTA); + } + + if (!isCreativeMode) { + this.applyDamage(stack, energyRequired); + } + playSound(level, pos, nextRate); + + return InteractionResult.SUCCESS; + } + + protected int getEachUseDuration() { + return AEServerConfig.getInstance().bottles.ticks * AEServerConfig.getInstance().bottles.eachUseDuration; + } + + public int getEnergyCost(int timeRate) { + if (timeRate <= 1) return getEachUseDuration(); + return timeRate / 2 * getEachUseDuration(); + } + + public boolean canUse(ItemStack stack, boolean isCreativeMode, int energyRequired) { + return getStoredEnergy(stack) >= energyRequired || isCreativeMode; + } + + protected abstract int getStoredEnergy(ItemStack stack); + + protected abstract void setStoredEnergy(ItemStack stack, int energy); + + protected abstract void applyDamage(ItemStack stack, int damage); + + public void playSound(Level level, BlockPos pos, int nextRate) { + switch (nextRate) { + case 1: + SoundUtilities.playNoteBlockHarpSound(level, pos, NOTES[0]); + break; + case 2: + SoundUtilities.playNoteBlockHarpSound(level, pos, NOTES[1]); + break; + case 4: + SoundUtilities.playNoteBlockHarpSound(level, pos, NOTES[2]); + break; + case 8: + SoundUtilities.playNoteBlockHarpSound(level, pos, NOTES[3]); + break; + case 16: + SoundUtilities.playNoteBlockHarpSound(level, pos, NOTES[4]); + break; + case 32: + SoundUtilities.playNoteBlockHarpSound(level, pos, NOTES[5]); + break; + case 64: + SoundUtilities.playNoteBlockHarpSound(level, pos, NOTES[6]); + break; + case 128: + SoundUtilities.playNoteBlockHarpSound(level, pos, NOTES[7]); + break; + case 256: + SoundUtilities.playNoteBlockHarpSound(level, pos, NOTES[8]); + break; + case 512: + SoundUtilities.playNoteBlockHarpSound(level, pos, NOTES[9]); + break; + default: + SoundUtilities.playNoteBlockHarpSound(level, pos, NOTES[10]); + } + } + + @Override + public boolean shouldCauseReequipAnimation(ItemStack oldStack, ItemStack newStack, boolean slotChanged) { + return !ItemStack.isSameItem(oldStack, newStack); + } +} \ No newline at end of file diff --git a/src/main/java/dev/zontreck/essentials/items/implementation/TimeBottle.java b/src/main/java/dev/zontreck/essentials/items/implementation/TimeBottle.java new file mode 100644 index 0000000..7cadd35 --- /dev/null +++ b/src/main/java/dev/zontreck/essentials/items/implementation/TimeBottle.java @@ -0,0 +1,106 @@ +package dev.zontreck.essentials.items.implementation; + +import dev.zontreck.essentials.configs.NBTKeys; +import dev.zontreck.essentials.configs.server.AEServerConfig; +import dev.zontreck.essentials.items.abstraction.AbstractBottle; +import dev.zontreck.essentials.util.StylesUtil; +import dev.zontreck.libzontreck.util.ChatHelpers; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.level.Level; + +import java.util.List; + +public class TimeBottle extends AbstractBottle +{ + + public TimeBottle() { + super(); + } + @Override + public boolean isFoil(ItemStack stack) { + sanityCheck(stack); + + return stack.getTag().contains(NBTKeys.STORED_TIME); + } + + private void sanityCheck(ItemStack stack) { + + if(!stack.hasTag() || stack.getTag()==null) + { + stack.setTag(new CompoundTag()); + } + } + + @Override + public void appendHoverText(ItemStack itemStack, Level world, List tooltip, TooltipFlag flag) { + super.appendHoverText(itemStack, world, tooltip, flag); + + int storedTime = this.getStoredEnergy(itemStack); + int storedSeconds = storedTime / AEServerConfig.getInstance().bottles.ticks; + int hours = storedSeconds / 3600; + int minutes = (storedSeconds % 3600) / 60; + int seconds = storedSeconds % 60; + + int totalAccumulatedTime = this.getTotalAccumulatedTime(itemStack); + int totalAccumulatedTimeSeconds = totalAccumulatedTime / AEServerConfig.getInstance().bottles.ticks; + int totalAccumulatedHours = totalAccumulatedTimeSeconds / 3600; + int totalAccumulatedMinutes = (totalAccumulatedTimeSeconds % 3600) / 60; + int totalAccumulatedSeconds = totalAccumulatedTimeSeconds % 60; + + tooltip.add(ChatHelpers.macro(AEServerConfig.getInstance().bottles.storedTimeStr, "" + hours, "" + minutes, "" + seconds)); + + tooltip.add(ChatHelpers.macro(AEServerConfig.getInstance().bottles.accumulatedTimeStr, "" + totalAccumulatedHours, "" + totalAccumulatedMinutes, "" + totalAccumulatedSeconds)); + } + + @Override + public int getStoredEnergy(ItemStack stack) { + return stack.getOrCreateTag().getInt(NBTKeys.STORED_TIME); + } + + @Override + public void setStoredEnergy(ItemStack stack, int energy) { + int newStoredTime = Math.min(energy, AEServerConfig.getInstance().bottles.maxTime); + stack.getOrCreateTag().putInt(NBTKeys.STORED_TIME, newStoredTime); + } + + @Override + public void applyDamage(ItemStack stack, int damage) { + setStoredEnergy(stack, getStoredEnergy(stack) - damage); + } + + public int getTotalAccumulatedTime(ItemStack stack) { + return stack.getOrCreateTag().getInt(NBTKeys.TOTAL_ACCUMULATED_TIME); + } + + public void setTotalAccumulatedTime(ItemStack stack, int value) { + int newValue = Math.min(value, AEServerConfig.getInstance().bottles.maxTime); + stack.getOrCreateTag().putInt(NBTKeys.TOTAL_ACCUMULATED_TIME, newValue); + } + + + @Override + public void inventoryTick(ItemStack itemStack, Level level, Entity entity, int itemSlot, boolean isSelected) { + super.inventoryTick(itemStack, level, entity, itemSlot, isSelected); + if (level.isClientSide) { + return; + } + + if (level.getGameTime() % AEServerConfig.getInstance().bottles.ticks == 0) { + int storedTime = this.getStoredEnergy(itemStack); + if (storedTime < AEServerConfig.getInstance().bottles.maxTime) { + this.setStoredEnergy(itemStack, storedTime + AEServerConfig.getInstance().bottles.ticks); + } + + int totalAccumulatedTime = this.getTotalAccumulatedTime(itemStack); + if (totalAccumulatedTime < AEServerConfig.getInstance().bottles.maxTime) { + this.setTotalAccumulatedTime(itemStack, totalAccumulatedTime + AEServerConfig.getInstance().bottles.ticks); + } + } + } +} diff --git a/src/main/java/dev/zontreck/essentials/util/SoundUtilities.java b/src/main/java/dev/zontreck/essentials/util/SoundUtilities.java new file mode 100644 index 0000000..7a6ab82 --- /dev/null +++ b/src/main/java/dev/zontreck/essentials/util/SoundUtilities.java @@ -0,0 +1,47 @@ +package dev.zontreck.essentials.util; + + +import net.minecraft.core.BlockPos; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.world.level.Level; + +/** + * {@link SoundUtilities#playNoteBlockHarpSound(Level, BlockPos, String)} was taken/derrived from Time-in-a-bottle github. + */ +public class SoundUtilities { + public static void playNoteBlockHarpSound(Level level, BlockPos pos, String note) { + // https://minecraft.gamepedia.com/Note_Block + switch (note) { + // Octave 1 + case "F#" -> level.playSound(null, pos, SoundEvents.NOTE_BLOCK_HARP.get(), SoundSource.BLOCKS, 0.5F, 0.5F); + case "G" -> level.playSound(null, pos, SoundEvents.NOTE_BLOCK_HARP.get(), SoundSource.BLOCKS, 0.5F, 0.529732F); + case "G#" -> level.playSound(null, pos, SoundEvents.NOTE_BLOCK_HARP.get(), SoundSource.BLOCKS, 0.5F, 0.561231F); + case "A" -> level.playSound(null, pos, SoundEvents.NOTE_BLOCK_HARP.get(), SoundSource.BLOCKS, 0.5F, 0.594604F); + case "A#" -> level.playSound(null, pos, SoundEvents.NOTE_BLOCK_HARP.get(), SoundSource.BLOCKS, 0.5F, 0.629961F); + case "B" -> level.playSound(null, pos, SoundEvents.NOTE_BLOCK_HARP.get(), SoundSource.BLOCKS, 0.5F, 0.667420F); + case "C" -> level.playSound(null, pos, SoundEvents.NOTE_BLOCK_HARP.get(), SoundSource.BLOCKS, 0.5F, 0.707107F); + case "C#" -> level.playSound(null, pos, SoundEvents.NOTE_BLOCK_HARP.get(), SoundSource.BLOCKS, 0.5F, 0.749154F); + case "D" -> level.playSound(null, pos, SoundEvents.NOTE_BLOCK_HARP.get(), SoundSource.BLOCKS, 0.5F, 0.793701F); + case "D#" -> level.playSound(null, pos, SoundEvents.NOTE_BLOCK_HARP.get(), SoundSource.BLOCKS, 0.5F, 0.840896F); + case "E" -> level.playSound(null, pos, SoundEvents.NOTE_BLOCK_HARP.get(), SoundSource.BLOCKS, 0.5F, 0.890899F); + case "F" -> level.playSound(null, pos, SoundEvents.NOTE_BLOCK_HARP.get(), SoundSource.BLOCKS, 0.5F, 0.943874F); + + + // Octave 2 + case "F#2" -> level.playSound(null, pos, SoundEvents.NOTE_BLOCK_HARP.get(), SoundSource.BLOCKS, 0.5F, 1F); + case "G2" -> level.playSound(null, pos, SoundEvents.NOTE_BLOCK_HARP.get(), SoundSource.BLOCKS, 0.5F, 1.059463F); + case "G#2" -> level.playSound(null, pos, SoundEvents.NOTE_BLOCK_HARP.get(), SoundSource.BLOCKS, 0.5F, 1.122462F); + case "A2" -> level.playSound(null, pos, SoundEvents.NOTE_BLOCK_HARP.get(), SoundSource.BLOCKS, 0.5F, 1.189207F); + case "A#2" -> level.playSound(null, pos, SoundEvents.NOTE_BLOCK_HARP.get(), SoundSource.BLOCKS, 0.5F, 1.259921F); + case "B2" -> level.playSound(null, pos, SoundEvents.NOTE_BLOCK_HARP.get(), SoundSource.BLOCKS, 0.5F, 1.334840F); + case "C2" -> level.playSound(null, pos, SoundEvents.NOTE_BLOCK_HARP.get(), SoundSource.BLOCKS, 0.5F, 1.414214F); + case "C#2" -> level.playSound(null, pos, SoundEvents.NOTE_BLOCK_HARP.get(), SoundSource.BLOCKS, 0.5F, 1.498307F); + case "D2" -> level.playSound(null, pos, SoundEvents.NOTE_BLOCK_HARP.get(), SoundSource.BLOCKS, 0.5F, 1.587401F); + case "D#2" -> level.playSound(null, pos, SoundEvents.NOTE_BLOCK_HARP.get(), SoundSource.BLOCKS, 0.5F, 1.681793F); + case "E2" -> level.playSound(null, pos, SoundEvents.NOTE_BLOCK_HARP.get(), SoundSource.BLOCKS, 0.5F, 1.781797F); + case "F2" -> level.playSound(null, pos, SoundEvents.NOTE_BLOCK_HARP.get(), SoundSource.BLOCKS, 0.5F, 1.887749F); + case "F#3" -> level.playSound(null, pos, SoundEvents.NOTE_BLOCK_HARP.get(), SoundSource.BLOCKS, 0.5F, 2F); + } + } +} diff --git a/src/main/java/dev/zontreck/essentials/util/StylesUtil.java b/src/main/java/dev/zontreck/essentials/util/StylesUtil.java new file mode 100644 index 0000000..df7c51b --- /dev/null +++ b/src/main/java/dev/zontreck/essentials/util/StylesUtil.java @@ -0,0 +1,10 @@ +package dev.zontreck.essentials.util; + +import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.Style; + +public class StylesUtil { + + public static final Style GREEN = Style.EMPTY.applyFormat(ChatFormatting.GREEN); + public static final Style GRAY = Style.EMPTY.applyFormat(ChatFormatting.GRAY); +} diff --git a/src/main/resources/assets/ariasessentials/lang/en_us.json b/src/main/resources/assets/ariasessentials/lang/en_us.json index 03ee39f..557f20d 100644 --- a/src/main/resources/assets/ariasessentials/lang/en_us.json +++ b/src/main/resources/assets/ariasessentials/lang/en_us.json @@ -1,4 +1,9 @@ { + "itemGroup.tabs.ariasessentials": "Aria's Essentials", + + "item.ariasessentials.tiab": "Time in a Bottle", + "item.ariasessentials.eiab": "Energy in a Bottle", + "key.category.ariasessentials": "Aria's Essentials", "key.ariasessentials.autowalk": "Auto Walk" } \ No newline at end of file diff --git a/src/main/resources/assets/ariasessentials/models/item/eiab.json b/src/main/resources/assets/ariasessentials/models/item/eiab.json new file mode 100644 index 0000000..47d2f64 --- /dev/null +++ b/src/main/resources/assets/ariasessentials/models/item/eiab.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ariasessentials:item/eiab" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ariasessentials/models/item/tiab.json b/src/main/resources/assets/ariasessentials/models/item/tiab.json new file mode 100644 index 0000000..4103a7a --- /dev/null +++ b/src/main/resources/assets/ariasessentials/models/item/tiab.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ariasessentials:item/tiab" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ariasessentials/textures/item/eiab.png b/src/main/resources/assets/ariasessentials/textures/item/eiab.png new file mode 100644 index 0000000000000000000000000000000000000000..128cf9cd514dbdd43227ab50b12ac0dafd01e728 GIT binary patch literal 2553 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ariasessentials/textures/item/eiab.png.mcmeta b/src/main/resources/assets/ariasessentials/textures/item/eiab.png.mcmeta new file mode 100644 index 0000000..5cc283a --- /dev/null +++ b/src/main/resources/assets/ariasessentials/textures/item/eiab.png.mcmeta @@ -0,0 +1,6 @@ +{ + "animation": { + "frametime": 2, + "interpolate": true + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ariasessentials/textures/item/tiab.aseprite b/src/main/resources/assets/ariasessentials/textures/item/tiab.aseprite new file mode 100644 index 0000000000000000000000000000000000000000..01d15013b662eea51b0c649a76be832a1346278c GIT binary patch literal 4305 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