package crazypants.enderio.item;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import net.minecraft.command.IEntitySelector;
import net.minecraft.entity.Entity;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.item.EntityXPOrb;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.MathHelper;
import net.minecraft.world.World;
import net.minecraft.world.chunk.Chunk;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import cpw.mods.fml.common.gameevent.TickEvent;
import cpw.mods.fml.common.registry.GameRegistry;
import cpw.mods.fml.relauncher.Side;
import crazypants.enderio.config.Config;
import crazypants.enderio.item.PacketMagnetState.SlotType;
import crazypants.enderio.network.PacketHandler;
import crazypants.util.BaublesUtil;
import static crazypants.enderio.item.darksteel.DarkSteelItems.itemMagnet;
import static crazypants.util.BotaniaUtil.hasSolegnoliaAround;
public class MagnetController {
public MagnetController() {
PacketHandler.INSTANCE.registerMessage(PacketMagnetState.class, PacketMagnetState.class, PacketHandler.nextID(), Side.SERVER);
}
@SubscribeEvent
public void onPlayerTick(TickEvent.PlayerTickEvent event) {
if (event.phase != TickEvent.Phase.END) {
return;
}
ActiveMagnet mag = getActiveMagnet(event.player);
if (mag != null && event.player.getHealth() > 0f) {
doHoover(event.player);
if(event.side == Side.SERVER && event.player.worldObj.getTotalWorldTime() % 20 == 0) {
ItemMagnet.drainPerSecondPower(mag.item);
event.player.inventory.setInventorySlotContents(mag.slot, mag.item);
event.player.inventory.markDirty();
}
}
}
private ActiveMagnet getActiveMagnet(EntityPlayer player) {
ItemStack[] inv = player.inventory.mainInventory;
int maxSlot = Config.magnetAllowInMainInventory ? 4 * 9 : 9;
for (int i = 0; i < maxSlot;i++) {
if(ItemMagnet.isActive(inv[i]) && ItemMagnet.hasPower(inv[i])) {
return new ActiveMagnet(inv[i], i);
}
}
return null;
}
private static final double collisionDistanceSq = 1.25 * 1.25;
private static final double speed = 0.035;
private static final double speed4 = speed * 4;
public void doHoover(EntityPlayer player) {
if (blacklist == null) {
initBlacklist();
}
AxisAlignedBB aabb = AxisAlignedBB.getBoundingBox(
player.posX - Config.magnetRange, player.posY - Config.magnetRange, player.posZ - Config.magnetRange,
player.posX + Config.magnetRange, player.posY + Config.magnetRange, player.posZ + Config.magnetRange);
List<Entity> interestingItems = selectEntitiesWithinAABB(player.worldObj, aabb);
if (interestingItems != null) {
for (Entity entity : interestingItems) {
double x = player.posX + 0.5D - entity.posX;
double y = player.posY + 1D - entity.posY;
double z = player.posZ + 0.5D - entity.posZ;
double distance = x * x + y * y + z * z;
if (distance < collisionDistanceSq) {
entity.onCollideWithPlayer(player);
} else {
double distancespeed = speed4 / distance;
entity.motionX += x * distancespeed;
if (y > 0) {
entity.motionY = 0.12;
} else {
entity.motionY += y * speed;
}
entity.motionZ += z * distancespeed;
}
}
}
}
private static List<Item> blacklist = null;
private static void initBlacklist() {
blacklist = new ArrayList<Item>();
for (String name : Config.magnetBlacklist) {
String[] parts = name.split(":");
if (parts.length == 2) {
Item item = GameRegistry.findItem(parts[0], parts[1]);
if (item != null) {
blacklist.add(item);
}
}
}
}
private List<Entity> selectEntitiesWithinAABB(World world, AxisAlignedBB bb) {
List<Entity> arraylist = null;
int itemsRemaining = Config.magnetMaxItems;
if (itemsRemaining <= 0) {
itemsRemaining = Integer.MAX_VALUE;
}
final int minChunkX = MathHelper.floor_double((bb.minX) / 16.0D);
final int maxChunkX = MathHelper.floor_double((bb.maxX) / 16.0D);
final int minChunkZ = MathHelper.floor_double((bb.minZ) / 16.0D);
final int maxChunkZ = MathHelper.floor_double((bb.maxZ) / 16.0D);
final int minChunkY = MathHelper.floor_double((bb.minY) / 16.0D);
final int maxChunkY = MathHelper.floor_double((bb.maxY) / 16.0D);
for (int chunkX = minChunkX; chunkX <= maxChunkX; ++chunkX) {
for (int chunkZ = minChunkZ; chunkZ <= maxChunkZ; ++chunkZ) {
Chunk chunk = world.getChunkFromChunkCoords(chunkX, chunkZ);
final int minChunkYClamped = MathHelper.clamp_int(minChunkY, 0, chunk.entityLists.length - 1);
final int maxChunkYClamped = MathHelper.clamp_int(maxChunkY, 0, chunk.entityLists.length - 1);
for (int chunkY = minChunkYClamped; chunkY <= maxChunkYClamped; ++chunkY) {
for (Entity entity : (List<Entity>) chunk.entityLists[chunkY]) {
if (!entity.isDead) {
boolean gotOne = false;
if (entity instanceof EntityItem && entity.boundingBox.intersectsWith(bb)) {
gotOne = !hasSolegnoliaAround(entity);
if (gotOne && !blacklist.isEmpty()) {
final Item item = ((EntityItem) entity).getEntityItem().getItem();
for (Item blacklisted : blacklist) {
if (blacklisted == item) {
gotOne = false;
break;
}
}
}
} else if (entity instanceof EntityXPOrb && entity.boundingBox.intersectsWith(bb)) {
gotOne = true;
}
if (gotOne) {
if (arraylist == null) {
arraylist = new ArrayList<Entity>(Config.magnetMaxItems > 0 ? Config.magnetMaxItems : 20);
}
arraylist.add(entity);
if (itemsRemaining-- <= 0) {
return arraylist;
}
}
}
}
}
}
}
return arraylist;
}
private static class ActiveMagnet {
ItemStack item;
int slot;
ActiveMagnet(ItemStack item, int slot) {
this.item = item;
this.slot = slot;
}
}
public static void setMagnetActive(EntityPlayerMP player, SlotType type, int slot, boolean isActive) {
ItemStack stack = null;
IInventory baubles = null;
int dropOff = -1;
switch (type) {
case INVENTORY:
stack = player.inventory.getStackInSlot(slot);
break;
case ARMOR:
return;
case BAUBLES:
baubles = BaublesUtil.instance().getBaubles(player);
if (baubles != null) {
stack = baubles.getStackInSlot(slot);
}
break;
}
if (stack == null || stack.getItem() == null || stack.getItem() != itemMagnet || ItemMagnet.isActive(stack) == isActive) {
return;
}
if (!Config.magnetAllowDeactivatedInBaublesSlot && type == SlotType.BAUBLES && !isActive) {
ItemStack[] inv = player.inventory.mainInventory;
for (int i = 0; i < inv.length && dropOff < 0; i++) {
if (inv[i] == null) {
dropOff = i;
}
}
if (dropOff < 0) {
return;
}
}
ItemMagnet.setActive(stack, isActive);
switch (type) {
case INVENTORY:
player.inventory.setInventorySlotContents(slot, stack);
player.inventory.markDirty();
break;
case ARMOR:
return;
case BAUBLES:
if (dropOff < 0) {
baubles.setInventorySlotContents(slot, stack);
} else {
baubles.setInventorySlotContents(slot, null);
player.inventory.setInventorySlotContents(dropOff, stack);
}
player.inventory.markDirty();
break;
}
}
}