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

Commit 7039223

Browse files
committed
Implement renewables
1 parent 1118867 commit 7039223

File tree

5 files changed

+368
-2
lines changed

5 files changed

+368
-2
lines changed

src/main/java/in/twizmwaz/cardinal/module/ModuleFactory.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
import in.twizmwaz.cardinal.module.modules.rage.RageBuilder;
6161
import in.twizmwaz.cardinal.module.modules.rank.RankModuleBuilder;
6262
import in.twizmwaz.cardinal.module.modules.regions.RegionModuleBuilder;
63+
import in.twizmwaz.cardinal.module.modules.renewables.RenewablesBuilder;
6364
import in.twizmwaz.cardinal.module.modules.respawn.RespawnModuleBuilder;
6465
import in.twizmwaz.cardinal.module.modules.score.ScoreModuleBuilder;
6566
import in.twizmwaz.cardinal.module.modules.scoreboard.ScoreboardModuleBuilder;
@@ -191,7 +192,8 @@ private void addBuilders() {
191192
StatsBuilder.class,
192193
FallingBlocksBuilder.class,
193194
SpectatorToolsBuilder.class,
194-
ArrowModuleBuilder.class
195+
ArrowModuleBuilder.class,
196+
RenewablesBuilder.class
195197
));
196198
}
197199

src/main/java/in/twizmwaz/cardinal/module/modules/filter/type/BlockFilter.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import in.twizmwaz.cardinal.module.modules.filter.parsers.BlockFilterParser;
66
import org.bukkit.Material;
77
import org.bukkit.block.Block;
8+
import org.bukkit.material.MaterialData;
89

910
import static in.twizmwaz.cardinal.module.modules.filter.FilterState.ABSTAIN;
1011
import static in.twizmwaz.cardinal.module.modules.filter.FilterState.ALLOW;
@@ -23,7 +24,6 @@ public BlockFilter(final BlockFilterParser parser) {
2324

2425
@Override
2526
public FilterState evaluate(final Object... objects) {
26-
2727
for (Object object : objects) {
2828
if (object instanceof Block) {
2929
if (((Block) object).getType().equals(material) && (damageValue == -1 || (int) ((Block) object).getState().getData().getData() == damageValue))
@@ -33,6 +33,10 @@ public FilterState evaluate(final Object... objects) {
3333
if ((object).equals(material))
3434
return ALLOW;
3535
else return DENY;
36+
} else if (object instanceof MaterialData) {
37+
if (((MaterialData) object).getItemType().equals(material) && (damageValue == -1 || (int) ((MaterialData) object).getData() == damageValue))
38+
return ALLOW;
39+
else return DENY;
3640
}
3741
}
3842
return (getParent() == null ? ABSTAIN : getParent().evaluate(objects));
Lines changed: 284 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,284 @@
1+
package in.twizmwaz.cardinal.module.modules.renewables;
2+
3+
import com.google.common.collect.Lists;
4+
import in.twizmwaz.cardinal.Cardinal;
5+
import in.twizmwaz.cardinal.GameHandler;
6+
import in.twizmwaz.cardinal.event.MatchEndEvent;
7+
import in.twizmwaz.cardinal.module.TaskedModule;
8+
import in.twizmwaz.cardinal.module.modules.filter.FilterModule;
9+
import in.twizmwaz.cardinal.module.modules.filter.FilterState;
10+
import in.twizmwaz.cardinal.module.modules.regions.RegionModule;
11+
import in.twizmwaz.cardinal.module.modules.team.TeamModule;
12+
import in.twizmwaz.cardinal.util.PacketUtils;
13+
import in.twizmwaz.cardinal.util.Teams;
14+
import net.minecraft.server.BlockPosition;
15+
import net.minecraft.server.PacketPlayOutWorldEvent;
16+
import net.minecraft.server.SoundCategory;
17+
import net.minecraft.server.SoundEffectType;
18+
import net.minecraft.server.World;
19+
import org.bukkit.Bukkit;
20+
import org.bukkit.Material;
21+
import org.bukkit.block.Block;
22+
import org.bukkit.block.BlockFace;
23+
import org.bukkit.craftbukkit.CraftWorld;
24+
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
25+
import org.bukkit.entity.Player;
26+
import org.bukkit.event.EventHandler;
27+
import org.bukkit.event.EventPriority;
28+
import org.bukkit.event.HandlerList;
29+
import org.bukkit.event.block.BlockBreakEvent;
30+
import org.bukkit.event.block.BlockPlaceEvent;
31+
import org.bukkit.event.entity.EntityExplodeEvent;
32+
import org.bukkit.event.player.PlayerBucketEmptyEvent;
33+
import org.bukkit.event.player.PlayerBucketFillEvent;
34+
import org.bukkit.material.MaterialData;
35+
import org.bukkit.util.BlockVector;
36+
import org.bukkit.util.Vector;
37+
38+
import java.util.HashMap;
39+
import java.util.List;
40+
import java.util.Map;
41+
import java.util.Random;
42+
43+
public class Renewable implements TaskedModule {
44+
45+
private RegionModule region;
46+
private FilterModule renewFilter;
47+
private FilterModule replaceFilter;
48+
private FilterModule shuffleFilter;
49+
private RenewMode mode;
50+
private double ratePerTick;
51+
private double intervalChance;
52+
private boolean grow;
53+
private boolean particles;
54+
private boolean sound;
55+
private int avoidPlayers;
56+
57+
private Random random = new Random();
58+
private double renewals;
59+
60+
private Map<BlockVector, MaterialData> blocks = new HashMap<>();
61+
private List<BlockVector> toRenew = Lists.newArrayList();
62+
private List<Integer> tasks = Lists.newArrayList();
63+
64+
private static BlockFace[] faces = {BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST, BlockFace.WEST, BlockFace.UP, BlockFace.DOWN};
65+
66+
Renewable(RegionModule region,
67+
FilterModule renewFilter,
68+
FilterModule replaceFilter,
69+
FilterModule shuffleFilter,
70+
double rate,
71+
double interval,
72+
boolean grow,
73+
boolean particles,
74+
boolean sound,
75+
int avoidPlayers) {
76+
this.region = region;
77+
this.renewFilter = renewFilter;
78+
this.replaceFilter = replaceFilter;
79+
this.shuffleFilter = shuffleFilter;
80+
this.mode = interval < 0 ? RenewMode.RATE : RenewMode.INTERVAL;
81+
this.intervalChance = 0.1 / interval;
82+
this.ratePerTick = rate / 20;
83+
this.grow = grow;
84+
this.particles = particles;
85+
this.sound = sound;
86+
this.avoidPlayers = avoidPlayers * avoidPlayers;
87+
}
88+
89+
@Override
90+
public void unload() {
91+
HandlerList.unregisterAll(this);
92+
}
93+
94+
@Override
95+
public void run() {
96+
if (GameHandler.getGameHandler().getMatch().isRunning() && mode.equals(RenewMode.RATE)) {
97+
renewals += ratePerTick;
98+
99+
int fails = 0, maxFails = 5 + (toRenew.size() / 4);
100+
101+
while(fails < maxFails && toRenew.size() > 0 && renewals > 1) {
102+
BlockVector loc = toRenew.get(random.nextInt(toRenew.size()));
103+
104+
Boolean renew = attemptRenew(loc);
105+
if (renew != null) {
106+
if (renew) renewals--;
107+
else fails++;
108+
}
109+
110+
}
111+
if (renewals > 1) renewals -= (int) renewals;
112+
}
113+
}
114+
115+
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
116+
public void onBlockBreak(BlockBreakEvent event) {
117+
editedBlock(event.getBlock().getLocation(), event.getBlock().getState().getMaterialData());
118+
}
119+
120+
121+
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
122+
public void onBlockPlace(BlockPlaceEvent event) {
123+
editedBlock(event.getBlock().getLocation(), event.getBlockReplacedState().getMaterialData());
124+
}
125+
126+
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
127+
public void onBucketFill(PlayerBucketFillEvent event) {
128+
editedBlock(event.getBlockClicked().getLocation(), event.getBlockClicked().getState().getMaterialData());
129+
}
130+
131+
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
132+
public void onBucketEmpty(PlayerBucketEmptyEvent event) {
133+
Block relative = event.getBlockClicked().getRelative(event.getBlockFace());
134+
editedBlock(relative.getLocation(), relative.getState().getMaterialData());
135+
}
136+
137+
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
138+
public void onBlockBlow(EntityExplodeEvent event) {
139+
for (Block block : event.blockList()) {
140+
editedBlock(block.getLocation(), block.getState().getMaterialData());
141+
}
142+
}
143+
144+
@EventHandler
145+
public void onMatchEnd(MatchEndEvent event) {
146+
for (int id : tasks) {
147+
Bukkit.getScheduler().cancelTask(id);
148+
}
149+
tasks.clear();
150+
}
151+
152+
public void stopTask(int id) {
153+
Bukkit.getScheduler().cancelTask(id);
154+
tasks.remove((Integer) id);
155+
}
156+
157+
private void editedBlock(Vector loc, MaterialData save) {
158+
if (isInRegion(loc)) {
159+
BlockVector block = loc.toBlockVector();
160+
if (!blocks.containsKey(block)) {
161+
blocks.put(block, save);
162+
}
163+
if (!toRenew.contains(block) && renewFilter.evaluate(save).equals(FilterState.ALLOW)) {
164+
toRenew.add(block);
165+
if (mode.equals(RenewMode.INTERVAL)) {
166+
RenewRunnable renewRunnable = new RenewRunnable(this, block);
167+
int taskId = Bukkit.getScheduler().scheduleSyncRepeatingTask(Cardinal.getInstance(), renewRunnable, 0L, 1L);
168+
renewRunnable.setTask(taskId);
169+
tasks.add(taskId);
170+
}
171+
}
172+
}
173+
}
174+
175+
public Boolean attemptRenew(BlockVector loc) {
176+
Block block = loc.toLocation(GameHandler.getGameHandler().getMatchWorld()).getBlock();
177+
178+
if (isRenewed(block)) {
179+
toRenew.remove(loc);
180+
return null;
181+
} else if (canRenew(block)) {
182+
resetBlock(block);
183+
toRenew.remove(loc);
184+
return true;
185+
} else {
186+
return false;
187+
}
188+
}
189+
190+
private void resetBlock(Block block) {
191+
MaterialData original = blocks.get(block.getLocation().toBlockVector());
192+
193+
block.setTypeIdAndData(original.getItemTypeId(), original.getData(), true);
194+
195+
World nmsWorld = ((CraftWorld) GameHandler.getGameHandler().getMatchWorld()).getHandle();
196+
if (sound) {
197+
SoundEffectType sound = CraftMagicNumbers.getBlock(original.getItemType()).getSoundEffects();
198+
nmsWorld.playSoundEffect(null, block.getX(), block.getY(), block.getZ(), sound.breakSound(), SoundCategory.BLOCKS, sound.b(), sound.a());
199+
}
200+
if (particles) {
201+
Vector loc = block.getLocation().add(0.5, 0.5, 0.5);
202+
PacketPlayOutWorldEvent packet = new PacketPlayOutWorldEvent(2001, new BlockPosition(loc.getX(), loc.getY(), loc.getZ()), original.getItemTypeId(), false);
203+
PacketUtils.broadcastPacket(packet);
204+
}
205+
}
206+
207+
private boolean hasAdjacentBlocks(Block block) {
208+
for (BlockFace face : faces) {
209+
Block relative = block.getRelative(face);
210+
if (!relative.getType().equals(Material.AIR) && isRenewed(relative)) return true;
211+
}
212+
return false;
213+
}
214+
215+
private boolean isRenewed(Block block) {
216+
if (!isInRegion(block.getLocation())) return false;
217+
BlockVector loc = block.getLocation().toBlockVector();
218+
if (!blocks.containsKey(loc)) {
219+
return true;
220+
} else if (shuffleFilter.evaluate(blocks.get(loc)).equals(FilterState.ALLOW)) {
221+
return shuffleFilter.evaluate(block).equals(FilterState.ALLOW);
222+
} else {
223+
return blocks.get(loc).equals(block.getState().getMaterialData());
224+
}
225+
}
226+
227+
public boolean canRenew(Block block) {
228+
BlockVector pos = block.getLocation().toVector().toBlockVector();
229+
230+
if(isInRegion(pos) && blocks.containsKey(pos) && !blocks.get(pos).getItemType().equals(Material.AIR)
231+
&& replaceFilter.evaluate(block).equals(FilterState.ALLOW) && (!grow || hasAdjacentBlocks(block))) {
232+
if (avoidPlayers != 0) {
233+
for (TeamModule team : Teams.getTeams()) {
234+
if (team.isObserver()) continue;
235+
for (Player player : (List<Player>) team) {
236+
if (player.getLocation().plus(0, 0.5, 0).distanceSquared(block.getLocation().plus(0.5, 0.5, 0.5)) < avoidPlayers) {
237+
return false;
238+
}
239+
}
240+
}
241+
}
242+
return true;
243+
}
244+
return false;
245+
}
246+
247+
private boolean isInRegion(Vector pos) {
248+
Vector vec = new Vector(pos.getBlockX() + 0.5, pos.getBlockY() + 0.5, pos.getBlockZ() + 0.5);
249+
return region.contains(vec);
250+
}
251+
252+
enum RenewMode {
253+
RATE(),
254+
INTERVAL();
255+
}
256+
257+
private class RenewRunnable implements Runnable {
258+
259+
private Renewable renewable;
260+
private BlockVector toRenew;
261+
private int taskId;
262+
263+
public RenewRunnable(Renewable renewable, BlockVector block) {
264+
this.renewable = renewable;
265+
this.toRenew = block;
266+
}
267+
268+
public void setTask(int taskId) {
269+
this.taskId = taskId;
270+
}
271+
272+
@Override
273+
public void run() {
274+
if (Math.random() <= renewable.intervalChance) {
275+
Boolean renew = renewable.attemptRenew(toRenew);
276+
if (renew == null || renew) {
277+
renewable.stopTask(taskId);
278+
}
279+
}
280+
}
281+
282+
}
283+
284+
}

0 commit comments

Comments
 (0)