This repository was archived by the owner on Nov 25, 2019. It is now read-only.
forked from OvercastNetwork/ProjectAres
-
Notifications
You must be signed in to change notification settings - Fork 13
Expand file tree
/
Copy pathWoolMatchModule.java
More file actions
224 lines (197 loc) · 9.49 KB
/
WoolMatchModule.java
File metadata and controls
224 lines (197 loc) · 9.49 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
package tc.oc.pgm.wool;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.inject.Inject;
import com.google.common.collect.ImmutableList;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.TranslatableComponent;
import org.bukkit.ChatColor;
import org.bukkit.DyeColor;
import org.bukkit.Material;
import org.bukkit.block.BlockState;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.inventory.InventoryMoveItemEvent;
import org.bukkit.event.inventory.InventoryOpenEvent;
import org.bukkit.event.inventory.PrepareItemCraftEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack;
import org.bukkit.util.Vector;
import tc.oc.commons.bukkit.util.BlockUtils;
import tc.oc.commons.bukkit.util.BukkitUtils;
import tc.oc.commons.core.stream.Collectors;
import tc.oc.time.Time;
import tc.oc.pgm.Config;
import tc.oc.pgm.PGMTranslations;
import tc.oc.pgm.events.BlockTransformEvent;
import tc.oc.pgm.events.ListenerScope;
import tc.oc.pgm.events.ParticipantBlockTransformEvent;
import tc.oc.pgm.goals.Contribution;
import tc.oc.pgm.goals.events.GoalCompleteEvent;
import tc.oc.pgm.goals.events.GoalStatusChangeEvent;
import tc.oc.pgm.match.Match;
import tc.oc.pgm.match.MatchModule;
import tc.oc.pgm.match.MatchPlayer;
import tc.oc.pgm.match.MatchScope;
import tc.oc.pgm.match.ParticipantState;
import tc.oc.pgm.match.Repeatable;
@ListenerScope(MatchScope.RUNNING)
public class WoolMatchModule extends MatchModule implements Listener {
private final List<MonumentWool> wools;
// Map of containers to a flag indicating whether they contained objective wool when the match started.
// For this to work, containers have to be checked for wool before their contents can be changed. To ensure this,
// containers are registered in this map the first time they are opened or accessed by a hopper or dispenser.
protected final Map<Inventory, Boolean> chests = new HashMap<>();
// Containers that did contain wool when the match started have an entry in this map representing the exact
// layout of the wools in the inventory. This is used to refill the container with wools.
protected final Map<Inventory, Map<Integer, ItemStack>> woolChests = new HashMap<>();
@Inject private WoolMatchModule(Match match, List<MonumentWoolFactory> wools) {
this.wools = wools.stream()
.map(def -> def.getGoal(match))
.collect(Collectors.toImmutableList());
}
public boolean isObjectiveWool(ItemStack stack) {
if(stack.getType() == Material.WOOL) {
for(MonumentWool wool : this.wools) {
if(wool.getDefinition().isObjectiveWool(stack)) return true;
}
}
return false;
}
private boolean containsObjectiveWool(Inventory inventory) {
for(MonumentWool wool : this.wools) {
if(wool.getDefinition().isHolding(inventory)) return true;
}
return false;
}
private void registerContainer(Inventory inv) {
// When a chest (or other block inventory) is accessed, check if it's a wool chest
Boolean isWoolChest = this.chests.get(inv);
if(isWoolChest == null) {
// If we haven't seen this chest yet, check it for wool
isWoolChest = this.containsObjectiveWool(inv);
this.chests.put(inv, isWoolChest);
if(isWoolChest) {
// If it is a wool chest, take a snapshot of the wools
Map<Integer, ItemStack> contents = new HashMap<>();
this.woolChests.put(inv, contents);
for(int slot = 0; slot < inv.getSize(); ++slot) {
ItemStack stack = inv.getItem(slot);
if(stack != null && this.isObjectiveWool(stack)) {
contents.put(slot, stack.clone());
}
}
}
}
}
@Repeatable(interval = @Time(seconds = 30), scope = MatchScope.RUNNING)
public void refillOneWoolPerContainer() {
if(!Config.Wool.autoRefillWoolChests()) return;
for(Entry<Inventory, Map<Integer, ItemStack>> chest : this.woolChests.entrySet()) {
Inventory inv = chest.getKey();
for(Entry<Integer, ItemStack> slotEntry : chest.getValue().entrySet()) {
int slot = slotEntry.getKey();
ItemStack wool = slotEntry.getValue();
ItemStack stack = inv.getItem(slotEntry.getKey());
if(stack == null) {
stack = wool.clone();
stack.setAmount(1);
inv.setItem(slot, stack);
break;
} else if(stack.isSimilar(wool) && stack.getAmount() < wool.getAmount()) {
stack.setAmount(stack.getAmount() + 1);
inv.setItem(slot, stack);
break;
}
}
}
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onInventoryOpen(InventoryOpenEvent event) {
// Register container blocks when they are opened
this.registerContainer(event.getInventory());
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onItemTransfer(InventoryMoveItemEvent event) {
// When a hopper or dispenser transfers an item, register both blocks involved
this.registerContainer(event.getSource());
this.registerContainer(event.getDestination());
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onContainerPlace(BlockPlaceEvent event) {
// Blacklist any placed container blocks
if(event.getBlock().getState() instanceof InventoryHolder) {
this.chests.put(((InventoryHolder) event.getBlock().getState()).getInventory(), false);
}
}
@EventHandler(priority = EventPriority.MONITOR)
public void placementCheck(final BlockTransformEvent event) {
if(this.match.getWorld() != event.getWorld()) return;
final MonumentWool wool = this.findMonumentWool(BlockUtils.center(event.getNewState()).toVector());
if(wool == null) return;
if(event.getNewState().getType() == Material.AIR) { // block is being destroyed
if(isValidWool(wool.getDyeColor(), event.getOldState())) {
event.setCancelled(true);
}
return;
}
// default to cancelled; only uncancel if player is placing the correct color wool (see below)
event.setCancelled(true);
ParticipantState player = ParticipantBlockTransformEvent.getPlayerState(event);
if(player != null) { // wool can only be placed by a player
BaseComponent woolName = BukkitUtils.woolName(wool.getDyeColor());
if(!isValidWool(wool.getDyeColor(), event.getNewState())) {
player.sendWarning(new TranslatableComponent("match.wool.placeWrong", woolName), true);
} else if(wool.getOwner() != player.getParty()) {
player.sendWarning(new TranslatableComponent("match.wool.placeOther", wool.getOwner().getComponentName(), woolName), true);
} else {
event.setCancelled(false);
wool.markPlaced();
this.match.callEvent(new GoalStatusChangeEvent(wool));
this.match.callEvent(new PlayerWoolPlaceEvent(player, wool, event.getNewState()));
this.match.callEvent(new GoalCompleteEvent(wool,
true,
c -> false,
c -> c.equals(wool.getOwner()),
ImmutableList.of(new Contribution(player, 1))));
}
}
}
@EventHandler
public void handleWoolCrafting(PrepareItemCraftEvent event) {
if(event.getRecipe() == null) return;
ItemStack result = event.getRecipe().getResult();
InventoryHolder holder = event.getInventory().getHolder();
if (holder instanceof Player) {
MatchPlayer playerHolder = this.match.getPlayer((Player) holder);
if (playerHolder != null && result != null && result.getType() == Material.WOOL) {
for(MonumentWool wool : this.wools) {
if(wool.getDefinition().isObjectiveWool(result)) {
if(!wool.getDefinition().isCraftable()) {
playerHolder.sendMessage(ChatColor.RED + PGMTranslations.t("match.wool.craftDisabled", playerHolder, BukkitUtils.woolMessage(wool.getDyeColor())));
event.getInventory().setResult(null);
}
}
}
}
}
}
private MonumentWool findMonumentWool(Vector point) {
for(MonumentWool wool : this.wools) {
if(wool.getDefinition().getPlacementRegion().contains(point)) {
return wool;
}
}
return null;
}
@SuppressWarnings("deprecation")
private static boolean isValidWool(DyeColor expectedColor, BlockState state) {
return state.getType() == Material.WOOL && expectedColor.getWoolData() == state.getRawData();
}
}