Created
June 14, 2015 15:03
-
-
Save aikar/06c42a2d7f72c18d5819 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.empireminecraft.systems.residence; | |
import com.empireminecraft.systems.residence.protection.ClaimedResidence; | |
@FunctionalInterface | |
public interface ResidenceTimer { | |
void onTick(ClaimedResidence res, String[] args, ResidenceTimerWrapper wrapper); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.empireminecraft.systems.residence; | |
import com.empireminecraft.systems.residence.protection.ClaimedResidence; | |
import com.empireminecraft.util.BukkitUtil; | |
import com.empireminecraft.util.RegexPatterns; | |
import com.empireminecraft.util.Util; | |
import com.google.common.collect.ArrayListMultimap; | |
import com.google.common.collect.Maps; | |
import com.google.common.collect.Multimap; | |
import org.bukkit.Bukkit; | |
import org.bukkit.Location; | |
import org.bukkit.entity.Item; | |
import org.bukkit.entity.Player; | |
import java.util.Collection; | |
import java.util.Iterator; | |
import java.util.Map; | |
public final class ResidenceTimerManager { | |
private static final Map<String, ResidenceTimer> timerMethods = Maps.newHashMap(); | |
private static final Multimap<Integer, ResidenceTimerWrapper> timers = ArrayListMultimap.create(); | |
private static int timerCounter = 0; | |
private ResidenceTimerManager() {} | |
public static void initialize() { | |
BukkitUtil.runTaskTimer(() -> { | |
final int bucketId = Bukkit.spigot().getTick() % 20; | |
final Collection<ResidenceTimerWrapper> timerBucket = timers.get(bucketId); | |
if (timerBucket != null && !timerBucket.isEmpty()) { | |
timerBucket.forEach(ResidenceTimerWrapper::tick); | |
} | |
}, 1); | |
registerTimers(); | |
} | |
private static void registerTimers() { | |
registerTimerMethod("cmd", (res, args, w) -> { | |
String cmd = Util.join(args); | |
cmd = Util.replaceStrings(cmd, | |
"%resname%", res.getName(), | |
"%resaddr%", res.getAddress().toString(), | |
"%resowner%", res.getOwner() | |
); | |
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), cmd); | |
}); | |
registerTimerMethod("teleport", (res, args, w) -> { | |
// Args: <sourceLocName1,sourceLocName2> <targetLocName> [radius=3] [all/items] | |
if (args.length < 2) { | |
Util.log("[timer:teleport] not enough args: " + res.getName()); | |
return; | |
} | |
String target = args[1]; | |
final Location targetLoc = res.getNamedLocations().get(target); | |
if (targetLoc == null) { | |
Util.log("[timer:teleport] Could not find targetLoc: " + res.getName()+":"+target); | |
return; | |
} | |
int radius = args.length > 2 ? Util.parseInt(args[2], 3) : 3; | |
boolean all = (args.length > 3 && "all".equals(args[3])); | |
boolean items = (args.length > 3 && "items".equals(args[3])); | |
final String[] sources = RegexPatterns.COMMA.split(args[0]); | |
for (String source : sources) { | |
final Location center = res.getNamedLocations().get(source); | |
if (center == null) { | |
Util.log("[timer:teleport] Could not find sourceLoc: " + res.getName()+":"+source); | |
continue; | |
} | |
if (!center.isChunkLoaded()) { | |
continue; | |
} | |
center.getWorld() | |
.getNearbyEntities(center, radius, radius, radius) | |
.stream().filter(entity -> all | |
|| (items && entity instanceof Item) | |
|| (!items && entity instanceof Player)) | |
.forEach(entity -> entity.teleport(targetLoc)); | |
} | |
}); | |
} | |
public static boolean isValidTimer(String name) { | |
name = RegexPatterns.COLON.split(name.toLowerCase())[0]; | |
return timerMethods.containsKey(name); | |
} | |
public static void registerTimerMethod(String name, ResidenceTimer timer) { | |
name = name.toLowerCase(); | |
timerMethods.put(name, timer); | |
} | |
public static void registerResidenceTimer(ClaimedResidence res, String name, int interval, String[] args) { | |
int base = interval % 20; | |
removeResidenceTimer(res, name); | |
name = name.toLowerCase(); | |
String timerName = RegexPatterns.COLON.split(name)[0]; | |
ResidenceTimer timer = timerMethods.get(timerName); | |
if (timer == null) { | |
Util.logSevere("Attempted to register invalid timer: " + name); | |
return; | |
} | |
// Offset will make it so every timer at say interval 10 | |
// doesn't all run on the same tick | |
int offset = timerCounter++ % 20; | |
ResidenceTimerWrapper wrapper = new ResidenceTimerWrapper(timer, res, name, args, interval); | |
for (int i = 0; i < 20; i++) { | |
// If Interval = 25, base = 5, only schedule on bucket 5. If <= 20, schedule for | |
// Every valid bucket the event runs in. For > 20, it'll run more often than | |
// Needed, but the ::tick method will enforce tick interval rate. | |
if ((interval <= 20 && i % base == 0) || (interval > 20 && i == base)) { | |
final int bucketKey = (i + offset) % 20; | |
timers.put(bucketKey, wrapper); | |
} | |
} | |
} | |
public static boolean removeResidenceTimer(ClaimedResidence residence, String name) { | |
boolean found = false; | |
final Iterator<ResidenceTimerWrapper> iterator = timers.values().iterator(); | |
while (iterator.hasNext()) { | |
final ResidenceTimerWrapper w = iterator.next(); | |
if (w.getRes() == residence && w.getName().equals(name.toLowerCase())) { | |
iterator.remove(); | |
found = true; | |
} | |
} | |
return found; | |
} | |
public static void loadResidence(ClaimedResidence res) { | |
res.getPersistentMeta().entrySet().forEach(e -> { | |
if (e.getKey().startsWith("timer_")) { | |
String timerName = e.getKey().substring(6); | |
final String[] split = RegexPatterns.COLON.split(e.getValue(), 2); | |
Integer interval = Util.parseInt(split[0]); | |
if (interval == null) { | |
return; | |
} | |
String[] args = split.length > 1 ? RegexPatterns.SPACE.split(split[1]) : new String[0]; | |
registerResidenceTimer(res, timerName, interval, args); | |
} | |
}); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.empireminecraft.systems.residence; | |
import com.empireminecraft.config.meta.PersistentMetaKey; | |
import com.empireminecraft.systems.residence.protection.ClaimedResidence; | |
import lombok.Data; | |
import lombok.NonNull; | |
import org.bukkit.Bukkit; | |
@Data | |
public class ResidenceTimerWrapper { | |
private final ResidenceTimer timer; | |
private final ClaimedResidence res; | |
private final String name; | |
private final String[] args; | |
private final int timerRate; | |
private int lastTick = Bukkit.spigot().getTick(); | |
ResidenceTimerWrapper(@NonNull ResidenceTimer timer, @NonNull ClaimedResidence res, | |
@NonNull String name, String[] args, int timerRate) { | |
this.timer = timer; | |
this.res = res; | |
this.name = name; | |
this.args = args; | |
this.timerRate = timerRate; | |
} | |
public void tick() { | |
int tick = Bukkit.spigot().getTick(); | |
if (tick - lastTick >= timerRate) { | |
lastTick += timerRate; | |
if (!res.hasPlayers() && res.hasPersistentMeta(PersistentMetaKey.RES_TIMER_REQUIRE_PLAYER+name)) { | |
return; | |
} | |
timer.onTick(res, args, this); | |
} | |
} | |
public void delay(int ticks) { | |
lastTick += ticks; | |
} | |
public void cancel() { | |
ResidenceTimerManager.removeResidenceTimer(res, name); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment