diff --git a/src/main/java/emu/grasscutter/data/GameData.java b/src/main/java/emu/grasscutter/data/GameData.java index 2f9f7763b..a1ef20a8e 100644 --- a/src/main/java/emu/grasscutter/data/GameData.java +++ b/src/main/java/emu/grasscutter/data/GameData.java @@ -302,6 +302,10 @@ public final class GameData { private static final Int2ObjectMap homeWorldLevelDataMap = new Int2ObjectOpenHashMap<>(); + @Getter + private static final Int2ObjectMap homeWorldModuleDataMap = + new Int2ObjectOpenHashMap<>(); + @Getter private static final Int2ObjectMap homeWorldNPCDataMap = new Int2ObjectOpenHashMap<>(); diff --git a/src/main/java/emu/grasscutter/data/excels/HomeWorldModuleData.java b/src/main/java/emu/grasscutter/data/excels/HomeWorldModuleData.java new file mode 100644 index 000000000..b4e4a845b --- /dev/null +++ b/src/main/java/emu/grasscutter/data/excels/HomeWorldModuleData.java @@ -0,0 +1,17 @@ +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 = "HomeworldModuleExcelConfigData.json") +@FieldDefaults(level = AccessLevel.PRIVATE) +@Getter +public class HomeWorldModuleData extends GameResource { + int Id; + boolean isFree; + int worldSceneId; + int defaultRoomSceneId; +} diff --git a/src/main/java/emu/grasscutter/game/home/GameHome.java b/src/main/java/emu/grasscutter/game/home/GameHome.java index d4a2348c5..a77bee5dc 100644 --- a/src/main/java/emu/grasscutter/game/home/GameHome.java +++ b/src/main/java/emu/grasscutter/game/home/GameHome.java @@ -9,19 +9,21 @@ import emu.grasscutter.database.DatabaseHelper; import emu.grasscutter.game.avatar.Avatar; import emu.grasscutter.game.player.Player; import emu.grasscutter.game.props.SceneType; -import emu.grasscutter.net.proto.HomeAvatarTalkFinishInfoOuterClass; +import emu.grasscutter.net.proto.HomeAvatarTalkFinishInfoOuterClass.HomeAvatarTalkFinishInfo; import emu.grasscutter.server.packet.send.*; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.IntSets; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Data; +import lombok.experimental.FieldDefaults; + import java.time.ZonedDateTime; import java.time.temporal.ChronoUnit; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; import java.util.stream.Stream; -import lombok.AccessLevel; -import lombok.Builder; -import lombok.Data; -import lombok.experimental.FieldDefaults; @Entity(value = "homes", useDiscriminator = false) @Data @@ -36,6 +38,9 @@ public class GameHome { || sceneData.getSceneType() == SceneType.SCENE_HOME_ROOM) .map(SceneData::getId) .collect(Collectors.toUnmodifiableSet()); + public static final Set HOME_MODULE_IDS = + GameData.getHomeWorldModuleDataMap().isEmpty() ? + IntSets.fromTo(1, 6) : GameData.getHomeWorldModuleDataMap().keySet(); @Id String id; @@ -181,6 +186,7 @@ public class GameHome { public void onOwnerLogin(Player player) { this.player = player; // update player pointer. (prevent offline player from sending packet) + this.fixModuleIdIfInvalid(); player.getSession().send(new PacketHomeBasicInfoNotify(player, false)); player.getSession().send(new PacketPlayerHomeCompInfoNotify(player)); player.getSession().send(new PacketHomeComfortInfoNotify(player)); @@ -194,6 +200,29 @@ public class GameHome { player.getSession().send(new PacketHomeResourceNotify(player)); } + private void fixModuleIdIfInvalid() { + if (this.player.hasSentLoginPackets() || this.player.getRealmList() == null) { + return; + } + + this.player.getRealmList().removeIf(integer -> !HOME_MODULE_IDS.contains(integer)); // Delete invalid module ids. + + if (this.player.getRealmList().isEmpty()) { + this.player.setRealmList(null); + this.player.save(); + return; + } + + if (this.player.getCurrentRealmId() <= 0 || !this.player.getCurHomeWorld().isRealmIdValid()) { + int firstRId = this.player.getRealmList().iterator().next(); + this.player.setCurrentRealmId(firstRId); + this.player.save(); + Grasscutter.getLogger().info("Set player {}'s current realm id to {} cuz the id is invalid.", this.player.getUid(), firstRId); + } + + this.player.getCurHomeWorld().refreshModuleManager(); // Apply module id fix. + } + public void onPlayerChangedAvatarCostume(Avatar avatar) { var world = this.player.getServer().getHomeWorldOrCreate(this.player); world.broadcastPacket( @@ -239,7 +268,7 @@ public class GameHome { return this.finishedTalkIdMap.get(avatarId); } - public List + public List toAvatarTalkFinishInfoProto() { if (this.finishedTalkIdMap == null) { this.finishedTalkIdMap = new HashMap<>(); @@ -248,7 +277,7 @@ public class GameHome { return this.finishedTalkIdMap.entrySet().stream() .map( e -> { - return HomeAvatarTalkFinishInfoOuterClass.HomeAvatarTalkFinishInfo.newBuilder() + return HomeAvatarTalkFinishInfo.newBuilder() .setAvatarId(e.getKey()) .addAllFinishTalkIdList(e.getValue()) .build(); diff --git a/src/main/java/emu/grasscutter/game/home/HomeModuleManager.java b/src/main/java/emu/grasscutter/game/home/HomeModuleManager.java index d25a3b788..6ecff98de 100644 --- a/src/main/java/emu/grasscutter/game/home/HomeModuleManager.java +++ b/src/main/java/emu/grasscutter/game/home/HomeModuleManager.java @@ -1,22 +1,25 @@ package emu.grasscutter.game.home; import com.github.davidmoten.guavamini.Lists; +import emu.grasscutter.game.home.suite.HomeSuiteItem; import emu.grasscutter.game.home.suite.event.HomeAvatarRewardEvent; import emu.grasscutter.game.home.suite.event.HomeAvatarSummonEvent; import emu.grasscutter.game.home.suite.event.SuiteEventType; import emu.grasscutter.game.inventory.GameItem; import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.proto.HomeAvatarRewardEventNotifyOuterClass; -import emu.grasscutter.net.proto.HomeAvatarSummonAllEventNotifyOuterClass; -import emu.grasscutter.net.proto.RetcodeOuterClass; +import emu.grasscutter.net.proto.HomeAvatarRewardEventNotifyOuterClass.HomeAvatarRewardEventNotify; +import emu.grasscutter.net.proto.HomeAvatarSummonAllEventNotifyOuterClass.HomeAvatarSummonAllEventNotify; +import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode; import emu.grasscutter.server.packet.send.PacketHomeAvatarSummonAllEventNotify; import emu.grasscutter.utils.Either; -import java.util.*; -import java.util.stream.Stream; import lombok.AccessLevel; import lombok.Getter; import lombok.experimental.FieldDefaults; +import javax.annotation.Nullable; +import java.util.*; +import java.util.stream.Stream; + @Getter @FieldDefaults(level = AccessLevel.PRIVATE) public class HomeModuleManager { @@ -24,7 +27,9 @@ public class HomeModuleManager { final HomeWorld homeWorld; final GameHome home; final int moduleId; + @Nullable final HomeScene outdoor; + @Nullable HomeScene indoor; final List rewardEvents; final List summonEvents; @@ -45,8 +50,14 @@ public class HomeModuleManager { return; } - this.outdoor.onTick(); - this.indoor.onTick(); + if (this.outdoor != null) { + this.outdoor.onTick(); + } + + if (this.indoor != null) { + this.indoor.onTick(); + } + this.summonEvents.removeIf(HomeAvatarSummonEvent::isTimeOver); } @@ -66,44 +77,45 @@ public class HomeModuleManager { private void fireAllAvatarRewardEvents() { this.rewardEvents.clear(); var allBlockItems = - Stream.of(this.getOutdoorSceneItem(), this.getIndoorSceneItem()) - .map(HomeSceneItem::getBlockItems) - .map(Map::values) - .flatMap(Collection::stream) - .toList(); + Stream.of(this.getOutdoorSceneItem(), this.getIndoorSceneItem()) + .filter(Objects::nonNull) + .map(HomeSceneItem::getBlockItems) + .map(Map::values) + .flatMap(Collection::stream) + .toList(); var suites = - allBlockItems.stream() - .map(HomeBlockItem::getSuiteList) - .filter(Objects::nonNull) - .flatMap(Collection::stream) - .distinct() - .toList(); + allBlockItems.stream() + .map(HomeBlockItem::getSuiteList) + .filter(Objects::nonNull) + .flatMap(Collection::stream) + .distinct() + .toList(); allBlockItems.stream() - .map(HomeBlockItem::getDeployNPCList) - .flatMap(Collection::stream) - .forEach( - avatar -> { - suites.forEach( - suite -> { - var data = - SuiteEventType.HOME_AVATAR_REWARD_EVENT.getEventDataFrom( - avatar.getAvatarId(), suite.getSuiteId()); - if (data == null || this.home.isRewardEventFinished(data.getId())) { - return; - } + .map(HomeBlockItem::getDeployNPCList) + .flatMap(Collection::stream) + .forEach( + avatar -> { + suites.forEach( + suite -> { + var data = + SuiteEventType.HOME_AVATAR_REWARD_EVENT.getEventDataFrom( + avatar.getAvatarId(), suite.getSuiteId()); + if (data == null || this.home.isRewardEventFinished(data.getId())) { + return; + } - this.rewardEvents.add( - new HomeAvatarRewardEvent( - homeOwner, - data.getId(), - data.getRewardID(), - data.getAvatarID(), - data.getSuiteId(), - suite.getGuid())); - }); + this.rewardEvents.add( + new HomeAvatarRewardEvent( + homeOwner, + data.getId(), + data.getRewardID(), + data.getAvatarID(), + data.getSuiteId(), + suite.getGuid())); }); + }); if (this.summonEvents != null) { var suiteIdList = this.rewardEvents.stream().map(HomeAvatarRewardEvent::getSuiteId).toList(); @@ -113,68 +125,71 @@ public class HomeModuleManager { private void cancelSummonEventsIfAvatarLeave() { var avatars = - Stream.of(this.getOutdoorSceneItem(), this.getIndoorSceneItem()) - .map(HomeSceneItem::getBlockItems) - .map(Map::values) - .flatMap(Collection::stream) - .map(HomeBlockItem::getDeployNPCList) - .flatMap(Collection::stream) - .map(HomeNPCItem::getAvatarId) - .toList(); + Stream.of(this.getOutdoorSceneItem(), this.getIndoorSceneItem()) + .filter(Objects::nonNull) + .map(HomeSceneItem::getBlockItems) + .map(Map::values) + .flatMap(Collection::stream) + .map(HomeBlockItem::getDeployNPCList) + .flatMap(Collection::stream) + .map(HomeNPCItem::getAvatarId) + .toList(); this.summonEvents.removeIf(event -> !avatars.contains(event.getAvatarId())); } public Either, Integer> claimAvatarRewards(int eventId) { if (this.rewardEvents.isEmpty()) { - return Either.right(RetcodeOuterClass.Retcode.RET_FAIL_VALUE); + return Either.right(Retcode.RET_FAIL_VALUE); } var event = this.rewardEvents.remove(0); if (event.getEventId() != eventId) { - return Either.right(RetcodeOuterClass.Retcode.RET_FAIL_VALUE); + return Either.right(Retcode.RET_FAIL_VALUE); } if (!this.homeOwner.getHome().onClaimAvatarRewards(eventId)) { - return Either.right(RetcodeOuterClass.Retcode.RET_FAIL_VALUE); + return Either.right(Retcode.RET_FAIL_VALUE); } return Either.left(event.giveRewards()); } public Either fireAvatarSummonEvent( - Player owner, int avatarId, int guid, int suiteId) { - var targetSuite = - ((HomeScene) owner.getScene()) - .getSceneItem().getBlockItems().values().stream() - .map(HomeBlockItem::getSuiteList) - .flatMap(Collection::stream) - .filter(suite -> suite.getGuid() == guid) - .findFirst() - .orElse(null); + Player owner, int avatarId, int guid, int suiteId) { + HomeSuiteItem targetSuite = null; + if (owner.getScene() instanceof HomeScene homeScene) { + targetSuite = homeScene + .getSceneItem().getBlockItems().values().stream() + .map(HomeBlockItem::getSuiteList) + .flatMap(Collection::stream) + .filter(suite -> suite.getGuid() == guid) + .findFirst() + .orElse(null); + } if (this.isInRewardEvent(avatarId)) { - return Either.right(RetcodeOuterClass.Retcode.RET_DUPLICATE_AVATAR_VALUE); + return Either.right(Retcode.RET_DUPLICATE_AVATAR_VALUE); } if (this.rewardEvents.stream().anyMatch(event -> event.getGuid() == guid)) { - return Either.right(RetcodeOuterClass.Retcode.RET_HOME_FURNITURE_GUID_ERROR_VALUE); + return Either.right(Retcode.RET_HOME_FURNITURE_GUID_ERROR_VALUE); } this.summonEvents.removeIf(event -> event.getGuid() == guid || event.getAvatarId() == avatarId); if (targetSuite == null) { - return Either.right(RetcodeOuterClass.Retcode.RET_HOME_CLIENT_PARAM_INVALID_VALUE); + return Either.right(Retcode.RET_HOME_CLIENT_PARAM_INVALID_VALUE); } var eventData = SuiteEventType.HOME_AVATAR_SUMMON_EVENT.getEventDataFrom(avatarId, suiteId); if (eventData == null) { - return Either.right(RetcodeOuterClass.Retcode.RET_HOME_CLIENT_PARAM_INVALID_VALUE); + return Either.right(Retcode.RET_HOME_CLIENT_PARAM_INVALID_VALUE); } var event = - new HomeAvatarSummonEvent( - owner, eventData.getId(), eventData.getRewardID(), avatarId, suiteId, guid); + new HomeAvatarSummonEvent( + owner, eventData.getId(), eventData.getRewardID(), avatarId, suiteId, guid); this.summonEvents.add(event); owner.sendPacket(new PacketHomeAvatarSummonAllEventNotify(owner)); return Either.left(event); @@ -184,38 +199,39 @@ public class HomeModuleManager { this.summonEvents.removeIf(event -> event.getEventId() == eventId); } - public HomeAvatarRewardEventNotifyOuterClass.HomeAvatarRewardEventNotify toRewardEventProto() { - var notify = HomeAvatarRewardEventNotifyOuterClass.HomeAvatarRewardEventNotify.newBuilder(); + public HomeAvatarRewardEventNotify toRewardEventProto() { + var notify = HomeAvatarRewardEventNotify.newBuilder(); if (!this.rewardEvents.isEmpty()) { notify.setRewardEvent(this.rewardEvents.get(0).toProto()).setIsEventTrigger(true); notify.addAllPendingList( - this.rewardEvents.subList(1, this.rewardEvents.size()).stream() - .map(HomeAvatarRewardEvent::toProto) - .toList()); + this.rewardEvents.subList(1, this.rewardEvents.size()).stream() + .map(HomeAvatarRewardEvent::toProto) + .toList()); } return notify.build(); } - public HomeAvatarSummonAllEventNotifyOuterClass.HomeAvatarSummonAllEventNotify - toSummonEventProto() { - return HomeAvatarSummonAllEventNotifyOuterClass.HomeAvatarSummonAllEventNotify.newBuilder() - .addAllSummonEventList( - this.summonEvents.stream().map(HomeAvatarSummonEvent::toProto).toList()) - .build(); + public HomeAvatarSummonAllEventNotify toSummonEventProto() { + return HomeAvatarSummonAllEventNotify.newBuilder() + .addAllSummonEventList( + this.summonEvents.stream().map(HomeAvatarSummonEvent::toProto).toList()) + .build(); } public boolean isInRewardEvent(int avatarId) { return this.rewardEvents.stream().anyMatch(e -> e.getAvatarId() == avatarId); } + @Nullable public HomeSceneItem getOutdoorSceneItem() { - return this.outdoor.getSceneItem(); + return this.outdoor == null ? null : this.outdoor.getSceneItem(); } + @Nullable public HomeSceneItem getIndoorSceneItem() { - return this.indoor.getSceneItem(); + return this.indoor == null ? null : this.indoor.getSceneItem(); } public void onSetModule() { @@ -223,8 +239,14 @@ public class HomeModuleManager { return; } - this.outdoor.addEntities(this.getOutdoorSceneItem().getAnimals(this.outdoor)); - this.indoor.addEntities(this.getIndoorSceneItem().getAnimals(this.indoor)); + if (this.outdoor != null) { + this.outdoor.addEntities(this.getOutdoorSceneItem().getAnimals(this.outdoor)); + } + + if (this.indoor != null) { + this.indoor.addEntities(this.getIndoorSceneItem().getAnimals(this.indoor)); + } + this.fireAllAvatarRewardEvents(); } @@ -233,7 +255,12 @@ public class HomeModuleManager { return; } - this.outdoor.getEntities().clear(); - this.indoor.getEntities().clear(); + if (this.outdoor != null) { + this.outdoor.getEntities().clear(); + } + + if (this.indoor != null) { + this.indoor.getEntities().clear(); + } } } diff --git a/src/main/java/emu/grasscutter/game/home/HomeWorld.java b/src/main/java/emu/grasscutter/game/home/HomeWorld.java index 1200a0f97..cf6257df2 100644 --- a/src/main/java/emu/grasscutter/game/home/HomeWorld.java +++ b/src/main/java/emu/grasscutter/game/home/HomeWorld.java @@ -3,7 +3,6 @@ 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.Scene; import emu.grasscutter.game.world.World; import emu.grasscutter.net.packet.BasePacket; import emu.grasscutter.net.proto.ChatInfoOuterClass; @@ -11,9 +10,11 @@ import emu.grasscutter.server.game.GameServer; import emu.grasscutter.server.packet.send.PacketDelTeamEntityNotify; import emu.grasscutter.server.packet.send.PacketPlayerChatNotify; import emu.grasscutter.server.packet.send.PacketPlayerGameTimeNotify; +import lombok.Getter; + +import javax.annotation.Nullable; import java.util.List; import java.util.function.Consumer; -import lombok.Getter; @Getter public class HomeWorld extends World { @@ -66,7 +67,7 @@ public class HomeWorld extends World { } public boolean isRealmIdValid() { - return this.getHost().getCurrentRealmId() > 0; + return this.getSceneById(this.getHost().getCurrentRealmId() + 2000) != null; } @Override @@ -147,11 +148,13 @@ public class HomeWorld extends World { player.setWorld(null); // Remove from scene - Scene scene = this.getSceneById(player.getSceneId()); - scene.removePlayer(player); + var scene = this.getSceneById(player.getSceneId()); + if (scene != null) { + scene.removePlayer(player); + } // Info packet for other players - if (this.getPlayers().size() > 0) { + if (!this.getPlayers().isEmpty()) { this.updatePlayerInfos(player); } @@ -167,6 +170,7 @@ public class HomeWorld extends World { } @Override + @Nullable public HomeScene getSceneById(int sceneId) { var scene = this.getScenes().get(sceneId); if (scene instanceof HomeScene homeScene) { diff --git a/src/main/java/emu/grasscutter/game/home/HomeWorldMPSystem.java b/src/main/java/emu/grasscutter/game/home/HomeWorldMPSystem.java index 0835975b0..95b8b6ec4 100644 --- a/src/main/java/emu/grasscutter/game/home/HomeWorldMPSystem.java +++ b/src/main/java/emu/grasscutter/game/home/HomeWorldMPSystem.java @@ -139,11 +139,18 @@ public class HomeWorldMPSystem extends BaseGameSystem { int realmId = 2000 + owner.getCurrentRealmId(); var item = targetHome.getHomeSceneItem(realmId); + var scene = world.getSceneById(realmId); targetHome.save(); - var pos = + + Position pos; + if (scene != null) { + pos = toSafe - ? world.getSceneById(realmId).getScriptManager().getConfig().born_pos - : item.getBornPos(); + ? scene.getScriptManager().getConfig().born_pos + : item.getBornPos(); + } else { + pos = item.getBornPos(); + } if (teleportPoint != 0) { var target = item.getTeleportPointPos(teleportPoint); diff --git a/src/main/java/emu/grasscutter/game/world/World.java b/src/main/java/emu/grasscutter/game/world/World.java index 4fa2cb809..c2635b53a 100644 --- a/src/main/java/emu/grasscutter/game/world/World.java +++ b/src/main/java/emu/grasscutter/game/world/World.java @@ -1,18 +1,21 @@ package emu.grasscutter.game.world; -import static emu.grasscutter.server.event.player.PlayerTeleportEvent.TeleportType.SCRIPT; - import emu.grasscutter.Grasscutter; import emu.grasscutter.data.GameData; import emu.grasscutter.data.excels.dungeon.DungeonData; -import emu.grasscutter.game.entity.*; +import emu.grasscutter.game.entity.EntityTeam; +import emu.grasscutter.game.entity.EntityWorld; import emu.grasscutter.game.player.Player; import emu.grasscutter.game.player.Player.SceneLoadState; -import emu.grasscutter.game.props.*; +import emu.grasscutter.game.props.EnterReason; +import emu.grasscutter.game.props.EntityIdType; +import emu.grasscutter.game.props.PlayerProperty; +import emu.grasscutter.game.props.SceneType; import emu.grasscutter.game.quest.enums.QuestContent; import emu.grasscutter.game.world.data.TeleportProperties; import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.proto.ChatInfoOuterClass.ChatInfo.*; +import emu.grasscutter.net.proto.ChatInfoOuterClass.ChatInfo.SystemHint; +import emu.grasscutter.net.proto.ChatInfoOuterClass.ChatInfo.SystemHintType; import emu.grasscutter.net.proto.EnterTypeOuterClass.EnterType; import emu.grasscutter.scripts.data.SceneConfig; import emu.grasscutter.server.event.player.PlayerTeleportEvent; @@ -21,12 +24,25 @@ import emu.grasscutter.server.game.GameServer; import emu.grasscutter.server.packet.send.*; import emu.grasscutter.utils.ConversionUtils; import io.netty.util.concurrent.FastThreadLocalThread; -import it.unimi.dsi.fastutil.ints.*; -import java.util.*; -import java.util.concurrent.*; -import lombok.*; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectMaps; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import lombok.Getter; +import lombok.val; import org.jetbrains.annotations.NotNull; +import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.LinkedBlockingDeque; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +import static emu.grasscutter.server.event.player.PlayerTeleportEvent.TeleportType.SCRIPT; + public class World implements Iterable { @Getter private final GameServer server; @Getter private Player host; @@ -124,6 +140,7 @@ public class World implements Iterable { * @param sceneId The scene ID. * @return The scene. */ + @Nullable public Scene getSceneById(int sceneId) { // Get scene normally var scene = this.getScenes().get(sceneId); 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 e05831d40..edc5829ab 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeChangeModuleReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeChangeModuleReq.java @@ -1,9 +1,11 @@ package emu.grasscutter.server.packet.recv; +import emu.grasscutter.Grasscutter; import emu.grasscutter.net.packet.Opcodes; import emu.grasscutter.net.packet.PacketHandler; import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.HomeChangeModuleReqOuterClass; +import emu.grasscutter.net.proto.HomeChangeModuleReqOuterClass.HomeChangeModuleReq; +import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode; import emu.grasscutter.server.event.player.PlayerTeleportEvent.TeleportType; import emu.grasscutter.server.game.GameSession; import emu.grasscutter.server.packet.send.PacketHomeAvatarTalkFinishInfoNotify; @@ -16,12 +18,20 @@ public class HandlerHomeChangeModuleReq extends PacketHandler { @Override public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - HomeChangeModuleReqOuterClass.HomeChangeModuleReq req = - HomeChangeModuleReqOuterClass.HomeChangeModuleReq.parseFrom(payload); + var req = HomeChangeModuleReq.parseFrom(payload); var homeWorld = session.getPlayer().getCurHomeWorld(); if (!homeWorld.getGuests().isEmpty()) { - session.send(new PacketHomeChangeModuleRsp()); + session.send(new PacketHomeChangeModuleRsp(Retcode.RET_HOME_HAS_GUEST)); + return; + } + + int realmId = 2000 + req.getTargetModuleId(); + var scene = homeWorld.getSceneById(realmId); + + if (scene == null) { + Grasscutter.getLogger().warn("scene == null! Changing module will fail."); + session.send(new PacketHomeChangeModuleRsp(Retcode.RET_INVALID_SCENE_ID)); return; } @@ -31,8 +41,6 @@ public class HandlerHomeChangeModuleReq extends PacketHandler { session.send(new PacketPlayerHomeCompInfoNotify(session.getPlayer())); session.send(new PacketHomeComfortInfoNotify(session.getPlayer())); - int realmId = 2000 + req.getTargetModuleId(); - var scene = homeWorld.getSceneById(realmId); var pos = scene.getScriptManager().getConfig().born_pos; homeWorld.transferPlayerToScene(session.getPlayer(), realmId, TeleportType.WAYPOINT, pos); 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 4764657c9..efd876aba 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeSceneJumpReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeSceneJumpReq.java @@ -35,7 +35,7 @@ public class HandlerHomeSceneJumpReq extends PacketHandler { } world.transferPlayerToScene( - session.getPlayer(), req.getIsEnterRoomScene() ? homeScene.getRoomSceneId() : realmId, pos); + session.getPlayer(), scene.getId(), pos); session.send(new PacketHomeSceneJumpRsp(req.getIsEnterRoomScene())); } 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 641d989ac..0762e2620 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketHomeChangeModuleRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketHomeChangeModuleRsp.java @@ -2,28 +2,26 @@ package emu.grasscutter.server.packet.send; import emu.grasscutter.net.packet.BasePacket; import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.HomeChangeModuleRspOuterClass; -import emu.grasscutter.net.proto.RetcodeOuterClass; +import emu.grasscutter.net.proto.HomeChangeModuleRspOuterClass.HomeChangeModuleRsp; +import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode; public class PacketHomeChangeModuleRsp extends BasePacket { public PacketHomeChangeModuleRsp(int targetModuleId) { super(PacketOpcodes.HomeChangeModuleRsp); - HomeChangeModuleRspOuterClass.HomeChangeModuleRsp proto = - HomeChangeModuleRspOuterClass.HomeChangeModuleRsp.newBuilder() - .setRetcode(0) - .setTargetModuleId(targetModuleId) - .build(); + var proto = HomeChangeModuleRsp.newBuilder() + .setRetcode(0) + .setTargetModuleId(targetModuleId) + .build(); this.setData(proto); } - public PacketHomeChangeModuleRsp() { + public PacketHomeChangeModuleRsp(Retcode retcode) { super(PacketOpcodes.HomeChangeModuleRsp); - this.setData( - HomeChangeModuleRspOuterClass.HomeChangeModuleRsp.newBuilder() - .setRetcode(RetcodeOuterClass.Retcode.RET_HOME_HAS_GUEST_VALUE)); + this.setData(HomeChangeModuleRsp.newBuilder() + .setRetcode(retcode.getNumber())); } } 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 6646efccb..238d8e862 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,14 @@ package emu.grasscutter.server.packet.send; +import emu.grasscutter.Grasscutter; 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 emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.HomeMarkPointNotifyOuterClass.HomeMarkPointNotify; +import emu.grasscutter.net.proto.HomeMarkPointSceneDataOuterClass.HomeMarkPointSceneData; + import java.util.Collection; import java.util.Set; @@ -13,49 +17,54 @@ public class PacketHomeMarkPointNotify extends BasePacket { public PacketHomeMarkPointNotify(Player player) { super(PacketOpcodes.HomeMarkPointNotify); - var proto = HomeMarkPointNotifyOuterClass.HomeMarkPointNotify.newBuilder(); + var proto = HomeMarkPointNotify.newBuilder(); var world = player.getCurHomeWorld(); var owner = world.getHost(); var home = world.getHome(); - if (owner.getRealmList() == null) { + if (owner.getRealmList() == null || owner.getRealmList().isEmpty()) { return; } // send current home mark points. var moduleId = owner.getCurrentRealmId(); + var scene = world.getSceneById(moduleId + 2000); + if (scene == null) { + Grasscutter.getLogger().warn("Current Realm id is invalid! SceneExcelConfigData.json, game resource not loaded correctly or the realm id maybe wrong?!"); + return; + } 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(homeSceneItem.getSceneId()); + .forEach( + homeSceneItem -> { + var markPointData = + HomeMarkPointSceneData.newBuilder() + .setModuleId(moduleId) + .setSceneId(homeSceneItem.getSceneId()); - 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()); - } + if (!homeSceneItem.isRoom()) { + var config = scene.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(); + 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); - }); + markPointData.addAllFurnitureList(marks); + proto.addMarkPointDataList(markPointData); + }); this.setData(proto); }