Cooking and unlocking recipies.

This commit is contained in:
GanyusLeftHorn 2022-07-02 01:11:58 -07:00 committed by Melledy
parent a957b8c5b8
commit d95a30a1a5
7 changed files with 210 additions and 1 deletions

View File

@ -7,11 +7,23 @@ import java.util.List;
import java.util.Set; import java.util.Set;
import emu.grasscutter.data.GameData; import emu.grasscutter.data.GameData;
import emu.grasscutter.data.common.ItemParamData;
import emu.grasscutter.data.excels.ItemData;
import emu.grasscutter.game.inventory.GameItem;
import emu.grasscutter.game.player.Player; import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.props.ActionReason;
import emu.grasscutter.net.proto.CookRecipeDataOuterClass; import emu.grasscutter.net.proto.CookRecipeDataOuterClass;
import emu.grasscutter.net.proto.PlayerCookArgsReqOuterClass.PlayerCookArgsReq;
import emu.grasscutter.net.proto.PlayerCookReqOuterClass.PlayerCookReq;
import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode;
import emu.grasscutter.server.packet.send.PacketCookDataNotify; import emu.grasscutter.server.packet.send.PacketCookDataNotify;
import emu.grasscutter.server.packet.send.PacketCookRecipeDataNotify;
import emu.grasscutter.server.packet.send.PacketPlayerCookArgsRsp;
import emu.grasscutter.server.packet.send.PacketPlayerCookRsp;
public class CookingManager { public class CookingManager {
private static final int MANUAL_PERFECT_COOK_QUALITY = 3;
private static Set<Integer> defaultUnlockedRecipies; private static Set<Integer> defaultUnlockedRecipies;
private final Player player; private final Player player;
@ -30,10 +42,83 @@ public class CookingManager {
} }
} }
/********************
* Unlocking for recipies.
********************/
public synchronized boolean unlockRecipe(GameItem recipeItem) {
// Make sure this is actually a cooking recipe.
if (!recipeItem.getItemData().getItemUse().get(0).getUseOp().equals("ITEM_USE_UNLOCK_COOK_RECIPE")) {
return false;
}
// Determine the recipe we should unlock.
int recipeId = Integer.parseInt(recipeItem.getItemData().getItemUse().get(0).getUseParam().get(0));
// Remove the item from the player's inventory.
// We need to do this here, before sending CookRecipeDataNotify, or the the UI won't correctly update.
player.getInventory().removeItem(recipeItem, 1);
// Tell the client that this blueprint is now unlocked and add the unlocked item to the player.
this.player.getUnlockedRecipies().put(recipeId, 0);
this.player.sendPacket(new PacketCookRecipeDataNotify(recipeId));
return true;
}
/******************** /********************
* Perform cooking. * Perform cooking.
********************/ ********************/
public void handlePlayerCookReq(PlayerCookReq req) {
// Get info from the request.
int recipeId = req.getRecipeId();
int quality = req.getQteQuality();
int count = req.getCookCount();
// Get recipe data.
var recipeData = GameData.getCookRecipeDataMap().get(recipeId);
if (recipeData == null) {
this.player.sendPacket(new PacketPlayerCookRsp(Retcode.RET_FAIL));
return;
}
// Get proficiency for player.
int proficiency = this.player.getUnlockedRecipies().getOrDefault(recipeId, 0);
// Try consuming materials.
boolean success = player.getInventory().payItems(recipeData.getInputVec().toArray(new ItemParamData[0]), count, ActionReason.Cook);
if (!success) {
this.player.sendPacket(new PacketPlayerCookRsp(Retcode.RET_FAIL)); //ToDo: Probably the wrong return code.
}
// Obtain results.
int qualityIndex =
quality == 0
? 2
: quality - 1;
ItemParamData resultParam = recipeData.getQualityOutputVec().get(qualityIndex);
ItemData resultItemData = GameData.getItemDataMap().get(resultParam.getItemId());
GameItem cookResult = new GameItem(resultItemData, resultParam.getCount() * count);
this.player.getInventory().addItem(cookResult);
// Increase player proficiency, if this was a manual perfect cook.
if (quality == MANUAL_PERFECT_COOK_QUALITY) {
proficiency = Math.min(proficiency + 1, recipeData.getMaxProficiency());
this.player.getUnlockedRecipies().put(recipeId, proficiency);
}
// Send response.
this.player.sendPacket(new PacketPlayerCookRsp(cookResult, quality, count, recipeId, proficiency));
}
/********************
* Cooking arguments.
********************/
public void handleCookArgsReq(PlayerCookArgsReq req) {
this.player.sendPacket(new PacketPlayerCookArgsRsp());
}
/******************** /********************
* Notify unlocked recipies. * Notify unlocked recipies.

View File

@ -852,6 +852,11 @@ public class InventoryManager {
// Unlock. // Unlock.
useSuccess = player.getServer().getCombineManger().unlockCombineDiagram(player, useItem); useSuccess = player.getServer().getCombineManger().unlockCombineDiagram(player, useItem);
} }
// Handle cooking recipies.
if (useItem.getItemData().getItemUse().get(0).getUseOp().equals("ITEM_USE_UNLOCK_COOK_RECIPE")) {
// Unlock.
useSuccess = player.getCookingManager().unlockRecipe(useItem);
}
break; break;
case MATERIAL_FURNITURE_FORMULA: case MATERIAL_FURNITURE_FORMULA:
case MATERIAL_FURNITURE_SUITE_FORMULA: case MATERIAL_FURNITURE_SUITE_FORMULA:

View File

@ -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.net.proto.PlayerCookArgsReqOuterClass;
import emu.grasscutter.server.game.GameSession;
@Opcodes(PacketOpcodes.PlayerCookArgsReq)
public class HandlerPlayerCookArgsReq extends PacketHandler {
@Override
public void handle(GameSession session, byte[] header, byte[] payload) throws Exception {
PlayerCookArgsReqOuterClass.PlayerCookArgsReq req = PlayerCookArgsReqOuterClass.PlayerCookArgsReq.parseFrom(payload);
session.getPlayer().getCookingManager().handleCookArgsReq(req);
}
}

View File

@ -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.net.proto.PlayerCookReqOuterClass;
import emu.grasscutter.server.game.GameSession;
@Opcodes(PacketOpcodes.PlayerCookReq)
public class HandlerPlayerCookReq extends PacketHandler {
@Override
public void handle(GameSession session, byte[] header, byte[] payload) throws Exception {
PlayerCookReqOuterClass.PlayerCookReq req = PlayerCookReqOuterClass.PlayerCookReq.parseFrom(payload);
session.getPlayer().getCookingManager().handlePlayerCookReq(req);
}
}

View File

@ -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.CookRecipeDataNotifyOuterClass.CookRecipeDataNotify;
import emu.grasscutter.net.proto.CookRecipeDataOuterClass.CookRecipeData;
public class PacketCookRecipeDataNotify extends BasePacket {
public PacketCookRecipeDataNotify(CookRecipeData recipe) {
super(PacketOpcodes.CookRecipeDataNotify);
CookRecipeDataNotify proto = CookRecipeDataNotify.newBuilder()
.setRecipeData(recipe)
.build();
this.setData(proto);
}
public PacketCookRecipeDataNotify(int recipeId) {
super(PacketOpcodes.CookRecipeDataNotify);
CookRecipeDataNotify proto = CookRecipeDataNotify.newBuilder()
.setRecipeData(CookRecipeData.newBuilder().setRecipeId(recipeId))
.build();
this.setData(proto);
}
}

View File

@ -0,0 +1,17 @@
package emu.grasscutter.server.packet.send;
import emu.grasscutter.net.packet.BasePacket;
import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.PlayerCookArgsRspOuterClass.PlayerCookArgsRsp;
public class PacketPlayerCookArgsRsp extends BasePacket {
public PacketPlayerCookArgsRsp() {
super(PacketOpcodes.PlayerCookArgsRsp);
PlayerCookArgsRsp proto = PlayerCookArgsRsp.newBuilder()
.build();
this.setData(proto);
}
}

View File

@ -0,0 +1,42 @@
package emu.grasscutter.server.packet.send;
import emu.grasscutter.game.inventory.GameItem;
import emu.grasscutter.net.packet.BasePacket;
import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.CookRecipeDataOuterClass.CookRecipeData;
import emu.grasscutter.net.proto.ItemParamOuterClass.ItemParam;
import emu.grasscutter.net.proto.PlayerCookRspOuterClass.PlayerCookRsp;
import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode;
public class PacketPlayerCookRsp extends BasePacket {
public PacketPlayerCookRsp(Retcode retcode) {
super(PacketOpcodes.PlayerCookRsp);
PlayerCookRsp proto = PlayerCookRsp.newBuilder()
.setRetcode(retcode.getNumber())
.build();
this.setData(proto);
}
public PacketPlayerCookRsp(GameItem output, int quality, int count, int recipeId, int proficiency) {
super(PacketOpcodes.PlayerCookRsp);
PlayerCookRsp proto = PlayerCookRsp.newBuilder()
.setRecipeData(
CookRecipeData.newBuilder()
.setRecipeId(recipeId)
.setProficiency(proficiency)
)
.setQteQuality(quality)
.addItemList(
ItemParam.newBuilder()
.setItemId(output.getItemId())
.setCount(output.getCount())
)
.setCookCount(count)
.build();
this.setData(proto);
}
}