I'm trying to add a bow charge indicator to the game overlay - a green transparent rectangle showing up at full charge.
I'm registerig a Event listener to get the Bow use:
public void load(FMLInitializationEvent event){
public static final BowListener bowListener = new BowListener();
...
MinecraftForge.EVENT_BUS.register(bowListener);
and I track the bow charge
public class BowListener {
public boolean scopeOn = false;
public float charge;
@SubscribeEvent
public void startUsingBow (PlayerUseItemEvent.Start event){
if (itemNotBow(event.item.getItem(), true)) return;
openScope();
charge = calcCharge(event.item.getItem(), event.duration);
}
@SubscribeEvent
public void continueUsingBow (PlayerUseItemEvent.Tick event){
if (itemNotBow(event.item.getItem(), false)) return;
charge = calcCharge(event.item.getItem(), event.duration);
}
@SubscribeEvent
public void stopUsingBow (PlayerUseItemEvent.Stop event){
if (itemNotBow(event.item.getItem(), false))return;
cancelScope();
}
private boolean itemNotBow (Item item, boolean start){
if (item instanceof ItemBow) {
if (start && scopeOn) {
FMLLog.info("DDDDDD>>> startUsingBow but scope still active");
}
if (!start && !scopeOn) {
FMLLog.info("DDDDDD>>> UsingBow but scope not active");
}
return false;
}
if (scopeOn) {
FMLLog.info("DDDDDD>>> UsingOtherThanBow but scope still active");
}
cancelScope();
return true;
}
private void cancelScope () {
charge = 0.0F;
scopeOn = false;
}
private void openScope () {
scopeOn = true;
}
private float calcCharge (Item item, int duration) {
int j = item.getMaxItemUseDuration(null) - duration;
float f = (float)j / 20.0F;
f = (f * f + f * 2.0F) / 3.0F;
if ((double)f < 0.1D) return 0.0F;
if (f > 1.0F) return 1.0F;
return f;
}
}
This works great for most of the servers, BUT if i'm going to certain other servers like shotbow.net, I'm getting called for "impossible" PlayerUseItemEvents.
I have set a BP on the line which holds "FMLLog.info("DDDDDD>>> UsingOtherThanBow but scope still active");" and get following stackdump:
Thread [Client thread] (Suspended (breakpoint at line 45 in BowListener))
BowListener.itemNotBow(Item, boolean) line: 45
BowListener.continueUsingBow(PlayerUseItemEvent$Tick) line: 24
ASMEventHandler_4_BowListener_continueUsingBow_Tick.invoke(Event) line: not available
ASMEventHandler.invoke(Event) line: 51
EventBus.post(Event) line: 122
ForgeEventFactory.onItemUseTick(EntityPlayer, ItemStack, int) line: 149
EntityOtherPlayerMP(EntityPlayer).onUpdate() line: 281
EntityOtherPlayerMP.onUpdate() line: 72
WorldClient(World).updateEntityWithOptionalForce(Entity, boolean) line: 2254
WorldClient(World).updateEntity(Entity) line: 2214
WorldClient(World).updateEntities() line: 2064
Minecraft.runTick() line: 2065
Minecraft.runGameLoop() line: 997
Minecraft.run() line: 912
Main.main(String[]) line: 112
NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]
NativeMethodAccessorImpl.invoke(Object, Object[]) line: not available
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: not available
Method.invoke(Object, Object...) line: not available
Launch.launch(String[]) line: 134
Launch.main(String[]) line: 28
and item is an ItemFood:"melon" But I don't have any melons, not in inventory nor in hotbar.
Did someone already observe this?
I'm a noob - I forgot to check the player in the event. I changed to:
public class BowListener {
public boolean scopeOn = false;
public float charge;
@SubscribeEvent
public void startUsingBow (PlayerUseItemEvent.Start event){
if (itemNotBow(event)) return;
scopeOn = true;
charge = calcCharge(event.item.getItem(), event.duration);
}
@SubscribeEvent
public void continueUsingBow (PlayerUseItemEvent.Tick event){
if (itemNotBow(event)) return;
charge = calcCharge(event.item.getItem(), event.duration);
}
@SubscribeEvent
public void stopUsingBow (PlayerUseItemEvent.Stop event){
if (itemNotBow(event)) return;
charge = 0.0F;
scopeOn = false;
}
private boolean itemNotBow (PlayerUseItemEvent event){
if (event.entityPlayer.getEntityId() != Minecraft.getMinecraft().thePlayer.getEntityId()) return true; // someone other is using item ...
if (event.item.getItem() instanceof ItemBow) return false;
return true;
}
private float calcCharge (Item item, int duration) {
int j = item.getMaxItemUseDuration(null) - duration;
float f = (float)j / 20.0F;
f = (f * f + f * 2.0F) / 3.0F;
if ((double)f < 0.1D) return 0.0F;
if (f > 1.0F) return 1.0F;
return f;
}
}