Skip to content

Commit

Permalink
fix: NPE related to home when player logs in.
Browse files Browse the repository at this point in the history
  • Loading branch information
hamusuke0323 committed Nov 7, 2023
1 parent 1fac319 commit acce510
Show file tree
Hide file tree
Showing 9 changed files with 224 additions and 132 deletions.
29 changes: 25 additions & 4 deletions src/main/java/emu/grasscutter/game/home/GameHome.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,17 @@
import emu.grasscutter.net.proto.HomeAvatarTalkFinishInfoOuterClass;
import emu.grasscutter.server.packet.send.*;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
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
Expand Down Expand Up @@ -181,6 +182,7 @@ public void onMainHouseChanged() {

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));
Expand All @@ -194,6 +196,25 @@ public void onOwnerLogin(Player player) {
player.getSession().send(new PacketHomeResourceNotify(player));
}

private void fixModuleIdIfInvalid() {
if (this.player.hasSentLoginPackets() || this.player.getRealmList() == null) {
return;
}

if (this.player.getRealmList().isEmpty()) {
this.player.setRealmList(null);
return;
}

if (this.player.getCurrentRealmId() <= 0 || !this.player.getCurHomeWorld().isRealmIdValid()) {
int firstRId = this.player.getRealmList().iterator().next();
this.player.setCurrentRealmId(firstRId);
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(
Expand Down
161 changes: 93 additions & 68 deletions src/main/java/emu/grasscutter/game/home/HomeModuleManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,24 @@
import emu.grasscutter.net.proto.RetcodeOuterClass;
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 {
final Player homeOwner;
final HomeWorld homeWorld;
final GameHome home;
final int moduleId;
@Nullable
final HomeScene outdoor;
@Nullable
HomeScene indoor;
final List<HomeAvatarRewardEvent> rewardEvents;
final List<HomeAvatarSummonEvent> summonEvents;
Expand All @@ -45,8 +49,14 @@ public void tick() {
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);
}

Expand All @@ -66,44 +76,45 @@ public void onUpdateArrangement() {
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;
}

this.rewardEvents.add(
new HomeAvatarRewardEvent(
homeOwner,
data.getId(),
data.getRewardID(),
data.getAvatarID(),
data.getSuiteId(),
suite.getGuid()));
});
.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()));
});
});

if (this.summonEvents != null) {
var suiteIdList = this.rewardEvents.stream().map(HomeAvatarRewardEvent::getSuiteId).toList();
Expand All @@ -113,14 +124,15 @@ private void fireAllAvatarRewardEvents() {

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()));
}
Expand All @@ -143,15 +155,15 @@ public Either<List<GameItem>, Integer> claimAvatarRewards(int eventId) {
}

public Either<HomeAvatarSummonEvent, Integer> fireAvatarSummonEvent(
Player owner, int avatarId, int guid, int suiteId) {
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);
((HomeScene) owner.getScene())
.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);
Expand All @@ -173,8 +185,8 @@ public Either<HomeAvatarSummonEvent, Integer> fireAvatarSummonEvent(
}

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);
Expand All @@ -190,41 +202,49 @@ public HomeAvatarRewardEventNotifyOuterClass.HomeAvatarRewardEventNotify toRewar
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() {
toSummonEventProto() {
return HomeAvatarSummonAllEventNotifyOuterClass.HomeAvatarSummonAllEventNotify.newBuilder()
.addAllSummonEventList(
this.summonEvents.stream().map(HomeAvatarSummonEvent::toProto).toList())
.build();
.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() {
if (this.moduleId == 0) {
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();
}

Expand All @@ -233,7 +253,12 @@ public void onRemovedModule() {
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();
}
}
}
16 changes: 10 additions & 6 deletions src/main/java/emu/grasscutter/game/home/HomeWorld.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,18 @@
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;
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 {
Expand Down Expand Up @@ -66,7 +67,7 @@ public int getActiveIndoorSceneId() {
}

public boolean isRealmIdValid() {
return this.getHost().getCurrentRealmId() > 0;
return this.getSceneById(this.getHost().getCurrentRealmId() + 2000) != null;
}

@Override
Expand Down Expand Up @@ -147,11 +148,13 @@ public synchronized void removePlayer(Player player) {
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);
}

Expand All @@ -167,6 +170,7 @@ public synchronized void removePlayer(Player player) {
}

@Override
@Nullable
public HomeScene getSceneById(int sceneId) {
var scene = this.getScenes().get(sceneId);
if (scene instanceof HomeScene homeScene) {
Expand Down
13 changes: 10 additions & 3 deletions src/main/java/emu/grasscutter/game/home/HomeWorldMPSystem.java
Original file line number Diff line number Diff line change
Expand Up @@ -139,11 +139,18 @@ public void enterHome(Player requester, Player owner, int teleportPoint, boolean

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);
Expand Down
Loading

0 comments on commit acce510

Please sign in to comment.