Compare 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
48 changed files with 726 additions and 273 deletions

No files matched your search

+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) {
}
}
}