diff --git a/src/main/java/emu/grasscutter/data/GameData.java b/src/main/java/emu/grasscutter/data/GameData.java index 01a450fe5..e3394de82 100644 --- a/src/main/java/emu/grasscutter/data/GameData.java +++ b/src/main/java/emu/grasscutter/data/GameData.java @@ -4,29 +4,51 @@ import emu.grasscutter.Grasscutter; import emu.grasscutter.data.binout.*; import emu.grasscutter.data.binout.config.*; import emu.grasscutter.data.binout.routes.Route; -import emu.grasscutter.data.custom.*; +import emu.grasscutter.data.custom.TrialAvatarActivityCustomData; +import emu.grasscutter.data.custom.TrialAvatarCustomData; import emu.grasscutter.data.excels.*; -import emu.grasscutter.data.excels.achievement.*; -import emu.grasscutter.data.excels.activity.*; +import emu.grasscutter.data.excels.achievement.AchievementData; +import emu.grasscutter.data.excels.achievement.AchievementGoalData; +import emu.grasscutter.data.excels.activity.ActivityCondExcelConfigData; +import emu.grasscutter.data.excels.activity.ActivityData; +import emu.grasscutter.data.excels.activity.ActivityShopData; +import emu.grasscutter.data.excels.activity.ActivityWatcherData; import emu.grasscutter.data.excels.avatar.*; import emu.grasscutter.data.excels.codex.*; import emu.grasscutter.data.excels.dungeon.*; -import emu.grasscutter.data.excels.giving.*; -import emu.grasscutter.data.excels.monster.*; -import emu.grasscutter.data.excels.quest.*; -import emu.grasscutter.data.excels.reliquary.*; +import emu.grasscutter.data.excels.giving.GivingData; +import emu.grasscutter.data.excels.giving.GivingGroupData; +import emu.grasscutter.data.excels.monster.MonsterCurveData; +import emu.grasscutter.data.excels.monster.MonsterData; +import emu.grasscutter.data.excels.monster.MonsterDescribeData; +import emu.grasscutter.data.excels.monster.MonsterSpecialNameData; +import emu.grasscutter.data.excels.quest.QuestData; +import emu.grasscutter.data.excels.quest.QuestGlobalVarData; +import emu.grasscutter.data.excels.reliquary.ReliquaryAffixData; +import emu.grasscutter.data.excels.reliquary.ReliquaryLevelData; +import emu.grasscutter.data.excels.reliquary.ReliquaryMainPropData; +import emu.grasscutter.data.excels.reliquary.ReliquarySetData; import emu.grasscutter.data.excels.scene.*; -import emu.grasscutter.data.excels.tower.*; +import emu.grasscutter.data.excels.tower.TowerFloorData; +import emu.grasscutter.data.excels.tower.TowerLevelData; +import emu.grasscutter.data.excels.tower.TowerScheduleData; import emu.grasscutter.data.excels.trial.*; -import emu.grasscutter.data.excels.weapon.*; -import emu.grasscutter.data.excels.world.*; +import emu.grasscutter.data.excels.weapon.WeaponCurveData; +import emu.grasscutter.data.excels.weapon.WeaponLevelData; +import emu.grasscutter.data.excels.weapon.WeaponPromoteData; +import emu.grasscutter.data.excels.world.WeatherData; +import emu.grasscutter.data.excels.world.WorldAreaData; +import emu.grasscutter.data.excels.world.WorldLevelData; import emu.grasscutter.data.server.*; import emu.grasscutter.game.dungeons.DungeonDropEntry; -import emu.grasscutter.game.quest.*; +import emu.grasscutter.game.quest.QuestEncryptionKey; +import emu.grasscutter.game.quest.RewindData; +import emu.grasscutter.game.quest.TeleportData; import emu.grasscutter.game.quest.enums.QuestCond; import emu.grasscutter.game.world.GroupReplacementData; import emu.grasscutter.utils.Utils; import it.unimi.dsi.fastutil.ints.*; + import java.lang.reflect.Field; import java.util.*; import javax.annotation.Nullable; @@ -257,6 +279,10 @@ public final class GameData { private static final Int2ObjectMap guideTriggerDataMap = new Int2ObjectOpenHashMap<>(); + @Getter + private static final Int2ObjectMap homeWorldAnimalDataMap = + new Int2ObjectOpenHashMap<>(); + @Getter private static final Int2ObjectMap homeWorldBgmDataMap = new Int2ObjectOpenHashMap<>(); diff --git a/src/main/java/emu/grasscutter/data/excels/HomeWorldAnimalData.java b/src/main/java/emu/grasscutter/data/excels/HomeWorldAnimalData.java new file mode 100644 index 000000000..885867a39 --- /dev/null +++ b/src/main/java/emu/grasscutter/data/excels/HomeWorldAnimalData.java @@ -0,0 +1,22 @@ +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.experimental.FieldDefaults; + +@ResourceType(name = "HomeworldAnimalExcelConfigData.json") +@FieldDefaults(level = AccessLevel.PRIVATE) +@Getter +public class HomeWorldAnimalData extends GameResource { + int furnitureID; + int monsterID; + int isRebirth; + int rebirthCD; + + @Override + public int getId() { + return this.furnitureID; + } +} diff --git a/src/main/java/emu/grasscutter/game/entity/EntityHomeAnimal.java b/src/main/java/emu/grasscutter/game/entity/EntityHomeAnimal.java new file mode 100644 index 000000000..65807e290 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/entity/EntityHomeAnimal.java @@ -0,0 +1,80 @@ +package emu.grasscutter.game.entity; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.excels.HomeWorldAnimalData; +import emu.grasscutter.game.props.ElementType; +import emu.grasscutter.game.world.Position; +import emu.grasscutter.game.world.Scene; +import emu.grasscutter.net.proto.VisionTypeOuterClass; +import emu.grasscutter.server.packet.send.PacketSceneEntityAppearNotify; +import emu.grasscutter.server.packet.send.PacketSceneEntityDisappearNotify; +import lombok.Getter; + +public class EntityHomeAnimal extends EntityMonster implements Rebornable { + private int rebornCDTickCount; + private final Position rebornPos; + @Getter + private final int rebirth; + @Getter + private final int rebirthCD; + private boolean disappeared; + + public EntityHomeAnimal(Scene scene, HomeWorldAnimalData data, Position pos) { + super(scene, GameData.getMonsterDataMap().get(data.getMonsterID()), pos, 1); + + this.rebornPos = pos.clone(); + this.rebirth = data.getIsRebirth(); + this.rebirthCD = data.getRebirthCD(); + } + + @Override + public void damage(float amount, int killerId, ElementType attackType) { + } + + @Override + public void onTick(int sceneTime) { + super.onTick(sceneTime); + + if (this.isInCD()) { + this.rebornCDTickCount--; + if (this.rebornCDTickCount <= 0) { + this.reborn(); + } + } + } + + @Override + public void onCreate() { + } + + @Override + public Position getRebornPos() { + return this.rebornPos; + } + + @Override + public int getRebornCD() { + return this.rebirthCD; + } + + @Override + public void onAiKillSelf() { + this.getScene().broadcastPacket(new PacketSceneEntityDisappearNotify(this, VisionTypeOuterClass.VisionType.VISION_TYPE_REMOVE)); + this.rebornCDTickCount = this.getRebornCD(); + this.disappeared = true; + } + + @Override + public void reborn() { + if (this.disappeared) { + this.disappeared = false; + this.getPosition().set(this.getRebornPos()); + this.getScene().broadcastPacket(new PacketSceneEntityAppearNotify(this)); + } + } + + @Override + public boolean isInCD() { + return this.disappeared; + } +} diff --git a/src/main/java/emu/grasscutter/game/entity/Rebornable.java b/src/main/java/emu/grasscutter/game/entity/Rebornable.java new file mode 100644 index 000000000..5fef23e1b --- /dev/null +++ b/src/main/java/emu/grasscutter/game/entity/Rebornable.java @@ -0,0 +1,15 @@ +package emu.grasscutter.game.entity; + +import emu.grasscutter.game.world.Position; + +public interface Rebornable { + Position getRebornPos(); + + int getRebornCD(); + + void onAiKillSelf(); + + void reborn(); + + boolean isInCD(); +} diff --git a/src/main/java/emu/grasscutter/game/home/HomeScene.java b/src/main/java/emu/grasscutter/game/home/HomeScene.java new file mode 100644 index 000000000..1325c23dd --- /dev/null +++ b/src/main/java/emu/grasscutter/game/home/HomeScene.java @@ -0,0 +1,61 @@ +package emu.grasscutter.game.home; + +import emu.grasscutter.data.excels.scene.SceneData; +import emu.grasscutter.game.entity.GameEntity; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.world.Scene; +import emu.grasscutter.server.packet.send.PacketSceneTimeNotify; + +public class HomeScene extends Scene { + public HomeScene(HomeWorld world, SceneData sceneData) { + super(world, sceneData); + this.setDontDestroyWhenEmpty(true); + } + + @Override + public boolean isPaused() { + return false; + } + + @Override + public HomeWorld getWorld() { + return (HomeWorld) super.getWorld(); + } + + public GameHome getHome() { + return this.getWorld().getHome(); + } + + public HomeSceneItem getSceneItem() { + return this.getHome().getHomeSceneItem(this.getId()); + } + + @Override + public void setPaused(boolean paused) { + } + + @Override + public void onTick() { + this.getEntities().values().forEach(gameEntity -> gameEntity.onTick(this.getSceneTimeSeconds())); + + this.finishLoading(); + this.checkPlayerRespawn(); + if (this.tickCount++ % 10 == 0) this.broadcastPacket(new PacketSceneTimeNotify(this)); + } + + @Override + public void checkNpcGroup() { + } + + @Override + public void checkSpawns() { + } + + @Override + public void addItemEntity(int itemId, int amount, GameEntity bornForm) { + } + + @Override + public void loadNpcForPlayerEnter(Player player) { + } +} diff --git a/src/main/java/emu/grasscutter/game/home/HomeSceneItem.java b/src/main/java/emu/grasscutter/game/home/HomeSceneItem.java index 4157fcb28..18d7e2bb7 100644 --- a/src/main/java/emu/grasscutter/game/home/HomeSceneItem.java +++ b/src/main/java/emu/grasscutter/game/home/HomeSceneItem.java @@ -1,10 +1,17 @@ package emu.grasscutter.game.home; -import dev.morphia.annotations.*; +import dev.morphia.annotations.Entity; +import dev.morphia.annotations.Id; import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.GameData; import emu.grasscutter.data.binout.HomeworldDefaultSaveData; +import emu.grasscutter.game.entity.EntityHomeAnimal; import emu.grasscutter.game.world.Position; +import emu.grasscutter.game.world.Scene; import emu.grasscutter.net.proto.HomeSceneArrangementInfoOuterClass.HomeSceneArrangementInfo; + +import java.util.Collection; +import java.util.List; import java.util.Map; import java.util.stream.Collectors; import lombok.*; @@ -71,6 +78,19 @@ public class HomeSceneItem { return mainHouse == null || mainHouse.getAsItem() == null; } + public List getAnimals(Scene scene) { + return this.blockItems.values().stream() + .map(HomeBlockItem::getDeployAnimalList) + .flatMap(Collection::stream) + .filter(homeAnimalItem -> GameData.getHomeWorldAnimalDataMap().containsKey(homeAnimalItem.getFurnitureId())) + .map(homeAnimalItem -> { + return new EntityHomeAnimal(scene, + GameData.getHomeWorldAnimalDataMap().get(homeAnimalItem.getFurnitureId()), + homeAnimalItem.getSpawnPos()); + }) + .toList(); + } + public int calComfort() { return this.blockItems.values().stream().mapToInt(HomeBlockItem::calComfort).sum(); } diff --git a/src/main/java/emu/grasscutter/game/home/HomeWorld.java b/src/main/java/emu/grasscutter/game/home/HomeWorld.java index 05f685362..85280564d 100644 --- a/src/main/java/emu/grasscutter/game/home/HomeWorld.java +++ b/src/main/java/emu/grasscutter/game/home/HomeWorld.java @@ -1,11 +1,14 @@ package emu.grasscutter.game.home; +import emu.grasscutter.data.GameData; import emu.grasscutter.game.entity.EntityTeam; import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.world.*; +import emu.grasscutter.game.world.Scene; +import emu.grasscutter.game.world.World; import emu.grasscutter.net.packet.BasePacket; import emu.grasscutter.net.proto.ChatInfoOuterClass; import emu.grasscutter.server.game.GameServer; + import emu.grasscutter.server.packet.send.*; import java.util.List; import lombok.Getter; @@ -20,6 +23,21 @@ public class HomeWorld extends World { server.registerHomeWorld(this); } + @Override + public void registerScene(Scene scene) { + this.addAnimalsToScene((HomeScene) scene); + super.registerScene(scene); + } + + @Override + public void deregisterScene(Scene scene) { + super.deregisterScene(scene); + } + + private void addAnimalsToScene(HomeScene scene) { + scene.getSceneItem().getAnimals(scene).forEach(scene::addEntity); + } + @Override public synchronized void addPlayer(Player player) { // Check if player already in @@ -117,6 +135,23 @@ public class HomeWorld extends World { .build())); } + @Override + public HomeScene getSceneById(int sceneId) { + var scene = this.getScenes().get(sceneId); + if (scene instanceof HomeScene homeScene) { + return homeScene; + } + + var sceneData = GameData.getSceneDataMap().get(sceneId); + if (sceneData != null) { + scene = new HomeScene(this, sceneData); + this.registerScene(scene); + return (HomeScene) scene; + } + + return null; + } + @Override public int getNextPeerId() { return this.getPlayers().size() + 1; diff --git a/src/main/java/emu/grasscutter/game/world/Scene.java b/src/main/java/emu/grasscutter/game/world/Scene.java index a42c96a2c..17f4212f1 100644 --- a/src/main/java/emu/grasscutter/game/world/Scene.java +++ b/src/main/java/emu/grasscutter/game/world/Scene.java @@ -1,7 +1,8 @@ package emu.grasscutter.game.world; import emu.grasscutter.Grasscutter; -import emu.grasscutter.data.*; +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.GameDepot; import emu.grasscutter.data.binout.SceneNpcBornEntry; import emu.grasscutter.data.binout.routes.Route; import emu.grasscutter.data.excels.ItemData; @@ -11,14 +12,16 @@ import emu.grasscutter.data.excels.scene.SceneData; import emu.grasscutter.data.excels.world.WorldLevelData; import emu.grasscutter.data.server.Grid; import emu.grasscutter.game.avatar.Avatar; -import emu.grasscutter.game.dungeons.*; +import emu.grasscutter.game.dungeons.DungeonManager; +import emu.grasscutter.game.dungeons.DungeonSettleListener; import emu.grasscutter.game.dungeons.challenge.WorldChallenge; import emu.grasscutter.game.dungeons.enums.DungeonPassConditionType; import emu.grasscutter.game.entity.*; import emu.grasscutter.game.entity.gadget.GadgetWorktop; import emu.grasscutter.game.inventory.GameItem; import emu.grasscutter.game.managers.blossom.BlossomManager; -import emu.grasscutter.game.player.*; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.player.TeamInfo; import emu.grasscutter.game.props.*; import emu.grasscutter.game.quest.QuestGroupSuite; import emu.grasscutter.game.world.data.TeleportProperties; @@ -26,22 +29,27 @@ import emu.grasscutter.net.packet.BasePacket; import emu.grasscutter.net.proto.*; import emu.grasscutter.net.proto.AttackResultOuterClass.AttackResult; import emu.grasscutter.net.proto.VisionTypeOuterClass.VisionType; -import emu.grasscutter.scripts.*; +import emu.grasscutter.scripts.SceneIndexManager; +import emu.grasscutter.scripts.SceneScriptManager; import emu.grasscutter.scripts.constants.EventType; -import emu.grasscutter.scripts.data.*; +import emu.grasscutter.scripts.data.SceneBlock; +import emu.grasscutter.scripts.data.SceneGroup; +import emu.grasscutter.scripts.data.ScriptArgs; import emu.grasscutter.server.event.entity.EntityCreationEvent; import emu.grasscutter.server.event.player.PlayerTeleportEvent; import emu.grasscutter.server.packet.send.*; import emu.grasscutter.server.scheduler.ServerTaskScheduler; import emu.grasscutter.utils.objects.KahnsSort; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; + import java.util.*; -import java.util.concurrent.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; import java.util.stream.Collectors; import javax.annotation.Nullable; import lombok.*; -public final class Scene { +public class Scene { @Getter private final World world; @Getter private final SceneData sceneData; @Getter private final List players; @@ -66,7 +74,7 @@ public final class Scene { @Getter @Setter private int killedMonsterCount; private Set npcBornEntrySet; @Getter private boolean finishedLoading = false; - @Getter private int tickCount = 0; + @Getter protected int tickCount = 0; @Getter private boolean isPaused = false; private final List afterLoadedCallbacks = new ArrayList<>(); @@ -456,7 +464,10 @@ public final class Scene { public void showOtherEntities(Player player) { GameEntity currentEntity = player.getTeamManager().getCurrentAvatarEntity(); List entities = - this.getEntities().values().stream().filter(entity -> entity != currentEntity).toList(); + this.getEntities().values().stream() + .filter(entity -> entity != currentEntity) + .filter(gameEntity -> !(gameEntity instanceof Rebornable rebornable) || !rebornable.isInCD()) + .toList(); player.sendPacket(new PacketSceneEntityAppearNotify(entities, VisionType.VISION_TYPE_MEET)); } @@ -583,7 +594,7 @@ public final class Scene { } /** Validates a player's current position. Teleports the player if the player is out of bounds. */ - private void checkPlayerRespawn() { + protected void checkPlayerRespawn() { if (this.getScriptManager().getConfig() == null) return; var diePos = this.getScriptManager().getConfig().die_y; diff --git a/src/main/java/emu/grasscutter/server/game/GameServer.java b/src/main/java/emu/grasscutter/server/game/GameServer.java index 39a3d9880..b2ebf1947 100644 --- a/src/main/java/emu/grasscutter/server/game/GameServer.java +++ b/src/main/java/emu/grasscutter/server/game/GameServer.java @@ -8,32 +8,41 @@ import emu.grasscutter.Grasscutter.ServerRunMode; import emu.grasscutter.database.DatabaseHelper; import emu.grasscutter.game.Account; import emu.grasscutter.game.battlepass.BattlePassSystem; -import emu.grasscutter.game.chat.*; +import emu.grasscutter.game.chat.ChatSystem; +import emu.grasscutter.game.chat.ChatSystemHandler; import emu.grasscutter.game.combine.CombineManger; -import emu.grasscutter.game.drop.*; +import emu.grasscutter.game.drop.DropSystem; +import emu.grasscutter.game.drop.DropSystemLegacy; import emu.grasscutter.game.dungeons.DungeonSystem; import emu.grasscutter.game.expedition.ExpeditionSystem; import emu.grasscutter.game.gacha.GachaSystem; -import emu.grasscutter.game.home.*; -import emu.grasscutter.game.managers.cooking.*; +import emu.grasscutter.game.home.HomeWorld; +import emu.grasscutter.game.home.HomeWorldMPSystem; +import emu.grasscutter.game.managers.cooking.CookingCompoundManager; +import emu.grasscutter.game.managers.cooking.CookingManager; import emu.grasscutter.game.managers.energy.EnergyManager; import emu.grasscutter.game.managers.stamina.StaminaManager; import emu.grasscutter.game.player.Player; import emu.grasscutter.game.quest.QuestSystem; import emu.grasscutter.game.shop.ShopSystem; -import emu.grasscutter.game.systems.*; +import emu.grasscutter.game.systems.AnnouncementSystem; +import emu.grasscutter.game.systems.InventorySystem; +import emu.grasscutter.game.systems.MultiplayerSystem; import emu.grasscutter.game.talk.TalkSystem; import emu.grasscutter.game.tower.TowerSystem; -import emu.grasscutter.game.world.*; +import emu.grasscutter.game.world.World; +import emu.grasscutter.game.world.WorldDataSystem; import emu.grasscutter.net.packet.PacketHandler; import emu.grasscutter.net.proto.SocialDetailOuterClass.SocialDetail; import emu.grasscutter.server.dispatch.DispatchClient; import emu.grasscutter.server.event.game.ServerTickEvent; -import emu.grasscutter.server.event.internal.*; +import emu.grasscutter.server.event.internal.ServerStartEvent; +import emu.grasscutter.server.event.internal.ServerStopEvent; import emu.grasscutter.server.event.types.ServerEvent; import emu.grasscutter.server.scheduler.ServerTaskScheduler; import emu.grasscutter.task.TaskMap; import emu.grasscutter.utils.Utils; + import it.unimi.dsi.fastutil.ints.*; import java.net.*; import java.time.*; @@ -283,6 +292,9 @@ public final class GameServer extends KcpServer implements Iterable { // Tick worlds. this.worlds.removeIf(World::onTick); + // Tick Home Worlds (Not remove, HomeWorld is constant). + this.homeWorlds.values().forEach(HomeWorld::onTick); + // Tick players. this.players.values().forEach(Player::onTick); diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerEntityAiKillSelfNotify.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerEntityAiKillSelfNotify.java new file mode 100644 index 000000000..a083229b3 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerEntityAiKillSelfNotify.java @@ -0,0 +1,19 @@ +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.game.entity.Rebornable; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.EntityAiKillSelfNotifyOuterClass; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.EntityAiKillSelfNotify) +public class HandlerEntityAiKillSelfNotify extends PacketHandler { + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + var entityId = EntityAiKillSelfNotifyOuterClass.EntityAiKillSelfNotify.parseFrom(payload).getEntityId(); + if (session.getPlayer().getScene().getEntityById(entityId) instanceof Rebornable rebornable) { + rebornable.onAiKillSelf(); + } + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeChangeEditModeReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeChangeEditModeReq.java index b05a64999..0bdb51fbc 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeChangeEditModeReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeChangeEditModeReq.java @@ -1,9 +1,15 @@ package emu.grasscutter.server.packet.recv; -import emu.grasscutter.net.packet.*; -import emu.grasscutter.net.proto.*; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.HomeChangeEditModeReqOuterClass; +import emu.grasscutter.net.proto.RetcodeOuterClass; import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.*; +import emu.grasscutter.server.packet.send.PacketHomeBasicInfoNotify; +import emu.grasscutter.server.packet.send.PacketHomeChangeEditModeRsp; +import emu.grasscutter.server.packet.send.PacketHomeComfortInfoNotify; +import emu.grasscutter.server.packet.send.PacketHomePreChangeEditModeNotify; @Opcodes(PacketOpcodes.HomeChangeEditModeReq) public class HandlerHomeChangeEditModeReq extends PacketHandler { @@ -24,6 +30,11 @@ public class HandlerHomeChangeEditModeReq extends PacketHandler { session.send(new PacketHomeBasicInfoNotify(session.getPlayer(), req.getIsEnterEditMode())); session.send(new PacketHomeComfortInfoNotify(session.getPlayer())); + if (!req.getIsEnterEditMode()) { + var scene = session.getPlayer().getScene(); + scene.addEntities(session.getPlayer().getCurHomeWorld().getHome().getHomeSceneItem(scene.getId()).getAnimals(scene)); + } + session.send(new PacketHomeChangeEditModeRsp(req.getIsEnterEditMode())); } } diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeEnterEditModeFinishReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeEnterEditModeFinishReq.java index 85f0655b5..214eabdb6 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeEnterEditModeFinishReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeEnterEditModeFinishReq.java @@ -1,6 +1,10 @@ package emu.grasscutter.server.packet.recv; -import emu.grasscutter.net.packet.*; +import emu.grasscutter.game.entity.EntityHomeAnimal; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.VisionTypeOuterClass; import emu.grasscutter.server.game.GameSession; import emu.grasscutter.server.packet.send.PacketHomeEnterEditModeFinishRsp; @@ -12,6 +16,10 @@ public class HandlerHomeEnterEditModeFinishReq extends PacketHandler { /* * This packet is about the edit mode */ + + var scene = session.getPlayer().getScene(); + scene.removeEntities(scene.getEntities().values().stream().filter(gameEntity -> gameEntity instanceof EntityHomeAnimal).toList(), VisionTypeOuterClass.VisionType.VISION_TYPE_REMOVE); + session.send(new PacketHomeEnterEditModeFinishRsp()); } }