Skip to content
Snippets Groups Projects
Commit e16633e3 authored by Akka's avatar Akka Committed by Melledy
Browse files

Implement the Home System (Serenitea Pot)

parent 399275e8
Branches
Tags
No related merge requests found
Showing
with 583 additions and 36 deletions
......@@ -76,7 +76,7 @@ dependencies {
implementation group: 'org.reflections', name: 'reflections', version: '0.10.2'
implementation group: 'dev.morphia.morphia', name: 'morphia-core', version: '2.2.6'
implementation group: 'dev.morphia.morphia', name: 'morphia-core', version: '2.2.7'
implementation group: 'org.greenrobot', name: 'eventbus-java', version: '3.3.1'
implementation group: 'org.danilopianini', name: 'java-quadtree', version: '0.1.9'
......
......@@ -7,12 +7,8 @@ import java.util.List;
import java.util.Map;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.binout.*;
import emu.grasscutter.utils.Utils;
import emu.grasscutter.data.binout.AbilityEmbryoEntry;
import emu.grasscutter.data.binout.AbilityModifierEntry;
import emu.grasscutter.data.binout.MainQuestData;
import emu.grasscutter.data.binout.OpenConfigEntry;
import emu.grasscutter.data.binout.ScenePointEntry;
import emu.grasscutter.data.excels.*;
import it.unimi.dsi.fastutil.ints.Int2ObjectLinkedOpenHashMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
......@@ -28,7 +24,9 @@ public class GameData {
private static final Map<String, OpenConfigEntry> openConfigEntries = new HashMap<>();
private static final Map<String, ScenePointEntry> scenePointEntries = new HashMap<>();
private static final Int2ObjectMap<MainQuestData> mainQuestData = new Int2ObjectOpenHashMap<>();
private static final Int2ObjectMap<HomeworldDefaultSaveData> homeworldDefaultSaveData = new Int2ObjectOpenHashMap<>();
// ExcelConfigs
private static final Int2ObjectMap<PlayerLevelData> playerLevelDataMap = new Int2ObjectOpenHashMap<>();
......@@ -140,7 +138,9 @@ public class GameData {
public static Int2ObjectMap<MainQuestData> getMainQuestDataMap() {
return mainQuestData;
}
public static Int2ObjectMap<HomeworldDefaultSaveData> getHomeworldDefaultSaveData() {
return homeworldDefaultSaveData;
}
public static Int2ObjectMap<AvatarData> getAvatarDataMap() {
return avatarDataMap;
}
......
package emu.grasscutter.data;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.google.gson.Gson;
import emu.grasscutter.data.binout.*;
import emu.grasscutter.utils.Utils;
import lombok.SneakyThrows;
import org.reflections.Reflections;
import com.google.gson.JsonElement;
......@@ -15,12 +19,6 @@ import com.google.gson.annotations.SerializedName;
import com.google.gson.reflect.TypeToken;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.binout.AbilityEmbryoEntry;
import emu.grasscutter.data.binout.AbilityModifier;
import emu.grasscutter.data.binout.AbilityModifierEntry;
import emu.grasscutter.data.binout.MainQuestData;
import emu.grasscutter.data.binout.OpenConfigEntry;
import emu.grasscutter.data.binout.ScenePointEntry;
import emu.grasscutter.data.binout.AbilityModifier.AbilityConfigData;
import emu.grasscutter.data.binout.AbilityModifier.AbilityModifierAction;
import emu.grasscutter.data.binout.AbilityModifier.AbilityModifierActionType;
......@@ -66,6 +64,40 @@ public class ResourceLoader {
loadQuests();
// Load scene points - must be done AFTER resources are loaded
loadScenePoints();
// Load default home layout
loadHomeworldDefaultSaveData();
// Custom - TODO move this somewhere else
try {
GameData.getAvatarSkillDepotDataMap().get(504).setAbilities(
new AbilityEmbryoEntry(
"",
new String[] {
"Avatar_PlayerBoy_ExtraAttack_Wind",
"Avatar_Player_UziExplode_Mix",
"Avatar_Player_UziExplode",
"Avatar_Player_UziExplode_Strike_01",
"Avatar_Player_UziExplode_Strike_02",
"Avatar_Player_WindBreathe",
"Avatar_Player_WindBreathe_CameraController"
}
));
GameData.getAvatarSkillDepotDataMap().get(704).setAbilities(
new AbilityEmbryoEntry(
"",
new String[] {
"Avatar_PlayerGirl_ExtraAttack_Wind",
"Avatar_Player_UziExplode_Mix",
"Avatar_Player_UziExplode",
"Avatar_Player_UziExplode_Strike_01",
"Avatar_Player_UziExplode_Strike_02",
"Avatar_Player_WindBreathe",
"Avatar_Player_WindBreathe_CameraController"
}
));
} catch (Exception e) {
Grasscutter.getLogger().error("Error loading abilities", e);
}
}
public static void loadResources() {
......@@ -394,6 +426,26 @@ public class ResourceLoader {
Grasscutter.getLogger().info("Loaded " + GameData.getMainQuestDataMap().size() + " MainQuestDatas.");
}
@SneakyThrows
private static void loadHomeworldDefaultSaveData(){
var folder = Files.list(Path.of(RESOURCE("BinOutput/HomeworldDefaultSave"))).toList();
var pattern = Pattern.compile("scene(.*)_home_config.json");
for(var file : folder){
var matcher = pattern.matcher(file.getFileName().toString());
if(!matcher.find()){
continue;
}
var sceneId = matcher.group(1);
var data = Grasscutter.getGsonFactory().fromJson(Files.readString(file), HomeworldDefaultSaveData.class);
GameData.getHomeworldDefaultSaveData().put(Integer.parseInt(sceneId), data);
}
Grasscutter.getLogger().info("Loaded " + GameData.getHomeworldDefaultSaveData().size() + " HomeworldDefaultSaveDatas.");
}
// BinOutput configs
public static class AvatarConfig {
......
package emu.grasscutter.data.binout;
import com.google.gson.annotations.SerializedName;
import emu.grasscutter.utils.Position;
import lombok.AccessLevel;
import lombok.Data;
import lombok.experimental.FieldDefaults;
import java.util.List;
@Data
@FieldDefaults(level = AccessLevel.PRIVATE)
public class HomeworldDefaultSaveData {
@SerializedName(value = "KFHBFNPDJBE", alternate = "PKACPHDGGEI")
List<HomeBlock> homeBlockLists;
@SerializedName(value = "IJNPADKGNKE", alternate = "MINCKHBNING")
Position bornPos;
@SerializedName("IPIIGEMFLHK")
Position bornRot;
@SerializedName("HHOLBNPIHEM")
Position djinPos;
@SerializedName("KNHCJKHCOAN")
HomeFurniture mainhouse;
@SerializedName("NIHOJFEKFPG")
List<HomeFurniture> doorLists;
@SerializedName("EPGELGEFJFK")
List<HomeFurniture> stairLists;
@Data
@FieldDefaults(level = AccessLevel.PRIVATE)
public static class HomeBlock{
@SerializedName(value = "FGIJCELCGFI", alternate = "PGDPDIDJEEL")
int blockId;
@SerializedName(value = "BEAPOFELABD", alternate = "MLIODLGDFHJ")
List<HomeFurniture> furnitures;
}
@Data
@FieldDefaults(level = AccessLevel.PRIVATE)
public static class HomeFurniture{
@SerializedName(value = "ENHNGKJBJAB", alternate = "KMAAJJHPNBA")
int id;
@SerializedName(value = "NGIEEIOLPPO", alternate = "JFKAHNCPDME")
Position pos;
//@SerializedName(value = "HEOCEHKEBFM", alternate = "LKCKOOGFDBM")
Position rot;
}
}
......@@ -2,14 +2,20 @@ package emu.grasscutter.data.excels;
import java.util.List;
import com.google.gson.annotations.SerializedName;
import emu.grasscutter.data.GameResource;
import emu.grasscutter.data.ResourceType;
import emu.grasscutter.data.common.ItemUseData;
import emu.grasscutter.game.inventory.*;
import emu.grasscutter.game.props.FightProperty;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet;
@ResourceType(name = {"MaterialExcelConfigData.json", "WeaponExcelConfigData.json", "ReliquaryExcelConfigData.json"})
@ResourceType(name = {"MaterialExcelConfigData.json",
"WeaponExcelConfigData.json",
"ReliquaryExcelConfigData.json",
"HomeWorldFurnitureExcelConfigData.json"
})
public class ItemData extends GameResource {
private int id;
......@@ -63,12 +69,19 @@ public class ItemData extends GameResource {
private long nameTextMapHash;
// Post load
private transient emu.grasscutter.game.inventory.MaterialType materialEnumType;
private transient emu.grasscutter.game.inventory.ItemType itemEnumType;
private transient emu.grasscutter.game.inventory.EquipType equipEnumType;
private transient MaterialType materialEnumType;
private transient ItemType itemEnumType;
private transient EquipType equipEnumType;
private IntSet addPropLevelSet;
// Furniture
private int comfort;
private List<Integer> furnType;
private List<Integer> furnitureGadgetID;
@SerializedName("JFDLJGDFIGL")
private int roomSceneId;
@Override
public int getId(){
return this.id;
......@@ -193,41 +206,57 @@ public class ItemData extends GameResource {
public int getMaxLevel() {
return maxLevel;
}
public emu.grasscutter.game.inventory.ItemType getItemType() {
public int getComfort() {
return comfort;
}
public List<Integer> getFurnType() {
return furnType;
}
public List<Integer> getFurnitureGadgetID() {
return furnitureGadgetID;
}
public int getRoomSceneId() {
return roomSceneId;
}
public ItemType getItemType() {
return this.itemEnumType;
}
public emu.grasscutter.game.inventory.MaterialType getMaterialType() {
public MaterialType getMaterialType() {
return this.materialEnumType;
}
public emu.grasscutter.game.inventory.EquipType getEquipType() {
public EquipType getEquipType() {
return this.equipEnumType;
}
public boolean canAddRelicProp(int level) {
return this.addPropLevelSet != null & this.addPropLevelSet.contains(level);
return this.addPropLevelSet != null && this.addPropLevelSet.contains(level);
}
public boolean isEquip() {
return this.itemEnumType == emu.grasscutter.game.inventory.ItemType.ITEM_RELIQUARY || this.itemEnumType == emu.grasscutter.game.inventory.ItemType.ITEM_WEAPON;
return this.itemEnumType == ItemType.ITEM_RELIQUARY || this.itemEnumType == ItemType.ITEM_WEAPON;
}
@Override
public void onLoad() {
this.itemEnumType = emu.grasscutter.game.inventory.ItemType.getTypeByName(getItemTypeString());
this.materialEnumType = emu.grasscutter.game.inventory.MaterialType.getTypeByName(getMaterialTypeString());
this.itemEnumType = ItemType.getTypeByName(getItemTypeString());
this.materialEnumType = MaterialType.getTypeByName(getMaterialTypeString());
if (this.itemEnumType == emu.grasscutter.game.inventory.ItemType.ITEM_RELIQUARY) {
this.equipEnumType = emu.grasscutter.game.inventory.EquipType.getTypeByName(this.equipType);
if (this.itemEnumType == ItemType.ITEM_RELIQUARY) {
this.equipEnumType = EquipType.getTypeByName(this.equipType);
if (this.addPropLevels != null && this.addPropLevels.length > 0) {
this.addPropLevelSet = new IntOpenHashSet(this.addPropLevels);
}
} else if (this.itemEnumType == emu.grasscutter.game.inventory.ItemType.ITEM_WEAPON) {
this.equipEnumType = emu.grasscutter.game.inventory.EquipType.EQUIP_WEAPON;
} else if (this.itemEnumType == ItemType.ITEM_WEAPON) {
this.equipEnumType = EquipType.EQUIP_WEAPON;
} else {
this.equipEnumType = emu.grasscutter.game.inventory.EquipType.EQUIP_NONE;
this.equipEnumType = EquipType.EQUIP_NONE;
}
if (this.getWeaponProperties() != null) {
......@@ -235,6 +264,13 @@ public class ItemData extends GameResource {
weaponProperty.onLoad();
}
}
if(this.getFurnType() != null){
this.furnType = this.furnType.stream().filter(x -> x > 0).toList();
}
if(this.getFurnitureGadgetID() != null){
this.furnitureGadgetID = this.furnitureGadgetID.stream().filter(x -> x > 0).toList();
}
}
public static class WeaponProperty {
......
......@@ -13,6 +13,7 @@ import emu.grasscutter.game.Account;
import emu.grasscutter.game.avatar.Avatar;
import emu.grasscutter.game.friends.Friendship;
import emu.grasscutter.game.gacha.GachaRecord;
import emu.grasscutter.game.home.GameHome;
import emu.grasscutter.game.inventory.GameItem;
import emu.grasscutter.game.mail.Mail;
import emu.grasscutter.game.player.Player;
......@@ -295,4 +296,10 @@ public final class DatabaseHelper {
public static boolean deleteQuest(GameMainQuest quest) {
return DatabaseManager.getGameDatastore().delete(quest).wasAcknowledged();
}
public static GameHome getHomeByUid(int id) {
return DatabaseManager.getGameDatastore().find(GameHome.class).filter(Filters.eq("ownerUid", id)).first();
}
public static void saveHome(GameHome gameHome) {
DatabaseManager.getGameDatastore().save(gameHome);
}
}
......@@ -16,6 +16,7 @@ import emu.grasscutter.game.Account;
import emu.grasscutter.game.avatar.Avatar;
import emu.grasscutter.game.friends.Friendship;
import emu.grasscutter.game.gacha.GachaRecord;
import emu.grasscutter.game.home.GameHome;
import emu.grasscutter.game.inventory.GameItem;
import emu.grasscutter.game.mail.Mail;
import emu.grasscutter.game.player.Player;
......@@ -30,7 +31,7 @@ public final class DatabaseManager {
private static final Class<?>[] mappedClasses = new Class<?>[] {
DatabaseCounter.class, Account.class, Player.class, Avatar.class, GameItem.class, Friendship.class,
GachaRecord.class, Mail.class, GameMainQuest.class
GachaRecord.class, Mail.class, GameMainQuest.class, GameHome.class
};
public static Datastore getGameDatastore() {
......
package emu.grasscutter.game.home;
import dev.morphia.annotations.Entity;
import dev.morphia.annotations.Id;
import dev.morphia.annotations.IndexOptions;
import dev.morphia.annotations.Indexed;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.GameData;
import emu.grasscutter.database.DatabaseHelper;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.server.packet.send.*;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Data;
import lombok.experimental.FieldDefaults;
import java.util.concurrent.ConcurrentHashMap;
@Entity(value = "homes", useDiscriminator = false)
@Data
@FieldDefaults(level = AccessLevel.PRIVATE)
@Builder(builderMethodName = "of")
public class GameHome {
@Id
String id;
@Indexed(options = @IndexOptions(unique = true))
long ownerUid;
ConcurrentHashMap<Integer, HomeSceneItem> sceneMap;
public void save(){
DatabaseHelper.saveHome(this);
}
public static GameHome getByUid(Integer uid){
var home = DatabaseHelper.getHomeByUid(uid);
if (home == null) {
home = GameHome.create(uid);
}
return home;
}
public static GameHome create(Integer uid){
return GameHome.of()
.ownerUid(uid)
.sceneMap(new ConcurrentHashMap<>())
.build();
}
public HomeSceneItem getHomeSceneItem(int sceneId) {
return sceneMap.computeIfAbsent(sceneId, e -> {
var defaultItem = GameData.getHomeworldDefaultSaveData().get(sceneId);
if (defaultItem != null){
Grasscutter.getLogger().info("Set player {} home {} to initial setting", ownerUid, sceneId);
return HomeSceneItem.parseFrom(defaultItem, sceneId);
}
return null;
});
}
public void onOwnerLogin(Player player) {
player.getSession().send(new PacketHomeBasicInfoNotify(player, false));
player.getSession().send(new PacketPlayerHomeCompInfoNotify(player));
player.getSession().send(new PacketHomeComfortInfoNotify(player));
player.getSession().send(new PacketFurnitureCurModuleArrangeCountNotify());
player.getSession().send(new PacketUnlockedFurnitureFormulaDataNotify());
}
}
package emu.grasscutter.game.home;
import dev.morphia.annotations.Entity;
import dev.morphia.annotations.Id;
import emu.grasscutter.data.binout.HomeworldDefaultSaveData;
import emu.grasscutter.net.proto.HomeBlockArrangementInfoOuterClass.HomeBlockArrangementInfo;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Data;
import lombok.experimental.FieldDefaults;
import java.util.List;
@Entity
@Data
@Builder(builderMethodName = "of")
@FieldDefaults(level = AccessLevel.PRIVATE)
public class HomeBlockItem {
@Id
int blockId;
boolean unlocked;
List<HomeFurnitureItem> deployFurnitureList;
public void update(HomeBlockArrangementInfo homeBlockArrangementInfo) {
this.blockId = homeBlockArrangementInfo.getBlockId();
this.deployFurnitureList = homeBlockArrangementInfo.getDeployFurniureListList().stream()
.map(HomeFurnitureItem::parseFrom)
.toList();
}
public int calComfort(){
return this.deployFurnitureList.stream()
.mapToInt(HomeFurnitureItem::getComfort)
.sum();
}
public HomeBlockArrangementInfo toProto() {
var proto = HomeBlockArrangementInfo.newBuilder()
.setBlockId(blockId)
.setIsUnlocked(unlocked)
.setComfortValue(calComfort());
this.deployFurnitureList.forEach(f -> proto.addDeployFurniureList(f.toProto()));
return proto.build();
}
public static HomeBlockItem parseFrom(HomeworldDefaultSaveData.HomeBlock homeBlock) {
return HomeBlockItem.of()
.blockId(homeBlock.getBlockId())
.unlocked(homeBlock.getFurnitures() != null)
.deployFurnitureList(
homeBlock.getFurnitures() == null ? List.of() :
homeBlock.getFurnitures().stream()
.map(HomeFurnitureItem::parseFrom)
.toList())
.build();
}
}
package emu.grasscutter.game.home;
import dev.morphia.annotations.Entity;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.binout.HomeworldDefaultSaveData;
import emu.grasscutter.data.excels.ItemData;
import emu.grasscutter.net.proto.HomeFurnitureDataOuterClass;
import emu.grasscutter.utils.Position;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Data;
import lombok.experimental.FieldDefaults;
@Entity
@Data
@FieldDefaults(level = AccessLevel.PRIVATE)
@Builder(builderMethodName = "of")
public class HomeFurnitureItem {
int furnitureId;
int guid;
int parentFurnitureIndex;
Position spawnPos;
Position spawnRot;
public HomeFurnitureDataOuterClass.HomeFurnitureData toProto(){
return HomeFurnitureDataOuterClass.HomeFurnitureData.newBuilder()
.setFurnitureId(furnitureId)
.setGuid(guid)
.setParentFurnitureIndex(parentFurnitureIndex)
.setSpawnPos(spawnPos.toProto())
.setSpawnRot(spawnRot.toProto())
.build();
}
public static HomeFurnitureItem parseFrom(HomeFurnitureDataOuterClass.HomeFurnitureData homeFurnitureData) {
return HomeFurnitureItem.of()
.furnitureId(homeFurnitureData.getFurnitureId())
.guid(homeFurnitureData.getGuid())
.parentFurnitureIndex(homeFurnitureData.getParentFurnitureIndex())
.spawnPos(new Position(homeFurnitureData.getSpawnPos()))
.spawnRot(new Position(homeFurnitureData.getSpawnRot()))
.build();
}
public static HomeFurnitureItem parseFrom(HomeworldDefaultSaveData.HomeFurniture homeFurniture) {
return HomeFurnitureItem.of()
.furnitureId(homeFurniture.getId())
.parentFurnitureIndex(1)
.spawnPos(homeFurniture.getPos() == null ? new Position() : homeFurniture.getPos())
.spawnRot(homeFurniture.getRot() == null ? new Position() : homeFurniture.getRot())
.build();
}
public ItemData getAsItem() {
return GameData.getItemDataMap().get(this.furnitureId);
}
public int getComfort() {
var item = getAsItem();
if (item == null){
return 0;
}
return item.getComfort();
}
}
package emu.grasscutter.game.home;
import dev.morphia.annotations.Entity;
import dev.morphia.annotations.Id;
import emu.grasscutter.data.binout.HomeworldDefaultSaveData;
import emu.grasscutter.net.proto.HomeBasicInfoOuterClass.HomeBasicInfo;
import emu.grasscutter.net.proto.HomeSceneArrangementInfoOuterClass.HomeSceneArrangementInfo;
import emu.grasscutter.utils.Position;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Data;
import lombok.experimental.FieldDefaults;
import java.util.Map;
import java.util.stream.Collectors;
@Entity
@Data
@Builder(builderMethodName = "of")
@FieldDefaults(level = AccessLevel.PRIVATE)
public class HomeSceneItem {
@Id
int sceneId;
Map<Integer, HomeBlockItem> blockItems;
Position bornPos;
Position bornRot;
Position djinnPos;
HomeFurnitureItem mainHouse;
public static HomeSceneItem parseFrom(HomeworldDefaultSaveData defaultItem, int sceneId) {
return HomeSceneItem.of()
.sceneId(sceneId)
.blockItems(defaultItem.getHomeBlockLists().stream()
.map(HomeBlockItem::parseFrom)
.collect(Collectors.toMap(HomeBlockItem::getBlockId, y -> y)))
.bornPos(defaultItem.getBornPos())
.bornRot(defaultItem.getBornRot() == null ? new Position() : defaultItem.getBornRot())
.djinnPos(defaultItem.getDjinPos() == null ? new Position() : defaultItem.getDjinPos())
.mainHouse(defaultItem.getMainhouse() == null ? null :
HomeFurnitureItem.parseFrom(defaultItem.getMainhouse()))
.build();
}
public void update(HomeSceneArrangementInfo arrangementInfo){
for(var blockItem : arrangementInfo.getBlockArrangementInfoListList()){
var block = this.blockItems.get(blockItem.getBlockId());
if(block == null){
System.out.println(111);
continue;
}
block.update(blockItem);
this.blockItems.put(blockItem.getBlockId(), block);
}
this.bornPos = new Position(arrangementInfo.getBornPos());
this.bornRot = new Position(arrangementInfo.getBornRot());
this.djinnPos = new Position(arrangementInfo.getDjinnPos());
this.mainHouse = HomeFurnitureItem.parseFrom(arrangementInfo.getMainHouse());
}
public int getRoomSceneId(){
if(mainHouse == null || mainHouse.getAsItem() == null){
return 0;
}
return mainHouse.getAsItem().getRoomSceneId();
}
public int calComfort(){
return this.blockItems.values().stream()
.mapToInt(HomeBlockItem::calComfort)
.sum();
}
public HomeSceneArrangementInfo toProto(){
var proto = HomeSceneArrangementInfo.newBuilder();
blockItems.values().forEach(b -> proto.addBlockArrangementInfoList(b.toProto()));
proto.setComfortValue(calComfort())
.setBornPos(bornPos.toProto())
.setBornRot(bornRot.toProto())
.setDjinnPos(djinnPos.toProto())
.setSceneId(sceneId)
.setTmpVersion(1);
if(mainHouse != null){
proto.setMainHouse(mainHouse.toProto());
}
return proto.build();
}
}
......@@ -267,6 +267,8 @@ public class Inventory implements Iterable<GameItem> {
getPlayer().setMora(player.getMora() + count);
case 203 -> // Genesis Crystals
getPlayer().setCrystals(player.getCrystals() + count);
case 204 -> // Home Coin
getPlayer().setHomeCoin(player.getHomeCoin() + count);
}
}
......@@ -280,6 +282,8 @@ public class Inventory implements Iterable<GameItem> {
return player.getCrystals();
case 106: // Resin
return player.getProperty(PlayerProperty.PROP_PLAYER_RESIN);
case 204: // Home Coin
return player.getHomeCoin();
default:
GameItem item = getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(itemId); // What if we ever want to operate on weapons/relics/furniture? :S
return (item == null) ? 0 : item.getCount();
......@@ -320,6 +324,8 @@ public class Inventory implements Iterable<GameItem> {
player.setCrystals(player.getCrystals() - (cost.getCount() * quantity));
case 106 -> // Resin
player.getResinManager().useResin(cost.getCount() * quantity);
case 204 -> // Home Coin
player.setHomeCoin(player.getHomeCoin() - (cost.getCount() * quantity));
default ->
removeItem(getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(cost.getId()), cost.getCount() * quantity);
}
......
......@@ -14,6 +14,8 @@ import emu.grasscutter.game.avatar.AvatarProfileData;
import emu.grasscutter.game.avatar.AvatarStorage;
import emu.grasscutter.game.entity.EntityMonster;
import emu.grasscutter.game.entity.EntityVehicle;
import emu.grasscutter.game.home.GameHome;
import emu.grasscutter.game.managers.DeforestationManager.DeforestationManager;
import emu.grasscutter.game.entity.EntityGadget;
import emu.grasscutter.game.entity.EntityItem;
import emu.grasscutter.game.entity.GameEntity;
......@@ -164,6 +166,7 @@ public class Player {
@Transient private ResinManager resinManager;
@Transient private ForgingManager forgingManager;
@Transient private DeforestationManager deforestationManager;
@Transient private GameHome home;
private long springLastUsed;
private HashMap<String, MapMark> mapMarks;
......@@ -376,7 +379,9 @@ public class Player {
public void setCurrentRealmId(Integer currentRealmId) {
this.currentRealmId = currentRealmId;
}
public GameHome getHome(){
return home;
}
public Position getPos() {
return pos;
}
......@@ -429,6 +434,14 @@ public class Player {
this.sendPacket(new PacketPlayerPropNotify(this, PlayerProperty.PROP_PLAYER_MCOIN));
}
public int getHomeCoin() {
return this.getProperty(PlayerProperty.PROP_PLAYER_HOME_COIN);
}
public void setHomeCoin(int coin) {
this.setProperty(PlayerProperty.PROP_PLAYER_HOME_COIN, coin);
this.sendPacket(new PacketPlayerPropNotify(this, PlayerProperty.PROP_PLAYER_HOME_COIN));
}
private int getExpRequired(int level) {
PlayerLevelData levelData = GameData.getPlayerLevelDataMap().get(level);
return levelData != null ? levelData.getExp() : 0;
......@@ -1316,14 +1329,16 @@ public class Player {
session.send(new PacketCodexDataFullNotify(this));
session.send(new PacketAllWidgetDataNotify(this));
session.send(new PacketWidgetGadgetAllDataNotify());
session.send(new PacketPlayerHomeCompInfoNotify(this));
session.send(new PacketHomeComfortInfoNotify(this));
session.send(new PacketCombineDataNotify(this.unlockedCombines));
this.forgingManager.sendForgeDataNotify();
this.resinManager.onPlayerLogin();
getTodayMoonCard(); // The timer works at 0:0, some users log in after that, use this method to check if they have received a reward today or not. If not, send the reward.
// Home
home = GameHome.getByUid(getUid());
home.onOwnerLogin(this);
session.send(new PacketPlayerEnterSceneNotify(this)); // Enter game world
session.send(new PacketPlayerLevelRewardUpdateNotify(rewardedLevels));
session.send(new PacketOpenStateUpdateNotify());
......
......@@ -414,6 +414,10 @@ public class Scene {
}
public void onTick() {
// disable script for home
if (this.getSceneType() == SceneType.SCENE_HOME_WORLD || this.getSceneType() == SceneType.SCENE_HOME_ROOM){
return;
}
if (this.getScriptManager().isInit()) {
this.checkBlocks();
} else {
......
......@@ -270,7 +270,9 @@ public class World implements Iterable<Player> {
enterType = EnterType.ENTER_TYPE_GOTO;
} else if (newScene.getSceneType() == SceneType.SCENE_HOME_WORLD) {
// Home
enterReason = EnterReason.EnterHome;
enterType = EnterType.ENTER_TYPE_SELF_HOME;
}
// Teleport packet
......
......@@ -777,6 +777,9 @@ public class PacketOpcodes {
public static final int HomeSceneJumpRsp = 4570;
public static final int HomeTransferReq = 4880;
public static final int HomeTransferRsp = 4767;
public static final int HomeUnknown1Notify = 4528;
public static final int HomeUnknown2Req = 4857;
public static final int HomeUnknown2Rsp = 4670;
public static final int HomeUpdateArrangementInfoReq = 4472;
public static final int HomeUpdateArrangementInfoRsp = 4822;
public static final int HomeUpdateFishFarmingInfoReq = 4604;
......
package emu.grasscutter.server.packet.recv;
import emu.grasscutter.net.packet.Opcodes;
import emu.grasscutter.net.packet.PacketHandler;
import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.server.game.GameSession;
import emu.grasscutter.server.packet.send.PacketFurnitureCurModuleArrangeCountNotify;
@Opcodes(PacketOpcodes.GetFurnitureCurModuleArrangeCountReq)
public class HandlerGetFurnitureCurModuleArrangeCountReq extends PacketHandler {
@Override
public void handle(GameSession session, byte[] header, byte[] payload) throws Exception {
session.send(new PacketFurnitureCurModuleArrangeCountNotify());
}
}
package emu.grasscutter.server.packet.recv;
import emu.grasscutter.net.packet.Opcodes;
import emu.grasscutter.net.packet.PacketHandler;
import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.server.game.GameSession;
import emu.grasscutter.server.packet.send.PacketPlayerHomeCompInfoNotify;
@Opcodes(PacketOpcodes.GetPlayerHomeCompInfoReq)
public class HandlerGetPlayerHomeCompInfoReq extends PacketHandler {
@Override
public void handle(GameSession session, byte[] header, byte[] payload) throws Exception {
session.send(new PacketPlayerHomeCompInfoNotify(session.getPlayer()));
}
}
package emu.grasscutter.server.packet.recv;
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.server.game.GameSession;
import emu.grasscutter.server.packet.send.*;
@Opcodes(PacketOpcodes.HomeChangeEditModeReq)
public class HandlerHomeChangeEditModeReq extends PacketHandler {
@Override
public void handle(GameSession session, byte[] header, byte[] payload) throws Exception {
var req = HomeChangeEditModeReqOuterClass.HomeChangeEditModeReq.parseFrom(payload);
session.send(new PacketHomeUnknown1Notify(req.getIsEnterEditMode()));
session.send(new PacketHomeBasicInfoNotify(session.getPlayer(), req.getIsEnterEditMode()));
session.send(new PacketHomeComfortInfoNotify(session.getPlayer()));
session.send(new PacketHomeChangeEditModeRsp(req.getIsEnterEditMode()));
}
}
package emu.grasscutter.server.packet.recv;
import emu.grasscutter.net.packet.Opcodes;
import emu.grasscutter.net.packet.PacketHandler;
import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.HomeGetArrangementInfoReqOuterClass;
import emu.grasscutter.server.game.GameSession;
import emu.grasscutter.server.packet.send.PacketHomeGetArrangementInfoRsp;
@Opcodes(PacketOpcodes.HomeGetArrangementInfoReq)
public class HandlerHomeGetArrangementInfoReq extends PacketHandler {
@Override
public void handle(GameSession session, byte[] header, byte[] payload) throws Exception {
var req = HomeGetArrangementInfoReqOuterClass.HomeGetArrangementInfoReq.parseFrom(payload);
session.send(new PacketHomeGetArrangementInfoRsp(session.getPlayer(), req.getSceneIdListList()));
}
}
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment