Test Failed
Pull Request — master (#172)
by Vincent
09:48
created

build(Builder)   A

Complexity

Conditions 1

Size

Total Lines 16
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 14
dl 0
loc 16
ccs 8
cts 8
cp 1
crap 1
rs 9.7
c 1
b 0
f 0
1
/*
2
 * This file is part of Araknemu.
3
 *
4
 * Araknemu is free software: you can redistribute it and/or modify
5
 * it under the terms of the GNU Lesser General Public License as published by
6
 * the Free Software Foundation, either version 3 of the License, or
7
 * (at your option) any later version.
8
 *
9
 * Araknemu is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU Lesser General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU Lesser General Public License
15
 * along with Araknemu.  If not, see <https://www.gnu.org/licenses/>.
16
 *
17
 * Copyright (c) 2017-2020 Vincent Quatrevieux
18
 */
19
20
package fr.quatrevieux.araknemu.game.admin.player;
21
22
import fr.quatrevieux.araknemu.common.account.Permission;
23
import fr.quatrevieux.araknemu.data.constant.Effect;
24
import fr.quatrevieux.araknemu.data.value.ItemTemplateEffectEntry;
25
import fr.quatrevieux.araknemu.data.world.transformer.ItemEffectsTransformer;
26
import fr.quatrevieux.araknemu.game.admin.AbstractCommand;
27
import fr.quatrevieux.araknemu.game.admin.AdminPerformer;
28
import fr.quatrevieux.araknemu.game.admin.exception.CommandException;
29
import fr.quatrevieux.araknemu.game.admin.formatter.Link;
30
import fr.quatrevieux.araknemu.game.item.Item;
31
import fr.quatrevieux.araknemu.game.item.ItemService;
32
import fr.quatrevieux.araknemu.game.item.effect.ItemEffect;
33
import fr.quatrevieux.araknemu.game.player.GamePlayer;
34
import org.apache.commons.lang3.StringUtils;
35
import org.kohsuke.args4j.Argument;
36
import org.kohsuke.args4j.CmdLineException;
37
import org.kohsuke.args4j.CmdLineParser;
38
import org.kohsuke.args4j.Option;
39
import org.kohsuke.args4j.OptionDef;
40
import org.kohsuke.args4j.spi.OptionHandler;
41
import org.kohsuke.args4j.spi.Parameters;
42
import org.kohsuke.args4j.spi.Setter;
43
44
import java.util.ArrayList;
45
import java.util.List;
46 1
47 1
/**
48 1
 * Get an item for the player
49 1
 */
50
public final class GetItem extends AbstractCommand<GetItem.Options> {
51
    private final GamePlayer player;
52
    private final ItemService service;
53 1
54 1
    public GetItem(GamePlayer player, ItemService service) {
55 1
        this.player = player;
56 1
        this.service = service;
57 1
    }
58
59 1
    @Override
60 1
    protected void build(Builder builder) {
61 1
        builder
62
            .description("Add an item to the player")
63
            .help(
64
                formatter -> formatter
65
                    .example("getitem 2425", "Generate a random 'Amulette du Bouftou'")
66
                    .example("!getitem 2425 3", "Generate 3 random 'Amulette du Bouftou', and ensure that the admin user is the target")
67
                    .example("${player:Robert} getitem 39", "Add to Robert the 'Petite Amulette du Hibou'")
68
                    .example("getitem --max 2425", "Generate an 'Amulette du Bouftou' with max stats")
69
                    .example("getitem --effects 5b#1#32#0#,5c#1#32#0#,5d#1#32#0#,5e#1#32#0#,5f#1#32#0# 40", "Cheated 'Petite Epée de Boisaille'")
70 1
                    .example("getitem --effects STOLEN_WATER:1:50,STOLEN_EARTH:1:50,STOLEN_WIND:1:50,STOLEN_FIRE:1:50,STOLEN_NEUTRAL:1:50 40", "Same as above")
71 1
72 1
                    .seeAlso("/ui itemsummoner", "Show the item picker", Link.Type.EXECUTE)
73 1
            )
74 1
            .requires(Permission.MANAGE_PLAYER)
75 1
        ;
76
    }
77 1
78
    @Override
79 1
    public String name() {
80
        return "getitem";
81 1
    }
82
83
    @Override
84
    public Options createArguments() {
85 1
        return new Options();
86
    }
87
88
    @Override
89
    public void execute(AdminPerformer performer, Options options) throws CommandException {
90 1
        for (int j = 0; j < options.times(); ++j) {
91
            final Item item = options.hasCustomEffects()
92 1
                ? service.retrieve(options.itemId(), options.effects())
93 1
                : service.create(options.itemId(), options.max())
94 1
            ;
95 1
96
            player.inventory().add(item, options.quantity());
97
98 1
            performer.success("Generate {} '{}'", options.quantity(), item.template().name());
99
100 1
            if (!item.effects().isEmpty()) {
101
                performer.success("Effects :");
102 1
103 1
                for (ItemEffect effect : item.effects()) {
104
                    performer.success("\t{}", effect.toString());
105 1
                }
106 1
            }
107 1
        }
108
    }
109
110 1
    public static final class Options {
111
        @Option(name = "--max", usage = "Generate item with maximized characteristics")
112
        private boolean max = false;
113 1
114 1
        @Option(name = "--each", usage = "Regenerate item stats for each QUANTITY items instead of generate the same item with QUANTITY")
115 1
        private boolean each = false;
116 1
117 1
        @Option(
118
            name = "--effects", handler = EffectsConverter.class,
119
            usage = "Set the item effects\n" +
120 1
                "The effects should be a list of effects separated with comma ','. Available formats :\n" +
121 1
                "Item template format : 64#b#f#0#1d5+10,7d#b#0#0#0d0+11,9a#f#0#0#0d0+15\n" +
122 1
                "Simplified format    : INFLICT_DAMAGE_NEUTRAL:11:15,ADD_VITALITY:11,SUB_AGILITY:15\n" +
123
                "This option is not compatible with --max option.\n" +
124
                "If a range value is set for a characteristic effect, a random value will be generated"
125
        )
126
        private List<ItemTemplateEffectEntry> effects = null;
127 1
128 1
        @Argument(
129
            required = true, index = 0, metaVar = "ITEM_ID",
130 1
            usage = "The id of the item to generate. It can be found using /ui itemsummoner command"
131 1
        )
132
        private int itemId;
133 1
134 1
        @Argument(
135
            index = 1, metaVar = "QUANTITY",
136 1
            usage = "The quantity of item to generate. By default all generated items will gets the same characteristics unless --each option is used."
137 1
        )
138
        private int quantity = 1;
139 1
140
        public boolean max() {
141
            return max;
142
        }
143 1
144
        public void setMax(boolean max) {
145
            this.max = max;
146
        }
147 1
148 1
        public boolean each() {
149
            return each;
150
        }
151 1
152
        public void setEach(boolean each) {
153 1
            this.each = each;
154 1
        }
155
156
        public List<ItemTemplateEffectEntry> effects() {
157 1
            return effects;
158 1
        }
159 1
160
        public boolean hasCustomEffects() {
161 1
            return effects != null;
162
        }
163
164 1
        public int itemId() {
165 1
            return itemId;
166
        }
167
168 1
        public int times() {
169
            return each ? quantity : 1;
170 1
        }
171 1
172
        public int quantity() {
173
            return each ? 1 : quantity;
174
        }
175 1
    }
176 1
177 1
    public static class EffectsConverter extends OptionHandler<ItemTemplateEffectEntry> {
178 1
        public EffectsConverter(CmdLineParser parser, OptionDef option, Setter<? super ItemTemplateEffectEntry> setter) {
179
            super(parser, option, setter);
180 1
        }
181
182
        @Override
183 1
        public int parseArguments(Parameters params) throws CmdLineException {
184 1
            for (ItemTemplateEffectEntry effect : parseEffects(params.getParameter(0))) {
185 1
                setter.addValue(effect);
186
            }
187
188
            return 1;
189
        }
190
191 1
        @Override
192
        public String getDefaultMetaVariable() {
193
            return "effects,...";
194
        }
195
196
        private List<ItemTemplateEffectEntry> parseEffects(String value) throws CmdLineException {
197
            if (value.contains("#")) {
198
                return new ItemEffectsTransformer().unserialize(value);
199
            }
200
201
            final List<ItemTemplateEffectEntry> effects = new ArrayList<>();
202
203
            for (String strEffect : StringUtils.split(value, ",")) {
204
                final String[] parts = StringUtils.split(strEffect, ":", 5);
205
                final Effect effect;
206
207
                try {
208
                    effect = Effect.valueOf(parts[0].toUpperCase());
209
                } catch (IllegalArgumentException e) {
210
                    throw new CmdLineException(owner, "Undefined effect " + parts[0], e);
211
                }
212
213
                effects.add(
214
                    new ItemTemplateEffectEntry(
215
                        effect,
216
                        parts.length > 1 ? Integer.parseInt(parts[1]) : 0,
217
                        parts.length > 2 ? Integer.parseInt(parts[2]) : 0,
218
                        parts.length > 3 ? Integer.parseInt(parts[3]) : 0,
219
                        parts.length > 4 ? parts[4]                   : ""
220
                    )
221
                );
222
            }
223
224
            return effects;
225
        }
226
    }
227
}
228