Skip to content

Commit

Permalink
Add Cake Fuel Tooltip (#20)
Browse files Browse the repository at this point in the history
* Display the fuel used to refill cakes in the item's tooltip
* Implement config caching with event-triggered invalidation to support accurate display of tooltips when multiple custom cakes are defined
* Implement TOP and WAILA information for fuel

Co-authored-by: Exa <[email protected]>
Co-authored-by: ALongStringOfNumbers <[email protected]>
  • Loading branch information
3 people committed Apr 9, 2021
1 parent b2d62fd commit a835783
Show file tree
Hide file tree
Showing 8 changed files with 323 additions and 141 deletions.
31 changes: 20 additions & 11 deletions src/main/java/jackyy/dimensionaledibles/DimensionalEdibles.java
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
package jackyy.dimensionaledibles;

import jackyy.dimensionaledibles.command.DimensionalEdiblesCommand;
import jackyy.dimensionaledibles.proxy.CommonProxy;
import jackyy.dimensionaledibles.registry.ModBlocks;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.item.ItemStack;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.SidedProxy;
import jackyy.dimensionaledibles.block.*;
import jackyy.dimensionaledibles.command.*;
import jackyy.dimensionaledibles.proxy.*;
import jackyy.dimensionaledibles.registry.*;
import net.minecraft.creativetab.*;
import net.minecraft.item.*;
import net.minecraftforge.fml.common.*;
import net.minecraftforge.fml.common.event.*;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.*;

@Mod(modid = DimensionalEdibles.MODID, name = DimensionalEdibles.MODNAME, version = DimensionalEdibles.VERSION, acceptedMinecraftVersions = DimensionalEdibles.MCVERSION, dependencies = DimensionalEdibles.DEPENDS, certificateFingerprint = "@FINGERPRINT@", useMetadata = true)
@Mod(modid = DimensionalEdibles.MODID,
name = DimensionalEdibles.MODNAME,
version = DimensionalEdibles.VERSION,
acceptedMinecraftVersions = DimensionalEdibles.MCVERSION,
dependencies = DimensionalEdibles.DEPENDS,
certificateFingerprint = "@FINGERPRINT@",
useMetadata = true)
@SuppressWarnings("unused")
public class DimensionalEdibles {

public static final String VERSION = "GRADLE:VERSION";
Expand All @@ -33,6 +39,7 @@ public ItemStack createIcon() {
@Mod.EventHandler
public void preInit(FMLPreInitializationEvent event) {
proxy.preInit(event);
BlockCustomCake.rebuildCache();
}

@Mod.EventHandler
Expand All @@ -47,7 +54,9 @@ public void postInit(FMLPostInitializationEvent event) {

@Mod.EventHandler
public void onFingerprintViolation(FMLFingerprintViolationEvent event) {
logger.warn("Invalid fingerprint detected! The file " + event.getSource().getName() + " may have been modified. This will NOT be supported by the mod author!");
logger.warn(
"Invalid fingerprint detected! The file \"{}\" may have been modified. This will NOT be supported by the mod author!",
event.getSource().getName());
}

@Mod.EventHandler
Expand Down
48 changes: 43 additions & 5 deletions src/main/java/jackyy/dimensionaledibles/block/BlockCakeBase.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import net.minecraft.block.material.*;
import net.minecraft.block.properties.*;
import net.minecraft.block.state.*;
import net.minecraft.client.resources.*;
import net.minecraft.client.util.*;
import net.minecraft.creativetab.*;
import net.minecraft.entity.*;
import net.minecraft.entity.player.*;
Expand All @@ -23,6 +25,8 @@
import javax.annotation.*;
import java.util.*;

import static jackyy.dimensionaledibles.DimensionalEdibles.*;
import static jackyy.dimensionaledibles.item.ItemBlockCustomCake.*;
import static jackyy.dimensionaledibles.util.TeleporterHandler.*;

/**
Expand Down Expand Up @@ -117,7 +121,7 @@ public boolean onBlockActivated(World worldIn,

ItemStack stack = playerIn.getHeldItem(hand);
if (!stack.isEmpty() &&
ItemStack.areItemsEqual(stack, getFuelItemStack()) &&
ItemStack.areItemsEqual(stack, getFuelItemStack(this.cakeDimension())) &&
fuelUntilFull != 0) {
if (meta >= 0) {
worldIn.setBlockState(pos, state.withProperty(BITES, meta), 2);
Expand Down Expand Up @@ -212,11 +216,21 @@ public void addProbeInfo(ProbeMode mode,
World world,
IBlockState blockState,
IProbeHitData data) {

ItemStack fuelStack = getFuelItemStack(this.cakeDimension());
//Only the custom cake falls back to a default empty ItemStack, so if the ItemStack is empty, the cake is a
//custom cake with a bad fuel entry
String fuel = fuelStack.isEmpty() ? I18n.format("tooltip.dimensionaledibles.custom_cake.bad_config") :
I18n.format(fuelStack.getTranslationKey() + ".name");

if (world.getBlockState(data.getPos()).getBlock() instanceof BlockCakeBase) {
probeInfo.horizontal(probeInfo.defaultLayoutStyle().alignment(ElementAlignment.ALIGN_CENTER))
.item(new ItemStack(Items.CAKE))
.text(TextFormatting.GREEN + "Bites: ")
.progress(MAX_BITES - blockState.getValue(BITES), MAX_BITES);
probeInfo.horizontal(probeInfo.defaultLayoutStyle().alignment(ElementAlignment.ALIGN_CENTER))
.item(fuelStack.isEmpty() ? new ItemStack(Blocks.BARRIER) : fuelStack)
.text(TextFormatting.GREEN + "Refill: " + fuel);
}
}

Expand All @@ -225,9 +239,15 @@ public List<String> getWailaBody(ItemStack itemStack,
List<String> currentTip,
IWailaDataAccessor accessor,
IWailaConfigHandler config) {

ItemStack fuelStack = getFuelItemStack(this.cakeDimension());
String fuel = fuelStack.isEmpty() ? I18n.format("tooltip.dimensionaledibles.custom_cake.bad_config") :
I18n.format(fuelStack.getTranslationKey() + ".name");

if (accessor.getBlockState().getBlock() instanceof BlockCakeBase) {
currentTip.add(TextFormatting.GRAY + "Bites: " +
(MAX_BITES - accessor.getBlockState().getValue(BITES)) + " / " + MAX_BITES);
currentTip.add(TextFormatting.GRAY + "Refill: " + fuel);
}
return currentTip;
}
Expand Down Expand Up @@ -255,8 +275,8 @@ protected void teleportPlayer(World world,
EntityPlayer player) {
EntityPlayerMP playerMP = (EntityPlayerMP) player;
BlockPos coords;
if (config().useCustomCoordinates())
coords = config().customCoords().toBlockPos();
if (config().useCustomCoordinates(this.cakeDimension()))
coords = config().customCoords(this.cakeDimension()).toBlockPos();
else
coords = calculateCoordinates(playerMP);

Expand Down Expand Up @@ -293,8 +313,13 @@ protected void consumeCake(World world,
* @return The Fuel as an ItemStack if the Config entry is well-formed,
* {@link #defaultFuel} otherwise.
*/
private ItemStack getFuelItemStack() {
Item configItem = Item.REGISTRY.getObject(new ResourceLocation(config().fuel()));
private ItemStack getFuelItemStack(int dim) {
String fuel = config().fuel(dim);
if (fuel == null || fuel.equals("")) {
logger.error("Could not parse fuel for cake (dimension \"{}\"). Falling back to default fuel.", dim);
return defaultFuel();
}
Item configItem = Item.REGISTRY.getObject(new ResourceLocation(fuel));
return configItem == null ? defaultFuel() : new ItemStack(configItem);
}

Expand All @@ -305,4 +330,17 @@ public void getSubBlocks(CreativeTabs tab,
if (registerItem())
list.add(new ItemStack(this));
}

@Override
@SideOnly(Side.CLIENT)
public void addInformation(ItemStack stack, World worldIn, List<String> tooltip, ITooltipFlag flagIn) {
super.addInformation(stack, worldIn, tooltip, flagIn);
ItemStack fuelStack = getFuelItemStack(getDimID(stack));
if (fuelStack == ItemStack.EMPTY)
tooltip.add(I18n.format("tooltip.dimensionaledibles.custom_cake.bad_config"));
else
// Why do I need to add ".name"? Thank you Lex.
tooltip.add(I18n.format("tooltip.dimensionaledibles.cake",
I18n.format(fuelStack.getTranslationKey() + ".name")));
}
}
127 changes: 87 additions & 40 deletions src/main/java/jackyy/dimensionaledibles/block/BlockCustomCake.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@

import jackyy.dimensionaledibles.*;
import jackyy.dimensionaledibles.block.tile.*;
import jackyy.dimensionaledibles.item.*;
import jackyy.dimensionaledibles.registry.*;
import jackyy.dimensionaledibles.util.*;
import net.minecraft.block.*;
import net.minecraft.block.state.*;
import net.minecraft.creativetab.*;
import net.minecraft.entity.player.*;
import net.minecraft.init.*;
import net.minecraft.item.*;
import net.minecraft.nbt.*;
import net.minecraft.tileentity.*;
Expand All @@ -16,20 +17,33 @@
import net.minecraft.world.*;
import net.minecraftforge.common.*;
import net.minecraftforge.fml.relauncher.*;
import org.apache.logging.log4j.*;

import javax.annotation.*;

import static jackyy.dimensionaledibles.DimensionalEdibles.*;

public class BlockCustomCake extends BlockCakeBase implements ITileEntityProvider {

private int customX = 0;
private int customY = 0;
private int customZ = 0;
/** Dimension of the last-clicked cake. */
private int cakeDimension;

private String cakeFuel;
private int cakeDimension = 0;
private static class CustomCake {
public ModConfig.CustomCoords customCoords = new ModConfig.CustomCoords(0,0,0);
private String cakeFuel = null;
private final int cakeDimension;

public CustomCake(int dim) {
this.cakeDimension = dim;
}

@Override
public String toString() {
return String.format("CustomCake[dim: %d, fuel: %s, coords: %s]",
cakeDimension, cakeFuel, customCoords);
}
}

private static Cache<Integer, CustomCake> cache = new Cache<>();

public BlockCustomCake() {
super();
Expand All @@ -47,9 +61,16 @@ public boolean onBlockActivated(World world,
float hitX,
float hitY,
float hitZ) {
this.cakeDimension = getDimension(world, pos);
this.cakeFuel = determineCakeFuel();
updateCustomCoordinates();



int dim = getDimension(world, pos);
if(!cache.containsKey(dim)) {
logger.error("No such dimension: \"{}\"", dim);
return true;
}

this.cakeDimension = dim;

return super.onBlockActivated(world, pos, state, player, hand, side, hitX, hitY, hitZ);
}
Expand All @@ -62,46 +83,63 @@ private int getDimension(World world,
throw new IllegalArgumentException("Specified position does not contain a Custom Cake");
}

private void updateCustomCoordinates() {
/**
* DO NOT CALL THIS METHOD OUTSIDE OF PREINIT AND CONFIG CHANGE EVENT HANDLERS.
* This should be private but Forge forced my hand.
*/
public static void rebuildCache() {
Cache<Integer,CustomCake> newCache = new Cache<>();

NonNullList<ItemStack> subBlocks = NonNullList.create();
new BlockCustomCake().getSubBlocks(CreativeTabs.BUILDING_BLOCKS, subBlocks);
for(ItemStack stack : subBlocks) {
int dimID = ItemBlockCustomCake.getDimID(stack);
newCache.putIfAbsent(dimID, new CustomCake(dimID));
}

for(String s : ModConfig.tweaks.customEdible.customCoords) {
try {
String[] parts = s.split(",");
if (parts.length < 4) {
logger.log(Level.ERROR,
s + " is not a valid input line! Format needs to be: <dimID>, <x>, <y>, <z>");
logger.error("\"{}\" is not a valid input line! Format needs to be: <dimID>, <x>, <y>, <z>", s);
continue;
}
if (Integer.parseInt(parts[0].trim()) == cakeDimension) {
customX = Integer.parseInt(parts[1].trim());
customY = Integer.parseInt(parts[2].trim());
customZ = Integer.parseInt(parts[3].trim());
int dim = Integer.parseInt(parts[0].trim());
if(!newCache.containsKey(dim)) {
logger.error("Unrecognized dimension: \"{}\"", dim);
return;
}
CustomCake cake = newCache.get(dim);

ModConfig.CustomCoords cc = cake.customCoords;
cc.x = Integer.parseInt(parts[1].trim());
cc.y = Integer.parseInt(parts[2].trim());
cc.z = Integer.parseInt(parts[3].trim());

} catch(NumberFormatException e) {
logger.log(Level.ERROR,
s + " is not a valid line input! The dimension ID needs to be a number!");
logger.error("\"{}\" is not a valid line input! The dimension ID needs to be a number!", s, e);
return;
}
}
}

private String determineCakeFuel() {
String fuel = "minecraft:air";
for(String s : ModConfig.tweaks.customEdible.customCake.fuel) {
try {
String[] parts = s.split(",");
if (parts.length < 2) {
logger.log(Level.ERROR,
s + " is not a valid input line! Format needs to be: <dimID>, <cakeFuel>");
continue;
}
if (Integer.parseInt(parts[0].trim()) == cakeDimension) {
fuel = parts[1].trim();
logger.error("\"{}\" is not a valid input line! Format needs to be: <dimID>, <cakeFuel>", s);
return;
}
int dim = Integer.parseInt(parts[0].trim());
CustomCake cake = newCache.get(dim);

cake.cakeFuel = parts[1].trim();
} catch(NumberFormatException e) {
logger.log(Level.ERROR,
s + " is not a valid line input! The dimension ID needs to be a number!");
logger.error("\"{}\" is not a valid line input! The dimension ID needs to be a number!", s, e);
return;
}
}
return fuel;

cache = newCache;
}

@Override
Expand All @@ -114,8 +152,7 @@ public void getSubBlocks(CreativeTabs tab,
try {
String[] parts = s.split(",");
if (parts.length < 2) {
logger.log(Level.ERROR,
s + " is not a valid input line! Format needs to be: <dimID>, <cakeName>");
logger.error("\"{}\" is not a valid input line! Format needs to be: <dimID>, <cakeName>", s);
continue;
}
int dimension = Integer.parseInt(parts[0].trim());
Expand All @@ -130,12 +167,10 @@ public void getSubBlocks(CreativeTabs tab,
nbt.setString("cakeName", parts[1].trim());
list.add(stack);
} else {
logger.log(Level.ERROR,
parts[0] + " is not a valid dimension ID! (Needs to be a number)");
logger.error("\"{}\" is not a valid dimension ID!", parts[0]);
}
} catch(NumberFormatException e) {
logger.log(Level.ERROR,
s + " is not a valid line input! The dimension ID needs to be a number!");
logger.error("\"{}\" is not a valid line input! The dimension ID needs to be a number!", s, e);
}
}
}
Expand All @@ -149,11 +184,23 @@ public TileEntity createNewTileEntity(@Nonnull World world,

private final ModConfig.CakeConfig conf = new ModConfig.CakeConfig() {
@Override
public String fuel() { return cakeFuel; }
public String fuel(int dim) {
return cache.getPropertyIfPresentOrNull(dim, c -> c.cakeFuel);
}

@Override
public boolean useCustomCoordinates() { return (customX != 0 || customY != 0 || customZ != 0); }
public boolean useCustomCoordinates(int dim) {
return cache.getPropertyIfPresentOrElse(dim, c -> {
ModConfig.CustomCoords cc = c.customCoords;
return (cc.x != 0 || cc.y != 0 || cc.z != 0);
}, () -> false);
}

@Override
public ModConfig.CustomCoords customCoords() { return new ModConfig.CustomCoords(customX, customY, customZ); }
public ModConfig.CustomCoords customCoords(int dim) {
return cache.getPropertyIfPresentOrElse(dim, c -> c.customCoords, () -> new CustomCake(dim).customCoords);
}

@Override
public boolean consumesFuel() { return ModConfig.tweaks.customEdible.customCake.consumeFuel; }
@Override
Expand Down
Loading

0 comments on commit a835783

Please sign in to comment.