CombineManger.java 6.15 KB
Newer Older
Akka's avatar
Akka committed
1
2
package emu.grasscutter.game.combine;

3
4
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.DataLoader;
Akka's avatar
Akka committed
5
import emu.grasscutter.data.GameData;
Melledy's avatar
Melledy committed
6
7
import emu.grasscutter.data.common.ItemParamData;
import emu.grasscutter.data.excels.CombineData;
ImmuState's avatar
ImmuState committed
8
import emu.grasscutter.game.inventory.GameItem;
9
import emu.grasscutter.game.inventory.Inventory;
Akka's avatar
Akka committed
10
11
import emu.grasscutter.game.inventory.ItemType;
import emu.grasscutter.game.player.Player;
ImmuState's avatar
ImmuState committed
12
import emu.grasscutter.game.props.ActionReason;
Akka's avatar
Akka committed
13
import emu.grasscutter.net.proto.RetcodeOuterClass;
14
import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode;
Akka's avatar
Akka committed
15
import emu.grasscutter.server.game.GameServer;
ImmuState's avatar
ImmuState committed
16
import emu.grasscutter.server.packet.send.PacketCombineFormulaDataNotify;
Akka's avatar
Akka committed
17
import emu.grasscutter.server.packet.send.PacketCombineRsp;
18
19
import emu.grasscutter.server.packet.send.PacketReliquaryDecomposeRsp;
import emu.grasscutter.utils.Utils;
Akka's avatar
Akka committed
20
import it.unimi.dsi.fastutil.Pair;
21
22
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
Akka's avatar
Akka committed
23

24
25
import java.io.InputStreamReader;
import java.io.Reader;
ImmuState's avatar
ImmuState committed
26
import java.util.ArrayList;
27
import java.util.Collection;
Akka's avatar
Akka committed
28
29
import java.util.List;

30
31
import com.google.gson.reflect.TypeToken;

Akka's avatar
Akka committed
32
33
public class CombineManger {
    private final GameServer gameServer;
34
	private final static Int2ObjectMap<List<Integer>> reliquaryDecomposeData = new Int2ObjectOpenHashMap<>();
Akka's avatar
Akka committed
35
36
37
38
39
40
41
42
43

    public GameServer getGameServer() {
        return gameServer;
    }

    public CombineManger(GameServer gameServer) {
        this.gameServer = gameServer;
    }

44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
    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);
		}
	}

ImmuState's avatar
ImmuState committed
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
    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")) {
			return false;
		}

		// Determine the combine item we should unlock.
		int combineId = Integer.parseInt(diagramItem.getItemData().getItemUse().get(0).getUseParam().get(0));

		// Remove the diagram from the player's inventory.
		// We need to do this here, before sending CombineFormulaDataNotify, or the the combine UI won't correctly
		// update when unlocking the diagram.
		player.getInventory().removeItem(diagramItem, 1);

		// Tell the client that this diagram is now unlocked and add the unlocked item to the player.
		player.getUnlockedCombines().add(combineId);
		player.sendPacket(new PacketCombineFormulaDataNotify(combineId));

		return true;
	}

Akka's avatar
Akka committed
81
82
83
84
85
86
87
88
89
90
91
92
    public CombineResult combineItem(Player player, int cid, int count){
        // check config exist
        if(!GameData.getCombineDataMap().containsKey(cid)){
            player.getWorld().getHost().sendPacket(new PacketCombineRsp());
            return null;
        }

        CombineData combineData = GameData.getCombineDataMap().get(cid);

        if(combineData.getPlayerLevel() > player.getLevel()){
            return null;
        }
ImmuState's avatar
ImmuState committed
93
94
95
96
97
98
99
100
101
102

        // consume items
        List<ItemParamData> material = new ArrayList<>(combineData.getMaterialItems());
        material.add(new ItemParamData(202, combineData.getScoinCost()));

        boolean success = player.getInventory().payItems(material.toArray(new ItemParamData[0]), count, ActionReason.Combine);

        // abort if not enough material
        if (!success) {
            player.sendPacket(new PacketCombineRsp(RetcodeOuterClass.Retcode.RET_ITEM_COMBINE_COUNT_NOT_ENOUGH_VALUE));
Akka's avatar
Akka committed
103
104
105
106
107
108
109
110
        }

        // make the result
        player.getInventory().addItem(combineData.getResultItemId(),
                combineData.getResultItemCount() * count);

        CombineResult result = new CombineResult();
        result.setMaterial(List.of());
Melledy's avatar
Melledy committed
111
        result.setResult(List.of(new ItemParamData(combineData.getResultItemId(),
Akka's avatar
Akka committed
112
113
114
115
116
117
118
119
                combineData.getResultItemCount() * count)));
        // TODO lucky characters
        result.setExtra(List.of());
        result.setBack(List.of());

        return result;
    }

120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
    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));
    }
Akka's avatar
Akka committed
160
}