Compare commits

...
17 Commits
Author SHA1 Message Date
Mikhail 8c5c51e6fa Fix mana spreader entity ID leak (#162) 2026-10-25 10:21:09 +00:00
Ressed 37379acd3d Backport upstream commit to fix desyncs in statement of Elf Portal (#158) 2026-10-25 09:11:37 +01:00
Eldrinn Elantey 3f62d4b8fe Fix Cocoon of Caprice not rendering in inventory and NEI (#160) 2026-10-11 18:48:07 +02:00
slprime 2257f1648c Fix NPE in NEI brewery handler when brew can't fill a container (#159) 2026-10-10 19:04:38 +03:00
micvog cefdfd7ca6 Fix Ring of Far Reach stacking reach on every dimension change (#157) 2026-10-04 03:20:27 -04:00
AlexSocol c802a448e4 Fix identity assignment in TileSpreader (#155) 2026-09-11 06:33:25 +00:00
Jason Mitchell daae5de075 Add back deprecated constructor, mark it as such (#156) 2026-09-10 23:26:22 -07:00
boubou19 abd62c1076 Cache slab unlocalized name (#152) 2026-08-25 10:55:50 +02:00
Caedis 8e709b0190 fix: use renderViewEntity instead of player for rendering (#151) 2026-08-08 00:44:58 -05:00
Ben a16181c480 add null check for explosionsource (#150) 2026-08-04 22:00:33 +02:00
Dream Master 9f9c413b48 update+deps+gradle+bs 2026-08-04 11:32:51 +07:00
boubou19 31eb7b3516 Fix render allocations (#149) 2026-08-03 18:11:04 +00:00
FourIsTheNumber d213b7bf0a Pottable flowers and mushrooms (#146) 2026-08-02 20:15:00 -04:00
boubou19 c168882a48 Cache reflection (#147) 2026-08-02 16:52:34 +02:00
Nikolay S. 073ae658b5 Improve the NEI handler for the Botanical Brewery (#144) 2026-07-26 15:08:12 +00:00
Ranzu 0e88bd8a9c Implement ColorUtils class to NEI handler (#143) 2026-07-16 23:24:11 -04:00
UltraProdigy 9d1709dd74 Delete Botania Contributing.md (#140) 2026-07-04 20:46:27 +02:00
49 changed files with 726 additions and 313 deletions

No files matched your search

-40
View File
@@ -1,40 +0,0 @@
Hey there. Looks like you want to contribute with an issue. Great. Here's what you have to do:
* Have a look through the [Botania FAQ](http://botaniamod.net/faq.php), to see if your issue has been solved already;
* Read through the steps on [Bug Reporting 101](http://vazkii.us/br101/) (You may skip this if you're already familiar with reporting issues, but it's good for newcomers);
* Note the following points:
* Issues regarding MCPC+/Cauldron that are not reproducible with forge only are **not accepted**;
* Issues regarding outdated versions of the mod are **not accepted**;
* Unless you manually update every mod on the pack to the latest, issues regarding any public modpack that is not officially maintained or supported by the botania developers (the ones in the modpack section of the website are not) are **not accepted**;
* Duplicate issues or issues that have been solved already (use the search feature!) will be closed without asking.
* Do not tag your issues' names. "Something Broke" is prefered to "[Bug] Something Broke" because there's a proper label system in place.
* Suggestions are **not** accepted here. Post them on the forums or reddit instead. If there's any still open they're old ones before this rule was added.
The following "bugs" are not accepted:
* Intended Behaviour
* Double tall flowers need be harvested with shears to not clutter the inventory
* Already fixed but people keep reporting it for some reason
* Wearing a Ring of Loki or Ring of the Aesir shows a wireframe below bedrock
* Not a botania problem/Not fixable
* Crash on startup with ChromatiCraft installed (update CC)
* Crash on startup with Blocks3D Mod installed
* Crash on opening the Lexica Botania with Enchiridion installed (update Enchiridion)
* Flowers don't render (Optifine issue)
* Mana Bursts get destroyed on Cauldron by the ClearLagg plugin (add botania:manaBurst to the ClearLagg blacklist)
* Force Relays destroy blocks when used very fast (Can't fix due to the nature of the block)
* Terrasteel crafting won't start (make sure your checkerboard is correct, there's Livingrock under the plate)
* The Horn of the Canopy doesn't break Thaumcraft leaves (Thaumcraft doesn't use the typical class or material)
* Some Baubles don't work properly on LAN (Baubles bug)
[Report the Issue](https://github.com/Vazkii/Botania/issues)!
You can find me at most times on [#vazkii @ irc.esper.net](http://webchat.esper.net/?channels=vazkii), if you need to speak with me about the issue you would report. Just make sure to use common sense and read what the bot tells you.
---
If you want to make a Pull Request keep these in mind:
* Do NOT use the github editor. Test your damn PRs before you submit them.
* I'm very strict when it comes to syntax. Make sure your PR's syntax matches the syntax of the rest of the code. That includes spacing after if/for/(etc), proper bracket usage, camel casing and copyleft headers on new classes.
* If your pull request edits very small chunks of code and isn't flawless I'll close it as it'll probably take less time to fix it myself rather than pull yours and change the code.
* Unless you have a very good reason for it, keep your PRs all in one commit. You can do it with [rebase](https://git-scm.com/docs/git-rebase).
+8 -9
View File
@@ -1,20 +1,19 @@
// Add your dependencies here
dependencies {
api('com.github.GTNewHorizons:Baubles-Expanded:2.2.14-GTNH:dev')
api('com.github.GTNewHorizons:GTNHLib:0.9.62:dev')
api('com.github.GTNewHorizons:Baubles-Expanded:2.2.21-GTNH:dev')
implementation('com.github.GTNewHorizons:GTNHLib:0.11.35:dev')
compileOnly('com.github.GTNewHorizons:BuildCraft:7.1.60:api') {transitive=false}
compileOnly('com.github.GTNewHorizons:ForgeMultipart:1.7.10:dev') {transitive=false}
devOnlyNonPublishable('com.github.GTNewHorizons:NotEnoughItems:2.8.96-GTNH:dev')
compileOnly('com.github.GTNewHorizons:Railcraft:9.17.26:api') {transitive=false}
compileOnly('com.github.GTNewHorizons:StorageDrawers:2.2.20-GTNH:api') {transitive=false}
compileOnly('com.github.GTNewHorizons:BuildCraft:7.1.63:api') {transitive=false}
compileOnly('com.github.GTNewHorizons:ForgeMultipart:1.7.11:dev') {transitive=false}
devOnlyNonPublishable('com.github.GTNewHorizons:NotEnoughItems:2.8.118-GTNH:dev')
compileOnly('com.github.GTNewHorizons:Railcraft:9.17.30:api') {transitive=false}
compileOnly('com.github.GTNewHorizons:StorageDrawers:2.2.26-GTNH:api') {transitive=false}
compileOnly('curse.maven:cofh-lib-220333:2388748')
compileOnly('curse.maven:minefactory-reloaded-66672:2366150')
compileOnly('thaumcraft:Thaumcraft:1.7.10-4.2.3.5:dev')
compileOnly("net.industrial-craft:industrialcraft-2:2.2.828-experimental:dev")
compileOnly("com.github.GTNewHorizons:StructureLib:1.4.34:dev")
compileOnly("com.github.GTNewHorizons:StructureLib:1.4.42:dev")
}
+10 -10
View File
@@ -1,12 +1,12 @@
#This file is generated by updateDaemonJvm
toolchainUrl.FREE_BSD.AARCH64=https\://api.foojay.io/disco/v3.0/ids/cf726b4a1c84b50457225f9bba6d7650/redirect
toolchainUrl.FREE_BSD.X86_64=https\://api.foojay.io/disco/v3.0/ids/fa1e318c287360478e3c83a9a3ef1007/redirect
toolchainUrl.LINUX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/cf726b4a1c84b50457225f9bba6d7650/redirect
toolchainUrl.LINUX.X86_64=https\://api.foojay.io/disco/v3.0/ids/fa1e318c287360478e3c83a9a3ef1007/redirect
toolchainUrl.MAC_OS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/c2dd35c9d0aaf0ba6ad0791320f99dfc/redirect
toolchainUrl.MAC_OS.X86_64=https\://api.foojay.io/disco/v3.0/ids/e5810bd7fd1f8a586644409d395a7e55/redirect
toolchainUrl.UNIX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/cf726b4a1c84b50457225f9bba6d7650/redirect
toolchainUrl.UNIX.X86_64=https\://api.foojay.io/disco/v3.0/ids/fa1e318c287360478e3c83a9a3ef1007/redirect
toolchainUrl.WINDOWS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/7b3c4877c0749019e6805bb61e421497/redirect
toolchainUrl.WINDOWS.X86_64=https\://api.foojay.io/disco/v3.0/ids/d76df094a9cbbabd3b08251f9e61444a/redirect
toolchainUrl.FREE_BSD.AARCH64=https\://api.foojay.io/disco/v3.0/ids/97d46b5ff4df0bf61e95652a190a5567/redirect
toolchainUrl.FREE_BSD.X86_64=https\://api.foojay.io/disco/v3.0/ids/9ef54a08e06b0754cee9fc95ed3a3134/redirect
toolchainUrl.LINUX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/97d46b5ff4df0bf61e95652a190a5567/redirect
toolchainUrl.LINUX.X86_64=https\://api.foojay.io/disco/v3.0/ids/9ef54a08e06b0754cee9fc95ed3a3134/redirect
toolchainUrl.MAC_OS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/1df82b76031285ef2e6a4f59ffe9299d/redirect
toolchainUrl.MAC_OS.X86_64=https\://api.foojay.io/disco/v3.0/ids/c7d5be6a02945ac2e045048ee54a7d32/redirect
toolchainUrl.UNIX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/97d46b5ff4df0bf61e95652a190a5567/redirect
toolchainUrl.UNIX.X86_64=https\://api.foojay.io/disco/v3.0/ids/9ef54a08e06b0754cee9fc95ed3a3134/redirect
toolchainUrl.WINDOWS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/643f404f769811f5f265fd66f7af5d89/redirect
toolchainUrl.WINDOWS.X86_64=https\://api.foojay.io/disco/v3.0/ids/38256085a73e137cb4937ea9c4807fec/redirect
toolchainVersion=25
+1 -1
View File
@@ -17,7 +17,7 @@ pluginManagement {
}
plugins {
id 'com.gtnewhorizons.gtnhsettingsconvention' version '2.0.24'
id 'com.gtnewhorizons.gtnhsettingsconvention' version '2.0.27'
}
@@ -18,7 +18,12 @@ import net.minecraft.item.ItemStack;
import net.minecraft.potion.PotionEffect;
/**
* The class for a Brew definition, each one is a singleton.
* A type of brew that can be created in the Botanical Brewery.
*
* <p>
* Each instance of this class represents a single <i>type</i> of brew that can be created in the brewery, similarly
* to how {@link net.minecraft.item.Item} and {@link net.minecraft.block.Block} work.
* </p>
*/
public class Brew {
@@ -31,11 +36,12 @@ public class Brew {
boolean canInfuseIncense = true;
/**
* @param key The key for this brew, used in NBT and the global map.
* @param name The unlocalized name of this potion.
* @param color The color for the potion to be rendered in the bottle, note that it will get
* changed a bit when it renders (for more or less brightness) to give a fancy effect.
* @param cost The cost, in Mana for this brew.
* @param effects A list of effects to apply to the player when they drink it.
* @param color The color for the potion to be rendered in the bottle. Note that it will get
* changed a bit when it renders (for more or less brightness) to give a fancy effect.
* @param cost The cost, in Mana for this brew. Must be positive.
* @param effects A list of potion effects to apply to the player when they drink it.
*/
public Brew(String key, String name, int color, int cost, PotionEffect... effects) {
this.key = key;
@@ -101,14 +107,14 @@ public class Brew {
}
/**
* Gets the insensitive unlocalized mana cost. This is used for the lexicon.
* Get the item-insensitive mana cost. This is used for the lexicon and for crafting costs.
*/
public int getManaCost() {
return cost;
}
/**
* Gets the mana cost for the ItemStack passed in.
* Gets the mana cost for the ItemStack passed in. In standard Botania, this is used only by the Cursed Blood Pendant.
*/
public int getManaCost(ItemStack stack) {
return getManaCost();
@@ -0,0 +1,32 @@
package vazkii.botania.api.brew;
import net.minecraft.item.ItemStack;
import vazkii.botania.api.BotaniaAPI;
/**
* Utility methods for checking the properties of {@link ItemStack}s related to Brews.
*/
public final class BrewUtilities {
/**
* Check if an {@link ItemStack} represents a filled Brew.
*
* @param stack The stack to check
* @return Whether this item contains a Brew.
*/
public static boolean isFilledBrew(ItemStack stack) {
if (!(stack.getItem() instanceof IBrewItem brewItem)) return false;
final Brew brew = brewItem.getBrew(stack);
return brew != null && brew != BotaniaAPI.fallbackBrew;
}
/**
* Check if an {@link ItemStack} is an empty Brew Container - an item that can go on the middle pedestal of the Botanical Brewery.
*
* @param stack The stack to check
* @return Whether this item is a Brew Container that does not contain a Brew.
*/
public static boolean isEmptyBrewContainer(ItemStack stack) {
return stack.getItem() instanceof IBrewContainer && !isFilledBrew(stack);
}
}
@@ -10,26 +10,32 @@
*/
package vazkii.botania.api.brew;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
/**
* An Item that implements this counts as a Brew Container, by which
* it can be used a center item for brew recipes and can contain
* a brew.
* An {@link Item} that implements this counts as a Brew Container, which allows it to be used a center item in the Botanical Brewery.
*/
public interface IBrewContainer {
/**
* Returs an ItemStack that should be an item that has the brew
* passed in.
* Fills an {@link ItemStack} of this container with a {@link Brew}.
* If the brew cannot be applied to this container, returns null instead.
*
* @param brew The brew which may or may not be applicable to this container.
* @param stack The stack of this item which is being filled. This stack is not mutated.
* @return A <i>new</i> {@link ItemStack} containing an {@link IBrewItem}, or null if this brew is not applicable.
* @apiNote The returned stack does not necessarily have to be the same {@link Item} as the empty container.
*/
public ItemStack getItemForBrew(Brew brew, ItemStack stack);
ItemStack getItemForBrew(Brew brew, ItemStack stack);
/**
* Gets the cost to add this brew onto this container. Return -1
* to not allow for the brew to be added. Normally you'd
* use brew.getManaCost(stack);
* Gets the cost to add this brew onto this container. The cost must be a positive number.
*
* @param brew The brew being applied, which must be applicable to this container. {@link IBrewContainer#getItemForBrew(Brew, ItemStack)} can be used to determine whether the brew is applicable.
* @param stack A stack of this empty container. This stack is not mutated.
* @return The mana cost for this recipe, which is a positive number.
*/
public int getManaCost(Brew brew, ItemStack stack);
int getManaCost(Brew brew, ItemStack stack);
}
@@ -10,15 +10,26 @@
*/
package vazkii.botania.api.brew;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import vazkii.botania.api.BotaniaAPI;
/**
* An Item that implements this is a Brew item, by which it contains
* a brew. This is only used in vanilla to prevent the brew item
* from going back into the brewery but other mods might use it for whatever.
* An {@link Item} that implements this is an item which can contain a {@link Brew}.
* <p>
* This is used in standard Botania to prevent finished brews from going back into the brewery & to enable NEI searches.
* However, other mods might use it for other purposes.
* </p>
*/
public interface IBrewItem {
public Brew getBrew(ItemStack brew);
/**
* Get the brew contained within a stack of this item.
*
* @param brew A stack of this item whose contents are being queried.
* @return The brew within this container, or {@link BotaniaAPI#fallbackBrew} or null if the stack does not contain
* a valid brew.
*/
Brew getBrew(ItemStack brew);
}
@@ -32,7 +32,9 @@ import vazkii.botania.common.core.helper.MathHelper;
public final class BossBarHandler {
public static final ResourceLocation defaultBossBar = new ResourceLocation(LibResources.GUI_BOSS_BAR);
static IBotaniaBoss currentBoss;
private static IBotaniaBoss currentBoss;
private static Entity lastBossEntity;
private static String lastBossName;
private static final BarCallback barUniformCallback = new BarCallback();
@@ -47,7 +49,13 @@ public final class BossBarHandler {
Minecraft mc = Minecraft.getMinecraft();
Rectangle bgRect = currentBoss.getBossBarTextureRect();
Rectangle fgRect = currentBoss.getBossBarHPTextureRect();
String name = currentBoss.func_145748_c_().getFormattedText();
Entity e = (Entity) currentBoss;
String name;
if(lastBossEntity != e) {
name = currentBoss.func_145748_c_().getFormattedText();
lastBossEntity = e;
lastBossName = name;
} else name = lastBossName;
int c = res.getScaledWidth() / 2;
int x = c - bgRect.width / 2;
int y = 20;
@@ -66,7 +74,6 @@ public final class BossBarHandler {
mc.fontRenderer.drawStringWithShadow(name, tx, y - 10, 0xA2018C);
GL11.glEnable(GL11.GL_BLEND);
Entity e = (Entity) currentBoss;
EntityPlayer p = mc.thePlayer;
if(e.isDead || !p.worldObj.loadedEntityList.contains(e) || MathHelper.pointDistanceSpace(e.posX, e.posY, e.posZ, p.posX, p.posY, p.posZ) > 32)
currentBoss = null;
@@ -10,6 +10,7 @@
*/
package vazkii.botania.client.core.handler;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Iterator;
@@ -30,13 +31,16 @@ import org.lwjgl.input.Keyboard;
import vazkii.botania.api.corporea.CorporeaHelper;
import vazkii.botania.common.lib.LibObfuscation;
import vazkii.botania.utils.ReflectionUtils;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import cpw.mods.fml.common.gameevent.TickEvent.ClientTickEvent;
import cpw.mods.fml.common.gameevent.TickEvent.Phase;
import cpw.mods.fml.relauncher.ReflectionHelper;
public class CorporeaAutoCompleteHandler {
private static final Field COMPLETE_FLAG = ReflectionUtils.findField(GuiChat.class, LibObfuscation.COMPLETE_FLAG);
private static final Field INPUT_FIELD = ReflectionUtils.findField(GuiChat.class, LibObfuscation.INPUT_FIELD);
boolean isAutoCompleted = false;
String originalString = "";
List<CompletionData> completions = new ArrayList<>();
@@ -83,7 +87,7 @@ public class CorporeaAutoCompleteHandler {
}
GuiChat chat = (GuiChat) screen;
if(isAutoCompleted) {
boolean valid = ReflectionHelper.getPrivateValue(GuiChat.class, chat, LibObfuscation.COMPLETE_FLAG);
boolean valid = ReflectionUtils.getBoolean(COMPLETE_FLAG, chat);
if(!valid)
isAutoCompleted = false;
}
@@ -99,7 +103,7 @@ public class CorporeaAutoCompleteHandler {
if(!CorporeaHelper.shouldAutoComplete())
return;
GuiTextField inputField = ReflectionHelper.getPrivateValue(GuiChat.class, chat, LibObfuscation.INPUT_FIELD);
GuiTextField inputField = (GuiTextField) ReflectionUtils.getObject(INPUT_FIELD, chat);
if(!isAutoCompleted)
buildAutoCompletes(inputField, chat);
if(isAutoCompleted && !completions.isEmpty())
@@ -127,7 +131,7 @@ public class CorporeaAutoCompleteHandler {
if(completions.isEmpty())
return;
position = -1;
ReflectionHelper.setPrivateValue(GuiChat.class, chat, true, LibObfuscation.COMPLETE_FLAG);
ReflectionUtils.setBoolean(COMPLETE_FLAG, chat, true);
StringBuilder stringbuilder = new StringBuilder();
CompletionData data;
for(Iterator<CompletionData> iterator = completions.iterator(); iterator.hasNext(); stringbuilder.append(data.string)) {
@@ -11,6 +11,7 @@
package vazkii.botania.client.core.handler;
import java.awt.Color;
import java.lang.reflect.Field;
import net.minecraft.block.Block;
import net.minecraft.block.BlockLiquid;
@@ -50,7 +51,6 @@ import vazkii.botania.api.wiki.IWikiProvider;
import vazkii.botania.api.wiki.WikiHooks;
import vazkii.botania.client.core.helper.RenderHelper;
import vazkii.botania.client.lib.LibResources;
import vazkii.botania.common.Botania;
import vazkii.botania.common.block.ModBlocks;
import vazkii.botania.common.block.tile.TileAltar;
import vazkii.botania.common.block.tile.TileRuneAltar;
@@ -65,15 +65,18 @@ import vazkii.botania.common.item.ModItems;
import vazkii.botania.common.item.equipment.bauble.ItemFlightTiara;
import vazkii.botania.common.item.equipment.bauble.ItemMonocle;
import vazkii.botania.common.lib.LibObfuscation;
import vazkii.botania.utils.ReflectionUtils;
import baubles.common.container.InventoryBaubles;
import baubles.common.lib.PlayerHandler;
import cpw.mods.fml.common.eventhandler.EventPriority;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import cpw.mods.fml.relauncher.ReflectionHelper;
public final class HUDHandler {
public static final ResourceLocation manaBar = new ResourceLocation(LibResources.GUI_MANA_HUD);
private static final Field REMAINING_HIGHLIGHT_TICKS = ReflectionUtils.findField(GuiIngame.class, LibObfuscation.REMAINING_HIGHLIGHT_TICKS);
@SubscribeEvent(priority = EventPriority.HIGHEST)
public void onDrawScreenPre(RenderGameOverlayEvent.Pre event) {
Minecraft mc = Minecraft.getMinecraft();
@@ -128,7 +131,7 @@ public final class HUDHandler {
renderCrystalCubeHUD(event.resolution, (TileCorporeaCrystalCube) tile);
}
if(!TileCorporeaIndex.InputHandler.getNearbyIndexes(mc.thePlayer).isEmpty() && mc.currentScreen != null && mc.currentScreen instanceof GuiChat) {
if(mc.currentScreen != null && mc.currentScreen instanceof GuiChat && TileCorporeaIndex.InputHandler.hasNearbyIndexes(mc.thePlayer)) {
profiler.startSection("nearIndex");
renderNearIndexDisplay(event.resolution);
profiler.endSection();
@@ -159,21 +162,23 @@ public final class HUDHandler {
profiler.endSection();
}*/
if(Botania.proxy.isClientPlayerWearingMonocle()) {
EntityPlayer player = mc.thePlayer;
InventoryBaubles baubles = PlayerHandler.getPlayerBaubles(player);
if(ItemMonocle.hasMonocle(baubles)) {
profiler.startSection("monocle");
ItemMonocle.renderHUD(event.resolution, mc.thePlayer);
ItemMonocle.renderHUD(event.resolution, player);
profiler.endSection();
}
profiler.startSection("manaBar");
EntityPlayer player = mc.thePlayer;
int totalMana = 0;
int totalMaxMana = 0;
boolean anyRequest = false;
boolean creative = false;
IInventory mainInv = player.inventory;
IInventory baublesInv = PlayerHandler.getPlayerBaubles(player);
IInventory baublesInv = baubles;
int invSize = mainInv.getSizeInventory();
int size = invSize;
@@ -221,7 +226,7 @@ public final class HUDHandler {
Profiler profiler = mc.mcProfiler;
profiler.startSection("wandMode");
int ticks = ReflectionHelper.getPrivateValue(GuiIngame.class, mc.ingameGUI, LibObfuscation.REMAINING_HIGHLIGHT_TICKS);
int ticks = ReflectionUtils.getInt(REMAINING_HIGHLIGHT_TICKS, mc.ingameGUI);
ticks -= 15;
if(ticks > 0) {
int alpha = Math.min(255, (int) (ticks * 256.0F / 10.0F));
@@ -257,8 +262,8 @@ public final class HUDHandler {
else return;
}
Color color = new Color(Color.HSBtoRGB(0.55F, (float) Math.min(1F, Math.sin(System.currentTimeMillis() / 200D) * 0.5 + 1F), 1F));
GL11.glColor4ub((byte) color.getRed(), (byte) color.getGreen(), (byte) color.getBlue(), (byte) (255 - color.getRed()));
int rgb = Color.HSBtoRGB(0.55F, (float) Math.min(1F, Math.sin(System.currentTimeMillis() / 200D) * 0.5 + 1F), 1F);
GL11.glColor4ub((byte) (rgb >> 16), (byte) (rgb >> 8), (byte) rgb, (byte) (255 - (rgb >> 16)));
mc.renderEngine.bindTexture(manaBar);
GL11.glEnable(GL11.GL_BLEND);
@@ -480,8 +485,7 @@ public final class HUDHandler {
RenderHelper.drawTexturedModalRect(x + 1, y + 1, 0, 0, 5, 100, 3);
Color color_ = new Color(color);
GL11.glColor4ub((byte) color_.getRed(), (byte) color_.getGreen(),(byte) color_.getBlue(), (byte) (255F * alpha));
GL11.glColor4ub((byte) (color >> 16), (byte) (color >> 8), (byte) color, (byte) (255F * alpha));
RenderHelper.drawTexturedModalRect(x + 1, y + 1, 0, 0, 5, Math.min(100, manaPercentage), 3);
}
}
@@ -33,6 +33,7 @@ public final class ItemsRemainingRenderHandler {
private static ItemStack stack;
private static int ticks, count;
private static String cachedText;
@SideOnly(Side.CLIENT)
public static void render(ScaledResolution resolution, float partTicks) {
@@ -62,17 +63,7 @@ public final class ItemsRemainingRenderHandler {
GL11.glColor4f(1F, 1F, 1F, 1F);
GL11.glEnable(GL11.GL_BLEND);
String text = EnumChatFormatting.GREEN + stack.getDisplayName();
if(count >= 0) {
int max = stack.getMaxStackSize();
int stacks = count / max;
int rem = count % max;
if(stacks == 0)
text = "" + count;
else text = count + " (" + EnumChatFormatting.AQUA + stacks + EnumChatFormatting.RESET + "*" + EnumChatFormatting.GRAY + max + EnumChatFormatting.RESET + "+" + EnumChatFormatting.YELLOW + rem + EnumChatFormatting.RESET + ")";
} else if(count == -1)
text = "\u221E";
String text = cachedText;
int color = 0x00FFFFFF | (int) (alpha * 0xFF) << 24;
mc.fontRenderer.drawStringWithShadow(text, x + 20, y + 6, color);
@@ -92,6 +83,22 @@ public final class ItemsRemainingRenderHandler {
ItemsRemainingRenderHandler.stack = stack;
ItemsRemainingRenderHandler.count = count;
ticks = stack == null ? 0 : maxTicks;
cachedText = "";
if(stack != null) {
String text = EnumChatFormatting.GREEN + stack.getDisplayName();
if(count >= 0) {
int max = stack.getMaxStackSize();
int stacks = count / max;
int rem = count % max;
if(stacks == 0)
text = "" + count;
else text = count + " (" + EnumChatFormatting.AQUA + stacks + EnumChatFormatting.RESET + "*" + EnumChatFormatting.GRAY + max + EnumChatFormatting.RESET + "+" + EnumChatFormatting.YELLOW + rem + EnumChatFormatting.RESET + ")";
} else if(count == -1)
text = "\u221E";
cachedText = text;
}
}
public static void set(EntityPlayer player, ItemStack displayStack, Pattern pattern) {
@@ -2,15 +2,14 @@
* This class was created by <Vazkii/ChickenBones>. It's distributed as
* part of the Botania Mod. Get the Source Code in github:
* https://github.com/Vazkii/Botania
*
*
* Botania is Open Source and distributed under the
* Botania License: http://botaniamod.net/license.php
*
*
* File Created @ [Feb 3, 2014, 9:05:38 PM (GMT)]
*/
package vazkii.botania.client.core.handler;
import java.awt.Color;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -51,10 +50,11 @@ public class LightningHandler {
static double interpPosY;
static double interpPosZ;
private static Vector3 getRelativeViewVector(Vector3 pos) {
Entity renderEntity = Minecraft.getMinecraft().renderViewEntity;
return new Vector3((float) renderEntity.posX - pos.x, (float) renderEntity.posY + renderEntity.getEyeHeight() - pos.y, (float) renderEntity.posZ - pos.z);
}
private final Vector3 scratchView = new Vector3();
private final Vector3 scratchPoint = new Vector3();
private final Vector3 scratchDiff1 = new Vector3();
private final Vector3 scratchDiff2 = new Vector3();
private final Vector3 scratchRound = new Vector3();
@SubscribeEvent
public void onRenderWorldLast(RenderWorldLastEvent event) {
@@ -67,12 +67,14 @@ public class LightningHandler {
profiler.endStartSection("lightning");
float frame = event.partialTicks;
Entity entity = Minecraft.getMinecraft().thePlayer;
TextureManager render = Minecraft.getMinecraft().renderEngine;
interpPosX = entity.lastTickPosX + (entity.posX - entity.lastTickPosX) * frame;
interpPosY = entity.lastTickPosY + (entity.posY - entity.lastTickPosY) * frame;
interpPosZ = entity.lastTickPosZ + (entity.posZ - entity.lastTickPosZ) * frame;
Entity viewEntity = Minecraft.getMinecraft().renderViewEntity;
interpPosX = viewEntity.lastTickPosX + (viewEntity.posX - viewEntity.lastTickPosX) * frame;
interpPosY = viewEntity.lastTickPosY + (viewEntity.posY - viewEntity.lastTickPosY) * frame;
interpPosZ = viewEntity.lastTickPosZ + (viewEntity.posZ - viewEntity.lastTickPosZ) * frame;
scratchView.set(viewEntity.posX, viewEntity.posY + viewEntity.getEyeHeight(), viewEntity.posZ);
GL11.glPushMatrix();
GL11.glTranslated(-interpPosX, -interpPosY, -interpPosZ);
@@ -130,22 +132,23 @@ public class LightningHandler {
int renderstart = (int) ((expandTime / 2 - bolt.particleMaxAge + bolt.particleAge) / (float) (expandTime / 2) * bolt.numsegments0);
int renderend = (int) ((bolt.particleAge + expandTime) / (float) expandTime * bolt.numsegments0);
for(Segment rendersegment : bolt.segments) {
for(int i = 0; i < bolt.segments.size(); i++) {
Segment rendersegment = bolt.segments.get(i);
if(rendersegment.segmentno < renderstart || rendersegment.segmentno > renderend)
continue;
Vector3 playervec = getRelativeViewVector(rendersegment.startpoint.point).multiply(-1);
Vector3 playervec = scratchPoint.set(rendersegment.startpoint.point).subtract(scratchView);
double width = 0.025F * (playervec.mag() / 5 + 1) * (1 + rendersegment.light) * 0.5F;
Vector3 diff1 = playervec.copy().crossProduct(rendersegment.prevdiff).normalize().multiply(width / rendersegment.sinprev);
Vector3 diff2 = playervec.copy().crossProduct(rendersegment.nextdiff).normalize().multiply(width / rendersegment.sinnext);
Vector3 diff1 = scratchDiff1.set(playervec).crossProduct(rendersegment.prevdiff).normalize().multiply(width / rendersegment.sinprev);
Vector3 diff2 = scratchDiff2.set(playervec).crossProduct(rendersegment.nextdiff).normalize().multiply(width / rendersegment.sinnext);
Vector3 startvec = rendersegment.startpoint.point;
Vector3 endvec = rendersegment.endpoint.point;
int color = inner ? bolt.colorInner : bolt.colorOuter;
tessellator.setColorRGBA_I(color, (int) (mainalpha * rendersegment.light * new Color(color).getAlpha()));
tessellator.setColorRGBA_I(color, (int) (mainalpha * rendersegment.light * 255));
tessellator.addVertexWithUV(endvec.x - diff2.x, endvec.y - diff2.y, endvec.z - diff2.z, 0.5, 0);
tessellator.addVertexWithUV(startvec.x - diff1.x, startvec.y - diff1.y, startvec.z - diff1.z, 0.5, 0);
@@ -153,7 +156,7 @@ public class LightningHandler {
tessellator.addVertexWithUV(endvec.x + diff2.x, endvec.y + diff2.y, endvec.z + diff2.z, 0.5, 1);
if(rendersegment.next == null) {
Vector3 roundend = rendersegment.endpoint.point.copy().add(rendersegment.diff.copy().normalize().multiply(width));
Vector3 roundend = scratchRound.set(rendersegment.diff).normalize().multiply(width).add(rendersegment.endpoint.point);
tessellator.addVertexWithUV(roundend.x - diff2.x, roundend.y - diff2.y, roundend.z - diff2.z, 0, 0);
tessellator.addVertexWithUV(endvec.x - diff2.x, endvec.y - diff2.y, endvec.z - diff2.z, 0.5, 0);
@@ -162,7 +165,7 @@ public class LightningHandler {
}
if(rendersegment.prev == null) {
Vector3 roundend = rendersegment.startpoint.point.copy().subtract(rendersegment.diff.copy().normalize().multiply(width));
Vector3 roundend = scratchRound.set(rendersegment.diff).normalize().multiply(width).multiply(-1).add(rendersegment.startpoint.point);
tessellator.addVertexWithUV(startvec.x - diff1.x, startvec.y - diff1.y, startvec.z - diff1.z, 0.5, 0);
tessellator.addVertexWithUV(roundend.x - diff1.x, roundend.y - diff1.y, roundend.z - diff1.z, 0, 0);
@@ -223,9 +226,9 @@ public class LightningHandler {
@Override
public int compare(Segment o1, Segment o2) {
int comp = Integer.valueOf(o1.splitno).compareTo(o2.splitno);
int comp = o1.splitno - o2.splitno;
if(comp == 0)
return Integer.valueOf(o1.segmentno).compareTo(o2.segmentno);
return o1.segmentno - o2.segmentno;
else return comp;
}
}
@@ -497,4 +500,4 @@ public class LightningHandler {
}
}
}
}
}
@@ -11,6 +11,7 @@
package vazkii.botania.client.core.handler;
import java.awt.Color;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
@@ -39,10 +40,12 @@ import vazkii.botania.common.core.handler.ConfigHandler;
import vazkii.botania.common.item.ItemLexicon;
import vazkii.botania.common.item.ModItems;
import vazkii.botania.common.lib.LibObfuscation;
import cpw.mods.fml.relauncher.ReflectionHelper;
import vazkii.botania.utils.ReflectionUtils;
public final class TooltipAdditionDisplayHandler {
private static final Field THE_SLOT = ReflectionUtils.findField(GuiContainer.class, LibObfuscation.THE_SLOT);
private static float lexiconLookupTime = 0F;
public static void render() {
@@ -50,7 +53,7 @@ public final class TooltipAdditionDisplayHandler {
GuiScreen gui = mc.currentScreen;
if(gui != null && gui instanceof GuiContainer && mc.thePlayer != null && mc.thePlayer.inventory.getItemStack() == null) {
GuiContainer container = (GuiContainer) gui;
Slot slot = ReflectionHelper.getPrivateValue(GuiContainer.class, container, LibObfuscation.THE_SLOT);
Slot slot = (Slot) ReflectionUtils.getObject(THE_SLOT, container);
if(slot != null && slot.getHasStack()) {
ItemStack stack = slot.getStack();
if(stack != null) {
@@ -0,0 +1,57 @@
package vazkii.botania.client.core.helper;
import codechicken.nei.ItemList;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import vazkii.botania.api.brew.BrewUtilities;
import vazkii.botania.api.brew.IBrewContainer;
import vazkii.botania.common.Botania;
import java.util.ArrayList;
import java.util.List;
public final class BrewHelper {
public static List<ItemStack> getBrewContainers() {
class Cache {
private static final List<ItemStack> BREW_CONTAINERS = List.copyOf(scanBrewContainers());
}
return Cache.BREW_CONTAINERS;
}
private static List<ItemStack> scanBrewContainers() {
ArrayList<ItemStack> containers = new ArrayList<>();
if (Botania.neiLoaded) {
for (ItemStack item : ItemList.items) {
if (item != null && BrewUtilities.isEmptyBrewContainer(item)) {
containers.add(item);
}
}
}
if (containers.isEmpty()) {
@SuppressWarnings("unchecked")
final Iterable<Item> itemRegistry = Item.itemRegistry;
ArrayList<ItemStack> potentialContainers = new ArrayList<>();
for (Item item : itemRegistry) {
if (item instanceof IBrewContainer) {
item.getSubItems(item, item.getCreativeTab(), potentialContainers);
for (ItemStack maybeContainer : potentialContainers) {
if (maybeContainer != null && BrewUtilities.isEmptyBrewContainer(maybeContainer)) {
containers.add(maybeContainer);
}
}
potentialContainers.clear();
}
}
}
return containers;
}
}
@@ -381,24 +381,38 @@ public class ClientProxy extends CommonProxy {
@Override
public void setExtraReach(EntityLivingBase entity, float reach) {
super.setExtraReach(entity, reach);
IExtendedPlayerController controller = getReachController(entity);
if(controller != null)
controller.setReachDistanceExtension(Math.max(0, controller.getReachDistanceExtension() + reach));
}
@Override
public void setClientExtraReach(EntityLivingBase entity, float reach) {
IExtendedPlayerController controller = getReachController(entity);
if(controller != null)
controller.setReachDistanceExtension(Math.max(0, reach));
}
private IExtendedPlayerController getReachController(EntityLivingBase entity) {
Minecraft mc = Minecraft.getMinecraft();
EntityPlayer player = mc.thePlayer;
// Player object might have changed, need to check the UUID.
if(entity.worldObj.isRemote && entity.getUniqueID().equals(player.getUniqueID())) {
if(!(mc.playerController instanceof IExtendedPlayerController)) {
GameType type = ReflectionHelper.getPrivateValue(PlayerControllerMP.class, mc.playerController, LibObfuscation.CURRENT_GAME_TYPE);
NetHandlerPlayClient net = ReflectionHelper.getPrivateValue(PlayerControllerMP.class, mc.playerController, LibObfuscation.NET_CLIENT_HANDLER);
BotaniaPlayerController controller = new BotaniaPlayerController(mc, net);
boolean isFlying = player.capabilities.isFlying;
boolean allowFlying = player.capabilities.allowFlying;
controller.setGameType(type);
player.capabilities.isFlying = isFlying;
player.capabilities.allowFlying = allowFlying;
mc.playerController = controller;
}
if(!entity.worldObj.isRemote || !entity.getUniqueID().equals(player.getUniqueID()))
return null;
((IExtendedPlayerController) mc.playerController).setReachDistanceExtension(Math.max(0, ((IExtendedPlayerController) mc.playerController).getReachDistanceExtension() + reach));
if(!(mc.playerController instanceof IExtendedPlayerController)) {
GameType type = ReflectionHelper.getPrivateValue(PlayerControllerMP.class, mc.playerController, LibObfuscation.CURRENT_GAME_TYPE);
NetHandlerPlayClient net = ReflectionHelper.getPrivateValue(PlayerControllerMP.class, mc.playerController, LibObfuscation.NET_CLIENT_HANDLER);
BotaniaPlayerController controller = new BotaniaPlayerController(mc, net);
boolean isFlying = player.capabilities.isFlying;
boolean allowFlying = player.capabilities.allowFlying;
controller.setGameType(type);
player.capabilities.isFlying = isFlying;
player.capabilities.allowFlying = allowFlying;
mc.playerController = controller;
}
return (IExtendedPlayerController) mc.playerController;
}
@Override
@@ -68,16 +68,20 @@ public class FXSparkle extends EntityFX {
Minecraft.getMinecraft().renderEngine.bindTexture(ConfigHandler.matrixMode ? ObfuscationHelper.getParticleTexture() : particles);
tessellator.startDrawingQuads();
for(FXSparkle sparkle : queuedRenders)
sparkle.renderQueued(tessellator);
if(!queuedRenders.isEmpty()) {
for(FXSparkle sparkle : queuedRenders)
sparkle.renderQueued(tessellator);
}
tessellator.draw();
ShaderHelper.useShader(ShaderHelper.filmGrain);
tessellator.startDrawingQuads();
for(FXSparkle sparkle : queuedCorruptRenders)
sparkle.renderQueued(tessellator);
tessellator.draw();
ShaderHelper.releaseShader();
if(!queuedCorruptRenders.isEmpty()) {
ShaderHelper.useShader(ShaderHelper.filmGrain);
tessellator.startDrawingQuads();
for(FXSparkle sparkle : queuedCorruptRenders)
sparkle.renderQueued(tessellator);
tessellator.draw();
ShaderHelper.releaseShader();
}
queuedRenders.clear();
queuedCorruptRenders.clear();
@@ -28,6 +28,14 @@ public final class ParticleRenderDispatcher {
// Called from LightningHandler.onRenderWorldLast since that was
// already registered. /shrug
public static void dispatch() {
if(FXSparkle.queuedRenders.isEmpty() && FXSparkle.queuedCorruptRenders.isEmpty() && FXWisp.queuedRenders.isEmpty() && FXWisp.queuedDepthIgnoringRenders.isEmpty()) {
sparkleFxCount = 0;
fakeSparkleFxCount = 0;
wispFxCount = 0;
depthIgnoringWispFxCount = 0;
return;
}
Tessellator tessellator = Tessellator.instance;
Profiler profiler = Minecraft.getMinecraft().mcProfiler;
@@ -1,22 +0,0 @@
package vazkii.botania.client.integration.nei;
import cpw.mods.fml.common.event.FMLInterModComms;
import net.minecraft.nbt.NBTTagCompound;
import vazkii.botania.client.integration.nei.recipe.RecipeHandlerBrewery;
public class IMCForNEI {
public static void IMCSender() {
sendCatalyst(RecipeHandlerBrewery.OVERLAY, "Botania:vial", -1);
sendCatalyst(RecipeHandlerBrewery.OVERLAY, "Botania:vial:1", -1);
sendCatalyst(RecipeHandlerBrewery.OVERLAY, "Botania:incenseStick", -1);
sendCatalyst(RecipeHandlerBrewery.OVERLAY, "Botania:bloodPendant", -1);
}
private static void sendCatalyst(String handlerName, String stack, int priority) {
NBTTagCompound nbt = new NBTTagCompound();
nbt.setString("handlerID", handlerName);
nbt.setString("itemName", stack);
nbt.setInteger("priority", priority);
FMLInterModComms.sendMessage("NotEnoughItems", "registerCatalystInfo", nbt);
}
}
@@ -26,7 +26,7 @@ public class NEIInputHandler implements IContainerInputHandler {
@Override
public boolean keyTyped(GuiContainer gui, char c, int i) {
Minecraft mc = Minecraft.getMinecraft();
if(TileCorporeaIndex.InputHandler.getNearbyIndexes(mc.thePlayer).isEmpty())
if(!TileCorporeaIndex.InputHandler.hasNearbyIndexes(mc.thePlayer))
return false;
int bind = NEIClientConfig.getKeyBinding(NEIBotaniaConfig.CORPOREA_KEY);
@@ -3,6 +3,7 @@ package vazkii.botania.client.integration.nei.recipe;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import net.minecraft.item.ItemStack;
import net.minecraft.util.StatCollector;
@@ -11,10 +12,15 @@ import net.minecraftforge.oredict.OreDictionary;
import org.lwjgl.opengl.GL11;
import vazkii.botania.api.BotaniaAPI;
import vazkii.botania.api.brew.Brew;
import vazkii.botania.api.brew.BrewUtilities;
import vazkii.botania.api.brew.IBrewContainer;
import vazkii.botania.api.brew.IBrewItem;
import vazkii.botania.api.recipe.RecipeBrew;
import vazkii.botania.client.core.handler.HUDHandler;
import vazkii.botania.client.core.helper.BrewHelper;
import vazkii.botania.client.lib.LibResources;
import vazkii.botania.common.block.tile.mana.TilePool;
import vazkii.botania.common.core.helper.ItemNBTHelper;
import vazkii.botania.common.item.ModItems;
import codechicken.lib.gui.GuiDraw;
@@ -45,6 +51,7 @@ public class RecipeHandlerBrewery extends TemplateRecipeHandler {
inputs.add(new PositionedStack(toVial, 39, 42));
output = new PositionedStack(recipe.getOutput(toVial), 87, 42);
mana = ((IBrewContainer) toVial.getItem()).getManaCost(recipe.getBrew(), toVial);
}
public CachedBreweryRecipe(RecipeBrew recipe) {
@@ -98,8 +105,13 @@ public class RecipeHandlerBrewery extends TemplateRecipeHandler {
@Override
public void drawBackground(int recipe) {
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
// Arrows
GuiDraw.changeTexture(getGuiTexture());
GuiDraw.drawTexturedModalRect(0, 0, 0, 0, 166, 65);
// Mana Bar
HUDHandler.renderManaBar(32, 67, 0x0000FF, 0.75F, ((CachedBreweryRecipe) arecipes.get(recipe)).mana, TilePool.MAX_MANA / 10);
}
@Override
@@ -116,22 +128,38 @@ public class RecipeHandlerBrewery extends TemplateRecipeHandler {
@Override
public void loadCraftingRecipes(ItemStack result) {
if (!(result.getItem() instanceof IBrewItem brew)) return;
final Brew targetBrew = brew.getBrew(result);
if (targetBrew == null || targetBrew == BotaniaAPI.fallbackBrew) return;
// Find the container(s) that can be filled to produce this result
for (RecipeBrew recipe : BotaniaAPI.brewRecipes) {
if (recipe != null && brew.getBrew(result) == recipe.getBrew()) {
arecipes.add(new CachedBreweryRecipe(recipe));
if (recipe == null || targetBrew != recipe.getBrew()) continue;
for (ItemStack emptyContainer : BrewHelper.getBrewContainers()) {
final ItemStack filledContainer = recipe.getOutput(emptyContainer);
if (filledContainer != null && result.isItemEqual(filledContainer) && Objects.equals(result.stackTagCompound, filledContainer.stackTagCompound)) {
arecipes.add(new CachedBreweryRecipe(recipe, emptyContainer));
}
}
}
}
@Override
public void loadUsageRecipes(ItemStack ingredient) {
if (BrewUtilities.isFilledBrew(ingredient)) {
// Filled brews cannot be inserted into a Botanical Brewery.
return;
}
if (ingredient.getItem() instanceof IBrewContainer) {
// Show all possible brews that can fill this empty container
for (RecipeBrew recipe : BotaniaAPI.brewRecipes) {
if (recipe != null && recipe.getOutput(ingredient) != null) {
arecipes.add(new CachedBreweryRecipe(recipe, ingredient));
}
}
} else {
// Show all brew recipes that can use this ingredient
for (RecipeBrew recipe : BotaniaAPI.brewRecipes) {
if (recipe == null) continue;
CachedBreweryRecipe crecipe = new CachedBreweryRecipe(recipe);
@@ -142,4 +170,8 @@ public class RecipeHandlerBrewery extends TemplateRecipeHandler {
}
}
@Override
public int getRecipeHeight(int recipe) {
return 80;
}
}
@@ -26,6 +26,7 @@ import vazkii.botania.api.lexicon.LexiconEntry;
import vazkii.botania.api.lexicon.LexiconRecipeMappings;
import vazkii.botania.client.integration.nei.NEIHelper;
import vazkii.botania.client.lib.LibResources;
import vazkii.botania.common.lib.LibColorUtils;
import vazkii.botania.common.item.ModItems;
import vazkii.botania.common.lexicon.page.PageText;
import codechicken.lib.gui.GuiDraw;
@@ -89,7 +90,7 @@ public class RecipeHandlerLexicaBotania extends TemplateRecipeHandler {
EnumChatFormatting.UNDERLINE + StatCollector.translateToLocal(recipeObj.entry.getUnlocalizedName()),
82,
30,
0x404040,
LibColorUtils.neiHandlerBotaniaLexicaTitle.getColor(),
false);
KnowledgeType type = recipeObj.entry.getKnowledgeType();
@@ -97,7 +98,7 @@ public class RecipeHandlerLexicaBotania extends TemplateRecipeHandler {
type.color + StatCollector.translateToLocal(type.getUnlocalizedName()).replaceAll("&[0-9a-fklmnor]", ""),
82,
42,
0x404040,
LibColorUtils.neiHandlerBotaniaLexicaKnowledge.getColor(),
false);
PageText.renderText(
@@ -105,6 +106,8 @@ public class RecipeHandlerLexicaBotania extends TemplateRecipeHandler {
42,
160,
200,
10,
LibColorUtils.neiHandlerBotaniaLexicaTagline.getColor(),
"\"" + StatCollector.translateToLocal(recipeObj.entry.getTagline()) + "\"");
String key = LexiconRecipeMappings.stackToString(recipeObj.item.item);
@@ -121,12 +124,12 @@ public class RecipeHandlerLexicaBotania extends TemplateRecipeHandler {
StatCollector.translateToLocal("botania.nei.lexicaSeparator"),
82,
80,
0x404040,
LibColorUtils.neiHandlerBotaniaLexicaExtraInfo.getColor(),
false);
s = quickInfoLocal;
}
PageText.renderText(5, 80, 160, 200, s);
PageText.renderText(5, 80, 160, 200, 10, LibColorUtils.neiHandlerBotaniaLexicaExtraInfoDesc.getColor(), s);
}
@Override
@@ -40,6 +40,13 @@ public class RecipeHandlerPetalApothecary extends TemplateRecipeHandler {
output = new PositionedStack(recipe.getOutput(), 111, 21);
}
// Kept for Alfheim, which calls super(recipe, false) from its NEI handler.
@Deprecated
@SuppressWarnings("unused")
public CachedPetalApothecaryRecipe(RecipePetals recipe, boolean addCenterItem) {
this(recipe);
}
public void setIngredients(List<Object> inputs) {
float degreePerInput = 360F / inputs.size();
float currentDegree = -90F;
@@ -74,10 +81,10 @@ public class RecipeHandlerPetalApothecary extends TemplateRecipeHandler {
@Override
public String getOverlayIdentifier() {
return "botania.petalApothecary";
return getRecipeID();
}
// Used by the Alfheim addon, identical to getOverlayIdentifier()
// Kept for Alfheim, which overrides this instead of getOverlayIdentifier().
@Deprecated
public String getRecipeID() {
return "botania.petalApothecary";
@@ -36,11 +36,11 @@ public class RenderSpecialFlower implements ISimpleBlockRenderingHandler, IMulti
@Override
public boolean renderWorldBlock(IBlockAccess blockAccess, int x, int y, int z, Block block, int modelId, RenderBlocks renderer) {
return renderCrossedSquares(blockAccess, block, x, y, z, renderer);
return renderCrossedSquares(blockAccess, block, x, y, z, 1.0F, true, renderer);
}
// Copied from RenderBlocks
public static boolean renderCrossedSquares(IBlockAccess blockAccess, Block block, int x, int y, int z, RenderBlocks render) {
public static boolean renderCrossedSquares(IBlockAccess blockAccess, Block block, int x, int y, int z, float scale, boolean doRandomShift, RenderBlocks render) {
Tessellator tessellator = Tessellator.instance;
tessellator.setBrightness(block.getMixedBrightnessForBlock(blockAccess, x, y, z));
float f = 1.0F;
@@ -64,16 +64,17 @@ public class RenderSpecialFlower implements ISimpleBlockRenderingHandler, IMulti
double d0 = z;
long sh;
sh = x * 3129871 ^ z * 116129781L ^ y;
sh = sh * sh * 42317861L + sh * 11L;
d1 += ((sh >> 16 & 15L) / 15.0F - 0.5D) * 0.3D;
d2 += (sh >> 32 & 15L) / 15.0F * -0.15D;
d0 += ((sh >> 24 & 15L) / 15.0F - 0.5D) * 0.3D;
if (doRandomShift) {
sh = x * 3129871 ^ z * 116129781L ^ y;
sh = sh * sh * 42317861L + sh * 11L;
d1 += ((sh >> 16 & 15L) / 15.0F - 0.5D) * 0.3D;
d2 += (sh >> 32 & 15L) / 15.0F * -0.15D;
d0 += ((sh >> 24 & 15L) / 15.0F - 0.5D) * 0.3D;
}
// Only change here, to use xyz rather than side/meta
IIcon icon = render.getBlockIcon(block, blockAccess, x, y, z, 0);
drawCrossedSquares(blockAccess, block, icon, x, y, z, d1, d2, d0, 1.0F, render);
drawCrossedSquares(blockAccess, block, icon, x, y, z, d1, d2, d0, scale, render);
return true;
}
@@ -10,6 +10,8 @@
*/
package vazkii.botania.client.render.item;
import java.lang.reflect.Field;
import net.minecraft.client.renderer.ItemRenderer;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.entity.player.EntityPlayer;
@@ -20,10 +22,13 @@ import net.minecraftforge.client.IItemRenderer;
import org.lwjgl.opengl.GL11;
import vazkii.botania.common.lib.LibObfuscation;
import cpw.mods.fml.relauncher.ReflectionHelper;
import vazkii.botania.utils.ReflectionUtils;
public class RenderBow implements IItemRenderer {
private static final Field ITEM_IN_USE = ReflectionUtils.findField(EntityPlayer.class, LibObfuscation.ITEM_IN_USE);
private static final Field ITEM_IN_USE_COUNT = ReflectionUtils.findField(EntityPlayer.class, LibObfuscation.ITEM_IN_USE_COUNT);
@Override
public boolean handleRenderType(ItemStack item, ItemRenderType type) {
return type != ItemRenderType.INVENTORY;
@@ -62,8 +67,11 @@ public class RenderBow implements IItemRenderer {
int dmg = item.getItemDamage();
IIcon icon = item.getItem().getIconFromDamageForRenderPass(dmg, 0);
if(player != null) {
ItemStack using = ReflectionHelper.getPrivateValue(EntityPlayer.class, player, LibObfuscation.ITEM_IN_USE);
int time = ReflectionHelper.getPrivateValue(EntityPlayer.class, player, LibObfuscation.ITEM_IN_USE_COUNT);
ItemStack using = (ItemStack) ReflectionUtils.getObject(ITEM_IN_USE, player);
int time = 0;
Object timeObj = ReflectionUtils.getObject(ITEM_IN_USE_COUNT, player);
if(timeObj != null)
time = (Integer) timeObj;
icon = item.getItem().getIcon(item, 0, player, using, time);
if(transform) {
GL11.glTranslatef(0.2F, -0.3F, 0.1F);
@@ -33,7 +33,8 @@ public class RenderTileCocoon extends TileEntitySpecialRenderer {
float rot = 0F;
float modval = 60F - (float) cocoon.timePassed / (float) TileCocoon.TOTAL_TIME * 30F;
if(cocoon.timePassed % modval < 10) {
// At timePassed 0 with partialTicks 0 (inventory/NEI render), log(0) makes rot NaN and the model disappears.
if(cocoon.timePassed > 0 && cocoon.timePassed % modval < 10) {
float mod = (cocoon.timePassed + partialTicks) % modval;
float v = mod / 5 * (float) Math.PI * 2;
rot = (float) Math.sin(v) * (float) Math.log(cocoon.timePassed + partialTicks);
@@ -10,6 +10,7 @@
*/
package vazkii.botania.client.render.world;
import java.lang.reflect.Field;
import java.util.Random;
import net.minecraft.client.Minecraft;
@@ -18,6 +19,7 @@ import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.client.renderer.RenderGlobal;
import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.entity.Entity;
import net.minecraft.util.MathHelper;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.Vec3;
@@ -28,7 +30,7 @@ import org.lwjgl.opengl.GL11;
import vazkii.botania.client.core.handler.ClientTickHandler;
import vazkii.botania.client.lib.LibResources;
import vazkii.botania.common.lib.LibObfuscation;
import cpw.mods.fml.relauncher.ReflectionHelper;
import vazkii.botania.utils.ReflectionUtils;
public class SkyblockSkyRenderer extends IRenderHandler {
@@ -45,22 +47,48 @@ public class SkyblockSkyRenderer extends IRenderHandler {
new ResourceLocation(LibResources.MISC_PLANET + "5.png")
};
private static final Field GL_SKY_LIST = ReflectionUtils.findField(RenderGlobal.class, LibObfuscation.GL_SKY_LIST);
private static final Field STAR_GL_CALL_LIST = ReflectionUtils.findField(RenderGlobal.class, LibObfuscation.STAR_GL_CALL_LIST);
// rainbow angles are deterministic per in-game day
private static int lastRainbowDay = -1;
private static float rainbowAngle1, rainbowAngle2;
// sky color samples, interpolated across ticks by partialTicks
private static int lastSkySampleTick = -1;
private static float skyRed0, skyGreen0, skyBlue0;
private static float skyRed1, skyGreen1, skyBlue1;
@Override
public void render(float partialTicks, WorldClient world, Minecraft mc) {
int glSkyList = ReflectionHelper.getPrivateValue(RenderGlobal.class, mc.renderGlobal, LibObfuscation.GL_SKY_LIST);
int starGLCallList = ReflectionHelper.getPrivateValue(RenderGlobal.class, mc.renderGlobal, LibObfuscation.STAR_GL_CALL_LIST);
int glSkyList = ReflectionUtils.getInt(GL_SKY_LIST, mc.renderGlobal);
int starGLCallList = ReflectionUtils.getInt(STAR_GL_CALL_LIST, mc.renderGlobal);
GL11.glDisable(GL11.GL_TEXTURE_2D);
Vec3 vec3 = world.getSkyColor(mc.renderViewEntity, partialTicks);
float f1 = (float)vec3.xCoord;
float f2 = (float)vec3.yCoord;
float f3 = (float)vec3.zCoord;
Entity viewEntity = mc.renderViewEntity;
int tick = ClientTickHandler.ticksInGame;
if(tick != lastSkySampleTick) {
if(lastSkySampleTick != -1) {
skyRed0 = skyRed1;
skyGreen0 = skyGreen1;
skyBlue0 = skyBlue1;
}
Vec3 sample = world.getSkyColor(viewEntity, 1.0F);
skyRed1 = (float) sample.xCoord;
skyGreen1 = (float) sample.yCoord;
skyBlue1 = (float) sample.zCoord;
lastSkySampleTick = tick;
}
float frac = Math.min(1F, Math.max(0F, partialTicks));
float f1 = skyRed0 + (skyRed1 - skyRed0) * frac;
float f2 = skyGreen0 + (skyGreen1 - skyGreen0) * frac;
float f3 = skyBlue0 + (skyBlue1 - skyBlue0) * frac;
float f6;
float insideVoid = 0;
if(mc.thePlayer.posY <= -2)
insideVoid = (float) Math.min(1F, -(mc.thePlayer.posY + 2) / 30F);
if(viewEntity.posY <= -2)
insideVoid = (float) Math.min(1F, -(viewEntity.posY + 2) / 30F);
f1 = Math.max(0F, f1 - insideVoid);
f2 = Math.max(0F, f2 - insideVoid);
@@ -241,9 +269,14 @@ public class SkyblockSkyRenderer extends IRenderHandler {
long time = world.getWorldTime() + 1000;
int day = (int) (time / 24000L);
Random rand = new Random(day * 0xFF);
float angle1 = rand.nextFloat() * 360F;
float angle2 = rand.nextFloat() * 360F;
if(lastRainbowDay != day) {
Random rand = new Random(day * 0xFF);
rainbowAngle1 = rand.nextFloat() * 360F;
rainbowAngle2 = rand.nextFloat() * 360F;
lastRainbowDay = day;
}
float angle1 = rainbowAngle1;
float angle2 = rainbowAngle2;
GL11.glColor4f(1F, 1F, 1F, effCelAng1 * (1F - insideVoid));
GL11.glRotatef(angle1, 0F, 1F, 0F);
GL11.glRotatef(angle2, 0F, 0F, 1F);
@@ -62,10 +62,13 @@ public class BlockAlfPortal extends BlockModContainer<TileAlfPortal> implements
@Override
public boolean onUsedByWand(EntityPlayer player, ItemStack stack, World world, int x, int y, int z, int side) {
boolean did = ((TileAlfPortal) world.getTileEntity(x, y, z)).onWanded();
if(did && player != null)
player.addStat(ModAchievements.elfPortalOpen, 1);
return did;
if(!world.isRemote) {
boolean did = ((TileAlfPortal) world.getTileEntity(x, y, z)).onWanded();
if(did && player != null)
player.addStat(ModAchievements.elfPortalOpen, 1);
return did;
}
return true;
}
@Override
@@ -10,12 +10,16 @@
*/
package vazkii.botania.common.block;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import com.gtnewhorizon.gtnhlib.api.IFlowerPottable;
import net.minecraft.block.Block;
import net.minecraft.block.BlockFlower;
import net.minecraft.block.IGrowable;
import net.minecraft.client.renderer.RenderBlocks;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.texture.IIconRegister;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.item.EntityItem;
@@ -23,13 +27,16 @@ import net.minecraft.entity.passive.EntitySheep;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.stats.Achievement;
import net.minecraft.util.IIcon;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import vazkii.botania.api.lexicon.ILexiconable;
import vazkii.botania.api.lexicon.LexiconEntry;
import vazkii.botania.client.core.helper.IconHelper;
import vazkii.botania.client.lib.LibRenderIDs;
import vazkii.botania.client.render.block.RenderSpecialFlower;
import vazkii.botania.common.Botania;
import vazkii.botania.common.achievement.IPickupAchievement;
import vazkii.botania.common.achievement.ModAchievements;
@@ -42,7 +49,7 @@ import cpw.mods.fml.common.registry.GameRegistry;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
public class BlockModFlower extends BlockFlower implements ILexiconable, IPickupAchievement, IGrowable {
public class BlockModFlower extends BlockFlower implements ILexiconable, IPickupAchievement, IGrowable, IFlowerPottable {
public static IIcon[] icons;
public static IIcon[] iconsAlt;
@@ -156,4 +163,12 @@ public class BlockModFlower extends BlockFlower implements ILexiconable, IPickup
world.setBlock(x, y + 1, z, flower, placeMeta | 8, flags);
}
@Override
public boolean renderFlowerPot(NBTTagCompound compound, IBlockAccess blockAccess, Block block, int x, int y, int z, RenderBlocks render) {
Tessellator tess = Tessellator.instance;
tess.addTranslation(0, 4F / 16F, 0);
boolean b = RenderSpecialFlower.renderCrossedSquares(blockAccess, block, x, y, z, 0.75F, false, render);
tess.addTranslation(0, -4F / 16F, 0);
return b;
}
}
@@ -13,6 +13,7 @@ package vazkii.botania.common.block.decor;
import java.util.List;
import java.util.Random;
import com.gtnewhorizon.gtnhlib.api.IFlowerPottable;
import net.minecraft.block.Block;
import net.minecraft.block.BlockMushroom;
import net.minecraft.client.renderer.texture.IIconRegister;
@@ -44,7 +45,7 @@ import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
@Optional.Interface(modid = "Thaumcraft", iface = "thaumcraft.api.crafting.IInfusionStabiliser", striprefs = true)
public class BlockModMushroom extends BlockMushroom implements IInfusionStabiliser, IHornHarvestable, ILexiconable {
public class BlockModMushroom extends BlockMushroom implements IInfusionStabiliser, IHornHarvestable, ILexiconable, IFlowerPottable {
public static IIcon[] icons;
public int originalLight;
@@ -10,6 +10,7 @@
*/
package vazkii.botania.common.block.subtile.functional;
import java.lang.reflect.Field;
import java.util.List;
import net.minecraft.entity.item.EntityItem;
@@ -21,10 +22,12 @@ import vazkii.botania.api.subtile.RadiusDescriptor;
import vazkii.botania.api.subtile.SubTileFunctional;
import vazkii.botania.common.lexicon.LexiconData;
import vazkii.botania.common.lib.LibObfuscation;
import cpw.mods.fml.relauncher.ReflectionHelper;
import vazkii.botania.utils.ReflectionUtils;
public class SubTilePollidisiac extends SubTileFunctional {
private static final Field IN_LOVE = ReflectionUtils.findField(EntityAnimal.class, LibObfuscation.IN_LOVE);
private static final int RANGE = 6;
@Override
@@ -42,7 +45,7 @@ public class SubTilePollidisiac extends SubTileFunctional {
if(mana < manaCost)
break;
int love = ReflectionHelper.getPrivateValue(EntityAnimal.class, animal, LibObfuscation.IN_LOVE);
int love = ReflectionUtils.getInt(IN_LOVE, animal);
if(animal.getGrowingAge() == 0 && love <= 0) {
for(EntityItem item : items) {
if(item.age < (60 + slowdown) || item.isDead)
@@ -56,7 +59,7 @@ public class SubTilePollidisiac extends SubTileFunctional {
mana -= manaCost;
ReflectionHelper.setPrivateValue(EntityAnimal.class, animal, 1200, LibObfuscation.IN_LOVE);
ReflectionUtils.setInt(IN_LOVE, animal, 1200);
animal.setTarget(null);
supertile.getWorldObj().setEntityState(animal, (byte)18);
}
@@ -10,6 +10,7 @@
*/
package vazkii.botania.common.block.subtile.functional;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
@@ -27,10 +28,14 @@ import vazkii.botania.api.subtile.RadiusDescriptor;
import vazkii.botania.api.subtile.SubTileFunctional;
import vazkii.botania.common.lexicon.LexiconData;
import vazkii.botania.common.lib.LibObfuscation;
import cpw.mods.fml.relauncher.ReflectionHelper;
import vazkii.botania.utils.ReflectionUtils;
public class SubTileTigerseye extends SubTileFunctional {
private static final Field TIME_SINCE_IGNITED = ReflectionUtils.findField(EntityCreeper.class, LibObfuscation.TIME_SINCE_IGNITED);
private static final Field TARGET_ENTITY_CLASS = ReflectionUtils.findField(EntityAIAvoidEntity.class, LibObfuscation.TARGET_ENTITY_CLASS);
private static final Field TARGET_CLASS = ReflectionUtils.findField(EntityAINearestAttackableTarget.class, LibObfuscation.TARGET_CLASS);
private static final int RANGE = 10;
private static final int RANGE_Y = 4;
@@ -58,7 +63,7 @@ public class SubTileTigerseye extends SubTileFunctional {
}
if(entity instanceof EntityCreeper) {
ReflectionHelper.setPrivateValue(EntityCreeper.class, (EntityCreeper) entity, 2, LibObfuscation.TIME_SINCE_IGNITED);
ReflectionUtils.setInt(TIME_SINCE_IGNITED, entity, 2);
entity.setAttackTarget(null);
}
@@ -71,16 +76,16 @@ public class SubTileTigerseye extends SubTileFunctional {
}
private boolean messWithRunAwayAI(EntityAIAvoidEntity aiEntry) {
if(ReflectionHelper.getPrivateValue(EntityAIAvoidEntity.class, aiEntry, LibObfuscation.TARGET_ENTITY_CLASS) == EntityOcelot.class) {
ReflectionHelper.setPrivateValue(EntityAIAvoidEntity.class, aiEntry, EntityPlayer.class, LibObfuscation.TARGET_ENTITY_CLASS);
if(ReflectionUtils.getObject(TARGET_ENTITY_CLASS, aiEntry) == EntityOcelot.class) {
ReflectionUtils.setObject(TARGET_ENTITY_CLASS, aiEntry, EntityPlayer.class);
return true;
}
return false;
}
private void messWithGetTargetAI(EntityAINearestAttackableTarget aiEntry) {
if(ReflectionHelper.getPrivateValue(EntityAINearestAttackableTarget.class, aiEntry, LibObfuscation.TARGET_CLASS) == EntityPlayer.class)
ReflectionHelper.setPrivateValue(EntityAINearestAttackableTarget.class, aiEntry, EntityEnderCrystal.class, LibObfuscation.TARGET_CLASS); // Something random that won't be around
if(ReflectionUtils.getObject(TARGET_CLASS, aiEntry) == EntityPlayer.class)
ReflectionUtils.setObject(TARGET_CLASS, aiEntry, EntityEnderCrystal.class); // Something random that won't be around
}
@Override
@@ -101,6 +101,7 @@ public class SubTileEntropinnyum extends SubTileGenerating {
if (world.isRemote || mana != 0 || !(Math.abs(supertile.xCoord - posX) <= RANGE && Math.abs(supertile.yCoord - posY) <= RANGE && Math.abs(supertile.zCoord - posZ) <= RANGE)) {
return false;
}
if (explosionSource == null) return false;
explosionSource.setDead();
mana += getMaxMana();
@@ -167,7 +167,8 @@ public class TileAlfPortal extends TileMod {
} else closeNow = false;
if(closeNow) {
worldObj.setBlockMetadataWithNotify(xCoord, yCoord, zCoord, 0, 1 | 2);
if(!worldObj.isRemote)
worldObj.setBlockMetadataWithNotify(xCoord, yCoord, zCoord, 0, 1 | 2);
for(int i = 0; i < 36; i++)
blockParticle(meta);
closeNow = false;
@@ -175,7 +176,8 @@ public class TileAlfPortal extends TileMod {
if(newMeta == 0)
for(int i = 0; i < 36; i++)
blockParticle(meta);
worldObj.setBlockMetadataWithNotify(xCoord, yCoord, zCoord, newMeta, 1 | 2);
if(!worldObj.isRemote)
worldObj.setBlockMetadataWithNotify(xCoord, yCoord, zCoord, newMeta, 1 | 2);
} else if(explode) {
worldObj.createExplosion(null, xCoord + .5, yCoord + 2.0, zCoord + .5, 3f, true);
explode = false;
@@ -22,8 +22,8 @@ import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.AxisAlignedBB;
import vazkii.botania.api.BotaniaAPI;
import vazkii.botania.api.brew.BrewUtilities;
import vazkii.botania.api.brew.IBrewContainer;
import vazkii.botania.api.brew.IBrewItem;
import vazkii.botania.api.internal.VanillaPacketDispatcher;
import vazkii.botania.api.mana.IManaReceiver;
import vazkii.botania.api.recipe.RecipeBrew;
@@ -42,7 +42,7 @@ public class TileBrewery extends TileSimpleInventory implements ISidedInventory,
public int signal = 0;
public boolean addItem(EntityPlayer player, ItemStack stack) {
if(recipe != null || stack == null || stack.getItem() instanceof IBrewItem && ((IBrewItem) stack.getItem()).getBrew(stack) != null && ((IBrewItem) stack.getItem()).getBrew(stack) != BotaniaAPI.fallbackBrew || getStackInSlot(0) == null != stack.getItem() instanceof IBrewContainer)
if (recipe != null || stack == null || BrewUtilities.isFilledBrew(stack) || (getStackInSlot(0) == null) != (stack.getItem() instanceof IBrewContainer))
return false;
boolean did = false;
@@ -153,10 +153,9 @@ public class TileBrewery extends TileSimpleInventory implements ISidedInventory,
public int getManaCost() {
ItemStack stack = getStackInSlot(0);
if(recipe == null || stack == null || !(stack.getItem() instanceof IBrewContainer))
if(recipe == null || stack == null || !(stack.getItem() instanceof IBrewContainer container))
return 0;
IBrewContainer container = (IBrewContainer) stack.getItem();
return container.getManaCost(recipe.getBrew(), stack);
return container.getManaCost(recipe.getBrew(), stack);
}
public void craftingFanciness() {
@@ -10,6 +10,7 @@
*/
package vazkii.botania.common.block.tile;
import java.lang.reflect.Field;
import java.util.List;
import net.minecraft.entity.Entity;
@@ -24,12 +25,19 @@ import net.minecraft.util.WeightedRandom;
import vazkii.botania.api.mana.IManaReceiver;
import vazkii.botania.common.Botania;
import vazkii.botania.common.lib.LibObfuscation;
import cpw.mods.fml.relauncher.ReflectionHelper;
import vazkii.botania.utils.ReflectionUtils;
public class TileSpawnerClaw extends TileMod implements IManaReceiver {
private static final String TAG_MANA = "mana";
private static final Field SPAWN_COUNT = ReflectionUtils.findField(MobSpawnerBaseLogic.class, LibObfuscation.SPAWN_COUNT);
private static final Field SPAWN_RANGE = ReflectionUtils.findField(MobSpawnerBaseLogic.class, LibObfuscation.SPAWN_RANGE);
private static final Field MAX_NEARBY_ENTITIES = ReflectionUtils.findField(MobSpawnerBaseLogic.class, LibObfuscation.MAX_NEARBY_ENTITIES);
private static final Field MAX_SPAWN_DELAY = ReflectionUtils.findField(MobSpawnerBaseLogic.class, LibObfuscation.MAX_SPAWN_DELAY);
private static final Field MIN_SPAWN_DELAY = ReflectionUtils.findField(MobSpawnerBaseLogic.class, LibObfuscation.MIN_SPAWN_DELAY);
private static final Field POTENTIAL_ENTITY_SPAWNS = ReflectionUtils.findField(MobSpawnerBaseLogic.class, LibObfuscation.POTENTIAL_ENTITY_SPAWNS);
int mana = 0;
@Override
@@ -61,9 +69,9 @@ public class TileSpawnerClaw extends TileMod implements IManaReceiver {
boolean flag = false;
int spawnCount = ReflectionHelper.getPrivateValue(MobSpawnerBaseLogic.class, logic, LibObfuscation.SPAWN_COUNT);
int spawnRange = ReflectionHelper.getPrivateValue(MobSpawnerBaseLogic.class, logic, LibObfuscation.SPAWN_RANGE);
int maxNearbyEntities = ReflectionHelper.getPrivateValue(MobSpawnerBaseLogic.class, logic, LibObfuscation.MAX_NEARBY_ENTITIES);
int spawnCount = ReflectionUtils.getInt(SPAWN_COUNT, logic);
int spawnRange = ReflectionUtils.getInt(SPAWN_RANGE, logic);
int maxNearbyEntities = ReflectionUtils.getInt(MAX_NEARBY_ENTITIES, logic);
for(int i = 0; i < spawnCount; ++i) {
Entity entity = EntityList.createEntityByName(logic.getEntityNameToSpawn(), logic.getSpawnerWorld());
@@ -103,9 +111,9 @@ public class TileSpawnerClaw extends TileMod implements IManaReceiver {
}
private void resetTimer(MobSpawnerBaseLogic logic) {
int maxSpawnDelay = ReflectionHelper.getPrivateValue(MobSpawnerBaseLogic.class, logic, LibObfuscation.MAX_SPAWN_DELAY);
int minSpawnDelay = ReflectionHelper.getPrivateValue(MobSpawnerBaseLogic.class, logic, LibObfuscation.MIN_SPAWN_DELAY);
List<MobSpawnerBaseLogic.WeightedRandomMinecart> potentialEntitySpawns = ReflectionHelper.getPrivateValue(MobSpawnerBaseLogic.class, logic, LibObfuscation.POTENTIAL_ENTITY_SPAWNS);
int maxSpawnDelay = ReflectionUtils.getInt(MAX_SPAWN_DELAY, logic);
int minSpawnDelay = ReflectionUtils.getInt(MIN_SPAWN_DELAY, logic);
List<MobSpawnerBaseLogic.WeightedRandomMinecart> potentialEntitySpawns = (List<MobSpawnerBaseLogic.WeightedRandomMinecart>) ReflectionUtils.getObject(POTENTIAL_ENTITY_SPAWNS, logic);
if(maxSpawnDelay <= minSpawnDelay)
logic.spawnDelay = minSpawnDelay;
@@ -285,6 +285,13 @@ public class TileCorporeaIndex extends TileCorporeaBase implements ICorporeaRequ
}
}
public static boolean hasNearbyIndexes(EntityPlayer player) {
for(TileCorporeaIndex index : indexes)
if(isInRangeOfIndex(player, index) && index.worldObj.isRemote == player.worldObj.isRemote)
return true;
return false;
}
public static List<TileCorporeaIndex> getNearbyIndexes(EntityPlayer player) {
List<TileCorporeaIndex> indexList = new ArrayList<>();
for(TileCorporeaIndex index : indexes)
@@ -296,7 +303,7 @@ public class TileCorporeaIndex extends TileCorporeaBase implements ICorporeaRequ
@Override
@SideOnly(Side.CLIENT)
public boolean shouldAutoComplete() {
return !getNearbyIndexes(Minecraft.getMinecraft().thePlayer).isEmpty();
return hasNearbyIndexes(Minecraft.getMinecraft().thePlayer);
}
}
@@ -302,7 +302,7 @@ public class TileSpreader extends TileSimpleInventory implements IManaCollector,
long least = compound.getLong(TAG_UUID_LEAST);
UUID identity = getIdentifierUnsafe();
if(identity == null || most != identity.getMostSignificantBits() || least != identity.getLeastSignificantBits())
identity = new UUID(most, least);
this.identity = new UUID(most, least);
} else getIdentifier();
mana = compound.getInteger(TAG_MANA);
@@ -464,8 +464,6 @@ public class TileSpreader extends TileSimpleInventory implements IManaCollector,
}
public EntityManaBurst getBurst(boolean fake) {
EntityManaBurst burst = new EntityManaBurst(this, fake);
boolean dreamwood = isDreamwood();
boolean ultra = isULTRA_SPREADER();
int maxMana = ultra ? 640 : dreamwood ? 240 : 160;
@@ -480,29 +478,31 @@ public class TileSpreader extends TileSimpleInventory implements IManaCollector,
if(lens != null && lens.getItem() instanceof ILensEffect)
((ILensEffect) lens.getItem()).apply(lens, props);
burst.setSourceLens(lens);
if(getCurrentMana() >= props.maxMana || fake) {
if(mapmakerOverride) {
burst.setColor(mmForcedColor);
burst.setMana(mmForcedManaPayload);
burst.setStartingMana(mmForcedManaPayload);
burst.setMinManaLoss(mmForcedTicksBeforeManaLoss);
burst.setManaLossPerTick(mmForcedManaLossPerTick);
burst.setGravity(mmForcedGravity);
burst.setMotion(burst.motionX * mmForcedVelocityMultiplier, burst.motionY * mmForcedVelocityMultiplier, burst.motionZ * mmForcedVelocityMultiplier);
} else {
burst.setColor(props.color);
burst.setMana(props.maxMana);
burst.setStartingMana(props.maxMana);
burst.setMinManaLoss(props.ticksBeforeManaLoss);
burst.setManaLossPerTick(props.manaLossPerTick);
burst.setGravity(props.gravity);
burst.setMotion(burst.motionX * props.motionModifier, burst.motionY * props.motionModifier, burst.motionZ * props.motionModifier);
}
if(getCurrentMana() < props.maxMana && !fake)
return null;
return burst;
// Construct the entity only after the mana check, every new Entity takes a global entity ID
EntityManaBurst burst = new EntityManaBurst(this, fake);
burst.setSourceLens(lens);
if(mapmakerOverride) {
burst.setColor(mmForcedColor);
burst.setMana(mmForcedManaPayload);
burst.setStartingMana(mmForcedManaPayload);
burst.setMinManaLoss(mmForcedTicksBeforeManaLoss);
burst.setManaLossPerTick(mmForcedManaLossPerTick);
burst.setGravity(mmForcedGravity);
burst.setMotion(burst.motionX * mmForcedVelocityMultiplier, burst.motionY * mmForcedVelocityMultiplier, burst.motionZ * mmForcedVelocityMultiplier);
} else {
burst.setColor(props.color);
burst.setMana(props.maxMana);
burst.setStartingMana(props.maxMana);
burst.setMinManaLoss(props.ticksBeforeManaLoss);
burst.setManaLossPerTick(props.manaLossPerTick);
burst.setGravity(props.gravity);
burst.setMotion(burst.motionX * props.motionModifier, burst.motionY * props.motionModifier, burst.motionZ * props.motionModifier);
}
return null;
return burst;
}
public ILensControl getLensController(ItemStack stack) {
@@ -10,14 +10,24 @@
*/
package vazkii.botania.common.core.helper;
import java.lang.reflect.Field;
import net.minecraft.client.particle.EffectRenderer;
import net.minecraft.util.ResourceLocation;
import vazkii.botania.common.lib.LibObfuscation;
import cpw.mods.fml.relauncher.ReflectionHelper;
import vazkii.botania.utils.ReflectionUtils;
public class ObfuscationHelper {
private static Field particleTextureField;
private static boolean particleTextureResolved = false;
public static ResourceLocation getParticleTexture() {
return ReflectionHelper.getPrivateValue(EffectRenderer.class, null, LibObfuscation.PARTICLE_TEXTURES);
if(!particleTextureResolved) {
particleTextureField = ReflectionUtils.findField(EffectRenderer.class, LibObfuscation.PARTICLE_TEXTURES);
particleTextureResolved = true;
}
return (ResourceLocation) ReflectionUtils.getObject(particleTextureField, null);
}
}
@@ -33,7 +33,6 @@ import vazkii.botania.api.BotaniaAPI;
import vazkii.botania.api.lexicon.ITwoNamedPage;
import vazkii.botania.api.lexicon.LexiconEntry;
import vazkii.botania.api.lexicon.LexiconPage;
import vazkii.botania.client.integration.nei.IMCForNEI;
import vazkii.botania.common.Botania;
import vazkii.botania.common.achievement.ModAchievements;
import vazkii.botania.common.block.ModBlocks;
@@ -153,10 +152,6 @@ public class CommonProxy {
new StatementAPIPlugin();
LexiconData.init();
if (Botania.neiLoaded) {
IMCForNEI.IMCSender();
}
}
public void postInit(FMLPostInitializationEvent event) {
@@ -261,6 +256,13 @@ public class CommonProxy {
((EntityPlayerMP) entity).theItemInWorldManager.setBlockReachDistance(Math.max(5, ((EntityPlayerMP) entity).theItemInWorldManager.getBlockReachDistance() + reach));
}
/**
* Sets (instead of adds to) the extra reach of the client player. No-op on the server.
*/
public void setClientExtraReach(EntityLivingBase entity, float reach) {
// NO-OP
}
public boolean openWikiPage(World world, Block block, MovingObjectPosition pos) {
return false;
}
@@ -11,6 +11,7 @@
package vazkii.botania.common.entity;
import java.awt.Rectangle;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -74,12 +75,14 @@ import vazkii.botania.common.core.helper.Vector3;
import vazkii.botania.common.item.ModItems;
import vazkii.botania.common.item.relic.ItemRelic;
import vazkii.botania.common.lib.LibObfuscation;
import cpw.mods.fml.relauncher.ReflectionHelper;
import vazkii.botania.utils.ReflectionUtils;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
public class EntityDoppleganger extends EntityCreature implements IBotaniaBossWithShader {
private static final Field IS_BAD_EFFECT = ReflectionUtils.findField(Potion.class, LibObfuscation.IS_BAD_EFFECT);
public static final int SPAWN_TICKS = 160;
private static final float RANGE = 12F;
private static final float MAX_HP = 800F;
@@ -587,7 +590,7 @@ public class EntityDoppleganger extends EntityCreature implements IBotaniaBossWi
List<PotionEffect> remove = new ArrayList<>();
Collection<PotionEffect> active = player.getActivePotionEffects();
for(PotionEffect effect : active)
if(effect.getDuration() < 200 && effect.getIsAmbient() && !ReflectionHelper.<Boolean, Potion>getPrivateValue(Potion.class, Potion.potionTypes[effect.getPotionID()], LibObfuscation.IS_BAD_EFFECT))
if(effect.getDuration() < 200 && effect.getIsAmbient() && !ReflectionUtils.getBoolean(IS_BAD_EFFECT, Potion.potionTypes[effect.getPotionID()], true))
remove.add(effect);
active.removeAll(remove);
@@ -866,6 +869,7 @@ public class EntityDoppleganger extends EntityCreature implements IBotaniaBossWi
private static Rectangle barRect;
@SideOnly(Side.CLIENT)
private static Rectangle hpBarRect;
private static ItemStack skullStack;
@Override
@SideOnly(Side.CLIENT)
@@ -891,11 +895,12 @@ public class EntityDoppleganger extends EntityCreature implements IBotaniaBossWi
int py = y + 12;
Minecraft mc = Minecraft.getMinecraft();
ItemStack stack = new ItemStack(Items.skull, 1, 3);
if(skullStack == null)
skullStack = new ItemStack(Items.skull, 1, 3);
mc.renderEngine.bindTexture(TextureMap.locationItemsTexture);
net.minecraft.client.renderer.RenderHelper.enableGUIStandardItemLighting();
GL11.glEnable(GL12.GL_RESCALE_NORMAL);
RenderItem.getInstance().renderItemIntoGUI(mc.fontRenderer, mc.renderEngine, stack, px, py);
RenderItem.getInstance().renderItemIntoGUI(mc.fontRenderer, mc.renderEngine, skullStack, px, py);
net.minecraft.client.renderer.RenderHelper.disableStandardItemLighting();
boolean unicode = mc.fontRenderer.getUnicodeFlag();
@@ -21,14 +21,16 @@ import vazkii.botania.common.core.handler.ConfigHandler;
import java.util.List;
public class ItemBlockModSlab extends ItemSlab {
private final String unlocalizedName;
public ItemBlockModSlab(Block blockSlab) {
super(blockSlab, ((BlockModSlab)blockSlab).getSingleBlock(), ((BlockModSlab)blockSlab).getFullBlock(), false);
unlocalizedName = blockSlab.getUnlocalizedName().replace("tile.", "tile.botania:");
}
@Override
public String getUnlocalizedName(ItemStack stack) {
return field_150939_a.getUnlocalizedName().replaceAll("tile.", "tile.botania:");
return unlocalizedName;
}
@Override
public void addInformation(ItemStack stack, EntityPlayer player, List<String> infoList, boolean advanced) {
@@ -33,6 +33,7 @@ import vazkii.botania.api.item.ICosmeticAttachable;
import vazkii.botania.api.item.ICosmeticBauble;
import vazkii.botania.common.lib.LibItemNames;
import baubles.api.BaubleType;
import baubles.common.container.InventoryBaubles;
import baubles.common.lib.PlayerHandler;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
@@ -104,8 +105,12 @@ public class ItemMonocle extends ItemBauble implements IBurstViewerBauble, ICosm
}
public static boolean hasMonocle(EntityPlayer player) {
return hasMonocle(PlayerHandler.getPlayerBaubles(player));
}
public static boolean hasMonocle(InventoryBaubles inv) {
for(int i = 0; i < 4; i++) {
ItemStack stack = PlayerHandler.getPlayerBaubles(player).getStackInSlot(i);
ItemStack stack = inv.getStackInSlot(i);
if(stack != null) {
Item item = stack.getItem();
if(item instanceof IBurstViewerBauble)
@@ -11,10 +11,13 @@
package vazkii.botania.common.item.equipment.bauble;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
import vazkii.botania.common.Botania;
import vazkii.botania.common.lib.LibItemNames;
import baubles.api.BaubleType;
import baubles.api.BaublesApi;
public class ItemReachRing extends ItemBauble {
@@ -27,6 +30,29 @@ public class ItemReachRing extends ItemBauble {
Botania.proxy.setExtraReach(player, 3.5F);
}
@Override
public void onPlayerLoad(ItemStack stack, EntityLivingBase player) {
if(player.worldObj.isRemote) {
// Baubles resends all baubles to the client on login and on every dimension change and calls this for each
// of them, but the client keeps its reach extension across dimension changes. Set it instead of adding to it.
Botania.proxy.setClientExtraReach(player, 3.5F * countWornRings(player));
} else super.onPlayerLoad(stack, player);
}
private static int countWornRings(EntityLivingBase player) {
if(!(player instanceof EntityPlayer))
return 0;
int count = 0;
IInventory baubles = BaublesApi.getBaubles((EntityPlayer) player);
for(int i = 0; i < baubles.getSizeInventory(); i++) {
ItemStack bauble = baubles.getStackInSlot(i);
if(bauble != null && bauble.getItem() instanceof ItemReachRing)
count++;
}
return count;
}
@Override
public void onUnequipped(ItemStack stack, EntityLivingBase player) {
Botania.proxy.setExtraReach(player, -3.5F);
@@ -19,12 +19,13 @@ import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.StatCollector;
import net.minecraftforge.oredict.OreDictionary;
import vazkii.botania.api.BotaniaAPI;
import vazkii.botania.api.brew.Brew;
import vazkii.botania.api.internal.IGuiLexiconEntry;
import vazkii.botania.api.lexicon.ILexicon;
import vazkii.botania.api.lexicon.ITwoNamedPage;
import vazkii.botania.api.lexicon.LexiconRecipeMappings;
import vazkii.botania.api.recipe.RecipeBrew;
import vazkii.botania.client.core.helper.BrewHelper;
import vazkii.botania.common.item.ModItems;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
@@ -51,50 +52,48 @@ public class PageBrew extends PageRecipe implements ITwoNamedPage {
FontRenderer renderer = Minecraft.getMinecraft().fontRenderer;
boolean unicode = renderer.getUnicodeFlag();
renderer.setUnicodeFlag(true);
String s = EnumChatFormatting.BOLD + String.format(StatCollector.translateToLocal("botaniamisc.brewOf"), StatCollector.translateToLocal(brew.getUnlocalizedName()));
String s = EnumChatFormatting.BOLD + StatCollector.translateToLocalFormatted("botaniamisc.brewOf", StatCollector.translateToLocal(brew.getUnlocalizedName()));
renderer.drawString(s, gui.getLeft() + gui.getWidth() / 2 - renderer.getStringWidth(s) / 2, y, 0x222222);
renderer.setUnicodeFlag(unicode);
PageText.renderText(x, y + 22, width, height, text);
ItemStack book = Minecraft.getMinecraft().thePlayer.getCurrentEquippedItem();
if(book != null && book.getItem() instanceof ILexicon && ((ILexicon) book.getItem()).isKnowledgeUnlocked(book, BotaniaAPI.elvenKnowledge)) {
renderItemAtLinePos(gui, 20, 2, y + 12, recipe.getOutput(new ItemStack(ModItems.vial)));
renderItemAtLinePos(gui, 20, 3, y + 12, recipe.getOutput(new ItemStack(ModItems.vial, 1, 1)));
} else renderItemAtLinePos(gui, 0, -1, y + 12, recipe.getOutput(new ItemStack(ModItems.vial)));
renderItemRow(gui, getOutputs(book), y + 12);
int i = 0;
y = gui.getTop() + gui.getHeight() - 54;
y = gui.getTop() + gui.getHeight() - 54;
List<Object> inputs = new ArrayList<>(recipe.getInputs());
int offset = gui.getWidth() / 2 - inputs.size() * 9;
for(Object input : inputs) {
if(input instanceof String)
input = OreDictionary.getOres((String) input).get(0);
renderItemRow(gui, inputs, y);
renderItemAtLinePos(gui, offset, i, y, (ItemStack) input);
i++;
}
super.renderRecipe(gui, mx, my);
super.renderRecipe(gui, mx, my);
}
@SideOnly(Side.CLIENT)
public void renderItemAtLinePos(IGuiLexiconEntry gui, int offset, int pos, int yPos, ItemStack stack) {
if(stack == null || stack.getItem() == null)
return;
stack = stack.copy();
@SideOnly(Side.CLIENT)
private void renderItemRow(IGuiLexiconEntry gui, List<?> inputs, int y) {
int spacing = Math.min(gui.getWidth() / inputs.size(), 18);
int x = gui.getLeft() + (gui.getWidth() - spacing * inputs.size()) / 2;
if(stack.getItemDamage() == Short.MAX_VALUE)
stack.setItemDamage(0);
for (Object input : inputs) {
ItemStack stack;
if (input instanceof String) {
stack = OreDictionary.getOres((String) input).get(0);
} else {
stack = (ItemStack) input;
}
int xPos = gui.getLeft() + (pos == -1 ? gui.getWidth() / 2 - 8 : pos * 18) + offset;
if (stack == null || stack.getItem() == null) continue;
ItemStack stack1 = stack.copy();
if(stack1.getItemDamage() == -1)
stack1.setItemDamage(0);
if (stack.getItemDamage() == Short.MAX_VALUE || stack.getItemDamage() == -1) {
ItemStack newStack = new ItemStack(stack.getItem(), stack.stackSize, 0);
newStack.stackTagCompound = stack.stackTagCompound;
stack = newStack;
}
renderItem(gui, xPos, yPos, stack1, false);
}
renderItem(gui, x, y, stack, false);
x += spacing;
}
}
@Override
public List<ItemStack> getDisplayedRecipes() {
@@ -105,6 +104,27 @@ public class PageBrew extends PageRecipe implements ITwoNamedPage {
return list;
}
private List<ItemStack> getOutputs(ItemStack lexicon) {
ArrayList<ItemStack> list = new ArrayList<>();
for (ItemStack empty : BrewHelper.getBrewContainers()) {
if (lexicon != null && lexicon.getItem() instanceof ILexicon lexItem) {
// Check if the lexicon has this item unlocked.
LexiconRecipeMappings.EntryData entry = LexiconRecipeMappings.getDataForStack(empty);
if (entry != null && (!entry.entry.isVisible() || !lexItem.isKnowledgeUnlocked(lexicon, entry.entry.getKnowledgeType()))) {
continue;
}
}
ItemStack filled = recipe.getOutput(empty);
if (filled != null) {
list.add(filled);
}
}
return list;
}
@Override
public void setSecondUnlocalizedName(String name) {
text = name;
@@ -13,6 +13,7 @@ package vazkii.botania.common.lexicon.page;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.lang.reflect.Field;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiScreen;
@@ -33,15 +34,18 @@ import vazkii.botania.api.lexicon.LexiconEntry;
import vazkii.botania.api.lexicon.LexiconRecipeMappings;
import vazkii.botania.client.core.helper.RenderHelper;
import vazkii.botania.client.lib.LibResources;
import cpw.mods.fml.relauncher.ReflectionHelper;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import vazkii.botania.common.core.helper.InventoryHelper;
import vazkii.botania.utils.ReflectionUtils;
public class PageCraftingRecipe extends PageRecipe {
private static final ResourceLocation craftingOverlay = new ResourceLocation(LibResources.GUI_CRAFTING_OVERLAY);
private static final Field RECIPE_WIDTH = ReflectionUtils.findField(ShapedOreRecipe.class, 4);
private static final Field RECIPE_HEIGHT = ReflectionUtils.findField(ShapedOreRecipe.class, 5);
List<IRecipe> recipes;
int ticksElapsed = 0;
int recipeAt = 0;
@@ -134,8 +138,8 @@ public class PageCraftingRecipe extends PageRecipe {
renderItemAtGridPos(gui, 1 + x, 1 + y, shaped.recipeItems[y * shaped.recipeWidth + x], true);
} else if(recipe instanceof ShapedOreRecipe) {
ShapedOreRecipe shaped = (ShapedOreRecipe) recipe;
int width = (Integer) ReflectionHelper.getPrivateValue(ShapedOreRecipe.class, shaped, 4);
int height = (Integer) ReflectionHelper.getPrivateValue(ShapedOreRecipe.class, shaped, 5);
int width = ReflectionUtils.getInt(RECIPE_WIDTH, shaped);
int height = ReflectionUtils.getInt(RECIPE_HEIGHT, shaped);
for(int y = 0; y < height; y++)
for(int x = 0; x < width; x++) {
@@ -47,8 +47,12 @@ public class PageText extends LexiconPage {
renderText(x, y, width, height, 10, unlocalizedText);
}
@SideOnly(Side.CLIENT)
public static void renderText(int x, int y, int width, int height, int paragraphSize, String unlocalizedText) {
renderText(x, y, width, height, paragraphSize, 0, unlocalizedText);
}
@SideOnly(Side.CLIENT)
public static void renderText(int x, int y, int width, int height, int paragraphSize, int color, String unlocalizedText) {
y += 10;
width -= 4;
@@ -132,7 +136,7 @@ public class PageText extends LexiconPage {
String tok = words.get(idx);
int tw = font.getStringWidth(tok);
font.drawString(tok, xi, y, 0);
font.drawString(tok, xi, y, color);
xi += tw;
if (justify && gi < gapIds.size() && idx == gapIds.get(gi)) {
@@ -0,0 +1,18 @@
package vazkii.botania.common.lib;
import com.gtnewhorizon.gtnhlib.color.ColorResource;
public class LibColorUtils {
private static final ColorResource.Factory color = new ColorResource.Factory("botania");
public static final ColorResource
// spotless:off
neiHandlerBotaniaLexicaTitle = color.rgb("neiHandlerBotaniaLexicaTitle", "0x404040"),
neiHandlerBotaniaLexicaKnowledge = color.rgb("neiHandlerBotaniaLexicaKnowledge", "0x404040"),
neiHandlerBotaniaLexicaTagline = color.rgb("neiHandlerBotaniaLexicaTagline", "0x404040"),
neiHandlerBotaniaLexicaExtraInfo = color.rgb("neiHandlerBotaniaLexicaExtraInfo", "0x404040"),
neiHandlerBotaniaLexicaExtraInfoDesc = color.rgb("neiHandlerBotaniaLexicaExtraInfoDesc", "0x404040");
// spotless:on
}
@@ -0,0 +1,85 @@
package vazkii.botania.utils;
import java.lang.reflect.Field;
public final class ReflectionUtils {
private ReflectionUtils() {}
public static Field findField(Class<?> clazz, String... names) {
for(String name : names) {
try {
Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
return field;
} catch(NoSuchFieldException e) {
// Try the next candidate name
}
}
return null;
}
public static Field findField(Class<?> clazz, int index) {
try {
Field field = clazz.getDeclaredFields()[index];
field.setAccessible(true);
return field;
} catch(Exception e) {
return null;
}
}
public static int getInt(Field field, Object instance) {
return getInt(field, instance, 0);
}
public static int getInt(Field field, Object instance, int def) {
try {
return field.getInt(instance);
} catch(Exception e) {
return def;
}
}
public static boolean getBoolean(Field field, Object instance) {
return getBoolean(field, instance, false);
}
public static boolean getBoolean(Field field, Object instance, boolean def) {
try {
return field.getBoolean(instance);
} catch(Exception e) {
return def;
}
}
public static Object getObject(Field field, Object instance) {
try {
return field.get(instance);
} catch(Exception e) {
return null;
}
}
public static void setInt(Field field, Object instance, int value) {
try {
field.setInt(instance, value);
} catch(Exception e) {
}
}
public static void setBoolean(Field field, Object instance, boolean value) {
try {
field.setBoolean(instance, value);
} catch(Exception e) {
}
}
public static void setObject(Field field, Object instance, Object value) {
try {
field.set(instance, value);
} catch(Exception e) {
}
}
}