Skip to content
Snippets Groups Projects
Commit 6338c171 authored by GanyusLeftHorn's avatar GanyusLeftHorn Committed by Melledy
Browse files

Add reliquary decomposition (aka strongbox).

parent 95244822
Branches
Tags
No related merge requests found
package emu.grasscutter.game.combine;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.DataLoader;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.common.ItemParamData;
import emu.grasscutter.data.excels.CombineData;
import emu.grasscutter.game.inventory.GameItem;
import emu.grasscutter.game.inventory.Inventory;
import emu.grasscutter.game.inventory.ItemType;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.props.ActionReason;
import emu.grasscutter.net.proto.RetcodeOuterClass;
import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode;
import emu.grasscutter.server.game.GameServer;
import emu.grasscutter.server.packet.send.PacketCombineFormulaDataNotify;
import emu.grasscutter.server.packet.send.PacketCombineRsp;
import emu.grasscutter.server.packet.send.PacketReliquaryDecomposeRsp;
import emu.grasscutter.utils.Utils;
import it.unimi.dsi.fastutil.Pair;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import com.google.gson.reflect.TypeToken;
public class CombineManger {
private final GameServer gameServer;
private final static Int2ObjectMap<List<Integer>> reliquaryDecomposeData = new Int2ObjectOpenHashMap<>();
public GameServer getGameServer() {
return gameServer;
......@@ -27,6 +41,22 @@ public class CombineManger {
this.gameServer = gameServer;
}
public static void initialize() {
// Read the data we need for strongbox.
try (Reader fileReader = new InputStreamReader(DataLoader.load("ReliquaryDecompose.json"))) {
List<ReliquaryDecomposeEntry> decomposeEntries = Grasscutter.getGsonFactory().fromJson(fileReader, TypeToken.getParameterized(Collection.class, ReliquaryDecomposeEntry.class).getType());
for (ReliquaryDecomposeEntry entry : decomposeEntries) {
reliquaryDecomposeData.put(entry.getConfigId(), entry.getItems());
}
Grasscutter.getLogger().debug("Loaded {} reliquary decompose entries.", reliquaryDecomposeData.size());
}
catch (Exception ex) {
Grasscutter.getLogger().error("Unable to load reliquary decompose data.", ex);
}
}
public boolean unlockCombineDiagram(Player player, GameItem diagramItem) {
// Make sure this is actually a diagram.
if (!diagramItem.getItemData().getItemUse().get(0).getUseOp().equals("ITEM_USE_UNLOCK_COMBINE")) {
......@@ -87,4 +117,44 @@ public class CombineManger {
return result;
}
public synchronized void decomposeReliquaries(Player player, int configId, int count, List<Long> input) {
// Check if the configId is legal.
List<Integer> possibleDrops = reliquaryDecomposeData.get(configId);
if (possibleDrops == null) {
player.sendPacket(new PacketReliquaryDecomposeRsp(Retcode.RET_RELIQUARY_DECOMPOSE_PARAM_ERROR));
return;
}
// Check if the number of input items matches the output count.
if (input.size() != count * 3) {
player.sendPacket(new PacketReliquaryDecomposeRsp(Retcode.RET_RELIQUARY_DECOMPOSE_PARAM_ERROR));
return;
}
// Check if all the input reliquaries actually are in the player's inventory.
for (long guid : input) {
if (player.getInventory().getItemByGuid(guid) == null) {
player.sendPacket(new PacketReliquaryDecomposeRsp(Retcode.RET_RELIQUARY_DECOMPOSE_PARAM_ERROR));
return;
}
}
// Delete the input reliquaries.
for (long guid : input) {
player.getInventory().removeItem(guid);
}
// Generate outoput reliquaries.
List<Long> resultItems = new ArrayList<>();
for (int i = 0; i < count; i++) {
int itemId = Utils.drawRandomListElement(possibleDrops);
GameItem newReliquary = new GameItem(itemId, 1);
player.getInventory().addItem(newReliquary);
resultItems.add(newReliquary.getGuid());
}
// Send packet.
player.sendPacket(new PacketReliquaryDecomposeRsp(resultItems));
}
}
package emu.grasscutter.game.combine;
import java.util.List;
public class ReliquaryDecomposeEntry {
private int configId;
private List<Integer> items;
public int getConfigId() {
return configId;
}
public void setConfigId(int configId) {
this.configId = configId;
}
public List<Integer> getItems() {
return items;
}
public void setItems(List<Integer> items) {
this.items = items;
}
}
......@@ -92,6 +92,7 @@ public final class GameServer extends KcpServer {
EnergyManager.initialize();
StaminaManager.initialize();
CookingManager.initialize();
CombineManger.initialize();
this.address = address;
this.packetHandler = new GameServerPacketHandler(PacketHandler.class);
......
package emu.grasscutter.server.packet.recv;
import emu.grasscutter.net.packet.Opcodes;
import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.ReliquaryDecomposeReqOuterClass.ReliquaryDecomposeReq;
import emu.grasscutter.net.packet.PacketHandler;
import emu.grasscutter.server.game.GameSession;
@Opcodes(PacketOpcodes.ReliquaryDecomposeReq)
public class HandlerReliquaryDecomposeReq extends PacketHandler {
@Override
public void handle(GameSession session, byte[] header, byte[] payload) throws Exception {
ReliquaryDecomposeReq req = ReliquaryDecomposeReq.parseFrom(payload);
session.getServer().getCombineManger().decomposeReliquaries(session.getPlayer(), req.getConfigId(), req.getTargetCount(), req.getGuidListList());
}
}
package emu.grasscutter.server.packet.send;
import java.util.List;
import emu.grasscutter.net.packet.BasePacket;
import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.ReliquaryDecomposeRspOuterClass.ReliquaryDecomposeRsp;
import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode;
public class PacketReliquaryDecomposeRsp extends BasePacket {
public PacketReliquaryDecomposeRsp(Retcode retcode) {
super(PacketOpcodes.ReliquaryDecomposeRsp);
ReliquaryDecomposeRsp proto = ReliquaryDecomposeRsp.newBuilder()
.setRetcode(retcode.getNumber())
.build();
this.setData(proto);
}
public PacketReliquaryDecomposeRsp(List<Long> output) {
super(PacketOpcodes.ReliquaryDecomposeRsp);
ReliquaryDecomposeRsp proto = ReliquaryDecomposeRsp.newBuilder()
.addAllGuidList(output)
.build();
this.setData(proto);
}
}
......@@ -399,4 +399,13 @@ public final class Utils {
// Should never happen.
return list.get(0);
}
/***
* Draws a random element from the given list, following a uniform probability distribution.
* @param list The list from which to draw the element.
* @return A randomly drawn element from the given list.
*/
public static <T> T drawRandomListElement(List<T> list) {
return drawRandomListElement(list, null);
}
}
[
{
"configId": 1,
"comment": "Gladiator",
"items": [75513, 75514, 75523, 75524, 75533, 75534, 75543, 75544, 75553, 75554]
},
{
"configId": 2,
"comment": "Wanderer's Troupe",
"items": [77513, 77514, 77523, 77524, 77533, 77534, 77543, 77544, 77553, 77554]
},
{
"configId": 3,
"comment": "Bloodstained",
"items": [82513, 82514, 82523, 82524, 82533, 82534, 82543, 82544, 82553, 82554]
},
{
"configId": 4,
"comment": "Noblesse",
"items": [81513, 81514, 81523, 81524, 81533, 81534, 81543, 81544, 81553, 81554]
}
]
\ No newline at end of file
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