mirror of
https://github.com/GTNewHorizons/ThaumicEnergistics.git
synced 2026-10-25 20:32:27 +00:00
Fix Cell Microscope drive scan (#127)
Co-authored-by: lc-1337 <62835225+lc-1337@users.noreply.github.com>
This commit is contained in:
1 parent
cbd89ad9bf
commit
bb327adb35
3 files changed
+287
-104
No files matched your search
@@ -1,50 +1,54 @@
|
||||
package thaumicenergistics.common.items;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import static appeng.util.item.AEItemStackType.ITEM_STACK_TYPE;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.texture.IIconRegister;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.item.EntityItem;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.inventory.IInventory;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.MovingObjectPosition;
|
||||
import net.minecraft.util.MovingObjectPosition.MovingObjectType;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import appeng.api.AEApi;
|
||||
import appeng.api.storage.ICellContainer;
|
||||
import appeng.api.storage.IMEInventory;
|
||||
import appeng.api.storage.ISaveProvider;
|
||||
import appeng.api.storage.StorageChannel;
|
||||
import appeng.api.storage.IMEInventoryHandler;
|
||||
import appeng.api.storage.data.IAEItemStack;
|
||||
import appeng.api.storage.data.IItemList;
|
||||
import appeng.items.storage.ItemBasicStorageCell;
|
||||
import appeng.util.IterationCounter;
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
import thaumcraft.api.research.ScanResult;
|
||||
import thaumcraft.common.Thaumcraft;
|
||||
import thaumcraft.common.items.relics.ItemThaumometer;
|
||||
import thaumcraft.common.lib.network.PacketHandler;
|
||||
import thaumcraft.common.lib.network.playerdata.PacketScannedToServer;
|
||||
import thaumcraft.common.lib.research.ScanManager;
|
||||
import thaumcraft.common.lib.utils.EntityUtils;
|
||||
import thaumicenergistics.common.network.packet.client.Packet_C_CellMicroscopeScanFeedback;
|
||||
import thaumicenergistics.common.registries.ThEStrings;
|
||||
|
||||
public class ItemCellMicroscope extends ItemThaumometer {
|
||||
|
||||
private static final String TAG_SCAN_TYPE = "scanType";
|
||||
private static final String TAG_SCAN_ENTITY = "scanEntity";
|
||||
private static final String TAG_SCAN_X = "scanX";
|
||||
private static final String TAG_SCAN_Y = "scanY";
|
||||
private static final String TAG_SCAN_Z = "scanZ";
|
||||
|
||||
private static final byte TARGET_NONE = 0;
|
||||
private static final byte TARGET_ENTITY_ITEM = 1;
|
||||
private static final byte TARGET_CELL_CONTAINER = 2;
|
||||
|
||||
public ItemCellMicroscope() {
|
||||
super();
|
||||
}
|
||||
|
||||
List<ItemStack> startCells = new ArrayList<ItemStack>();
|
||||
TileEntity cellSaveManager = null;
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
@Override
|
||||
public void registerIcons(IIconRegister ir) {
|
||||
@@ -68,11 +72,14 @@ public class ItemCellMicroscope extends ItemThaumometer {
|
||||
|
||||
@Override
|
||||
public ItemStack onItemRightClick(ItemStack stack, World world, EntityPlayer p) {
|
||||
ScanTarget target = this.findScanTarget(world, p);
|
||||
|
||||
if (world.isRemote) {
|
||||
ArrayList<ItemStack> cells = this.doScan(stack, world, p, 0);
|
||||
if (cells.size() != 0) {
|
||||
this.startCells = cells;
|
||||
}
|
||||
this.playScanEffects(world, target, 0);
|
||||
} else if (target.isValid()) {
|
||||
this.writeScanTarget(stack, target);
|
||||
} else {
|
||||
this.clearScanTarget(stack);
|
||||
}
|
||||
|
||||
p.setItemInUse(stack, this.getMaxItemUseDuration(stack));
|
||||
@@ -81,46 +88,49 @@ public class ItemCellMicroscope extends ItemThaumometer {
|
||||
|
||||
@Override
|
||||
public void onUsingTick(ItemStack stack, EntityPlayer p, int count) {
|
||||
if (p.worldObj.isRemote && Objects
|
||||
.equals(p.getCommandSenderName(), Minecraft.getMinecraft().thePlayer.getCommandSenderName())) {
|
||||
ScanTarget target = this.findScanTarget(p.worldObj, p);
|
||||
|
||||
ArrayList<ItemStack> cells = this.doScan(stack, p.worldObj, p, count);
|
||||
|
||||
if (cells.size() != 0 && cells.equals(this.startCells)) {
|
||||
|
||||
if (count <= 5) {
|
||||
p.stopUsingItem();
|
||||
this.startCells.clear();
|
||||
for (ItemStack cell : cells) {
|
||||
doCellScan(p, cell);
|
||||
}
|
||||
}
|
||||
|
||||
if (count % 2 == 0) {
|
||||
p.worldObj.playSound(
|
||||
p.posX,
|
||||
p.posY,
|
||||
p.posZ,
|
||||
"thaumcraft:cameraticks",
|
||||
0.2F,
|
||||
0.45F + ((float) count / 50) + p.worldObj.rand.nextFloat() * 0.1F,
|
||||
false);
|
||||
}
|
||||
} else {
|
||||
this.startCells.clear();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void doCellScan(EntityPlayer p, ItemStack cell) {
|
||||
IMEInventory<IAEItemStack> inv = AEApi.instance().registries().cell()
|
||||
.getCellInventory(cell, (ISaveProvider) cellSaveManager, StorageChannel.ITEMS);
|
||||
|
||||
if (inv == null) {
|
||||
if (p.worldObj.isRemote) {
|
||||
this.playScanEffects(p.worldObj, target, count);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.matchesStoredScanTarget(stack, target)) {
|
||||
this.clearScanTarget(stack);
|
||||
p.stopUsingItem();
|
||||
return;
|
||||
}
|
||||
|
||||
if (count <= 5) {
|
||||
p.stopUsingItem();
|
||||
this.clearScanTarget(stack);
|
||||
this.doScan(p, target);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
private void doScan(EntityPlayer p, ScanTarget target) {
|
||||
if (target.type == TARGET_ENTITY_ITEM && target.entityItem != null) {
|
||||
this.doCellScan(p, target.entityItem.getEntityItem());
|
||||
} else if (target.type == TARGET_CELL_CONTAINER && target.tile instanceof ICellContainer) {
|
||||
List<IMEInventoryHandler> cellArray = ((ICellContainer) target.tile).getCellArray(ITEM_STACK_TYPE);
|
||||
for (IMEInventoryHandler cell : cellArray) {
|
||||
this.doInventoryScan(p, cell);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void doCellScan(EntityPlayer p, ItemStack cell) {
|
||||
IMEInventory<IAEItemStack> inv = AEApi.instance().registries().cell()
|
||||
.getCellInventory(cell, null, ITEM_STACK_TYPE);
|
||||
|
||||
this.doInventoryScan(p, inv);
|
||||
}
|
||||
|
||||
private void doInventoryScan(EntityPlayer p, IMEInventory<IAEItemStack> inv) {
|
||||
if (inv == null) return;
|
||||
|
||||
IItemList<IAEItemStack> itemList = inv
|
||||
.getAvailableItems(AEApi.instance().storage().createItemList(), IterationCounter.fetchNewId());
|
||||
|
||||
@@ -128,72 +138,193 @@ public class ItemCellMicroscope extends ItemThaumometer {
|
||||
ScanResult sr = new ScanResult((byte) 1, Item.getIdFromItem(i.getItem()), i.getItemDamage(), null, "");
|
||||
if (ScanManager.isValidScanTarget(p, sr, "@")) {
|
||||
|
||||
ScanManager.completeScan(p, sr, "@");
|
||||
PacketHandler.INSTANCE.sendToServer(new PacketScannedToServer(sr, p, "@"));
|
||||
if (!ScanManager.completeScan(p, sr, "@")) {
|
||||
// Thaumcraft syncs successful scans to the client, but not failed ones.
|
||||
// Run the client-side scan path manually so failure hints are shown.
|
||||
Packet_C_CellMicroscopeScanFeedback.sendScanFeedback(p, sr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ArrayList<ItemStack> doScan(ItemStack stack, World world, EntityPlayer p, int count) {
|
||||
|
||||
ArrayList<ItemStack> cellsOutput = new ArrayList<>();
|
||||
private ScanTarget findScanTarget(World world, EntityPlayer p) {
|
||||
Entity pointedEntity = EntityUtils.getPointedEntity(p.worldObj, p, 0.5D, 10.0D, 0.0F, true);
|
||||
|
||||
if (pointedEntity != null) {
|
||||
if (pointedEntity instanceof EntityItem) {
|
||||
if (((EntityItem) pointedEntity).getEntityItem().getItem() instanceof ItemBasicStorageCell) {
|
||||
MovingObjectPosition mop = this.getMovingObjectPositionFromPlayer(p.worldObj, p, true);
|
||||
try {
|
||||
Thaumcraft.proxy.blockRunes(
|
||||
world,
|
||||
mop.blockX,
|
||||
(double) mop.blockY + 0.50D,
|
||||
mop.blockZ,
|
||||
0.3F,
|
||||
0.3F,
|
||||
0.7F + world.rand.nextFloat() * 0.7F,
|
||||
15,
|
||||
-0.03F);
|
||||
} catch (Exception ignored) {}
|
||||
cellSaveManager = null;
|
||||
cellsOutput.add(((EntityItem) pointedEntity).getEntityItem());
|
||||
return cellsOutput;
|
||||
}
|
||||
if (pointedEntity instanceof EntityItem entityItem) {
|
||||
if (this.isItemStorageCell(entityItem.getEntityItem())) {
|
||||
return ScanTarget.forEntityItem(entityItem);
|
||||
}
|
||||
}
|
||||
|
||||
MovingObjectPosition lookingAtBlock = Minecraft.getMinecraft().objectMouseOver;
|
||||
TileEntity blockAtPos = world
|
||||
.getTileEntity(lookingAtBlock.blockX, lookingAtBlock.blockY, lookingAtBlock.blockZ);
|
||||
if (blockAtPos instanceof ICellContainer) {
|
||||
((ICellContainer) blockAtPos).getCellArray(StorageChannel.ITEMS);
|
||||
IInventory inv = (IInventory) blockAtPos;
|
||||
cellSaveManager = blockAtPos;
|
||||
try {
|
||||
Thaumcraft.proxy.blockRunes(
|
||||
world,
|
||||
lookingAtBlock.blockX,
|
||||
lookingAtBlock.blockY,
|
||||
lookingAtBlock.blockZ,
|
||||
0.3F,
|
||||
0.3F,
|
||||
0.7F + world.rand.nextFloat() * 0.7F,
|
||||
15,
|
||||
-0.03F);
|
||||
} catch (Exception ignored) {}
|
||||
for (int i = 0; i < inv.getSizeInventory(); i++) {
|
||||
ItemStack itemStack = inv.getStackInSlot(i);
|
||||
if (itemStack != null) {
|
||||
cellsOutput.add(itemStack);
|
||||
}
|
||||
MovingObjectPosition lookingAtBlock = this.getMovingObjectPositionFromPlayer(world, p, true);
|
||||
if ((lookingAtBlock != null) && (lookingAtBlock.typeOfHit == MovingObjectType.BLOCK)) {
|
||||
TileEntity blockAtPos = world
|
||||
.getTileEntity(lookingAtBlock.blockX, lookingAtBlock.blockY, lookingAtBlock.blockZ);
|
||||
|
||||
if (blockAtPos instanceof ICellContainer) {
|
||||
return ScanTarget.forCellContainer(lookingAtBlock, blockAtPos);
|
||||
}
|
||||
}
|
||||
return cellsOutput;
|
||||
|
||||
return ScanTarget.none();
|
||||
}
|
||||
|
||||
private boolean isItemStorageCell(ItemStack stack) {
|
||||
if (stack == null) return false;
|
||||
|
||||
return AEApi.instance().registries().cell().getCellInventory(stack, null, ITEM_STACK_TYPE) != null;
|
||||
}
|
||||
|
||||
private void playScanEffects(World world, ScanTarget target, int count) {
|
||||
if (!target.isValid()) return;
|
||||
|
||||
if (count % 2 == 0) {
|
||||
world.playSound(
|
||||
target.effectX,
|
||||
target.effectY,
|
||||
target.effectZ,
|
||||
"thaumcraft:cameraticks",
|
||||
0.2F,
|
||||
0.45F + ((float) count / 50) + world.rand.nextFloat() * 0.1F,
|
||||
false);
|
||||
}
|
||||
|
||||
try {
|
||||
Thaumcraft.proxy.blockRunes(
|
||||
world,
|
||||
target.effectX,
|
||||
target.effectY,
|
||||
target.effectZ,
|
||||
0.3F,
|
||||
0.3F,
|
||||
0.7F + world.rand.nextFloat() * 0.7F,
|
||||
15,
|
||||
-0.03F);
|
||||
} catch (Exception ignored) {}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the scan target selected at right-click time so the server can verify that the player is still looking at
|
||||
* the same cell when the use action completes. These tags are temporary and are cleared when scanning stops.
|
||||
*/
|
||||
private void writeScanTarget(ItemStack stack, ScanTarget target) {
|
||||
NBTTagCompound tag = stack.getTagCompound();
|
||||
if (tag == null) {
|
||||
tag = new NBTTagCompound();
|
||||
stack.setTagCompound(tag);
|
||||
}
|
||||
|
||||
tag.setByte(TAG_SCAN_TYPE, target.type);
|
||||
tag.setInteger(TAG_SCAN_ENTITY, target.entityId);
|
||||
tag.setInteger(TAG_SCAN_X, target.x);
|
||||
tag.setInteger(TAG_SCAN_Y, target.y);
|
||||
tag.setInteger(TAG_SCAN_Z, target.z);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rejects the scan if the player moved to a different entity or block during the charge-up period.
|
||||
*/
|
||||
private boolean matchesStoredScanTarget(ItemStack stack, ScanTarget target) {
|
||||
if (!target.isValid() || !stack.hasTagCompound()) return false;
|
||||
|
||||
NBTTagCompound tag = stack.getTagCompound();
|
||||
byte type = tag.getByte(TAG_SCAN_TYPE);
|
||||
if (type != target.type) return false;
|
||||
|
||||
if (type == TARGET_ENTITY_ITEM) {
|
||||
return tag.getInteger(TAG_SCAN_ENTITY) == target.entityId;
|
||||
}
|
||||
|
||||
return (tag.getInteger(TAG_SCAN_X) == target.x) && (tag.getInteger(TAG_SCAN_Y) == target.y)
|
||||
&& (tag.getInteger(TAG_SCAN_Z) == target.z);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the temporary scan target after completion, cancellation, or target mismatch so the item does not keep
|
||||
* stale target data.
|
||||
*/
|
||||
private void clearScanTarget(ItemStack stack) {
|
||||
if (!stack.hasTagCompound()) return;
|
||||
|
||||
NBTTagCompound tag = stack.getTagCompound();
|
||||
tag.removeTag(TAG_SCAN_TYPE);
|
||||
tag.removeTag(TAG_SCAN_ENTITY);
|
||||
tag.removeTag(TAG_SCAN_X);
|
||||
tag.removeTag(TAG_SCAN_Y);
|
||||
tag.removeTag(TAG_SCAN_Z);
|
||||
|
||||
if (tag.hasNoTags()) {
|
||||
stack.setTagCompound(null);
|
||||
}
|
||||
}
|
||||
|
||||
public void onPlayerStoppedUsing(ItemStack par1ItemStack, World par2World, EntityPlayer par3EntityPlayer,
|
||||
int par4) {
|
||||
super.onPlayerStoppedUsing(par1ItemStack, par2World, par3EntityPlayer, par4);
|
||||
this.startCells.clear();
|
||||
this.clearScanTarget(par1ItemStack);
|
||||
}
|
||||
|
||||
private static class ScanTarget {
|
||||
|
||||
private final byte type;
|
||||
private final int entityId;
|
||||
private final int x;
|
||||
private final int y;
|
||||
private final int z;
|
||||
private final double effectX;
|
||||
private final double effectY;
|
||||
private final double effectZ;
|
||||
private final EntityItem entityItem;
|
||||
private final TileEntity tile;
|
||||
|
||||
private ScanTarget(byte type, int entityId, int x, int y, int z, double effectX, double effectY, double effectZ,
|
||||
EntityItem entityItem, TileEntity tile) {
|
||||
this.type = type;
|
||||
this.entityId = entityId;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.effectX = effectX;
|
||||
this.effectY = effectY;
|
||||
this.effectZ = effectZ;
|
||||
this.entityItem = entityItem;
|
||||
this.tile = tile;
|
||||
}
|
||||
|
||||
private static ScanTarget none() {
|
||||
return new ScanTarget(TARGET_NONE, 0, 0, 0, 0, 0, 0, 0, null, null);
|
||||
}
|
||||
|
||||
private static ScanTarget forEntityItem(EntityItem entityItem) {
|
||||
return new ScanTarget(
|
||||
TARGET_ENTITY_ITEM,
|
||||
entityItem.getEntityId(),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
entityItem.posX,
|
||||
entityItem.posY + 0.5D,
|
||||
entityItem.posZ,
|
||||
entityItem,
|
||||
null);
|
||||
}
|
||||
|
||||
private static ScanTarget forCellContainer(MovingObjectPosition position, TileEntity tile) {
|
||||
return new ScanTarget(
|
||||
TARGET_CELL_CONTAINER,
|
||||
0,
|
||||
position.blockX,
|
||||
position.blockY,
|
||||
position.blockZ,
|
||||
position.blockX,
|
||||
position.blockY,
|
||||
position.blockZ,
|
||||
null,
|
||||
tile);
|
||||
}
|
||||
|
||||
private boolean isValid() {
|
||||
return this.type != TARGET_NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import cpw.mods.fml.common.network.simpleimpl.SimpleNetworkWrapper;
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import thaumicenergistics.common.ThaumicEnergistics;
|
||||
import thaumicenergistics.common.network.packet.client.Packet_C_ArcaneCraftingTerminal;
|
||||
import thaumicenergistics.common.network.packet.client.Packet_C_CellMicroscopeScanFeedback;
|
||||
import thaumicenergistics.common.network.packet.client.Packet_C_DistillationEncoder;
|
||||
import thaumicenergistics.common.network.packet.client.Packet_C_EssentiaVibrationChamber;
|
||||
import thaumicenergistics.common.network.packet.client.Packet_C_ExportBusVoidButtonUpdate;
|
||||
@@ -127,6 +128,9 @@ public class NetworkHandler {
|
||||
// Sync packet
|
||||
registerPacket(Packet_C_Sync.class);
|
||||
|
||||
// Cell microscope
|
||||
registerPacket(Packet_C_CellMicroscopeScanFeedback.class);
|
||||
|
||||
registerPacket(Packet_S_NEIRecipe.class);
|
||||
}
|
||||
|
||||
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
package thaumicenergistics.common.network.packet.client;
|
||||
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.Item;
|
||||
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import thaumcraft.api.research.ScanResult;
|
||||
import thaumcraft.common.lib.research.ScanManager;
|
||||
import thaumicenergistics.common.network.NetworkHandler;
|
||||
|
||||
public class Packet_C_CellMicroscopeScanFeedback extends ThEClientPacket {
|
||||
|
||||
private int itemId;
|
||||
private int itemDamage;
|
||||
|
||||
public static void sendScanFeedback(final EntityPlayer player, final ScanResult scanResult) {
|
||||
Packet_C_CellMicroscopeScanFeedback packet = new Packet_C_CellMicroscopeScanFeedback();
|
||||
|
||||
packet.player = player;
|
||||
packet.itemId = scanResult.id;
|
||||
packet.itemDamage = scanResult.meta;
|
||||
|
||||
NetworkHandler.sendPacketToClient(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void readData(final ByteBuf stream) {
|
||||
this.itemId = stream.readInt();
|
||||
this.itemDamage = stream.readInt();
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
@Override
|
||||
protected void wrappedExecute() {
|
||||
ScanResult scanResult = new ScanResult((byte) 1, this.itemId, this.itemDamage, null, "");
|
||||
if (Item.getItemById(this.itemId) != null) {
|
||||
ScanManager.completeScan(this.player, scanResult, "@");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeData(final ByteBuf stream) {
|
||||
stream.writeInt(this.itemId);
|
||||
stream.writeInt(this.itemDamage);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user