From ed97201473b44a445479ed350b506a43ff6f07ba Mon Sep 17 00:00:00 2001 From: hamusuke Date: Sun, 3 Sep 2023 00:52:56 +0900 Subject: [PATCH] fix: arrangement of main house is duplicated even if player changes module (#2325) * fix: arrangement of main house is duplicated even if player change module * removeIf * Update src/main/java/emu/grasscutter/game/home/GameHome.java Co-authored-by: Magix <27646710+KingRainbow44@users.noreply.github.com> --------- Co-authored-by: Magix <27646710+KingRainbow44@users.noreply.github.com> --- .../emu/grasscutter/game/home/GameHome.java | 83 ++++++++++++++----- .../game/home/HomeFurnitureItem.java | 3 +- .../grasscutter/game/home/HomeSceneItem.java | 7 +- .../recv/HandlerHomeChangeModuleReq.java | 7 ++ .../packet/recv/HandlerHomeSceneJumpReq.java | 6 +- .../HandlerHomeUpdateArrangementInfoReq.java | 7 ++ .../send/PacketHomeChangeModuleRsp.java | 11 ++- .../send/PacketHomeComfortInfoNotify.java | 2 +- .../send/PacketHomeMarkPointNotify.java | 52 ++++++------ 9 files changed, 126 insertions(+), 52 deletions(-) diff --git a/src/main/java/emu/grasscutter/game/home/GameHome.java b/src/main/java/emu/grasscutter/game/home/GameHome.java index b9ddd1d71..e078b8f2d 100644 --- a/src/main/java/emu/grasscutter/game/home/GameHome.java +++ b/src/main/java/emu/grasscutter/game/home/GameHome.java @@ -12,6 +12,7 @@ import emu.grasscutter.game.props.SceneType; import emu.grasscutter.net.proto.HomeAvatarTalkFinishInfoOuterClass; import emu.grasscutter.server.packet.send.*; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; + import java.time.ZonedDateTime; import java.time.temporal.ChronoUnit; import java.util.*; @@ -51,6 +52,7 @@ public class GameHome { int storedFetterExp; List furnitureMakeSlotItemList; ConcurrentHashMap sceneMap; + ConcurrentHashMap mainHouseMap; Set unlockedHomeBgmList; int enterHomeOption; Map> finishedTalkIdMap; @@ -60,6 +62,9 @@ public class GameHome { if (home == null) { home = GameHome.create(uid); } + + home.fixMainHouseIfOld(); + return home; } @@ -69,12 +74,25 @@ public class GameHome { public static GameHome create(Integer uid) { return GameHome.of() - .ownerUid(uid) - .level(1) - .sceneMap(new ConcurrentHashMap<>()) - .unlockedHomeBgmList(new HashSet<>()) - .finishedTalkIdMap(new HashMap<>()) - .build(); + .ownerUid(uid) + .level(1) + .sceneMap(new ConcurrentHashMap<>()) + .mainHouseMap(new ConcurrentHashMap<>()) + .unlockedHomeBgmList(new HashSet<>()) + .finishedTalkIdMap(new HashMap<>()) + .build(); + } + + // Data fixer. + private void fixMainHouseIfOld() { + if (this.getMainHouseMap() == null) { + Grasscutter.getLogger().debug("Player {}'s main house will be deleted due to GC update! (ps. sorry XD)", this.getPlayer().getUid()); + this.mainHouseMap = new ConcurrentHashMap<>(); // assign. + } + + this.getSceneMap().values().removeIf(homeSceneItem -> homeSceneItem.getSceneId() > 2200); + + this.save(); } public void save() { @@ -82,6 +100,10 @@ public class GameHome { } public HomeSceneItem getHomeSceneItem(int sceneId) { + if (sceneId >= 2200) { + return this.getMainHouseItem(this.getPlayer().getCurrentRealmId() + 2000); + } + return sceneMap.computeIfAbsent( sceneId, e -> { @@ -98,8 +120,31 @@ public class GameHome { }); } + public HomeSceneItem getMainHouseItem(int outdoorSceneId) { + return this.getMainHouseMap().computeIfAbsent(outdoorSceneId, integer -> { + var curHomeSceneItem = this.getHomeSceneItem(outdoorSceneId); + var roomSceneId = curHomeSceneItem.getRoomSceneId(); + var defaultItem = GameData.getHomeworldDefaultSaveData().get(roomSceneId); + if (defaultItem == null) { + Grasscutter.getLogger().info("defaultItem == null! returns Liyue style house."); + return HomeSceneItem.parseFrom(GameData.getHomeworldDefaultSaveData().get(2202), 2202); // Liyue style + } + + Grasscutter.getLogger().info("Set player {} main house {} to initial setting", this.ownerUid, roomSceneId); + return HomeSceneItem.parseFrom(defaultItem, roomSceneId); + }); + } + + public void onMainHouseChanged() { + Grasscutter.getLogger().debug("main house changed!"); + var outdoor = this.getPlayer().getCurrentRealmId() + 2000; + this.getMainHouseMap().remove(outdoor); // delete main house in current scene. + this.getMainHouseItem(outdoor); // put new main house with default arrangement. + this.save(); + } + public void onOwnerLogin(Player player) { - if (this.player == null) this.player = player; + this.player = player; // update player pointer. (prevent offline player from sending packet) player.getSession().send(new PacketHomeBasicInfoNotify(player, false)); player.getSession().send(new PacketPlayerHomeCompInfoNotify(player)); player.getSession().send(new PacketHomeComfortInfoNotify(player)); @@ -273,19 +318,19 @@ public class GameHome { }); // Check as realm 5 inside is not in defaults and will be null - if (Objects.nonNull(sceneMap.get(player.getCurrentRealmId() + 2200))) { + if (Objects.nonNull(mainHouseMap.get(player.getCurrentRealmId() + 2000))) { // Indoors avatars - sceneMap - .get(player.getCurrentRealmId() + 2200) - .getBlockItems() - .forEach( - (i, e) -> { - e.getDeployNPCList() - .forEach( - id -> { - invitedAvatars.add(id.getAvatarId()); - }); - }); + mainHouseMap + .get(player.getCurrentRealmId() + 2000) + .getBlockItems() + .forEach( + (i, e) -> { + e.getDeployNPCList() + .forEach( + id -> { + invitedAvatars.add(id.getAvatarId()); + }); + }); } // Add exp to all avatars diff --git a/src/main/java/emu/grasscutter/game/home/HomeFurnitureItem.java b/src/main/java/emu/grasscutter/game/home/HomeFurnitureItem.java index 040f47347..2e1bd2703 100644 --- a/src/main/java/emu/grasscutter/game/home/HomeFurnitureItem.java +++ b/src/main/java/emu/grasscutter/game/home/HomeFurnitureItem.java @@ -5,6 +5,7 @@ import emu.grasscutter.data.GameData; import emu.grasscutter.data.binout.HomeworldDefaultSaveData; import emu.grasscutter.data.excels.ItemData; import emu.grasscutter.game.world.Position; + import emu.grasscutter.net.proto.*; import java.util.Set; import java.util.stream.Collectors; @@ -65,7 +66,7 @@ public class HomeFurnitureItem implements HomeMarkPointProtoFactory { } public ItemData getAsItem() { - return GameData.getItemDataMap().get(this.furnitureId); + return this.furnitureId == 0 ? null : GameData.getItemDataMap().get(this.furnitureId); } public int getComfort() { diff --git a/src/main/java/emu/grasscutter/game/home/HomeSceneItem.java b/src/main/java/emu/grasscutter/game/home/HomeSceneItem.java index c2984a0cf..a313c08dc 100644 --- a/src/main/java/emu/grasscutter/game/home/HomeSceneItem.java +++ b/src/main/java/emu/grasscutter/game/home/HomeSceneItem.java @@ -9,6 +9,7 @@ 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; @@ -62,7 +63,11 @@ public class HomeSceneItem { this.bornRot = new Position(arrangementInfo.getBornRot()); this.djinnPos = new Position(arrangementInfo.getDjinnPos()); this.homeBgmId = arrangementInfo.getBgmId(); - this.mainHouse = HomeFurnitureItem.parseFrom(arrangementInfo.getMainHouse()); + + if (!this.isRoom() && arrangementInfo.hasMainHouse()) { + this.mainHouse = HomeFurnitureItem.parseFrom(arrangementInfo.getMainHouse()); + } + this.tmpVersion = arrangementInfo.getTmpVersion(); } diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeChangeModuleReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeChangeModuleReq.java index e4e397269..ccb9262a3 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeChangeModuleReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeChangeModuleReq.java @@ -8,6 +8,7 @@ import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.proto.HomeChangeModuleReqOuterClass; import emu.grasscutter.server.event.player.PlayerTeleportEvent.TeleportType; import emu.grasscutter.server.game.GameSession; + import emu.grasscutter.server.packet.send.PacketHomeAvatarTalkFinishInfoNotify; import emu.grasscutter.server.packet.send.PacketHomeChangeModuleRsp; import emu.grasscutter.server.packet.send.PacketHomeComfortInfoNotify; @@ -20,6 +21,12 @@ public class HandlerHomeChangeModuleReq extends PacketHandler { public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { HomeChangeModuleReqOuterClass.HomeChangeModuleReq req = HomeChangeModuleReqOuterClass.HomeChangeModuleReq.parseFrom(payload); + + if (!session.getPlayer().getCurHomeWorld().getGuests().isEmpty()) { + session.send(new PacketHomeChangeModuleRsp()); + return; + } + session.getPlayer().setCurrentRealmId(req.getTargetModuleId()); session.send(new PacketHomeAvatarTalkFinishInfoNotify(session.getPlayer())); session.send(new PacketHomeChangeModuleRsp(req.getTargetModuleId())); diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeSceneJumpReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeSceneJumpReq.java index d365be12f..4764657c9 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeSceneJumpReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeSceneJumpReq.java @@ -1,6 +1,8 @@ package emu.grasscutter.server.packet.recv; -import emu.grasscutter.net.packet.*; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.proto.HomeSceneJumpReqOuterClass; import emu.grasscutter.server.game.GameSession; import emu.grasscutter.server.packet.send.PacketHomeSceneJumpRsp; @@ -22,7 +24,7 @@ public class HandlerHomeSceneJumpReq extends PacketHandler { var scene = world.getSceneById(req.getIsEnterRoomScene() ? homeScene.getRoomSceneId() : realmId); var pos = scene.getScriptManager().getConfig().born_pos; - var rot = home.getSceneMap().get(scene.getId()).getBornRot(); + var rot = home.getHomeSceneItem(scene.getId()).getBornRot(); // Make player face correct direction when entering or exiting session.getPlayer().getRotation().set(rot); diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeUpdateArrangementInfoReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeUpdateArrangementInfoReq.java index be36159e4..84edb8c9d 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeUpdateArrangementInfoReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeUpdateArrangementInfoReq.java @@ -5,6 +5,8 @@ import emu.grasscutter.net.packet.PacketHandler; import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.proto.HomeUpdateArrangementInfoReqOuterClass; import emu.grasscutter.server.game.GameSession; + +import emu.grasscutter.server.packet.send.PacketHomeBasicInfoNotify; import emu.grasscutter.server.packet.send.PacketHomeAvatarTalkFinishInfoNotify; import emu.grasscutter.server.packet.send.PacketHomeMarkPointNotify; import emu.grasscutter.server.packet.send.PacketHomeUpdateArrangementInfoRsp; @@ -20,8 +22,13 @@ public class HandlerHomeUpdateArrangementInfoReq extends PacketHandler { var homeScene = session.getPlayer().getHome().getHomeSceneItem(session.getPlayer().getSceneId()); + var roomSceneId = homeScene.getRoomSceneId(); homeScene.update(req.getSceneArrangementInfo()); + if (roomSceneId != homeScene.getRoomSceneId()) { + session.getPlayer().getHome().onMainHouseChanged(); + } + session.send(new PacketHomeBasicInfoNotify(session.getPlayer(), session.getPlayer().isInEditMode())); session.send(new PacketHomeAvatarTalkFinishInfoNotify(session.getPlayer())); session.send(new PacketHomeMarkPointNotify(session.getPlayer())); diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketHomeChangeModuleRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketHomeChangeModuleRsp.java index de279cf3d..85055bf04 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketHomeChangeModuleRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketHomeChangeModuleRsp.java @@ -1,7 +1,9 @@ package emu.grasscutter.server.packet.send; -import emu.grasscutter.net.packet.*; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.proto.HomeChangeModuleRspOuterClass; +import emu.grasscutter.net.proto.RetcodeOuterClass; public class PacketHomeChangeModuleRsp extends BasePacket { @@ -16,4 +18,11 @@ public class PacketHomeChangeModuleRsp extends BasePacket { this.setData(proto); } + + public PacketHomeChangeModuleRsp() { + super(PacketOpcodes.HomeChangeModuleRsp); + + this.setData(HomeChangeModuleRspOuterClass.HomeChangeModuleRsp.newBuilder() + .setRetcode(RetcodeOuterClass.Retcode.RET_HOME_HAS_GUEST_VALUE)); + } } diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketHomeComfortInfoNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketHomeComfortInfoNotify.java index 29604f58e..9197c4ff0 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketHomeComfortInfoNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketHomeComfortInfoNotify.java @@ -22,7 +22,7 @@ public class PacketHomeComfortInfoNotify extends BasePacket { var homeScene = player.getHome().getHomeSceneItem(moduleId + 2000); var blockComfortList = homeScene.getBlockItems().values().stream().map(HomeBlockItem::calComfort).toList(); - var homeRoomScene = player.getHome().getHomeSceneItem(homeScene.getRoomSceneId()); + var homeRoomScene = player.getHome().getMainHouseItem(moduleId + 2000); comfortInfoList.add( HomeModuleComfortInfoOuterClass.HomeModuleComfortInfo.newBuilder() diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketHomeMarkPointNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketHomeMarkPointNotify.java index c3b44eea8..9fff3088a 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketHomeMarkPointNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketHomeMarkPointNotify.java @@ -1,10 +1,13 @@ package emu.grasscutter.server.packet.send; -import emu.grasscutter.game.home.*; +import emu.grasscutter.game.home.HomeBlockItem; +import emu.grasscutter.game.home.HomeMarkPointProtoFactory; import emu.grasscutter.game.player.Player; + import emu.grasscutter.net.packet.*; import emu.grasscutter.net.proto.*; import java.util.Collection; +import java.util.Set; public class PacketHomeMarkPointNotify extends BasePacket { @@ -20,38 +23,33 @@ public class PacketHomeMarkPointNotify extends BasePacket { return; } - for (var moduleId : owner.getRealmList()) { - var homeScene = home.getHomeSceneItem(moduleId + 2000); + // send current home mark points. + var moduleId = owner.getCurrentRealmId(); + var homeScene = home.getHomeSceneItem(moduleId + 2000); + var mainHouse = home.getMainHouseItem(moduleId + 2000); + Set.of(homeScene, mainHouse).forEach(homeSceneItem -> { var markPointData = - HomeMarkPointSceneDataOuterClass.HomeMarkPointSceneData.newBuilder() - .setModuleId(moduleId) - .setSceneId(moduleId + 2000) - .setSafePointPos( - homeScene.isRoom() - ? VectorOuterClass.Vector.newBuilder().build() - : world - .getSceneById(moduleId + 2000) - .getScriptManager() - .getConfig() - .born_pos - .toProto()) - .setTeapotSpiritPos( - homeScene.isRoom() - ? VectorOuterClass.Vector.newBuilder().build() - : homeScene.getDjinnPos().toProto()); + HomeMarkPointSceneDataOuterClass.HomeMarkPointSceneData.newBuilder() + .setModuleId(moduleId) + .setSceneId(homeSceneItem.getSceneId()); - var marks = - homeScene.getBlockItems().values().stream() - .map(HomeBlockItem::getMarkPointProtoFactories) - .flatMap(Collection::stream) - .filter(HomeMarkPointProtoFactory::isProtoConvertible) - .map(HomeMarkPointProtoFactory::toMarkPointProto) - .toList(); + if (!homeSceneItem.isRoom()) { + var config = world.getSceneById(moduleId + 2000).getScriptManager().getConfig(); + markPointData.setSafePointPos(config == null ? homeSceneItem.getBornPos().toProto() : config.born_pos.toProto()) + .setTeapotSpiritPos(homeSceneItem.getDjinnPos().toProto()); + } + + var marks = homeSceneItem.getBlockItems().values().stream() + .map(HomeBlockItem::getMarkPointProtoFactories) + .flatMap(Collection::stream) + .filter(HomeMarkPointProtoFactory::isProtoConvertible) + .map(HomeMarkPointProtoFactory::toMarkPointProto) + .toList(); markPointData.addAllFurnitureList(marks); proto.addMarkPointDataList(markPointData); - } + }); this.setData(proto); }