From d35ff068cf270c0138c493f1be99c03736fb55a9 Mon Sep 17 00:00:00 2001 From: Akka <104902222+Akka0@users.noreply.github.com> Date: Thu, 16 Jun 2022 17:25:20 +0800 Subject: [PATCH] implement furniture make system --- proto/FurnitureMakeBeHelpedData.proto | 13 ++ proto/FurnitureMakeData.proto | 12 ++ proto/FurnitureMakeHelpData.proto | 8 + proto/FurnitureMakeMakeInfo.proto | 8 + proto/FurnitureMakeReq.proto | 10 ++ proto/FurnitureMakeRsp.proto | 19 +++ proto/FurnitureMakeSlot.proto | 9 ++ proto/FurnitureMakeStartReq.proto | 12 ++ proto/FurnitureMakeStartRsp.proto | 13 ++ proto/TakeFurnitureMakeReq.proto | 13 ++ proto/TakeFurnitureMakeRsp.proto | 17 ++ proto/UnlockedFurnitureSuiteDataNotify.proto | 11 ++ .../java/emu/grasscutter/data/GameData.java | 8 + .../data/excels/FurnitureMakeConfigData.java | 37 +++++ .../data/excels/HomeWorldLevelData.java | 37 +++++ .../game/home/FurnitureMakeSlotItem.java | 33 ++++ .../emu/grasscutter/game/home/GameHome.java | 12 +- .../grasscutter/game/home/HomeSceneItem.java | 1 - .../game/managers/FurnitureManager.java | 146 ++++++++++++++++++ .../game/managers/InventoryManager.java | 11 +- .../emu/grasscutter/game/player/Player.java | 21 +++ .../packet/recv/HandlerFurnitureMakeReq.java | 16 ++ .../recv/HandlerFurnitureMakeStartReq.java | 20 +++ .../packet/recv/HandlerHomeSceneJumpReq.java | 2 +- .../recv/HandlerTakeFurnitureMakeReq.java | 19 +++ .../packet/send/PacketFurnitureMakeRsp.java | 25 +++ .../send/PacketFurnitureMakeStartRsp.java | 28 ++++ .../send/PacketHomeMarkPointNotify.java | 7 +- .../send/PacketTakeFurnitureMakeRsp.java | 38 +++++ ...ketUnlockedFurnitureFormulaDataNotify.java | 14 +- ...acketUnlockedFurnitureSuiteDataNotify.java | 21 +++ 31 files changed, 623 insertions(+), 18 deletions(-) create mode 100644 proto/FurnitureMakeBeHelpedData.proto create mode 100644 proto/FurnitureMakeData.proto create mode 100644 proto/FurnitureMakeHelpData.proto create mode 100644 proto/FurnitureMakeMakeInfo.proto create mode 100644 proto/FurnitureMakeReq.proto create mode 100644 proto/FurnitureMakeRsp.proto create mode 100644 proto/FurnitureMakeSlot.proto create mode 100644 proto/FurnitureMakeStartReq.proto create mode 100644 proto/FurnitureMakeStartRsp.proto create mode 100644 proto/TakeFurnitureMakeReq.proto create mode 100644 proto/TakeFurnitureMakeRsp.proto create mode 100644 proto/UnlockedFurnitureSuiteDataNotify.proto create mode 100644 src/main/java/emu/grasscutter/data/excels/FurnitureMakeConfigData.java create mode 100644 src/main/java/emu/grasscutter/data/excels/HomeWorldLevelData.java create mode 100644 src/main/java/emu/grasscutter/game/home/FurnitureMakeSlotItem.java create mode 100644 src/main/java/emu/grasscutter/game/managers/FurnitureManager.java create mode 100644 src/main/java/emu/grasscutter/server/packet/recv/HandlerFurnitureMakeReq.java create mode 100644 src/main/java/emu/grasscutter/server/packet/recv/HandlerFurnitureMakeStartReq.java create mode 100644 src/main/java/emu/grasscutter/server/packet/recv/HandlerTakeFurnitureMakeReq.java create mode 100644 src/main/java/emu/grasscutter/server/packet/send/PacketFurnitureMakeRsp.java create mode 100644 src/main/java/emu/grasscutter/server/packet/send/PacketFurnitureMakeStartRsp.java create mode 100644 src/main/java/emu/grasscutter/server/packet/send/PacketTakeFurnitureMakeRsp.java create mode 100644 src/main/java/emu/grasscutter/server/packet/send/PacketUnlockedFurnitureSuiteDataNotify.java diff --git a/proto/FurnitureMakeBeHelpedData.proto b/proto/FurnitureMakeBeHelpedData.proto new file mode 100644 index 000000000..f5c3fe086 --- /dev/null +++ b/proto/FurnitureMakeBeHelpedData.proto @@ -0,0 +1,13 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +import "ProfilePicture.proto"; + +message FurnitureMakeBeHelpedData { + string player_name = 1; + uint32 time = 2; + uint32 uid = 3; + uint32 icon = 4; + ProfilePicture profile_picture = 5; +} diff --git a/proto/FurnitureMakeData.proto b/proto/FurnitureMakeData.proto new file mode 100644 index 000000000..3231ce1a9 --- /dev/null +++ b/proto/FurnitureMakeData.proto @@ -0,0 +1,12 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +message FurnitureMakeData { + uint32 index = 1; + uint32 make_id = 2; + uint32 begin_time = 3; + uint32 dur_time = 4; + uint32 accelerate_time = 5; + uint32 avatar_id = 6; +} diff --git a/proto/FurnitureMakeHelpData.proto b/proto/FurnitureMakeHelpData.proto new file mode 100644 index 000000000..298773c7b --- /dev/null +++ b/proto/FurnitureMakeHelpData.proto @@ -0,0 +1,8 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +message FurnitureMakeHelpData { + uint32 uid = 1; + uint32 times = 2; +} diff --git a/proto/FurnitureMakeMakeInfo.proto b/proto/FurnitureMakeMakeInfo.proto new file mode 100644 index 000000000..d59a108de --- /dev/null +++ b/proto/FurnitureMakeMakeInfo.proto @@ -0,0 +1,8 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +message FurnitureMakeMakeInfo { + uint32 furniture_id = 1; + uint32 make_count = 2; +} diff --git a/proto/FurnitureMakeReq.proto b/proto/FurnitureMakeReq.proto new file mode 100644 index 000000000..7247cd475 --- /dev/null +++ b/proto/FurnitureMakeReq.proto @@ -0,0 +1,10 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +// CmdId: 4551 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true +message FurnitureMakeReq { +} diff --git a/proto/FurnitureMakeRsp.proto b/proto/FurnitureMakeRsp.proto new file mode 100644 index 000000000..4a63c198e --- /dev/null +++ b/proto/FurnitureMakeRsp.proto @@ -0,0 +1,19 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +import "FurnitureMakeBeHelpedData.proto"; +import "FurnitureMakeHelpData.proto"; +import "FurnitureMakeMakeInfo.proto"; +import "FurnitureMakeSlot.proto"; + +// CmdId: 4530 +// EnetChannelId: 0 +// EnetIsReliable: true +message FurnitureMakeRsp { + int32 retcode = 6; + FurnitureMakeSlot furniture_make_slot = 10; + repeated FurnitureMakeHelpData help_data_list = 13; + repeated FurnitureMakeBeHelpedData helped_data_list = 12; + repeated FurnitureMakeMakeInfo make_info_list = 11; +} diff --git a/proto/FurnitureMakeSlot.proto b/proto/FurnitureMakeSlot.proto new file mode 100644 index 000000000..5d4b32e7e --- /dev/null +++ b/proto/FurnitureMakeSlot.proto @@ -0,0 +1,9 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +import "FurnitureMakeData.proto"; + +message FurnitureMakeSlot { + repeated FurnitureMakeData furniture_make_data_list = 1; +} diff --git a/proto/FurnitureMakeStartReq.proto b/proto/FurnitureMakeStartReq.proto new file mode 100644 index 000000000..d1bca84cf --- /dev/null +++ b/proto/FurnitureMakeStartReq.proto @@ -0,0 +1,12 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +// CmdId: 4582 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true +message FurnitureMakeStartReq { + uint32 make_id = 1; + uint32 avatar_id = 14; +} diff --git a/proto/FurnitureMakeStartRsp.proto b/proto/FurnitureMakeStartRsp.proto new file mode 100644 index 000000000..518489f06 --- /dev/null +++ b/proto/FurnitureMakeStartRsp.proto @@ -0,0 +1,13 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +import "FurnitureMakeSlot.proto"; + +// CmdId: 4463 +// EnetChannelId: 0 +// EnetIsReliable: true +message FurnitureMakeStartRsp { + int32 retcode = 8; + FurnitureMakeSlot furniture_make_slot = 10; +} diff --git a/proto/TakeFurnitureMakeReq.proto b/proto/TakeFurnitureMakeReq.proto new file mode 100644 index 000000000..d2f8b05f0 --- /dev/null +++ b/proto/TakeFurnitureMakeReq.proto @@ -0,0 +1,13 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +// CmdId: 4768 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true +message TakeFurnitureMakeReq { + uint32 index = 9; + uint32 make_id = 4; + bool is_fast_finish = 2; +} diff --git a/proto/TakeFurnitureMakeRsp.proto b/proto/TakeFurnitureMakeRsp.proto new file mode 100644 index 000000000..4c33aeb36 --- /dev/null +++ b/proto/TakeFurnitureMakeRsp.proto @@ -0,0 +1,17 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +import "FurnitureMakeSlot.proto"; +import "ItemParam.proto"; + +// CmdId: 4599 +// EnetChannelId: 0 +// EnetIsReliable: true +message TakeFurnitureMakeRsp { + int32 retcode = 9; + uint32 make_id = 2; + FurnitureMakeSlot furniture_make_slot = 15; + repeated ItemParam output_item_list = 10; + repeated ItemParam return_item_list = 5; +} diff --git a/proto/UnlockedFurnitureSuiteDataNotify.proto b/proto/UnlockedFurnitureSuiteDataNotify.proto new file mode 100644 index 000000000..dc0667c03 --- /dev/null +++ b/proto/UnlockedFurnitureSuiteDataNotify.proto @@ -0,0 +1,11 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +// CmdId: 4717 +// EnetChannelId: 0 +// EnetIsReliable: true +message UnlockedFurnitureSuiteDataNotify { + bool is_all = 10; + repeated uint32 furniture_suite_id_list = 15; +} diff --git a/src/main/java/emu/grasscutter/data/GameData.java b/src/main/java/emu/grasscutter/data/GameData.java index 054e87348..9d81e6f6e 100644 --- a/src/main/java/emu/grasscutter/data/GameData.java +++ b/src/main/java/emu/grasscutter/data/GameData.java @@ -87,6 +87,8 @@ public class GameData { private static final Int2ObjectMap towerLevelDataMap = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap towerScheduleDataMap = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap forgeDataMap = new Int2ObjectOpenHashMap<>(); + private static final Int2ObjectMap homeWorldLevelDataMap = new Int2ObjectOpenHashMap<>(); + private static final Int2ObjectMap furnitureMakeConfigDataMap = new Int2ObjectOpenHashMap<>(); // Cache private static Map> fetters = new HashMap<>(); @@ -377,4 +379,10 @@ public class GameData { public static Int2ObjectMap getForgeDataMap() { return forgeDataMap; } + public static Int2ObjectMap getHomeWorldLevelDataMap() { + return homeWorldLevelDataMap; + } + public static Int2ObjectMap getFurnitureMakeConfigDataMap() { + return furnitureMakeConfigDataMap; + } } diff --git a/src/main/java/emu/grasscutter/data/excels/FurnitureMakeConfigData.java b/src/main/java/emu/grasscutter/data/excels/FurnitureMakeConfigData.java new file mode 100644 index 000000000..96deb6b23 --- /dev/null +++ b/src/main/java/emu/grasscutter/data/excels/FurnitureMakeConfigData.java @@ -0,0 +1,37 @@ +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import emu.grasscutter.data.common.ItemParamData; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.experimental.FieldDefaults; + +import java.util.List; + +@Getter +@FieldDefaults(level = AccessLevel.PRIVATE) +@ResourceType(name = {"FurnitureMakeExcelConfigData.json"}) +public class FurnitureMakeConfigData extends GameResource { + + int configID; + int furnitureItemID; + int count; + int exp; + List materialItems; + int makeTime; + int maxAccelerateTime; + int quickFetchMaterialNum; + + @Override + public int getId() { + return configID; + } + + @Override + public void onLoad() { + this.materialItems = materialItems.stream() + .filter(x -> x.getId() > 0) + .toList(); + } +} diff --git a/src/main/java/emu/grasscutter/data/excels/HomeWorldLevelData.java b/src/main/java/emu/grasscutter/data/excels/HomeWorldLevelData.java new file mode 100644 index 000000000..a0ddd62f7 --- /dev/null +++ b/src/main/java/emu/grasscutter/data/excels/HomeWorldLevelData.java @@ -0,0 +1,37 @@ +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; + +import java.util.List; + +@Getter +@FieldDefaults(level = AccessLevel.PRIVATE) +@ResourceType(name = {"HomeworldLevelExcelConfigData.json"}) +public class HomeWorldLevelData extends GameResource { + + int level; + int exp; + int homeCoinStoreLimit; + int homeFetterExpStoreLimit; + int rewardId; + int furnitureMakeSlotCount; + int outdoorUnlockBlockCount; + int freeUnlockModuleCount; + int deployNpcCount; + int limitShopGoodsCount; + List levelFuncs; + + @Override + public int getId() { + return level; + } + + @Override + public void onLoad() { + super.onLoad(); + } +} diff --git a/src/main/java/emu/grasscutter/game/home/FurnitureMakeSlotItem.java b/src/main/java/emu/grasscutter/game/home/FurnitureMakeSlotItem.java new file mode 100644 index 000000000..d0b8dcbc0 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/home/FurnitureMakeSlotItem.java @@ -0,0 +1,33 @@ +package emu.grasscutter.game.home; + +import dev.morphia.annotations.Entity; +import dev.morphia.annotations.Id; +import emu.grasscutter.net.proto.FurnitureMakeDataOuterClass; +import emu.grasscutter.net.proto.FurnitureMakeSlotOuterClass; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Data; +import lombok.experimental.FieldDefaults; + +@Entity +@Data +@FieldDefaults(level = AccessLevel.PRIVATE) +@Builder(builderMethodName = "of") +public class FurnitureMakeSlotItem { + @Id + int index; + int makeId; + int avatarId; + int beginTime; + int durTime; + + public FurnitureMakeDataOuterClass.FurnitureMakeData toProto() { + return FurnitureMakeDataOuterClass.FurnitureMakeData.newBuilder() + .setIndex(index) + .setAvatarId(avatarId) + .setMakeId(makeId) + .setBeginTime(beginTime) + .setDurTime(durTime) + .build(); + } +} diff --git a/src/main/java/emu/grasscutter/game/home/GameHome.java b/src/main/java/emu/grasscutter/game/home/GameHome.java index fb4a94556..1021b3c14 100644 --- a/src/main/java/emu/grasscutter/game/home/GameHome.java +++ b/src/main/java/emu/grasscutter/game/home/GameHome.java @@ -6,6 +6,7 @@ import dev.morphia.annotations.IndexOptions; import dev.morphia.annotations.Indexed; import emu.grasscutter.Grasscutter; import emu.grasscutter.data.GameData; +import emu.grasscutter.data.excels.HomeWorldLevelData; import emu.grasscutter.database.DatabaseHelper; import emu.grasscutter.game.player.Player; import emu.grasscutter.server.packet.send.*; @@ -14,6 +15,7 @@ import lombok.Builder; import lombok.Data; import lombok.experimental.FieldDefaults; +import java.util.List; import java.util.concurrent.ConcurrentHashMap; @Entity(value = "homes", useDiscriminator = false) @@ -28,6 +30,9 @@ public class GameHome { @Indexed(options = @IndexOptions(unique = true)) long ownerUid; + int level; + int exp; + List furnitureMakeSlotItemList; ConcurrentHashMap sceneMap; public void save(){ @@ -45,6 +50,7 @@ public class GameHome { public static GameHome create(Integer uid){ return GameHome.of() .ownerUid(uid) + .level(1) .sceneMap(new ConcurrentHashMap<>()) .build(); } @@ -65,6 +71,10 @@ public class GameHome { player.getSession().send(new PacketPlayerHomeCompInfoNotify(player)); player.getSession().send(new PacketHomeComfortInfoNotify(player)); player.getSession().send(new PacketFurnitureCurModuleArrangeCountNotify()); - player.getSession().send(new PacketHomeMarkPointNotify(player, this)); + player.getSession().send(new PacketHomeMarkPointNotify(player)); + } + + public HomeWorldLevelData getLevelData(){ + return GameData.getHomeWorldLevelDataMap().get(level); } } diff --git a/src/main/java/emu/grasscutter/game/home/HomeSceneItem.java b/src/main/java/emu/grasscutter/game/home/HomeSceneItem.java index 77ef40317..352ba18db 100644 --- a/src/main/java/emu/grasscutter/game/home/HomeSceneItem.java +++ b/src/main/java/emu/grasscutter/game/home/HomeSceneItem.java @@ -4,7 +4,6 @@ import dev.morphia.annotations.Entity; import dev.morphia.annotations.Id; import emu.grasscutter.Grasscutter; 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; diff --git a/src/main/java/emu/grasscutter/game/managers/FurnitureManager.java b/src/main/java/emu/grasscutter/game/managers/FurnitureManager.java new file mode 100644 index 000000000..814bc7d6f --- /dev/null +++ b/src/main/java/emu/grasscutter/game/managers/FurnitureManager.java @@ -0,0 +1,146 @@ +package emu.grasscutter.game.managers; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.common.ItemParamData; +import emu.grasscutter.game.home.FurnitureMakeSlotItem; +import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.proto.ItemParamOuterClass; +import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode; +import emu.grasscutter.server.packet.send.*; +import emu.grasscutter.utils.Utils; + +import java.util.ArrayList; +import java.util.List; + +public class FurnitureManager { + private final Player player; + + public FurnitureManager(Player player) { + this.player = player; + } + + public void onLogin(){ + notifyUnlockFurniture(); + notifyUnlockFurnitureSuite(); + } + + public void notifyUnlockFurniture(){ + player.getSession().send(new PacketUnlockedFurnitureFormulaDataNotify(player.getUnlockedFurniture())); + } + + public void notifyUnlockFurnitureSuite(){ + player.getSession().send(new PacketUnlockedFurnitureSuiteDataNotify(player.getUnlockedFurnitureSuite())); + } + + public synchronized boolean unlockFurnitureOrSuite(GameItem useItem){ + // Check + if (!List.of("ITEM_USE_UNLOCK_FURNITURE_FORMULA", "ITEM_USE_UNLOCK_FURNITURE_SUITE") + .contains(useItem.getItemData().getItemUse().get(0).getUseOp())) { + return false; + } + + int furnitureIdOrSuiteId = Integer.parseInt(useItem.getItemData().getItemUse().get(0).getUseParam().get(0)); + + // Remove first + player.getInventory().removeItem(useItem, 1); + + if("ITEM_USE_UNLOCK_FURNITURE_FORMULA".equals(useItem.getItemData().getItemUse().get(0).getUseOp())){ + player.getUnlockedFurniture().add(furnitureIdOrSuiteId); + notifyUnlockFurniture(); + }else{ + player.getUnlockedFurnitureSuite().add(furnitureIdOrSuiteId); + notifyUnlockFurnitureSuite(); + } + return true; + } + + public void startMake(int makeId, int avatarId) { + var makeData = GameData.getFurnitureMakeConfigDataMap().get(makeId); + if(makeData == null){ + player.getSession().send(new PacketFurnitureMakeStartRsp(Retcode.RET_FURNITURE_MAKE_CONFIG_ERROR_VALUE, null)); + return; + } + + // check slot count + if (player.getHome().getLevelData().getFurnitureMakeSlotCount() <= player.getHome().getFurnitureMakeSlotItemList().size()){ + player.getSession().send(new PacketFurnitureMakeStartRsp(Retcode.RET_FURNITURE_MAKE_SLOT_FULL_VALUE, null)); + return; + } + + // pay items first + if(!player.getInventory().payItems(makeData.getMaterialItems().toArray(new ItemParamData[0]))){ + player.getSession().send(new PacketFurnitureMakeStartRsp(Retcode.RET_HOME_FURNITURE_COUNT_NOT_ENOUGH_VALUE, null)); + return; + } + + var furnitureSlot = FurnitureMakeSlotItem.of() + .avatarId(avatarId) + .makeId(makeId) + .beginTime(Utils.getCurrentSeconds()) + .durTime(makeData.getMakeTime()) + .build(); + + // add furniture make task + player.getHome().getFurnitureMakeSlotItemList().add(furnitureSlot); + player.getSession().send(new PacketFurnitureMakeStartRsp(Retcode.RET_SUCC_VALUE, + player.getHome().getFurnitureMakeSlotItemList().stream() + .map(FurnitureMakeSlotItem::toProto) + .toList() + )); + + player.getHome().save(); + } + + public void queryStatus() { + if (player.getHome().getFurnitureMakeSlotItemList() == null){ + player.getHome().setFurnitureMakeSlotItemList(new ArrayList<>()); + } + + player.sendPacket(new PacketFurnitureMakeRsp(player.getHome())); + } + + + public void take(int index, int makeId, boolean isFastFinish) { + var makeData = GameData.getFurnitureMakeConfigDataMap().get(makeId); + if(makeData == null){ + player.getSession().send(new PacketTakeFurnitureMakeRsp(Retcode.RET_FURNITURE_MAKE_CONFIG_ERROR_VALUE, makeId, null, null)); + return; + } + + var slotItem = player.getHome().getFurnitureMakeSlotItemList().stream() + .filter(x -> x.getIndex() == index && x.getMakeId() == makeId) + .findFirst(); + + if(slotItem.isEmpty()){ + player.getSession().send(new PacketTakeFurnitureMakeRsp(Retcode.RET_FURNITURE_MAKE_NO_MAKE_DATA_VALUE, makeId, null, null)); + return; + } + + // pay the speedup item + if(isFastFinish && !player.getInventory().payItem(107013,1)){ + player.getSession().send(new PacketTakeFurnitureMakeRsp(Retcode.RET_FURNITURE_MAKE_UNFINISH_VALUE, makeId, null, null)); + return; + } + + // check if player can take + if(slotItem.get().getBeginTime() + slotItem.get().getDurTime() >= Utils.getCurrentSeconds() && !isFastFinish){ + player.getSession().send(new PacketTakeFurnitureMakeRsp(Retcode.RET_FURNITURE_MAKE_UNFINISH_VALUE, makeId, null, null)); + return; + } + + player.getInventory().addItem(makeData.getFurnitureItemID(), makeData.getCount()); + player.getHome().getFurnitureMakeSlotItemList().remove(slotItem.get()); + + player.getSession().send(new PacketTakeFurnitureMakeRsp(Retcode.RET_SUCC_VALUE, makeId, + List.of(ItemParamOuterClass.ItemParam.newBuilder() + .setItemId(makeData.getFurnitureItemID()) + .setCount(makeData.getCount()) + .build()), + player.getHome().getFurnitureMakeSlotItemList().stream() + .map(FurnitureMakeSlotItem::toProto) + .toList() + )); + player.getHome().save(); + } +} diff --git a/src/main/java/emu/grasscutter/game/managers/InventoryManager.java b/src/main/java/emu/grasscutter/game/managers/InventoryManager.java index b73cb3dd4..361f54382 100644 --- a/src/main/java/emu/grasscutter/game/managers/InventoryManager.java +++ b/src/main/java/emu/grasscutter/game/managers/InventoryManager.java @@ -6,7 +6,6 @@ import java.util.List; import java.util.Map; import java.util.stream.Collectors; -import emu.grasscutter.Grasscutter; import emu.grasscutter.data.GameData; import emu.grasscutter.data.binout.OpenConfigEntry; import emu.grasscutter.data.binout.OpenConfigEntry.SkillPointModifier; @@ -22,14 +21,12 @@ import emu.grasscutter.data.excels.AvatarSkillDepotData.InherentProudSkillOpens; import emu.grasscutter.game.avatar.Avatar; import emu.grasscutter.game.inventory.GameItem; import emu.grasscutter.game.inventory.ItemType; -import emu.grasscutter.game.inventory.MaterialType; import emu.grasscutter.game.player.Player; import emu.grasscutter.game.props.ActionReason; import emu.grasscutter.game.shop.ShopChestBatchUseTable; import emu.grasscutter.game.shop.ShopChestTable; import emu.grasscutter.net.proto.ItemParamOuterClass.ItemParam; import emu.grasscutter.net.proto.MaterialInfoOuterClass.MaterialInfo; -import emu.grasscutter.server.packet.send.PacketForgeFormulaDataNotify; import emu.grasscutter.server.game.GameServer; import emu.grasscutter.server.packet.send.*; import emu.grasscutter.utils.Utils; @@ -861,6 +858,14 @@ public class InventoryManager { // Unlock. useSuccess = player.getServer().getCombineManger().unlockCombineDiagram(player, useItem); } + break; + case MATERIAL_FURNITURE_FORMULA: + case MATERIAL_FURNITURE_SUITE_FORMULA: + if (useItem.getItemData().getItemUse() == null) { + break; + } + useSuccess = player.getFurnitureManager().unlockFurnitureOrSuite(useItem); + break; case MATERIAL_CONSUME_BATCH_USE: // Make sure we have usage data for this material. diff --git a/src/main/java/emu/grasscutter/game/player/Player.java b/src/main/java/emu/grasscutter/game/player/Player.java index e3299971e..a1a19ca29 100644 --- a/src/main/java/emu/grasscutter/game/player/Player.java +++ b/src/main/java/emu/grasscutter/game/player/Player.java @@ -27,6 +27,7 @@ import emu.grasscutter.game.inventory.GameItem; import emu.grasscutter.game.inventory.Inventory; import emu.grasscutter.game.mail.Mail; import emu.grasscutter.game.mail.MailHandler; +import emu.grasscutter.game.managers.FurnitureManager; import emu.grasscutter.game.managers.InsectCaptureManager; import emu.grasscutter.game.managers.ResinManager; import emu.grasscutter.game.managers.deforestation.DeforestationManager; @@ -99,6 +100,8 @@ public class Player { private Set costumeList; private Set unlockedForgingBlueprints; private Set unlockedCombines; + private Set unlockedFurniture; + private Set unlockedFurnitureSuite; private List activeForges; private Integer widgetId; @@ -167,6 +170,7 @@ public class Player { @Transient private ForgingManager forgingManager; @Transient private DeforestationManager deforestationManager; @Transient private GameHome home; + @Transient private FurnitureManager furnitureManager; private long springLastUsed; private HashMap mapMarks; @@ -202,6 +206,8 @@ public class Player { this.towerData = new TowerData(); this.unlockedForgingBlueprints = new HashSet<>(); this.unlockedCombines = new HashSet<>(); + this.unlockedFurniture = new HashSet<>(); + this.unlockedFurnitureSuite = new HashSet<>(); this.activeForges = new ArrayList<>(); this.setSceneId(3); @@ -228,6 +234,7 @@ public class Player { this.energyManager = new EnergyManager(this); this.resinManager = new ResinManager(this); this.forgingManager = new ForgingManager(this); + this.furnitureManager = new FurnitureManager(this); } // On player creation @@ -261,6 +268,7 @@ public class Player { this.resinManager = new ResinManager(this); this.deforestationManager = new DeforestationManager(this); this.forgingManager = new ForgingManager(this); + this.furnitureManager = new FurnitureManager(this); } public int getUid() { @@ -565,6 +573,14 @@ public class Player { return this.unlockedCombines; } + public Set getUnlockedFurniture() { + return unlockedFurniture; + } + + public Set getUnlockedFurnitureSuite() { + return unlockedFurnitureSuite; + } + public List getActiveForges() { return this.activeForges; } @@ -1183,6 +1199,10 @@ public class Player { return this.forgingManager; } + public FurnitureManager getFurnitureManager() { + return furnitureManager; + } + public AbilityManager getAbilityManager() { return abilityManager; } @@ -1335,6 +1355,7 @@ public class Player { 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. + this.furnitureManager.onLogin(); // Home home = GameHome.getByUid(getUid()); home.onOwnerLogin(this); diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerFurnitureMakeReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerFurnitureMakeReq.java new file mode 100644 index 000000000..97d42a2b1 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerFurnitureMakeReq.java @@ -0,0 +1,16 @@ +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; + +@Opcodes(PacketOpcodes.FurnitureMakeReq) +public class HandlerFurnitureMakeReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + session.getPlayer().getFurnitureManager().queryStatus(); + } + +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerFurnitureMakeStartReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerFurnitureMakeStartReq.java new file mode 100644 index 000000000..7376d80f2 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerFurnitureMakeStartReq.java @@ -0,0 +1,20 @@ +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.FurnitureMakeStartReqOuterClass; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.FurnitureMakeStartReq) +public class HandlerFurnitureMakeStartReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + var req = FurnitureMakeStartReqOuterClass.FurnitureMakeStartReq.parseFrom(payload); + + session.getPlayer().getFurnitureManager().startMake(req.getMakeId(), req.getAvatarId()); + + } + +} 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 4f6bcd2b4..5525c8103 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeSceneJumpReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeSceneJumpReq.java @@ -24,7 +24,7 @@ public class HandlerHomeSceneJumpReq extends PacketHandler { Scene scene = session.getPlayer().getWorld().getSceneById(req.getIsEnterRoomScene() ? homeScene.getRoomSceneId() : realmId); Position pos = scene.getScriptManager().getConfig().born_pos; - + session.getPlayer().getWorld().transferPlayerToScene( session.getPlayer(), req.getIsEnterRoomScene() ? homeScene.getRoomSceneId() : realmId, diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerTakeFurnitureMakeReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerTakeFurnitureMakeReq.java new file mode 100644 index 000000000..92eda3669 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerTakeFurnitureMakeReq.java @@ -0,0 +1,19 @@ +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.TakeFurnitureMakeReqOuterClass; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.TakeFurnitureMakeReq) +public class HandlerTakeFurnitureMakeReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + var req = TakeFurnitureMakeReqOuterClass.TakeFurnitureMakeReq.parseFrom(payload); + + session.getPlayer().getFurnitureManager().take(req.getIndex(), req.getMakeId(), req.getIsFastFinish()); + } + +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketFurnitureMakeRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketFurnitureMakeRsp.java new file mode 100644 index 000000000..65124d047 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketFurnitureMakeRsp.java @@ -0,0 +1,25 @@ +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.home.FurnitureMakeSlotItem; +import emu.grasscutter.game.home.GameHome; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.FurnitureMakeRspOuterClass; +import emu.grasscutter.net.proto.FurnitureMakeSlotOuterClass; + +public class PacketFurnitureMakeRsp extends BasePacket { + + public PacketFurnitureMakeRsp(GameHome home) { + super(PacketOpcodes.FurnitureMakeRsp); + + var proto = FurnitureMakeRspOuterClass.FurnitureMakeRsp.newBuilder(); + + proto.setFurnitureMakeSlot(FurnitureMakeSlotOuterClass.FurnitureMakeSlot.newBuilder() + .addAllFurnitureMakeDataList(home.getFurnitureMakeSlotItemList().stream() + .map(FurnitureMakeSlotItem::toProto) + .toList()) + .build()); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketFurnitureMakeStartRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketFurnitureMakeStartRsp.java new file mode 100644 index 000000000..4dd0ddb61 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketFurnitureMakeStartRsp.java @@ -0,0 +1,28 @@ +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.FurnitureMakeDataOuterClass; +import emu.grasscutter.net.proto.FurnitureMakeSlotOuterClass; +import emu.grasscutter.net.proto.FurnitureMakeStartRspOuterClass; + +import java.util.List; + +public class PacketFurnitureMakeStartRsp extends BasePacket { + + public PacketFurnitureMakeStartRsp(int ret, List furnitureMakeData) { + super(PacketOpcodes.FurnitureMakeStartRsp); + + var proto = FurnitureMakeStartRspOuterClass.FurnitureMakeStartRsp.newBuilder(); + + proto.setRetcode(ret); + + if(furnitureMakeData != null){ + proto.setFurnitureMakeSlot(FurnitureMakeSlotOuterClass.FurnitureMakeSlot.newBuilder() + .addAllFurnitureMakeDataList(furnitureMakeData) + .build()); + } + + this.setData(proto); + } +} 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 bc9f019c4..ab732e93d 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketHomeMarkPointNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketHomeMarkPointNotify.java @@ -12,13 +12,16 @@ import java.util.Collection; public class PacketHomeMarkPointNotify extends BasePacket { - public PacketHomeMarkPointNotify(Player player, GameHome home) { + public PacketHomeMarkPointNotify(Player player) { super(PacketOpcodes.HomeMarkPointNotify); var proto = HomeMarkPointNotifyOuterClass.HomeMarkPointNotify.newBuilder(); + if(player.getRealmList() == null){ + return; + } for(var moduleId : player.getRealmList()){ - var homeScene = home.getHomeSceneItem(moduleId + 2000); + var homeScene = player.getHome().getHomeSceneItem(moduleId + 2000); var markPointData = HomeMarkPointSceneDataOuterClass.HomeMarkPointSceneData.newBuilder() .setModuleId(moduleId) diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketTakeFurnitureMakeRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketTakeFurnitureMakeRsp.java new file mode 100644 index 000000000..18cc49832 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketTakeFurnitureMakeRsp.java @@ -0,0 +1,38 @@ +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.data.common.ItemParamData; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.FurnitureMakeDataOuterClass; +import emu.grasscutter.net.proto.FurnitureMakeSlotOuterClass; +import emu.grasscutter.net.proto.ItemParamOuterClass; +import emu.grasscutter.net.proto.TakeFurnitureMakeRspOuterClass; + +import java.util.List; + +public class PacketTakeFurnitureMakeRsp extends BasePacket { + + public PacketTakeFurnitureMakeRsp(int ret, + int makeId, + List output, + List others) { + super(PacketOpcodes.TakeFurnitureMakeRsp); + + var proto = TakeFurnitureMakeRspOuterClass.TakeFurnitureMakeRsp.newBuilder(); + + proto.setRetcode(ret) + .setMakeId(makeId); + + if(output != null){ + proto.addAllOutputItemList(output); + } + + if(others != null){ + proto.setFurnitureMakeSlot(FurnitureMakeSlotOuterClass.FurnitureMakeSlot.newBuilder() + .addAllFurnitureMakeDataList(others) + .build()); + } + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketUnlockedFurnitureFormulaDataNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketUnlockedFurnitureFormulaDataNotify.java index 6c71be1eb..3ca0468c6 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketUnlockedFurnitureFormulaDataNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketUnlockedFurnitureFormulaDataNotify.java @@ -4,22 +4,16 @@ import emu.grasscutter.net.packet.BasePacket; import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.proto.UnlockedFurnitureFormulaDataNotifyOuterClass; +import java.util.Set; + public class PacketUnlockedFurnitureFormulaDataNotify extends BasePacket { - public PacketUnlockedFurnitureFormulaDataNotify() { + public PacketUnlockedFurnitureFormulaDataNotify(Set unlockList) { super(PacketOpcodes.UnlockedFurnitureFormulaDataNotify); var proto = UnlockedFurnitureFormulaDataNotifyOuterClass.UnlockedFurnitureFormulaDataNotify.newBuilder(); - proto.addFurnitureIdList(361207); - proto.addFurnitureIdList(362202); - proto.addFurnitureIdList(362304); - proto.addFurnitureIdList(363102); - proto.addFurnitureIdList(363103); - proto.addFurnitureIdList(363203); - proto.addFurnitureIdList(370201); - proto.addFurnitureIdList(370302); - + proto.addAllFurnitureIdList(unlockList); proto.setIsAll(true); this.setData(proto); diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketUnlockedFurnitureSuiteDataNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketUnlockedFurnitureSuiteDataNotify.java new file mode 100644 index 000000000..9d6b33209 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketUnlockedFurnitureSuiteDataNotify.java @@ -0,0 +1,21 @@ +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.UnlockedFurnitureSuiteDataNotifyOuterClass; + +import java.util.Set; + +public class PacketUnlockedFurnitureSuiteDataNotify extends BasePacket { + + public PacketUnlockedFurnitureSuiteDataNotify(Set unlockList) { + super(PacketOpcodes.UnlockedFurnitureSuiteDataNotify); + + var proto = UnlockedFurnitureSuiteDataNotifyOuterClass.UnlockedFurnitureSuiteDataNotify.newBuilder(); + + proto.addAllFurnitureSuiteIdList(unlockList); + proto.setIsAll(true); + + this.setData(proto); + } +}