From 5feabc8f9a7c341d1d7f66a6a6b1b6e084a53f87 Mon Sep 17 00:00:00 2001
From: Melledy <52122272+Melledy@users.noreply.github.com>
Date: Tue, 19 Jul 2022 02:51:26 -0700
Subject: [PATCH] Add `Entity::OnInteract`

---
 .../grasscutter/game/entity/EntityGadget.java | 20 ++++++--
 .../grasscutter/game/entity/EntityItem.java   | 28 +++++++++++
 .../game/entity/EntityMonster.java            |  6 +++
 .../game/entity/EntityVehicle.java            |  6 +++
 .../grasscutter/game/entity/GameEntity.java   | 11 ++++
 .../game/entity/gadget/GadgetChest.java       |  7 +--
 .../emu/grasscutter/game/player/Player.java   | 50 +++----------------
 .../emu/grasscutter/game/world/Scene.java     | 30 +++++++----
 8 files changed, 97 insertions(+), 61 deletions(-)

diff --git a/src/main/java/emu/grasscutter/game/entity/EntityGadget.java b/src/main/java/emu/grasscutter/game/entity/EntityGadget.java
index fe2b60f7..2d84cafa 100644
--- a/src/main/java/emu/grasscutter/game/entity/EntityGadget.java
+++ b/src/main/java/emu/grasscutter/game/entity/EntityGadget.java
@@ -3,6 +3,7 @@ package emu.grasscutter.game.entity;
 import emu.grasscutter.data.GameData;
 import emu.grasscutter.data.excels.GadgetData;
 import emu.grasscutter.game.entity.gadget.*;
+import emu.grasscutter.game.player.Player;
 import emu.grasscutter.game.props.EntityIdType;
 import emu.grasscutter.game.props.EntityType;
 import emu.grasscutter.game.props.LifeState;
@@ -15,6 +16,7 @@ import emu.grasscutter.net.proto.EntityAuthorityInfoOuterClass.EntityAuthorityIn
 import emu.grasscutter.net.proto.EntityClientDataOuterClass.EntityClientData;
 import emu.grasscutter.net.proto.EntityRendererChangedInfoOuterClass.EntityRendererChangedInfo;
 import emu.grasscutter.net.proto.FightPropPairOuterClass.FightPropPair;
+import emu.grasscutter.net.proto.GadgetInteractReqOuterClass.GadgetInteractReq;
 import emu.grasscutter.net.proto.MotionInfoOuterClass.MotionInfo;
 import emu.grasscutter.net.proto.PropPairOuterClass.PropPair;
 import emu.grasscutter.net.proto.ProtEntityTypeOuterClass.ProtEntityType;
@@ -22,6 +24,7 @@ import emu.grasscutter.net.proto.SceneEntityAiInfoOuterClass.SceneEntityAiInfo;
 import emu.grasscutter.net.proto.SceneEntityInfoOuterClass.SceneEntityInfo;
 import emu.grasscutter.net.proto.SceneGadgetInfoOuterClass.SceneGadgetInfo;
 import emu.grasscutter.net.proto.VectorOuterClass.Vector;
+import emu.grasscutter.net.proto.VisionTypeOuterClass.VisionType;
 import emu.grasscutter.scripts.constants.EventType;
 import emu.grasscutter.scripts.data.SceneGadget;
 import emu.grasscutter.scripts.data.ScriptArgs;
@@ -150,6 +153,19 @@ public class EntityGadget extends EntityBaseGadget {
 		if (this.fightProp == null) this.fightProp = new Int2FloatOpenHashMap();
 		return this.fightProp;
 	}
+	
+	@Override
+    public void onInteract(Player player, GadgetInteractReq interactReq) {
+	    if (this.getContent() == null) {
+            return;
+        }
+
+        boolean shouldDelete = this.getContent().onInteract(player, interactReq);
+
+        if (shouldDelete) {
+            this.getScene().killEntity(this);
+        }
+	}
 
 	@Override
 	public void onCreate() {
@@ -213,8 +229,4 @@ public class EntityGadget extends EntityBaseGadget {
 
 		return entityInfo.build();
 	}
-	public void die() {
-		getScene().broadcastPacket(new PacketLifeStateChangeNotify(this, LifeState.LIFE_DEAD));
-		this.onDeath(0);
-	}
 }
diff --git a/src/main/java/emu/grasscutter/game/entity/EntityItem.java b/src/main/java/emu/grasscutter/game/entity/EntityItem.java
index 791b230a..63817f7c 100644
--- a/src/main/java/emu/grasscutter/game/entity/EntityItem.java
+++ b/src/main/java/emu/grasscutter/game/entity/EntityItem.java
@@ -3,6 +3,7 @@ package emu.grasscutter.game.entity;
 import emu.grasscutter.data.excels.ItemData;
 import emu.grasscutter.game.inventory.GameItem;
 import emu.grasscutter.game.player.Player;
+import emu.grasscutter.game.props.ActionReason;
 import emu.grasscutter.game.props.EntityIdType;
 import emu.grasscutter.game.props.PlayerProperty;
 import emu.grasscutter.game.world.Scene;
@@ -12,6 +13,8 @@ import emu.grasscutter.net.proto.EntityAuthorityInfoOuterClass.EntityAuthorityIn
 import emu.grasscutter.net.proto.EntityClientDataOuterClass.EntityClientData;
 import emu.grasscutter.net.proto.EntityRendererChangedInfoOuterClass.EntityRendererChangedInfo;
 import emu.grasscutter.net.proto.GadgetBornTypeOuterClass.GadgetBornType;
+import emu.grasscutter.net.proto.GadgetInteractReqOuterClass.GadgetInteractReq;
+import emu.grasscutter.net.proto.InteractTypeOuterClass.InteractType;
 import emu.grasscutter.net.proto.MotionInfoOuterClass.MotionInfo;
 import emu.grasscutter.net.proto.PropPairOuterClass.PropPair;
 import emu.grasscutter.net.proto.ProtEntityTypeOuterClass.ProtEntityType;
@@ -19,6 +22,7 @@ import emu.grasscutter.net.proto.SceneEntityAiInfoOuterClass.SceneEntityAiInfo;
 import emu.grasscutter.net.proto.SceneEntityInfoOuterClass.SceneEntityInfo;
 import emu.grasscutter.net.proto.SceneGadgetInfoOuterClass.SceneGadgetInfo;
 import emu.grasscutter.net.proto.VectorOuterClass.Vector;
+import emu.grasscutter.server.packet.send.PacketGadgetInteractRsp;
 import emu.grasscutter.utils.Position;
 import emu.grasscutter.utils.ProtoHelper;
 import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap;
@@ -99,6 +103,30 @@ public class EntityItem extends EntityBaseGadget {
 	public boolean isShare() {
 		return share;
 	}
+	
+	@Override
+	public void onInteract(Player player, GadgetInteractReq interactReq) {
+	    // check drop owner to avoid someone picked up item in others' world
+        if (!this.isShare()) {
+            int dropOwner = (int) (this.getGuid() >> 32);
+            if (dropOwner != player.getUid()) {
+                return;
+            }
+        }
+        
+        this.getScene().removeEntity(this);
+        GameItem item = new GameItem(this.getItemData(), this.getCount());
+        
+        // Add to inventory
+        boolean success = player.getInventory().addItem(item, ActionReason.SubfieldDrop);
+        if (success) {
+            if (!this.isShare()) { // not shared drop
+                player.sendPacket(new PacketGadgetInteractRsp(this, InteractType.INTERACT_TYPE_PICK_ITEM));
+            } else {
+                this.getScene().broadcastPacket(new PacketGadgetInteractRsp(this, InteractType.INTERACT_TYPE_PICK_ITEM));
+            }
+        }
+    }
 
 	@Override
 	public SceneEntityInfo toProto() {
diff --git a/src/main/java/emu/grasscutter/game/entity/EntityMonster.java b/src/main/java/emu/grasscutter/game/entity/EntityMonster.java
index b8c47e3d..eacc0ca6 100644
--- a/src/main/java/emu/grasscutter/game/entity/EntityMonster.java
+++ b/src/main/java/emu/grasscutter/game/entity/EntityMonster.java
@@ -16,6 +16,7 @@ import emu.grasscutter.net.proto.EntityAuthorityInfoOuterClass.EntityAuthorityIn
 import emu.grasscutter.net.proto.EntityClientDataOuterClass.EntityClientData;
 import emu.grasscutter.net.proto.EntityRendererChangedInfoOuterClass.EntityRendererChangedInfo;
 import emu.grasscutter.net.proto.FightPropPairOuterClass.FightPropPair;
+import emu.grasscutter.net.proto.GadgetInteractReqOuterClass.GadgetInteractReq;
 import emu.grasscutter.net.proto.MonsterBornTypeOuterClass.MonsterBornType;
 import emu.grasscutter.net.proto.PropPairOuterClass.PropPair;
 import emu.grasscutter.net.proto.ProtEntityTypeOuterClass.ProtEntityType;
@@ -112,6 +113,11 @@ public class EntityMonster extends GameEntity {
 		this.poseId = poseId;
 	}
 	
+	@Override
+    public void onInteract(Player player, GadgetInteractReq interactReq) {
+        player.getInsectCaptureManager().arrestSmallCreature(this);
+    }
+	
 	@Override
 	public void onCreate() {
 		// Lua event
diff --git a/src/main/java/emu/grasscutter/game/entity/EntityVehicle.java b/src/main/java/emu/grasscutter/game/entity/EntityVehicle.java
index ceab84bc..a8381b8d 100644
--- a/src/main/java/emu/grasscutter/game/entity/EntityVehicle.java
+++ b/src/main/java/emu/grasscutter/game/entity/EntityVehicle.java
@@ -10,6 +10,7 @@ import emu.grasscutter.net.proto.AnimatorParameterValueInfoPairOuterClass.Animat
 import emu.grasscutter.net.proto.EntityAuthorityInfoOuterClass.EntityAuthorityInfo;
 import emu.grasscutter.net.proto.EntityRendererChangedInfoOuterClass.EntityRendererChangedInfo;
 import emu.grasscutter.net.proto.FightPropPairOuterClass.*;
+import emu.grasscutter.net.proto.GadgetInteractReqOuterClass.GadgetInteractReq;
 import emu.grasscutter.net.proto.MotionInfoOuterClass.MotionInfo;
 import emu.grasscutter.net.proto.PropPairOuterClass.PropPair;
 import emu.grasscutter.net.proto.ProtEntityTypeOuterClass.ProtEntityType;
@@ -82,6 +83,11 @@ public class EntityVehicle extends EntityBaseGadget {
 	public Position getRotation() {
 		return this.rot;
 	}
+	
+	@Override
+    public void onInteract(Player player, GadgetInteractReq interactReq) {
+	    player.getInsectCaptureManager().arrestSmallCreature(this);
+	}
 
 	@Override
 	public SceneEntityInfo toProto() {
diff --git a/src/main/java/emu/grasscutter/game/entity/GameEntity.java b/src/main/java/emu/grasscutter/game/entity/GameEntity.java
index 21d8f817..c571f54f 100644
--- a/src/main/java/emu/grasscutter/game/entity/GameEntity.java
+++ b/src/main/java/emu/grasscutter/game/entity/GameEntity.java
@@ -3,12 +3,14 @@ package emu.grasscutter.game.entity;
 import java.util.HashMap;
 import java.util.Map;
 
+import emu.grasscutter.game.player.Player;
 import emu.grasscutter.game.props.FightProperty;
 import emu.grasscutter.game.props.LifeState;
 import emu.grasscutter.game.world.Scene;
 import emu.grasscutter.game.world.SpawnDataEntry;
 import emu.grasscutter.game.world.World;
 import emu.grasscutter.net.proto.FightPropPairOuterClass.FightPropPair;
+import emu.grasscutter.net.proto.GadgetInteractReqOuterClass.GadgetInteractReq;
 import emu.grasscutter.net.proto.MotionInfoOuterClass.MotionInfo;
 import emu.grasscutter.net.proto.MotionStateOuterClass.MotionState;
 import emu.grasscutter.net.proto.SceneEntityInfoOuterClass.SceneEntityInfo;
@@ -228,6 +230,15 @@ public abstract class GameEntity {
 		}
 	}
 	
+	/**
+     * Called when a player interacts with this entity
+     * @param player Player that is interacting with this entity
+	 * @param interactReq Interact request protobuf data
+     */
+    public void onInteract(Player player, GadgetInteractReq interactReq) {
+        
+    }
+	
     /**
      * Called when this entity is added to the world
      */
diff --git a/src/main/java/emu/grasscutter/game/entity/gadget/GadgetChest.java b/src/main/java/emu/grasscutter/game/entity/gadget/GadgetChest.java
index 02da258f..1fb14624 100644
--- a/src/main/java/emu/grasscutter/game/entity/gadget/GadgetChest.java
+++ b/src/main/java/emu/grasscutter/game/entity/gadget/GadgetChest.java
@@ -3,6 +3,7 @@ package emu.grasscutter.game.entity.gadget;
 import emu.grasscutter.Grasscutter;
 import emu.grasscutter.game.entity.EntityGadget;
 import emu.grasscutter.game.player.Player;
+import emu.grasscutter.game.props.LifeState;
 import emu.grasscutter.net.proto.BossChestInfoOuterClass.BossChestInfo;
 import emu.grasscutter.net.proto.GadgetInteractReqOuterClass.GadgetInteractReq;
 import emu.grasscutter.net.proto.InterOpTypeOuterClass.InterOpType;
@@ -11,6 +12,7 @@ import emu.grasscutter.net.proto.InteractTypeOuterClass.InteractType;
 import emu.grasscutter.net.proto.SceneGadgetInfoOuterClass.SceneGadgetInfo;
 import emu.grasscutter.scripts.constants.ScriptGadgetState;
 import emu.grasscutter.server.packet.send.PacketGadgetInteractRsp;
+import emu.grasscutter.server.packet.send.PacketLifeStateChangeNotify;
 
 public class GadgetChest extends GadgetContent {
 	
@@ -31,14 +33,13 @@ public class GadgetChest extends GadgetContent {
 			return false;
 		}else{
 			var success = handler.onInteract(this, player);
-			if (!success){
+			if (!success) {
 				return false;
 			}
 
 			getGadget().updateState(ScriptGadgetState.ChestOpened);
 			player.sendPacket(new PacketGadgetInteractRsp(this.getGadget(), InteractTypeOuterClass.InteractType.INTERACT_TYPE_OPEN_CHEST));
-			// let the chest disappear
-			getGadget().die();
+			
 			return true;
 		}
 	}
diff --git a/src/main/java/emu/grasscutter/game/player/Player.java b/src/main/java/emu/grasscutter/game/player/Player.java
index 60a15646..013f96c9 100644
--- a/src/main/java/emu/grasscutter/game/player/Player.java
+++ b/src/main/java/emu/grasscutter/game/player/Player.java
@@ -995,52 +995,14 @@ public class Player {
 		return this.getMailHandler().replaceMailByIndex(index, message);
 	}
 
-
-	public void interactWith(int gadgetEntityId, GadgetInteractReq opType) {
-		GameEntity entity = getScene().getEntityById(gadgetEntityId);
-		if (entity == null) {
+	public void interactWith(int gadgetEntityId, GadgetInteractReq interactReq) {
+		GameEntity target = getScene().getEntityById(gadgetEntityId);
+		
+		if (target == null) {
 			return;
 		}
-
-		// Handle
-		if (entity instanceof EntityItem drop) {
-			// Pick item
-			if (!drop.isShare()) // check drop owner to avoid someone picked up item in others' world
-			{
-				int dropOwner = (int)(drop.getGuid() >> 32);
-				if (dropOwner != getUid()) {
-					return;
-				}
-			}
-			entity.getScene().removeEntity(entity);
-			GameItem item = new GameItem(drop.getItemData(), drop.getCount());
-			// Add to inventory
-			boolean success = getInventory().addItem(item, ActionReason.SubfieldDrop);
-			if (success) {
-				if (!drop.isShare()) { // not shared drop
-					this.sendPacket(new PacketGadgetInteractRsp(drop, InteractType.INTERACT_TYPE_PICK_ITEM));
-				}else{
-					this.getScene().broadcastPacket(new PacketGadgetInteractRsp(drop, InteractType.INTERACT_TYPE_PICK_ITEM));
-				}
-			}
-		} else if (entity instanceof EntityGadget gadget) {
-			if (gadget.getContent() == null) {
-				return;
-			}
-
-			boolean shouldDelete = gadget.getContent().onInteract(this, opType);
-
-			if (shouldDelete) {
-				entity.getScene().removeEntity(entity, VisionType.VISION_TYPE_REMOVE);
-			}
-		} else if (entity instanceof EntityMonster monster) {
-			insectCaptureManager.arrestSmallCreature(monster);
-		} else if (entity instanceof EntityVehicle vehicle) {// try to arrest it, example: glowworm
-			insectCaptureManager.arrestSmallCreature(vehicle);
-		} else {
-			// Delete directly
-			entity.getScene().removeEntity(entity);
-		}
+		
+		target.onInteract(this, interactReq);
 	}
 
 	public void onPause() {
diff --git a/src/main/java/emu/grasscutter/game/world/Scene.java b/src/main/java/emu/grasscutter/game/world/Scene.java
index 85a57129..d13bc3ef 100644
--- a/src/main/java/emu/grasscutter/game/world/Scene.java
+++ b/src/main/java/emu/grasscutter/game/world/Scene.java
@@ -379,19 +379,28 @@ public class Scene {
 		// Sanity check
 		target.damage(result.getDamage(), result.getAttackerId());
 	}
+	
+	public void killEntity(GameEntity target) {
+	    killEntity(target, 0);
+	}
 
 	public void killEntity(GameEntity target, int attackerId) {
-		GameEntity attacker = getEntityById(attackerId);
-
-		//Check codex
-		if (attacker instanceof EntityClientGadget) {
-			var clientGadgetOwner = getEntityById(((EntityClientGadget) attacker).getOwnerEntityId());
-			if(clientGadgetOwner instanceof EntityAvatar) {
-				((EntityClientGadget) attacker).getOwner().getCodex().checkAnimal(target, CodexAnimalData.CodexAnimalUnlockCondition.CODEX_COUNT_TYPE_KILL);
-			}
+		GameEntity attacker = null;
+		
+		if (attackerId > 0) {
+		    attacker = getEntityById(attackerId);
 		}
-		else if (attacker instanceof EntityAvatar) {
-			((EntityAvatar) attacker).getPlayer().getCodex().checkAnimal(target, CodexAnimalData.CodexAnimalUnlockCondition.CODEX_COUNT_TYPE_KILL);
+
+		if (attacker != null) {
+		    // Check codex
+		    if (attacker instanceof EntityClientGadget gadgetAttacker) {
+	            var clientGadgetOwner = getEntityById(gadgetAttacker.getOwnerEntityId());
+	            if (clientGadgetOwner instanceof EntityAvatar) {
+	                ((EntityClientGadget) attacker).getOwner().getCodex().checkAnimal(target, CodexAnimalData.CodexAnimalUnlockCondition.CODEX_COUNT_TYPE_KILL);
+	            }
+	        } else if (attacker instanceof EntityAvatar avatarAttacker) {
+	            avatarAttacker.getPlayer().getCodex().checkAnimal(target, CodexAnimalData.CodexAnimalUnlockCondition.CODEX_COUNT_TYPE_KILL);
+	        }
 		}
 
 		// Packet
@@ -402,6 +411,7 @@ public class Scene {
 			getWorld().getServer().getDropSystem().callDrop((EntityMonster) target);
 		}
 
+		// Remove entity from world
 		this.removeEntity(target);
 
 		// Death event
-- 
GitLab