Adds in the time bottle from time in a bottle. With plans to add an energy variant

This commit is contained in:
Zontreck 2024-02-15 02:33:41 -07:00
parent b954fead1c
commit de845ddffd
23 changed files with 734 additions and 2 deletions

View file

@ -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());
}

View file

@ -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;

View file

@ -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<TimeBoostEntity>
{
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();
}
}

View file

@ -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";
}

View file

@ -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());

View file

@ -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;
}
}

View file

@ -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<EntityType<?>> REGISTER = DeferredRegister.create(ForgeRegistries.ENTITY_TYPES, AriasEssentials.MODID);
public static RegistryObject<EntityType<TimeBoostEntity>> TIAB_ENTITY = REGISTER.register("tiab_entity_type", ()->EntityType.Builder.<TimeBoostEntity>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);
}
}

View file

@ -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<Integer> 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<ClientGamePacketListener> 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<BlockEntity> ticker = targetTE.getBlockState().getTicker(level, (BlockEntityType<BlockEntity>) 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);
}
}
}

View file

@ -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<CreativeModeTab> REGISTER = DeferredRegister.create(Registries.CREATIVE_MODE_TAB, AriasEssentials.MODID);
public static void register(IEventBus bus) {
REGISTER.register(bus);
}
public static final List<Supplier<? extends ItemLike>> AE_TAB_ITEMS = new ArrayList<>();
public static RegistryObject<CreativeModeTab> 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 <T extends Item> RegistryObject<T> addToAETab(RegistryObject<T> item)
{
AE_TAB_ITEMS.add(item);
return item;
}
}

View file

@ -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
{
}

View file

@ -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<Item> REGISTRY = DeferredRegister.create(ForgeRegistries.ITEMS, AriasEssentials.MODID);
public static void register(IEventBus bus) {
REGISTRY.register(bus);
}
public static RegistryObject<Item> TIME_IN_A_BOTTLE = CreativeModeTabs.addToAETab(REGISTRY.register("tiab", ()->new TimeBottle()));
}

View file

@ -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<TimeBoostEntity> 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);
}
}

View file

@ -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<Component> 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);
}
}
}
}

View file

@ -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);
}
}
}

View file

@ -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);
}

View file

@ -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"
}

View file

@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": {
"layer0": "ariasessentials:item/eiab"
}
}

View file

@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": {
"layer0": "ariasessentials:item/tiab"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

View file

@ -0,0 +1,6 @@
{
"animation": {
"frametime": 2,
"interpolate": true
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

View file

@ -0,0 +1,6 @@
{
"animation": {
"frametime": 2,
"interpolate": true
}
}