mirror of
https://github.com/MightyPirates/OpenComputers.git
synced 2025-09-09 15:25:56 -04:00
Fixes an issue where a robot without an inventory was deleting the
drops. The core problem here actually is that OC agents try to pull items directly out of killed/destroyed blocks via capturedDrops, and the robots also pick up items from collision. The collision code was written to always destroy the drops. The code that tries to pull items out of capturedDrops spawns items in world when there is no room in the robot. Mob drops cause collision pickup AND run the capturedDrops code. When collision doesn't take anything, and kills the drops, the items are lost. The best fix would be to stop taking items directly from capturedDrops, but this code has been here for some time, and we'll leave it for now. The next best fix is to not always destroy drops on collision, but let mc code handle collision cleanup as it was designed. Then, when taking capturedDrops directly, first check if there is an inventory. This solution leaves one last loop hole, collision doesn't find a place in inventory and thus has valid world drops. We can't ignore collision for attacks because the mobs are putting items in the world. But instead, we need to stop capturedDrops action from spawning in the world. closes #3172
This commit is contained in:
parent
a713ee9741
commit
56f8fdbaa9
@ -187,11 +187,11 @@ class Player(val agent: internal.Agent) extends FakePlayer(agent.world.asInstanc
|
||||
private def collectDroppedItems(itemsBefore: Iterable[EntityItem]) {
|
||||
val itemsAfter = adjacentItems
|
||||
val itemsDropped = itemsAfter -- itemsBefore
|
||||
for (drop <- itemsDropped) {
|
||||
|
||||
drop.delayBeforeCanPickup = 0
|
||||
drop.onCollideWithPlayer(this)
|
||||
drop.setDead()
|
||||
if (itemsDropped.nonEmpty) {
|
||||
for (drop <- itemsDropped) {
|
||||
drop.delayBeforeCanPickup = 0
|
||||
drop.onCollideWithPlayer(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -288,11 +288,20 @@ trait Agent extends traits.WorldControl with traits.InventoryControl with traits
|
||||
entity.captureDrops = true
|
||||
}
|
||||
|
||||
|
||||
protected def endConsumeDrops(player: Player, entity: Entity) {
|
||||
entity.captureDrops = false
|
||||
for (drop <- entity.capturedDrops) {
|
||||
val stack = drop.getEntityItem
|
||||
InventoryUtils.addToPlayerInventory(stack, player)
|
||||
// this inventory size check is a HACK to preserve old behavior that a agent can suck items out
|
||||
// of the capturedDrops. Ideally, we'd only pick up items off the ground. We could clear the
|
||||
// capturedDrops when Player.attackTargetEntityWithCurrentItem() is called
|
||||
// But this felt slightly less hacky, slightly
|
||||
if (player.inventory.getSizeInventory > 0) {
|
||||
for (drop <- entity.capturedDrops) {
|
||||
if (!drop.isDead) {
|
||||
val stack = drop.getEntityItem
|
||||
InventoryUtils.addToPlayerInventory(stack, player, spawnInWorld = false)
|
||||
}
|
||||
}
|
||||
}
|
||||
entity.capturedDrops.clear()
|
||||
}
|
||||
|
@ -369,7 +369,7 @@ object InventoryUtils {
|
||||
/**
|
||||
* Try inserting an item stack into a player inventory. If that fails, drop it into the world.
|
||||
*/
|
||||
def addToPlayerInventory(stack: ItemStack, player: EntityPlayer): Unit = {
|
||||
def addToPlayerInventory(stack: ItemStack, player: EntityPlayer, spawnInWorld: Boolean = true): Unit = {
|
||||
if (stack != null) {
|
||||
if (player.inventory.addItemStackToInventory(stack)) {
|
||||
player.inventory.markDirty()
|
||||
@ -377,7 +377,7 @@ object InventoryUtils {
|
||||
player.openContainer.detectAndSendChanges()
|
||||
}
|
||||
}
|
||||
if (stack.stackSize > 0) {
|
||||
if (stack.stackSize > 0 && spawnInWorld) {
|
||||
player.dropPlayerItemWithRandomChoice(stack, false)
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user