Add `Entity::OnInteract`

This commit is contained in:
Melledy 2022-07-19 02:51:26 -07:00
parent 1a2f7fb5a7
commit 5feabc8f9a
8 changed files with 97 additions and 61 deletions

View File

@ -3,6 +3,7 @@ package emu.grasscutter.game.entity;
import emu.grasscutter.data.GameData; import emu.grasscutter.data.GameData;
import emu.grasscutter.data.excels.GadgetData; import emu.grasscutter.data.excels.GadgetData;
import emu.grasscutter.game.entity.gadget.*; import emu.grasscutter.game.entity.gadget.*;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.props.EntityIdType; import emu.grasscutter.game.props.EntityIdType;
import emu.grasscutter.game.props.EntityType; import emu.grasscutter.game.props.EntityType;
import emu.grasscutter.game.props.LifeState; 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.EntityClientDataOuterClass.EntityClientData;
import emu.grasscutter.net.proto.EntityRendererChangedInfoOuterClass.EntityRendererChangedInfo; import emu.grasscutter.net.proto.EntityRendererChangedInfoOuterClass.EntityRendererChangedInfo;
import emu.grasscutter.net.proto.FightPropPairOuterClass.FightPropPair; 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.MotionInfoOuterClass.MotionInfo;
import emu.grasscutter.net.proto.PropPairOuterClass.PropPair; import emu.grasscutter.net.proto.PropPairOuterClass.PropPair;
import emu.grasscutter.net.proto.ProtEntityTypeOuterClass.ProtEntityType; 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.SceneEntityInfoOuterClass.SceneEntityInfo;
import emu.grasscutter.net.proto.SceneGadgetInfoOuterClass.SceneGadgetInfo; import emu.grasscutter.net.proto.SceneGadgetInfoOuterClass.SceneGadgetInfo;
import emu.grasscutter.net.proto.VectorOuterClass.Vector; import emu.grasscutter.net.proto.VectorOuterClass.Vector;
import emu.grasscutter.net.proto.VisionTypeOuterClass.VisionType;
import emu.grasscutter.scripts.constants.EventType; import emu.grasscutter.scripts.constants.EventType;
import emu.grasscutter.scripts.data.SceneGadget; import emu.grasscutter.scripts.data.SceneGadget;
import emu.grasscutter.scripts.data.ScriptArgs; import emu.grasscutter.scripts.data.ScriptArgs;
@ -150,6 +153,19 @@ public class EntityGadget extends EntityBaseGadget {
if (this.fightProp == null) this.fightProp = new Int2FloatOpenHashMap(); if (this.fightProp == null) this.fightProp = new Int2FloatOpenHashMap();
return this.fightProp; 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 @Override
public void onCreate() { public void onCreate() {
@ -213,8 +229,4 @@ public class EntityGadget extends EntityBaseGadget {
return entityInfo.build(); return entityInfo.build();
} }
public void die() {
getScene().broadcastPacket(new PacketLifeStateChangeNotify(this, LifeState.LIFE_DEAD));
this.onDeath(0);
}
} }

View File

@ -3,6 +3,7 @@ package emu.grasscutter.game.entity;
import emu.grasscutter.data.excels.ItemData; import emu.grasscutter.data.excels.ItemData;
import emu.grasscutter.game.inventory.GameItem; import emu.grasscutter.game.inventory.GameItem;
import emu.grasscutter.game.player.Player; import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.props.ActionReason;
import emu.grasscutter.game.props.EntityIdType; import emu.grasscutter.game.props.EntityIdType;
import emu.grasscutter.game.props.PlayerProperty; import emu.grasscutter.game.props.PlayerProperty;
import emu.grasscutter.game.world.Scene; 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.EntityClientDataOuterClass.EntityClientData;
import emu.grasscutter.net.proto.EntityRendererChangedInfoOuterClass.EntityRendererChangedInfo; import emu.grasscutter.net.proto.EntityRendererChangedInfoOuterClass.EntityRendererChangedInfo;
import emu.grasscutter.net.proto.GadgetBornTypeOuterClass.GadgetBornType; 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.MotionInfoOuterClass.MotionInfo;
import emu.grasscutter.net.proto.PropPairOuterClass.PropPair; import emu.grasscutter.net.proto.PropPairOuterClass.PropPair;
import emu.grasscutter.net.proto.ProtEntityTypeOuterClass.ProtEntityType; 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.SceneEntityInfoOuterClass.SceneEntityInfo;
import emu.grasscutter.net.proto.SceneGadgetInfoOuterClass.SceneGadgetInfo; import emu.grasscutter.net.proto.SceneGadgetInfoOuterClass.SceneGadgetInfo;
import emu.grasscutter.net.proto.VectorOuterClass.Vector; import emu.grasscutter.net.proto.VectorOuterClass.Vector;
import emu.grasscutter.server.packet.send.PacketGadgetInteractRsp;
import emu.grasscutter.utils.Position; import emu.grasscutter.utils.Position;
import emu.grasscutter.utils.ProtoHelper; import emu.grasscutter.utils.ProtoHelper;
import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap; import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap;
@ -99,6 +103,30 @@ public class EntityItem extends EntityBaseGadget {
public boolean isShare() { public boolean isShare() {
return share; 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 @Override
public SceneEntityInfo toProto() { public SceneEntityInfo toProto() {

View File

@ -16,6 +16,7 @@ import emu.grasscutter.net.proto.EntityAuthorityInfoOuterClass.EntityAuthorityIn
import emu.grasscutter.net.proto.EntityClientDataOuterClass.EntityClientData; import emu.grasscutter.net.proto.EntityClientDataOuterClass.EntityClientData;
import emu.grasscutter.net.proto.EntityRendererChangedInfoOuterClass.EntityRendererChangedInfo; import emu.grasscutter.net.proto.EntityRendererChangedInfoOuterClass.EntityRendererChangedInfo;
import emu.grasscutter.net.proto.FightPropPairOuterClass.FightPropPair; 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.MonsterBornTypeOuterClass.MonsterBornType;
import emu.grasscutter.net.proto.PropPairOuterClass.PropPair; import emu.grasscutter.net.proto.PropPairOuterClass.PropPair;
import emu.grasscutter.net.proto.ProtEntityTypeOuterClass.ProtEntityType; import emu.grasscutter.net.proto.ProtEntityTypeOuterClass.ProtEntityType;
@ -112,6 +113,11 @@ public class EntityMonster extends GameEntity {
this.poseId = poseId; this.poseId = poseId;
} }
@Override
public void onInteract(Player player, GadgetInteractReq interactReq) {
player.getInsectCaptureManager().arrestSmallCreature(this);
}
@Override @Override
public void onCreate() { public void onCreate() {
// Lua event // Lua event

View File

@ -10,6 +10,7 @@ import emu.grasscutter.net.proto.AnimatorParameterValueInfoPairOuterClass.Animat
import emu.grasscutter.net.proto.EntityAuthorityInfoOuterClass.EntityAuthorityInfo; import emu.grasscutter.net.proto.EntityAuthorityInfoOuterClass.EntityAuthorityInfo;
import emu.grasscutter.net.proto.EntityRendererChangedInfoOuterClass.EntityRendererChangedInfo; import emu.grasscutter.net.proto.EntityRendererChangedInfoOuterClass.EntityRendererChangedInfo;
import emu.grasscutter.net.proto.FightPropPairOuterClass.*; 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.MotionInfoOuterClass.MotionInfo;
import emu.grasscutter.net.proto.PropPairOuterClass.PropPair; import emu.grasscutter.net.proto.PropPairOuterClass.PropPair;
import emu.grasscutter.net.proto.ProtEntityTypeOuterClass.ProtEntityType; import emu.grasscutter.net.proto.ProtEntityTypeOuterClass.ProtEntityType;
@ -82,6 +83,11 @@ public class EntityVehicle extends EntityBaseGadget {
public Position getRotation() { public Position getRotation() {
return this.rot; return this.rot;
} }
@Override
public void onInteract(Player player, GadgetInteractReq interactReq) {
player.getInsectCaptureManager().arrestSmallCreature(this);
}
@Override @Override
public SceneEntityInfo toProto() { public SceneEntityInfo toProto() {

View File

@ -3,12 +3,14 @@ package emu.grasscutter.game.entity;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.props.FightProperty; import emu.grasscutter.game.props.FightProperty;
import emu.grasscutter.game.props.LifeState; import emu.grasscutter.game.props.LifeState;
import emu.grasscutter.game.world.Scene; import emu.grasscutter.game.world.Scene;
import emu.grasscutter.game.world.SpawnDataEntry; import emu.grasscutter.game.world.SpawnDataEntry;
import emu.grasscutter.game.world.World; import emu.grasscutter.game.world.World;
import emu.grasscutter.net.proto.FightPropPairOuterClass.FightPropPair; 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.MotionInfoOuterClass.MotionInfo;
import emu.grasscutter.net.proto.MotionStateOuterClass.MotionState; import emu.grasscutter.net.proto.MotionStateOuterClass.MotionState;
import emu.grasscutter.net.proto.SceneEntityInfoOuterClass.SceneEntityInfo; 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 * Called when this entity is added to the world
*/ */

View File

@ -3,6 +3,7 @@ package emu.grasscutter.game.entity.gadget;
import emu.grasscutter.Grasscutter; import emu.grasscutter.Grasscutter;
import emu.grasscutter.game.entity.EntityGadget; import emu.grasscutter.game.entity.EntityGadget;
import emu.grasscutter.game.player.Player; import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.props.LifeState;
import emu.grasscutter.net.proto.BossChestInfoOuterClass.BossChestInfo; import emu.grasscutter.net.proto.BossChestInfoOuterClass.BossChestInfo;
import emu.grasscutter.net.proto.GadgetInteractReqOuterClass.GadgetInteractReq; import emu.grasscutter.net.proto.GadgetInteractReqOuterClass.GadgetInteractReq;
import emu.grasscutter.net.proto.InterOpTypeOuterClass.InterOpType; 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.net.proto.SceneGadgetInfoOuterClass.SceneGadgetInfo;
import emu.grasscutter.scripts.constants.ScriptGadgetState; import emu.grasscutter.scripts.constants.ScriptGadgetState;
import emu.grasscutter.server.packet.send.PacketGadgetInteractRsp; import emu.grasscutter.server.packet.send.PacketGadgetInteractRsp;
import emu.grasscutter.server.packet.send.PacketLifeStateChangeNotify;
public class GadgetChest extends GadgetContent { public class GadgetChest extends GadgetContent {
@ -31,14 +33,13 @@ public class GadgetChest extends GadgetContent {
return false; return false;
}else{ }else{
var success = handler.onInteract(this, player); var success = handler.onInteract(this, player);
if (!success){ if (!success) {
return false; return false;
} }
getGadget().updateState(ScriptGadgetState.ChestOpened); getGadget().updateState(ScriptGadgetState.ChestOpened);
player.sendPacket(new PacketGadgetInteractRsp(this.getGadget(), InteractTypeOuterClass.InteractType.INTERACT_TYPE_OPEN_CHEST)); player.sendPacket(new PacketGadgetInteractRsp(this.getGadget(), InteractTypeOuterClass.InteractType.INTERACT_TYPE_OPEN_CHEST));
// let the chest disappear
getGadget().die();
return true; return true;
} }
} }

View File

@ -995,52 +995,14 @@ public class Player {
return this.getMailHandler().replaceMailByIndex(index, message); return this.getMailHandler().replaceMailByIndex(index, message);
} }
public void interactWith(int gadgetEntityId, GadgetInteractReq interactReq) {
public void interactWith(int gadgetEntityId, GadgetInteractReq opType) { GameEntity target = getScene().getEntityById(gadgetEntityId);
GameEntity entity = getScene().getEntityById(gadgetEntityId);
if (entity == null) { if (target == null) {
return; return;
} }
// Handle target.onInteract(this, interactReq);
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);
}
} }
public void onPause() { public void onPause() {

View File

@ -379,19 +379,28 @@ public class Scene {
// Sanity check // Sanity check
target.damage(result.getDamage(), result.getAttackerId()); target.damage(result.getDamage(), result.getAttackerId());
} }
public void killEntity(GameEntity target) {
killEntity(target, 0);
}
public void killEntity(GameEntity target, int attackerId) { public void killEntity(GameEntity target, int attackerId) {
GameEntity attacker = getEntityById(attackerId); GameEntity attacker = null;
//Check codex if (attackerId > 0) {
if (attacker instanceof EntityClientGadget) { attacker = getEntityById(attackerId);
var clientGadgetOwner = getEntityById(((EntityClientGadget) attacker).getOwnerEntityId());
if(clientGadgetOwner instanceof EntityAvatar) {
((EntityClientGadget) attacker).getOwner().getCodex().checkAnimal(target, CodexAnimalData.CodexAnimalUnlockCondition.CODEX_COUNT_TYPE_KILL);
}
} }
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 // Packet
@ -402,6 +411,7 @@ public class Scene {
getWorld().getServer().getDropSystem().callDrop((EntityMonster) target); getWorld().getServer().getDropSystem().callDrop((EntityMonster) target);
} }
// Remove entity from world
this.removeEntity(target); this.removeEntity(target);
// Death event // Death event