mirror of
https://github.com/Ellpeck/ActuallyAdditions.git
synced 2024-11-26 00:38:35 +01:00
Added power requirements to Teleport Staff, Added Crystal Flux Cap, more
This commit is contained in:
parent
8b525252a5
commit
0a036ee1ef
10 changed files with 249 additions and 39 deletions
|
@ -116,7 +116,7 @@ e2c81adfe240117fa0ce2e3dfcfd04f4e1034153 assets/actuallyadditions/blockstates/wh
|
||||||
3670535838b4c26d01afe7ee4807c53a6cbaba12 assets/actuallyadditions/blockstates/white_wall_block.json
|
3670535838b4c26d01afe7ee4807c53a6cbaba12 assets/actuallyadditions/blockstates/white_wall_block.json
|
||||||
78e89628e3c6e891f2994b2a1794672f69826516 assets/actuallyadditions/blockstates/wood_casing_block.json
|
78e89628e3c6e891f2994b2a1794672f69826516 assets/actuallyadditions/blockstates/wood_casing_block.json
|
||||||
207adf3d139369e983100a6002f6f77d36d40916 assets/actuallyadditions/blockstates/xp_solidifier_block.json
|
207adf3d139369e983100a6002f6f77d36d40916 assets/actuallyadditions/blockstates/xp_solidifier_block.json
|
||||||
55b66cc71e99edafb64079276e79d9a4806ce168 assets/actuallyadditions/lang/en_us.json
|
232fcdd6be180accae0f5e5abd68700e70c514c7 assets/actuallyadditions/lang/en_us.json
|
||||||
8ce3f2af3288773fb581a3668c2cb90b64c9ee2f assets/actuallyadditions/models/block/advanced_item_laser_relay_block.json
|
8ce3f2af3288773fb581a3668c2cb90b64c9ee2f assets/actuallyadditions/models/block/advanced_item_laser_relay_block.json
|
||||||
de74eda6290d47ef2b26961693e537d7b8795a06 assets/actuallyadditions/models/block/atomic_reconstructor_block.json
|
de74eda6290d47ef2b26961693e537d7b8795a06 assets/actuallyadditions/models/block/atomic_reconstructor_block.json
|
||||||
16a76926a07fc8fa10e4a3949d15ad2ca6920bb8 assets/actuallyadditions/models/block/battery_box_block.json
|
16a76926a07fc8fa10e4a3949d15ad2ca6920bb8 assets/actuallyadditions/models/block/battery_box_block.json
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{
|
{
|
||||||
|
"actuallyadditions.storage.crystal-flux": "%s/%s Crystal Flux",
|
||||||
"actuallyadditions.tooltip.booklet.manual.one": "Or \"Booklet\", if you will",
|
"actuallyadditions.tooltip.booklet.manual.one": "Or \"Booklet\", if you will",
|
||||||
"actuallyadditions.tooltip.booklet.manual.three": "Use while holding to open.",
|
"actuallyadditions.tooltip.booklet.manual.three": "Use while holding to open.",
|
||||||
"actuallyadditions.tooltip.booklet.manual.two": "This book guides you through all of the feature Actually Additions has to over.",
|
"actuallyadditions.tooltip.booklet.manual.two": "This book guides you through all of the feature Actually Additions has to over.",
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
package de.ellpeck.actuallyadditions.common.capability;
|
||||||
|
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.util.Direction;
|
||||||
|
import net.minecraftforge.common.capabilities.Capability;
|
||||||
|
import net.minecraftforge.common.capabilities.ICapabilityProvider;
|
||||||
|
import net.minecraftforge.common.util.LazyOptional;
|
||||||
|
import net.minecraftforge.energy.CapabilityEnergy;
|
||||||
|
import net.minecraftforge.energy.IEnergyStorage;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
public class CrystalFluxProvider implements ICapabilityProvider {
|
||||||
|
private ItemStack stack;
|
||||||
|
private int energy;
|
||||||
|
private LazyOptional<IEnergyStorage> capability = LazyOptional.of(() -> new CrystalFluxStorage(stack, energy));
|
||||||
|
|
||||||
|
public CrystalFluxProvider(ItemStack stack, int energy) {
|
||||||
|
this.stack = stack;
|
||||||
|
this.energy = energy;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable Direction side) {
|
||||||
|
return cap == CapabilityEnergy.ENERGY ? capability.cast() : LazyOptional.empty();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
package de.ellpeck.actuallyadditions.common.capability;
|
||||||
|
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraftforge.energy.EnergyStorage;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main Capability for Item Energry storage otherwise referenced as Crystal Flux
|
||||||
|
*/
|
||||||
|
public class CrystalFluxStorage extends EnergyStorage {
|
||||||
|
public static final String NBT_TAG = "crystal-flux";
|
||||||
|
private final ItemStack stack;
|
||||||
|
|
||||||
|
public CrystalFluxStorage(ItemStack stack, int capacity) {
|
||||||
|
super(capacity, Integer.MAX_VALUE, Integer.MAX_VALUE);
|
||||||
|
|
||||||
|
this.stack = stack;
|
||||||
|
|
||||||
|
// hasTag doesn't let the IDE know that the getTag is now safe to use. Instead we're wrapping
|
||||||
|
// it up in a requireNonNull to stop IDE bitching
|
||||||
|
this.energy = stack.hasTag() && Objects.requireNonNull(stack.getTag()).contains(NBT_TAG)
|
||||||
|
? stack.getTag().getInt(NBT_TAG)
|
||||||
|
: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int extractEnergy(int maxExtract, boolean simulate) {
|
||||||
|
int extracted = super.extractEnergy(maxExtract, simulate);
|
||||||
|
|
||||||
|
if (extracted > 0 && !simulate) {
|
||||||
|
stack.getOrCreateTag().putInt(NBT_TAG, getEnergyStored());
|
||||||
|
}
|
||||||
|
|
||||||
|
return extracted;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int receiveEnergy(int maxReceive, boolean simulate) {
|
||||||
|
int received = super.receiveEnergy(maxReceive, simulate);
|
||||||
|
|
||||||
|
if (received > 0 && !simulate) {
|
||||||
|
stack.getOrCreateTag().putInt(NBT_TAG, getEnergyStored());
|
||||||
|
}
|
||||||
|
|
||||||
|
return received;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,114 @@
|
||||||
|
package de.ellpeck.actuallyadditions.common.items;
|
||||||
|
|
||||||
|
import de.ellpeck.actuallyadditions.common.capability.CrystalFluxProvider;
|
||||||
|
import de.ellpeck.actuallyadditions.common.capability.CrystalFluxStorage;
|
||||||
|
import de.ellpeck.actuallyadditions.common.utilities.Help;
|
||||||
|
import de.ellpeck.actuallyadditions.common.utilities.VisualHelper;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
|
import net.minecraft.client.util.ITooltipFlag;
|
||||||
|
import net.minecraft.client.world.ClientWorld;
|
||||||
|
import net.minecraft.item.ItemGroup;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.nbt.CompoundNBT;
|
||||||
|
import net.minecraft.util.NonNullList;
|
||||||
|
import net.minecraft.util.math.MathHelper;
|
||||||
|
import net.minecraft.util.text.ITextComponent;
|
||||||
|
import net.minecraft.util.text.TextFormatting;
|
||||||
|
import net.minecraft.util.text.TranslationTextComponent;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
import net.minecraftforge.common.capabilities.ICapabilityProvider;
|
||||||
|
import net.minecraftforge.energy.CapabilityEnergy;
|
||||||
|
import net.minecraftforge.energy.IEnergyStorage;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import java.text.NumberFormat;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
public abstract class CrystalFluxItem extends ActuallyItem {
|
||||||
|
// Handles modifying an int to a string of either alt ? 100,000 : 100K
|
||||||
|
private static final BiFunction<Integer, Boolean, String> PRETTY = (value, alt) ->
|
||||||
|
alt ? NumberFormat.getIntegerInstance().format(value) : Help.compressedValue(value);
|
||||||
|
|
||||||
|
private final Supplier<Integer> maxFlux;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We use a supplier here to allow for config values to be passed around so we are able to
|
||||||
|
* call the config values get method so we're always getting the most up-to-date value.
|
||||||
|
*
|
||||||
|
* @param maxFlux max energy this item can store
|
||||||
|
*/
|
||||||
|
public CrystalFluxItem(Properties properties, Supplier<Integer> maxFlux) {
|
||||||
|
super(properties);
|
||||||
|
|
||||||
|
this.maxFlux = maxFlux;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public ICapabilityProvider initCapabilities(ItemStack stack, @Nullable CompoundNBT nbt) {
|
||||||
|
return new CrystalFluxProvider(stack, maxFlux.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
@Override
|
||||||
|
public void addInformation(ItemStack stack, @Nullable World worldIn, List<ITextComponent> tooltip, ITooltipFlag flagIn) {
|
||||||
|
super.addInformation(stack, worldIn, tooltip, flagIn);
|
||||||
|
|
||||||
|
stack.getCapability(CapabilityEnergy.ENERGY).ifPresent(energy ->
|
||||||
|
tooltip.add(this.getEnergyPretty(energy, Screen.hasShiftDown()).mergeStyle(TextFormatting.GRAY)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fillItemGroup(ItemGroup group, NonNullList<ItemStack> items) {
|
||||||
|
super.fillItemGroup(group, items);
|
||||||
|
if (!isInGroup(group)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ItemStack chargedItem = new ItemStack(this);
|
||||||
|
chargedItem.getOrCreateTag().putInt(CrystalFluxStorage.NBT_TAG, this.maxFlux.get());
|
||||||
|
items.add(chargedItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a tidy string either as 100,000 or 100K for example.
|
||||||
|
*
|
||||||
|
* @param energy energy capability
|
||||||
|
* @return either a pretty value or a pretty compressed value
|
||||||
|
*/
|
||||||
|
private TranslationTextComponent getEnergyPretty(IEnergyStorage energy, boolean showCompressed) {
|
||||||
|
return Help.trans(
|
||||||
|
"storage.crystal-flux",
|
||||||
|
PRETTY.apply(energy.getEnergyStored(), showCompressed),
|
||||||
|
PRETTY.apply(energy.getMaxEnergyStored(), showCompressed)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean showDurabilityBar(ItemStack stack) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getRGBDurabilityForDisplay(ItemStack stack) {
|
||||||
|
ClientWorld clientWorld = Minecraft.getInstance().world;
|
||||||
|
if (clientWorld != null) {
|
||||||
|
float[] color = VisualHelper.getWheelColor(clientWorld.getGameTime() % 256);
|
||||||
|
return MathHelper.rgb(color[0] / 255F, color[1] / 255F, color[2] / 255F);
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.getRGBDurabilityForDisplay(stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getDurabilityForDisplay(ItemStack stack) {
|
||||||
|
return stack.getCapability(CapabilityEnergy.ENERGY)
|
||||||
|
.map(energy -> 1D - (energy.getEnergyStored() / (double) energy.getMaxEnergyStored()))
|
||||||
|
.orElse(0D);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
@ParametersAreNonnullByDefault
|
||||||
|
@MethodsReturnNonnullByDefault
|
||||||
|
package de.ellpeck.actuallyadditions.common.items;
|
||||||
|
|
||||||
|
import mcp.MethodsReturnNonnullByDefault;
|
||||||
|
import javax.annotation.ParametersAreNonnullByDefault;
|
|
@ -1,7 +1,6 @@
|
||||||
package de.ellpeck.actuallyadditions.common.items.useables;
|
package de.ellpeck.actuallyadditions.common.items.useables;
|
||||||
|
|
||||||
import de.ellpeck.actuallyadditions.common.items.ActuallyItem;
|
import de.ellpeck.actuallyadditions.common.items.CrystalFluxItem;
|
||||||
import de.ellpeck.actuallyadditions.common.items.IUseItem;
|
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.entity.player.ServerPlayerEntity;
|
import net.minecraft.entity.player.ServerPlayerEntity;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
|
@ -11,10 +10,13 @@ import net.minecraft.util.math.BlockRayTraceResult;
|
||||||
import net.minecraft.util.math.RayTraceResult;
|
import net.minecraft.util.math.RayTraceResult;
|
||||||
import net.minecraft.util.math.vector.Vector3f;
|
import net.minecraft.util.math.vector.Vector3f;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
import net.minecraftforge.energy.CapabilityEnergy;
|
||||||
|
|
||||||
|
public class TeleportStaffItem extends CrystalFluxItem {
|
||||||
|
private static final int BASE_COST_PER_USE = 200;
|
||||||
|
|
||||||
public class TeleportStaffItem extends ActuallyItem implements IUseItem {
|
|
||||||
public TeleportStaffItem() {
|
public TeleportStaffItem() {
|
||||||
super(baseProps());
|
super(baseProps(), () -> 250000);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -24,56 +26,35 @@ public class TeleportStaffItem extends ActuallyItem implements IUseItem {
|
||||||
return super.onItemRightClick(world, player, hand);
|
return super.onItemRightClick(world, player, hand);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
RayTraceResult traceResult = player.pick(100, 1.0f, false);
|
RayTraceResult traceResult = player.pick(100, 1.0f, false);
|
||||||
if (traceResult.getType() != RayTraceResult.Type.BLOCK || !this.canUse(stack)) {
|
if (traceResult.getType() != RayTraceResult.Type.BLOCK) {
|
||||||
return super.onItemRightClick(world, player, hand);
|
return super.onItemRightClick(world, player, hand);
|
||||||
}
|
}
|
||||||
|
|
||||||
BlockPos pos = ((BlockRayTraceResult) traceResult).getPos();
|
BlockRayTraceResult blockTrace = ((BlockRayTraceResult) traceResult);
|
||||||
BlockPos toPos = pos.offset(((BlockRayTraceResult) traceResult).getFace(), 1);
|
BlockPos toPos = blockTrace.getPos().offset(blockTrace.getFace(), 1);
|
||||||
|
|
||||||
Vector3f centerOfHit = new Vector3f(toPos.getX(), toPos.getY(), toPos.getZ());
|
Vector3f centerOfHit = new Vector3f(toPos.getX(), toPos.getY(), toPos.getZ());
|
||||||
centerOfHit.add(.5f, (((BlockRayTraceResult) traceResult).getFace().getAxis() == Direction.Axis.Y ? .5f : 0), .5f);
|
centerOfHit.add(.5f, (blockTrace.getFace().getAxis() == Direction.Axis.Y ? .5f : 0), .5f);
|
||||||
|
|
||||||
// power cost for thing
|
int energyCost = BASE_COST_PER_USE + (int) (BASE_COST_PER_USE * player.getDistanceSq(toPos.getX(), toPos.getY(), toPos.getZ()));
|
||||||
// int use = baseUse + (int) (baseUse * pos.hitVec.distanceTo(new Vec3d(player.posX, player.posY + (player.getEyeHeight() - player.getDefaultEyeHeight()), player.posZ)));
|
boolean canUse = stack.getCapability(CapabilityEnergy.ENERGY).map(e -> e.getEnergyStored() >= energyCost).orElse(false);
|
||||||
|
|
||||||
|
if (!canUse) {
|
||||||
|
return super.onItemRightClick(world, player, hand);
|
||||||
|
}
|
||||||
|
|
||||||
if (!player.isCreative()) {
|
if (!player.isCreative()) {
|
||||||
player.getCooldownTracker().setCooldown(this, 50);
|
player.getCooldownTracker().setCooldown(this, 50);
|
||||||
|
stack.getCapability(CapabilityEnergy.ENERGY).ifPresent(energy ->
|
||||||
|
energy.extractEnergy(energyCost, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
player.dismount();
|
player.dismount();
|
||||||
player.playSound(SoundEvents.ENTITY_ENDERMAN_TELEPORT, SoundCategory.PLAYERS, 1.0f, 1.0f);
|
world.playSound(null, toPos.getX(), toPos.getY(), toPos.getZ(), SoundEvents.ENTITY_ENDERMAN_TELEPORT, SoundCategory.PLAYERS, 1.0f, 1.0f);
|
||||||
((ServerPlayerEntity) player).connection.setPlayerLocation(centerOfHit.getX(), centerOfHit.getY(), centerOfHit.getZ(), player.rotationYaw, player.rotationPitch);
|
((ServerPlayerEntity) player).connection.setPlayerLocation(centerOfHit.getX(), centerOfHit.getY(), centerOfHit.getZ(), player.rotationYaw, player.rotationPitch);
|
||||||
//
|
|
||||||
// if (pos != null && (pos.typeOfHit == RayTraceResult.Type.BLOCK || player.rotationPitch >= -5)) {
|
|
||||||
// int side = pos.sideHit.ordinal();
|
|
||||||
// if (side != -1) {
|
|
||||||
// double x = pos.hitVec.x - (side == 4 ? 0.5 : 0) + (side == 5 ? 0.5 : 0);
|
|
||||||
// double y = pos.hitVec.y - (side == 0 ? 2.0 : 0) + (side == 1 ? 0.5 : 0);
|
|
||||||
// double z = pos.hitVec.z - (side == 2 ? 0.5 : 0) + (side == 3 ? 0.5 : 0);
|
|
||||||
// int baseUse = 200;
|
|
||||||
// int use = baseUse + (int) (baseUse * pos.hitVec.distanceTo(new Vec3d(player.posX, player.posY + (player.getEyeHeight() - player.getDefaultEyeHeight()), player.posZ)));
|
|
||||||
// if (this.getEnergyStored(stack) >= use) {
|
|
||||||
// ((EntityPlayerMP) player).connection.setPlayerLocation(x, y, z, player.rotationYaw, player.rotationPitch);
|
|
||||||
// player.dismountRidingEntity();
|
|
||||||
// world.playSound(null, player.posX, player.posY, player.posZ, SoundEvents.ENTITY_ENDERMEN_TELEPORT, SoundCategory.PLAYERS, 1.0F, 1.0F);
|
|
||||||
// if (!player.capabilities.isCreativeMode) {
|
|
||||||
// this.extractEnergyInternal(stack, use, false);
|
|
||||||
// player.getCooldownTracker().setCooldown(this, 50);
|
|
||||||
// }
|
|
||||||
// return ActionResult.newResult(EnumActionResult.SUCCESS, stack);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
player.swingArm(hand);
|
player.swingArm(hand);
|
||||||
return ActionResult.resultSuccess(stack);
|
return ActionResult.resultSuccess(stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean canUse(ItemStack stack) {
|
|
||||||
return true; // todo: add energy logic
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,4 +16,20 @@ public class Help {
|
||||||
public static TranslationTextComponent trans(String key, Object... args) {
|
public static TranslationTextComponent trans(String key, Object... args) {
|
||||||
return new TranslationTextComponent(String.format("%s.%s", ActuallyAdditions.MOD_ID, key), args);
|
return new TranslationTextComponent(String.format("%s.%s", ActuallyAdditions.MOD_ID, key), args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pretty values, turns numbers like 100000000 into 100M
|
||||||
|
*
|
||||||
|
* @param value value you need prettified
|
||||||
|
* @return a pretty string
|
||||||
|
*/
|
||||||
|
public static String compressedValue(int value) {
|
||||||
|
if (value < 1000)
|
||||||
|
return String.valueOf(value);
|
||||||
|
|
||||||
|
int exp = (int) (Math.log(value) / Math.log(1000));
|
||||||
|
return String.format("%,d%c",
|
||||||
|
(int) (value / Math.pow(1000, exp)),
|
||||||
|
"KMGTPE_____".charAt(exp - 1));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
package de.ellpeck.actuallyadditions.common.utilities;
|
||||||
|
|
||||||
|
public class VisualHelper {
|
||||||
|
/**
|
||||||
|
* Stolen from Ell's original code, because lazy. What does it do? Something with wheels? (It's an hsb selector)
|
||||||
|
*/
|
||||||
|
public static float[] getWheelColor(float pos) {
|
||||||
|
if (pos < 85.0f) { return new float[] { pos * 3.0F, 255.0f - pos * 3.0f, 0.0f }; }
|
||||||
|
if (pos < 170.0f) { return new float[] { 255.0f - (pos -= 85.0f) * 3.0f, 0.0f, pos * 3.0f }; }
|
||||||
|
return new float[] { 0.0f, (pos -= 170.0f) * 3.0f, 255.0f - pos * 3.0f };
|
||||||
|
}
|
||||||
|
}
|
|
@ -316,6 +316,9 @@ public class GeneratorLanguage extends LanguageProvider {
|
||||||
addPrefixed("tooltip.booklet.manual.two", "This book guides you through all of the feature Actually Additions has to over.");
|
addPrefixed("tooltip.booklet.manual.two", "This book guides you through all of the feature Actually Additions has to over.");
|
||||||
addPrefixed("tooltip.booklet.manual.three", "Use while holding to open.");
|
addPrefixed("tooltip.booklet.manual.three", "Use while holding to open.");
|
||||||
|
|
||||||
|
// Storage
|
||||||
|
addPrefixed("storage.crystal-flux", "%s/%s Crystal Flux");
|
||||||
|
|
||||||
add("itemGroup.actuallyadditions", "Actually Additions");
|
add("itemGroup.actuallyadditions", "Actually Additions");
|
||||||
|
|
||||||
// Mics
|
// Mics
|
||||||
|
|
Loading…
Reference in a new issue