Fix no static gadget in the map,example: no tree but a fruit in the air (#1415)

* fixGadget

* fixGadget

* add gadgetObject

* fix bug
This commit is contained in:
zhaodice 2022-07-02 02:41:53 +08:00 committed by GitHub
parent 696206c73c
commit 5416a2f9fd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 36529 additions and 93 deletions

View File

@ -39,13 +39,13 @@ public class EntityGadget extends EntityBaseGadget {
private final Position pos;
private final Position rot;
private int gadgetId;
private int state;
private int pointType;
private GadgetContent content;
private Int2FloatOpenHashMap fightProp;
private SceneGadget metaGadget;
public EntityGadget(Scene scene, int gadgetId, Position pos, Position rot) {
super(scene);
this.data = GameData.getGadgetDataMap().get(gadgetId);
@ -63,7 +63,7 @@ public class EntityGadget extends EntityBaseGadget {
this(scene, gadgetId, pos, rot);
this.content = content;
}
public GadgetData getGadgetData() {
return data;
}
@ -77,7 +77,7 @@ public class EntityGadget extends EntityBaseGadget {
public Position getRotation() {
return this.rot;
}
public int getGadgetId() {
return gadgetId;
}
@ -93,7 +93,7 @@ public class EntityGadget extends EntityBaseGadget {
public void setState(int state) {
this.state = state;
}
public void updateState(int state){
this.setState(state);
this.getScene().broadcastPacket(new PacketGadgetStateNotify(this, state));
@ -130,7 +130,7 @@ public class EntityGadget extends EntityBaseGadget {
if (getContent() != null || getGadgetData() == null || getGadgetData().getType() == null) {
return;
}
EntityType type = getGadgetData().getType();
GadgetContent content = switch (type) {
case GatherPoint -> new GadgetGatherPoint(this);
@ -138,9 +138,10 @@ public class EntityGadget extends EntityBaseGadget {
case Worktop -> new GadgetWorktop(this);
case RewardStatue -> new GadgetRewardStatue(this);
case Chest -> new GadgetChest(this);
case Gadget -> new GadgetObject(this);
default -> null;
};
this.content = content;
}
@ -149,7 +150,7 @@ public class EntityGadget extends EntityBaseGadget {
if (this.fightProp == null) this.fightProp = new Int2FloatOpenHashMap();
return this.fightProp;
}
@Override
public void onCreate() {
// Lua event
@ -166,7 +167,7 @@ public class EntityGadget extends EntityBaseGadget {
}
getScene().getScriptManager().callEvent(EventType.EVENT_ANY_GADGET_DIE, new ScriptArgs(this.getConfigId()));
}
@Override
public SceneEntityInfo toProto() {
EntityAuthorityInfo authority = EntityAuthorityInfo.newBuilder()
@ -175,7 +176,7 @@ public class EntityGadget extends EntityBaseGadget {
.setAiInfo(SceneEntityAiInfo.newBuilder().setIsAiOpen(true).setBornPos(Vector.newBuilder()))
.setBornPos(Vector.newBuilder())
.build();
SceneEntityInfo.Builder entityInfo = SceneEntityInfo.newBuilder()
.setEntityId(getId())
.setEntityType(ProtEntityType.PROT_ENTITY_TYPE_GADGET)
@ -184,13 +185,13 @@ public class EntityGadget extends EntityBaseGadget {
.setEntityClientData(EntityClientData.newBuilder())
.setEntityAuthorityInfo(authority)
.setLifeState(1);
PropPair pair = PropPair.newBuilder()
.setType(PlayerProperty.PROP_LEVEL.getId())
.setPropValue(ProtoHelper.newPropValue(PlayerProperty.PROP_LEVEL, 1))
.build();
entityInfo.addPropList(pair);
// We do not use the getter to null check because the getter will create a fight prop map if it is null
if (this.fightProp != null) {
this.addAllFightPropsToEntityInfo(entityInfo);
@ -203,13 +204,13 @@ public class EntityGadget extends EntityBaseGadget {
.setGadgetState(this.getState())
.setIsEnableInteract(true)
.setAuthorityPeerId(this.getScene().getWorld().getHostPeerId());
if (this.getContent() != null) {
this.getContent().onBuildProto(gadgetInfo);
}
entityInfo.setGadget(gadgetInfo);
return entityInfo.build();
}
public void die() {

View File

@ -0,0 +1,22 @@
package emu.grasscutter.game.entity.gadget;
import emu.grasscutter.game.entity.EntityGadget;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.net.proto.GadgetInteractReqOuterClass;
import emu.grasscutter.net.proto.SceneGadgetInfoOuterClass;
public class GadgetObject extends GadgetContent{
public GadgetObject(EntityGadget gadget) {
super(gadget);
}
@Override
public boolean onInteract(Player player, GadgetInteractReqOuterClass.GadgetInteractReq req) {
return false;
}
@Override
public void onBuildProto(SceneGadgetInfoOuterClass.SceneGadgetInfo.Builder gadgetInfo) {
}
}

View File

@ -75,11 +75,11 @@ public class Scene {
public World getWorld() {
return world;
}
public SceneData getSceneData() {
return this.sceneData;
}
public SceneType getSceneType() {
return getSceneData().getSceneType();
}
@ -201,18 +201,18 @@ public class Scene {
public boolean isInScene(GameEntity entity) {
return this.entities.containsKey(entity.getId());
}
public synchronized void addPlayer(Player player) {
// Check if player already in
if (getPlayers().contains(player)) {
return;
}
// Remove player from prev scene
if (player.getScene() != null) {
player.getScene().removePlayer(player);
}
// Add
getPlayers().add(player);
player.setSceneId(this.getId());
@ -220,31 +220,31 @@ public class Scene {
this.setupPlayerAvatars(player);
}
public synchronized void removePlayer(Player player) {
// Remove from challenge if leaving
if (this.getChallenge() != null && this.getChallenge().inProgress()) {
player.sendPacket(new PacketDungeonChallengeFinishNotify(this.getChallenge()));
}
// Remove player from scene
getPlayers().remove(player);
player.setScene(null);
// Remove player avatars
this.removePlayerAvatars(player);
// Remove player gadgets
for (EntityBaseGadget gadget : player.getTeamManager().getGadgets()) {
this.removeEntity(gadget);
}
// Deregister scene if not in use
if (this.getPlayerCount() <= 0 && !this.dontDestroyWhenEmpty()) {
this.getWorld().deregisterScene(this);
}
}
private void setupPlayerAvatars(Player player) {
// Clear entities from old team
player.getTeamManager().getActiveTeam().clear();
@ -255,13 +255,13 @@ public class Scene {
EntityAvatar entity = new EntityAvatar(player.getScene(), player.getAvatars().getAvatarById(avatarId));
player.getTeamManager().getActiveTeam().add(entity);
}
// Limit character index in case its out of bounds
if (player.getTeamManager().getCurrentCharacterIndex() >= player.getTeamManager().getActiveTeam().size() || player.getTeamManager().getCurrentCharacterIndex() < 0) {
player.getTeamManager().setCurrentCharacterIndex(player.getTeamManager().getCurrentCharacterIndex() - 1);
}
}
private void removePlayerAvatars(Player player) {
Iterator<EntityAvatar> it = player.getTeamManager().getActiveTeam().iterator();
while (it.hasNext()) {
@ -269,18 +269,18 @@ public class Scene {
it.remove();
}
}
public void spawnPlayer(Player player) {
if (this.isInScene(player.getTeamManager().getCurrentAvatarEntity())) {
return;
}
if (player.getTeamManager().getCurrentAvatarEntity().getFightProperty(FightProperty.FIGHT_PROP_CUR_HP) <= 0f) {
player.getTeamManager().getCurrentAvatarEntity().setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, 1f);
}
this.addEntity(player.getTeamManager().getCurrentAvatarEntity());
// Notify the client of any extra skill charges
for (EntityAvatar entity : player.getTeamManager().getActiveTeam()) {
if (entity.getAvatar().getSkillExtraChargeMap().size() > 0) {
@ -288,12 +288,12 @@ public class Scene {
}
}
}
private void addEntityDirectly(GameEntity entity) {
getEntities().put(entity.getId(), entity);
entity.onCreate(); // Call entity create event
}
public synchronized void addEntity(GameEntity entity) {
this.addEntityDirectly(entity);
this.broadcastPacket(new PacketSceneEntityAppearNotify(entity));
@ -307,7 +307,7 @@ public class Scene {
public void addEntities(Collection<? extends GameEntity> entities){
addEntities(entities, VisionType.VISION_TYPE_BORN);
}
public synchronized void addEntities(Collection<? extends GameEntity> entities, VisionType visionType) {
if(entities == null || entities.isEmpty()){
return;
@ -315,18 +315,18 @@ public class Scene {
for (GameEntity entity : entities) {
this.addEntityDirectly(entity);
}
this.broadcastPacket(new PacketSceneEntityAppearNotify(entities, visionType));
}
private GameEntity removeEntityDirectly(GameEntity entity) {
return getEntities().remove(entity.getId());
}
public void removeEntity(GameEntity entity) {
this.removeEntity(entity, VisionType.VISION_TYPE_DIE);
}
public synchronized void removeEntity(GameEntity entity, VisionType visionType) {
GameEntity removed = this.removeEntityDirectly(entity);
if (removed != null) {
@ -351,7 +351,7 @@ public class Scene {
public void showOtherEntities(Player player) {
List<GameEntity> entities = new LinkedList<>();
GameEntity currentEntity = player.getTeamManager().getCurrentAvatarEntity();
for (GameEntity entity : this.getEntities().values()) {
if (entity == currentEntity) {
continue;
@ -361,26 +361,26 @@ public class Scene {
player.sendPacket(new PacketSceneEntityAppearNotify(entities, VisionType.VISION_TYPE_MEET));
}
public void handleAttack(AttackResult result) {
//GameEntity attacker = getEntityById(result.getAttackerId());
GameEntity target = getEntityById(result.getDefenseId());
if (target == null) {
return;
}
// Godmode check
if (target instanceof EntityAvatar) {
if (((EntityAvatar) target).getPlayer().inGodmode()) {
return;
}
}
// Sanity check
target.damage(result.getDamage(), result.getAttackerId());
}
public void killEntity(GameEntity target, int attackerId) {
GameEntity attacker = getEntityById(attackerId);
@ -404,7 +404,7 @@ public class Scene {
}
this.removeEntity(target);
// Death event
target.onDeath(attackerId);
}
@ -427,96 +427,102 @@ public class Scene {
challenge.onCheckTimeOut();
}
}
public int getEntityLevel(int baseLevel, int worldLevelOverride) {
int level = worldLevelOverride > 0 ? worldLevelOverride + baseLevel - 22 : baseLevel;
level = level >= 100 ? 100 : level;
level = level <= 0 ? 1 : level;
return level;
}
// TODO - Test
public synchronized void checkSpawns() {
int RANGE = 100;
SpatialIndex<SpawnGroupEntry> list = GameDepot.getSpawnListById(this.getId());
Set<SpawnDataEntry> visible = new HashSet<>();
for (Player player : this.getPlayers()) {
int RANGE = 100;
Position position = player.getPos();
Collection<SpawnGroupEntry> entries = list.query(
new double[] {player.getPos().getX() - RANGE, player.getPos().getZ() - RANGE},
new double[] {player.getPos().getX() + RANGE, player.getPos().getZ() + RANGE}
new double[] {position.getX() - RANGE, position.getZ() - RANGE},
new double[] {position.getX() + RANGE, position.getZ() + RANGE}
);
for (SpawnGroupEntry entry : entries) {
for (SpawnDataEntry spawnData : entry.getSpawns()) {
visible.add(spawnData);
}
}
}
// World level
WorldLevelData worldLevelData = GameData.getWorldLevelDataMap().get(getWorld().getWorldLevel());
int worldLevelOverride = 0;
if (worldLevelData != null) {
worldLevelOverride = worldLevelData.getMonsterLevel();
}
// Todo
List<GameEntity> toAdd = new LinkedList<>();
List<GameEntity> toRemove = new LinkedList<>();
var spawnedEntities = this.getSpawnedEntities();
for (SpawnDataEntry entry : visible) {
// If spawn entry is in our view and hasnt been spawned/killed yet, we should spawn it
if (!this.getSpawnedEntities().contains(entry) && !this.getDeadSpawnedEntities().contains(entry)) {
if (!spawnedEntities.contains(entry) && !this.getDeadSpawnedEntities().contains(entry)) {
// Entity object holder
GameEntity entity = null;
// Check if spawn entry is monster or gadget
if (entry.getMonsterId() > 0) {
MonsterData data = GameData.getMonsterDataMap().get(entry.getMonsterId());
if (data == null) continue;
int level = this.getEntityLevel(entry.getLevel(), worldLevelOverride);
EntityMonster monster = new EntityMonster(this, data, entry.getPos(), level);
monster.getRotation().set(entry.getRot());
monster.setGroupId(entry.getGroup().getGroupId());
monster.setPoseId(entry.getPoseId());
monster.setConfigId(entry.getConfigId());
monster.setSpawnEntry(entry);
entity = monster;
} else if (entry.getGadgetId() > 0) {
EntityGadget gadget = new EntityGadget(this, entry.getGadgetId(), entry.getPos(), entry.getRot());
gadget.setGroupId(entry.getGroup().getGroupId());
gadget.setConfigId(entry.getConfigId());
gadget.setSpawnEntry(entry);
int state = entry.getGadgetState();
if(state>0) {
gadget.setState(state);
}
gadget.buildContent();
gadget.setFightProperty(FightProperty.FIGHT_PROP_BASE_HP, 99999);
gadget.setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, 99999);
gadget.setFightProperty(FightProperty.FIGHT_PROP_MAX_HP, 99999);
entity = gadget;
}
if (entity == null) continue;
// Add to scene and spawned list
toAdd.add(entity);
getSpawnedEntities().add(entry);
spawnedEntities.add(entry);
}
}
for (GameEntity entity : this.getEntities().values()) {
if (entity.getSpawnEntry() != null && !visible.contains(entity.getSpawnEntry())) {
var spawnEntry = entity.getSpawnEntry();
if (spawnEntry != null && !visible.contains(spawnEntry)) {
toRemove.add(entity);
spawnedEntities.remove(spawnEntry);
}
}
if (toAdd.size() > 0) {
toAdd.stream().forEach(this::addEntityDirectly);
this.broadcastPacket(new PacketSceneEntityAppearNotify(toAdd, VisionType.VISION_TYPE_BORN));
@ -615,10 +621,10 @@ public class Scene {
if (group.init_config == null) {
continue;
}
// Load garbages
List<SceneGadget> garbageGadgets = group.getGarbageGadgets();
if (garbageGadgets != null) {
entities.addAll(garbageGadgets.stream().map(g -> scriptManager.createGadget(group.id, group.block_id, g))
.filter(Objects::nonNull)
@ -647,7 +653,7 @@ public class Scene {
//groups.forEach(g -> scriptManager.callEvent(EventType.EVENT_GROUP_LOAD, null));
Grasscutter.getLogger().info("Scene {} loaded {} group(s)", this.getId(), groups.size());
}
public void onUnloadBlock(SceneBlock block) {
List<GameEntity> toRemove = this.getEntities().values().stream()
.filter(e -> e.getBlockId() == block.id).toList();
@ -669,53 +675,53 @@ public class Scene {
Grasscutter.getLogger().info("Scene {} Block {} is unloaded.", this.getId(), block.id);
}
// Gadgets
public void onPlayerCreateGadget(EntityClientGadget gadget) {
// Directly add
this.addEntityDirectly(gadget);
// Add to owner's gadget list
gadget.getOwner().getTeamManager().getGadgets().add(gadget);
// Optimization
if (this.getPlayerCount() == 1 && this.getPlayers().get(0) == gadget.getOwner()) {
return;
}
this.broadcastPacketToOthers(gadget.getOwner(), new PacketSceneEntityAppearNotify(gadget));
}
public void onPlayerDestroyGadget(int entityId) {
GameEntity entity = getEntities().get(entityId);
if (entity == null || !(entity instanceof EntityClientGadget)) {
return;
}
// Get and remove entity
EntityClientGadget gadget = (EntityClientGadget) entity;
this.removeEntityDirectly(gadget);
// Remove from owner's gadget list
gadget.getOwner().getTeamManager().getGadgets().remove(gadget);
// Optimization
if (this.getPlayerCount() == 1 && this.getPlayers().get(0) == gadget.getOwner()) {
return;
}
this.broadcastPacketToOthers(gadget.getOwner(), new PacketSceneEntityDisappearNotify(gadget, VisionType.VISION_TYPE_DIE));
}
// Broadcasting
public void broadcastPacket(BasePacket packet) {
// Send to all players - might have to check if player has been sent data packets
for (Player player : this.getPlayers()) {
player.getSession().send(packet);
}
}
public void broadcastPacketToOthers(Player excludedPlayer, BasePacket packet) {
// Optimization
if (this.getPlayerCount() == 1 && this.getPlayers().get(0) == excludedPlayer) {

View File

@ -12,9 +12,10 @@ public class SpawnDataEntry {
private int level;
private int poseId;
private int gatherItemId;
private int gadgetState;
private Position pos;
private Position rot;
public SpawnGroupEntry getGroup() {
return group;
}
@ -26,23 +27,27 @@ public class SpawnDataEntry {
public int getMonsterId() {
return monsterId;
}
public int getGadgetId() {
return gadgetId;
}
public int getConfigId() {
public int getGadgetState() {
return gadgetState;
}
public int getConfigId() {
return configId;
}
public int getLevel() {
return level;
}
public int getPoseId() {
return poseId;
}
public int getGatherItemId() {
return gatherItemId;
}
@ -50,18 +55,18 @@ public class SpawnDataEntry {
public Position getPos() {
return pos;
}
public Position getRot() {
return rot;
}
public static class SpawnGroupEntry {
private int sceneId;
private int groupId;
private int blockId;
private Position pos;
private List<SpawnDataEntry> spawns;
public int getSceneId() {
return sceneId;
}

File diff suppressed because one or more lines are too long