Skip to content
This repository was archived by the owner on Mar 8, 2022. It is now read-only.

Commit ed56c0d

Browse files
committed
[skip-ci]quest claim/verification/cancellation #31
1 parent 2308427 commit ed56c0d

File tree

7 files changed

+154
-84
lines changed

7 files changed

+154
-84
lines changed

src/main/java/cat/nyaa/HamsterEcoHelper/quest/QuestCommands.java

+6
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,12 @@ public void postQuest(CommandSender sender, Arguments args) {
3838
msg(sender, "user.quest.not_station");
3939
return;
4040
}
41+
42+
if (!plugin.eco.enoughMoney(asPlayer(sender), station.postingFee)) {
43+
msg(sender, "user.quest.wizard.not_enough_money_posting");
44+
return;
45+
}
46+
4147
new QuestWizard(station.id, asPlayer(sender), 30);
4248
}
4349

src/main/java/cat/nyaa/HamsterEcoHelper/quest/QuestCommon.java

+88-75
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,14 @@
77
import cat.nyaa.HamsterEcoHelper.utils.database.tables.quest.QuestEntry;
88
import cat.nyaa.HamsterEcoHelper.utils.database.tables.quest.QuestInstance;
99
import cat.nyaa.HamsterEcoHelper.utils.database.tables.quest.QuestStation;
10-
import cat.nyaa.nyaacore.database.BaseDatabase;
1110
import cat.nyaa.nyaacore.utils.InventoryUtils;
12-
import net.milkbowl.vault.item.Items;
1311
import org.bukkit.Bukkit;
1412
import org.bukkit.Location;
13+
import org.bukkit.OfflinePlayer;
1514
import org.bukkit.entity.Player;
16-
import org.bukkit.inventory.Inventory;
1715
import org.bukkit.inventory.ItemStack;
1816

1917
import java.time.ZonedDateTime;
20-
import java.util.ArrayList;
2118
import java.util.List;
2219
import java.util.UUID;
2320

@@ -76,7 +73,7 @@ public static void claimQuest(Player player, String questId) {
7673
throw new RuntimeException("user.quest.menu.reject_unfinished");
7774
}
7875

79-
if (!quest.claimable) throw new RuntimeException("user.quest.menu.reject_unavailable");
76+
if (!quest.claimable || quest.masked) throw new RuntimeException("user.quest.menu.reject_unavailable");
8077
if (quest.isExpired()) throw new RuntimeException("user.quest.menu.reject_expired");
8178
// TODO prereq etc.
8279

@@ -88,13 +85,15 @@ public static void claimQuest(Player player, String questId) {
8885
q.status = IN_PROGRESS;
8986
q.startTime = ZonedDateTime.now();
9087

91-
quest.claimable = false;
92-
93-
db.query(QuestEntry.class).whereEq("id", questId).update(quest, "claimable");
88+
if (!quest.isRecurrentQuest) {
89+
quest.claimable = false;
90+
db.query(QuestEntry.class).whereEq("id", questId).update(quest, "claimable");
91+
}
9492
db.query(QuestInstance.class).insert(q);
9593
}
9694
}
9795

96+
/* Check the database for all in-progress quest of this player and submit them */
9897
public static void submitQuest(Player player) {
9998
String playerId = player.getUniqueId().toString();
10099
Database db = HamsterEcoHelper.instance.database;
@@ -104,112 +103,126 @@ public static void submitQuest(Player player) {
104103
.select();
105104
for (QuestInstance q : quests) {
106105
String questId = q.questId;
107-
QuestEntry e = selectUniqueUnchecked(db.query(QuestEntry.class).whereEq("id", questId));
108-
// TODO reset quest claimable
106+
QuestEntry e = db.query(QuestEntry.class).whereEq("id", questId).selectUniqueUnchecked();
109107
if (e == null) {
110108
player.sendMessage(I18n.format("user.quest.submit.no_entry", questId));
111-
q.status = CANCELLED;
112-
db.query(QuestInstance.class).update(q, "status");
109+
q.status = INVALID;
110+
q.endTime = ZonedDateTime.now();
111+
db.query(QuestInstance.class).whereEq("id", q.id).update(q, "status", "end_time");
113112
continue;
114113
}
115114

115+
player.sendMessage(I18n.format("user.quest.submit.submitting", e.questName));
116+
116117
if (!e.completedInTime(q.startTime)) {
117118
player.sendMessage(I18n.format("user.quest.submit.timeout"));
118119
q.status = TIMEOUT;
119-
db.query(QuestInstance.class).update(q, "status");
120+
q.endTime = ZonedDateTime.now();
121+
if (!e.isRecurrentQuest && !e.isExpired()) {
122+
e.claimable = true;
123+
db.query(QuestEntry.class).whereEq("id", e.id).update(e, "claimable");
124+
}
125+
db.query(QuestInstance.class).whereEq("id", q.id).update(q, "status", "end_time");
120126
continue;
121127
}
122128

123129
if (e.targetType == QuestEntry.QuestType.OTHER) {
124130
player.sendMessage(I18n.format("user.quest.submit.need_verification"));
131+
UUID publisherId = UUID.fromString(e.publisher);
132+
if (Bukkit.getPlayer(publisherId) != null) Bukkit.getPlayer(publisherId).sendMessage(
133+
I18n.format("user.quest.quest_need_verify", player.getName(), e.questName));
125134
q.status = UNVERIFIED;
126-
db.query(QuestInstance.class).update(q, "status");
135+
q.endTime = ZonedDateTime.now();
136+
db.query(QuestInstance.class).whereEq("id", q.id).update(q, "status", "end_time");
127137
} else if (e.targetType == QuestEntry.QuestType.ITEM) {
128-
List<ItemStack> ret = withdrawInventoryAtomic(player.getInventory(), e.targetItems);
138+
List<ItemStack> ret = InventoryUtils.withdrawInventoryAtomic(player.getInventory(), e.targetItems);
129139
if (ret == null) {
130-
// TODO return target item to publisher notification.
131-
//for (ItemStack item : e.targetItems) Utils.giveItem(Bukkit.getOfflinePlayer(UUID.fromString(e.publisher)), item);
140+
UUID publisherId = UUID.fromString(e.publisher);
141+
for (ItemStack item : e.targetItems) Utils.giveItem(Bukkit.getOfflinePlayer(publisherId), item);
142+
msgIfOnline(e.publisher, "user.quest.quest_complete_by");
132143
switch (e.rewardType) {
133144
case ITEM: for (ItemStack i : e.rewardItem) Utils.giveItem(player, i); break;
134145
case MONEY: HamsterEcoHelper.instance.eco.deposit(player, e.rewardMoney); break;
135146
default: break;
136147
}
137148
q.status = COMPLETED;
138-
// TODO update endTime
139-
db.query(QuestInstance.class).update(q, "status");
149+
q.endTime = ZonedDateTime.now();
150+
db.query(QuestInstance.class).whereEq("id", q.id).update(q, "status", "end_time");
140151
player.sendMessage(I18n.format("user.quest.submit.quest_complete", e.id));
141152
} else {
142153
player.sendMessage(I18n.format("user.quest.submit.target_not_satisfy", e.id));
143154
}
144155
} else {
145156
player.sendMessage(I18n.format("user.quest.submit.bad_target_type", e.id));
146-
q.status = CANCELLED;
147-
db.query(QuestInstance.class).update(q, "status");
157+
q.status = INVALID;
158+
q.endTime = ZonedDateTime.now();
159+
db.query(QuestInstance.class).whereEq("id", q.id).update(q, "status", "end_time");
148160
}
149-
150-
151-
152161
}
153162
}
154163

155-
// TODO move to NC
156-
private static <T> T selectUniqueUnchecked(BaseDatabase.Query<T> q) {
157-
try {
158-
return q.selectUnique();
159-
} catch (RuntimeException ex) {
160-
return null;
164+
public static void confirmQuest(String questInstanceId, boolean confirmed) {
165+
Database db = HamsterEcoHelper.instance.database;
166+
QuestInstance questInstance = db.query(QuestInstance.class).whereEq("id", questInstanceId).selectUnique();
167+
if (questInstance.status != UNVERIFIED) throw new IllegalArgumentException("quest status incorrect, expecting UNVERIFIED: " + questInstanceId);
168+
QuestEntry questEntry = db.query(QuestEntry.class).whereEq("id", questInstance.questId).selectUnique();
169+
UUID claimerId = UUID.fromString(questInstance.claimer);
170+
if (!confirmed) {
171+
msgIfOnline(claimerId, "user.quest.rejected", questEntry.questName);
172+
questInstance.status = QuestInstance.QuestStatus.REJECTED;
173+
db.query(QuestInstance.class).whereEq("id", questInstanceId).update(questInstance, "status");
174+
if (!questEntry.isRecurrentQuest && !questEntry.isExpired()) {
175+
questEntry.claimable = true;
176+
db.query(QuestEntry.class).whereEq("id", questEntry.id).update(questEntry, "claimable");
177+
}
178+
} else {
179+
OfflinePlayer claimer = Bukkit.getOfflinePlayer(claimerId);
180+
switch (questEntry.rewardType) {
181+
case ITEM: for (ItemStack i : questEntry.rewardItem) Utils.giveItem(claimer, i); break;
182+
case MONEY: HamsterEcoHelper.instance.eco.deposit(claimer, questEntry.rewardMoney); break;
183+
default: break;
184+
}
185+
questInstance.status = COMPLETED;
186+
db.query(QuestInstance.class).whereEq("id", questInstanceId).update(questInstance, "status");
187+
msgIfOnline(claimerId, "user.quest.verified", questEntry.questName);
161188
}
162189
}
163190

164-
/**
165-
* Remove items from inventory.
166-
* Either all removed or none removed.
167-
* @param inv the inventory
168-
* @param itemToBeTaken items to be removed
169-
* @return If null, then all designated items are removed. If not null, it contains the items missing
170-
* TODO move to NC
171-
*/
172-
private static List<ItemStack> withdrawInventoryAtomic(Inventory inv, List<ItemStack> itemToBeTaken) {
173-
ItemStack[] itemStacks = inv.getContents();
174-
ItemStack[] cloneStacks = new ItemStack[itemStacks.length];
175-
for (int i = 0; i < itemStacks.length; i++) {
176-
cloneStacks[i] = itemStacks[i] == null ? null : itemStacks[i].clone();
191+
public static void cancelQuest(String questInstanceId) {
192+
Database db = HamsterEcoHelper.instance.database;
193+
QuestInstance questInstance = db.query(QuestInstance.class).whereEq("id", questInstanceId).selectUnique();
194+
if (questInstance.status != IN_PROGRESS && questInstance.status != UNVERIFIED)
195+
throw new IllegalArgumentException("quest status incorrect, expecting IN_PROGRESS or UNVERIFIED: " + questInstanceId);
196+
QuestEntry questEntry = db.query(QuestEntry.class).whereEq("id", questInstance.questId).selectUnique();
197+
msgIfOnline(questInstance.claimer, "user.quest.cancelled", questEntry.questName);
198+
questInstance.status = QuestInstance.QuestStatus.CANCELLED;
199+
questInstance.endTime = ZonedDateTime.now();
200+
db.query(QuestInstance.class).whereEq("id", questInstance.id).update(questInstance, "status", "end_time");
201+
if (!questEntry.isRecurrentQuest && !questEntry.isExpired()) {
202+
questEntry.claimable = true;
203+
db.query(QuestEntry.class).whereEq("id", questEntry.id).update(questEntry, "claimable");
177204
}
205+
}
178206

179-
List<ItemStack> ret = new ArrayList<>();
180-
181-
for (ItemStack item : itemToBeTaken) {
182-
int sizeReq = item.getAmount();
183-
184-
for (int i = 0; i < cloneStacks.length;i++) {
185-
if (cloneStacks[i] == null) continue;
186-
if (cloneStacks[i].isSimilar(item)) {
187-
int sizeSupp = cloneStacks[i].getAmount();
188-
if (sizeSupp > sizeReq) {
189-
cloneStacks[i].setAmount(sizeSupp - sizeReq);
190-
sizeReq = 0;
191-
break;
192-
} else {
193-
cloneStacks[i] = null;
194-
sizeReq -= sizeSupp;
195-
if (sizeReq == 0) break;
196-
}
197-
}
198-
}
207+
public static void withdrawQuest(String questEntryId) {
208+
Database db = HamsterEcoHelper.instance.database;
209+
QuestEntry questEntry = db.query(QuestEntry.class).whereEq("id", questEntryId).selectUnique();
210+
for (QuestInstance qi : db.query(QuestInstance.class).whereEq("questId", questEntryId).select())
211+
if (qi.status == IN_PROGRESS || qi.status == UNVERIFIED)
212+
cancelQuest(qi.id);
213+
questEntry.masked = true;
214+
db.query(QuestEntry.class).whereEq("id", questEntryId).update(questEntry, "masked");
215+
msgIfOnline(questEntry.publisher, "user.quest.withdrawn", questEntry.questName);
216+
}
199217

200-
if (sizeReq > 0) {
201-
ItemStack n = item.clone();
202-
item.setAmount(sizeReq);
203-
ret.add(n);
204-
}
205-
}
218+
private static void msgIfOnline(String id, String template, Object... objs) {;
219+
UUID uid = UUID.fromString(id);
220+
msgIfOnline(uid, template, objs);
221+
}
206222

207-
if (ret.size() == 0) {
208-
inv.setContents(cloneStacks);
209-
return null;
210-
} else {
211-
return ret;
223+
private static void msgIfOnline(UUID uid, String template, Object... objs) {
224+
if (Bukkit.getPlayer(uid) != null) {
225+
Bukkit.getPlayer(uid).sendMessage(I18n.format(template, objs));
212226
}
213227
}
214-
215228
}

src/main/java/cat/nyaa/HamsterEcoHelper/quest/QuestWizard.java

+39-3
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import cat.nyaa.HamsterEcoHelper.I18n;
55
import cat.nyaa.HamsterEcoHelper.utils.Utils;
66
import cat.nyaa.HamsterEcoHelper.utils.database.tables.quest.QuestEntry;
7+
import cat.nyaa.HamsterEcoHelper.utils.database.tables.quest.QuestStation;
78
import org.bukkit.Bukkit;
89
import org.bukkit.ChatColor;
910
import org.bukkit.Material;
@@ -78,6 +79,8 @@ enum State {
7879
WAITING_TIME_LIMIT,
7980
WAITING_EXPIRE_IN,
8081

82+
WAITING_ICON_MATERIAL, // TODO
83+
8184
WAITING_IS_RECURRENT,
8285
WAITING_CLAIM_LIMIT,
8386
WAITING_ENABLED,
@@ -95,10 +98,15 @@ public QuestWizard(String stationUUID, Player p, int timeoutSeconds) {
9598
entry.publisher = p.getUniqueId().toString();
9699
entry.stationId = stationUUID;
97100
state = State.WAITING_NAME;
98-
p.sendMessage(I18n.format("user.quest.wizard." + state.name().toLowerCase()));
99101
Bukkit.getServer().getPluginManager().registerEvents(this, HamsterEcoHelper.instance);
100102
timer = new Timer(timeout);
101103
this.reallyTakeItem = !p.hasPermission("heh.quest.admin");
104+
Bukkit.getScheduler().runTaskLater(HamsterEcoHelper.instance, new Runnable() {
105+
@Override
106+
public void run() {
107+
p.sendMessage(I18n.format("user.quest.wizard." + state.name().toLowerCase()));
108+
}
109+
}, 1L);
102110
}
103111

104112
private void cancelWizard() {
@@ -205,9 +213,15 @@ public void onPlayerChat(PlayerChatEvent ev) {
205213
try {
206214
player.sendMessage(input);
207215
double money = Double.parseDouble(input);
216+
if (reallyTakeItem) {
217+
if (!HamsterEcoHelper.instance.eco.enoughMoney(player, money)) {
218+
player.sendMessage(I18n.format("user.quest.wizard.not_enough_money"));
219+
break;
220+
}
221+
HamsterEcoHelper.instance.eco.withdraw(player, money);
222+
}
208223
entry.rewardMoney = money;
209224
state = WAITING_TIME_LIMIT;
210-
HamsterEcoHelper.instance.eco.withdraw(player, money);
211225
} catch (NumberFormatException ex) {
212226
player.sendMessage(I18n.format("user.quest.wizard.invalid_number"));
213227
}
@@ -236,10 +250,32 @@ public void onPlayerChat(PlayerChatEvent ev) {
236250
}
237251
entry.questExpire = ZonedDateTime.now().plus(dur);
238252
}
253+
state = reallyTakeItem ? FINISH : WAITING_IS_RECURRENT;
254+
break;
255+
case WAITING_IS_RECURRENT:
256+
entry.isRecurrentQuest = "yes".equalsIgnoreCase(input);
257+
state = reallyTakeItem ? FINISH : WAITING_ENABLED;
258+
break;
259+
case WAITING_ENABLED:
260+
entry.claimable = "yes".equalsIgnoreCase(input);
261+
entry.masked = !entry.claimable;
239262
state = FINISH;
240263
break;
241264
case FINISH:
242-
entry.claimable = true;
265+
if (reallyTakeItem) {
266+
entry.claimable = true;
267+
QuestStation station = HamsterEcoHelper.instance.database.query(QuestStation.class).whereEq("id", this.station.toString()).selectUniqueUnchecked();
268+
if (station == null) {
269+
player.sendMessage(I18n.format("user.quest.wizard.station_invalid", this.station.toString()));
270+
cancelWizard();
271+
return;
272+
}
273+
if (!HamsterEcoHelper.instance.eco.enoughMoney(player, station.postingFee)) {
274+
player.sendMessage(I18n.format("user.quest.wizard.not_enough_money_posting"));
275+
break;
276+
}
277+
HamsterEcoHelper.instance.eco.withdraw(player, station.postingFee); // TODO system balance
278+
}
243279
entry.iconMaterial = Material.BOOK_AND_QUILL.name();
244280
HamsterEcoHelper.instance.database.query(QuestEntry.class).insert(entry);
245281
HandlerList.unregisterAll(this);

src/main/java/cat/nyaa/HamsterEcoHelper/utils/Utils.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import cat.nyaa.HamsterEcoHelper.HamsterEcoHelper;
44
import cat.nyaa.nyaacore.utils.InventoryUtils;
5+
import cat.nyaa.nyaacore.utils.ItemStackUtils;
56
import cat.nyaa.nyaacore.utils.ReflectionUtils;
67
import com.google.common.io.BaseEncoding;
78
import org.bukkit.Bukkit;
@@ -98,7 +99,7 @@ public static String getItemName(ItemStack item) {
9899
}
99100

100101
public static String encodeItemStack(ItemStack item) {
101-
byte[] nbt = ReflectionUtils.dumpRawNbt(item);
102+
byte[] nbt = ItemStackUtils.toBinaryNbt(item);
102103
byte[] compressedNbt = null;
103104
try {
104105
Deflater compresser = new Deflater();
@@ -135,7 +136,7 @@ public static ItemStack decodeItemStack(String item) {
135136
decompresser.end();
136137
bos.close();
137138
nbt = bos.toByteArray();
138-
return ReflectionUtils.loadItemStackFromNbt(nbt);
139+
return ItemStackUtils.fromBinaryNbt(nbt);
139140
} catch (DataFormatException | IOException ex) {
140141
throw new RuntimeException(ex);
141142
}

src/main/java/cat/nyaa/HamsterEcoHelper/utils/database/tables/quest/QuestEntry.java

+2
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ public enum QuestType {
4646
public Long singlePlayerClaimLimit = -1L; // how many time a single player can claim this quest, valid only if is recurrent quest
4747
@DataColumn
4848
public String iconMaterial = "";
49+
@DataColumn
50+
public Boolean masked = false;
4951

5052
public QuestType prerequisiteType = QuestType.NONE; // NONE, ITEM or MONEY
5153
public List<ItemStack> prerequisiteItems = new ArrayList<>();

src/main/java/cat/nyaa/HamsterEcoHelper/utils/database/tables/quest/QuestInstance.java

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ public enum QuestStatus {
1717

1818
COMPLETED,
1919
CANCELLED,
20+
REJECTED,
2021
TIMEOUT,
2122
INVALID;
2223
}

0 commit comments

Comments
 (0)