├── .travis.yml ├── src ├── main │ ├── resources │ │ ├── autoreferee.properties │ │ ├── config.yml │ │ ├── map.xml │ │ ├── webstats │ │ │ ├── report.css │ │ │ ├── report.js │ │ │ └── report.htm │ │ ├── examples │ │ │ ├── default.xml │ │ │ └── kits.xml │ │ ├── plugin.yml │ │ └── colors.csv │ └── java │ │ └── org │ │ └── mctourney │ │ └── autoreferee │ │ ├── util │ │ ├── commands │ │ │ ├── CommandHandler.java │ │ │ ├── CommandPermissionException.java │ │ │ ├── CommandRegistrationException.java │ │ │ ├── AutoRefPermission.java │ │ │ ├── AutoRefCommand.java │ │ │ └── CommandDocumentationGenerator.java │ │ ├── Metadatable.java │ │ ├── NullChunkGenerator.java │ │ ├── metrics │ │ │ ├── IncrementPlotter.java │ │ │ └── PieChartGraph.java │ │ ├── worldsearch │ │ │ ├── CallableGetSnapshots.java │ │ │ ├── ObjectiveExhaustion.java │ │ │ ├── _Entry.java │ │ │ ├── WorkerValidateResults.java │ │ │ ├── Unsafe_InspectVillagerTrades.java │ │ │ ├── WorkerContainerSearch.java │ │ │ ├── WorkerAsyncSearchSnapshots.java │ │ │ ├── WorkerEntitySearch.java │ │ │ └── ObjectiveExhaustionMasterTask.java │ │ ├── midi │ │ │ ├── ToneUtil.java │ │ │ ├── NoteBlockReceiver.java │ │ │ └── MidiUtil.java │ │ ├── LocationUtil.java │ │ ├── ArmorPoints.java │ │ ├── BookUtil.java │ │ ├── MapImageGenerator.java │ │ ├── QueryUtil.java │ │ ├── SportBukkitUtil.java │ │ ├── AchievementPoints.java │ │ ├── TeleportationUtil.java │ │ ├── ColorConverter.java │ │ ├── BlockData.java │ │ └── PlayerUtil.java │ │ ├── AutoRefereeTools.java │ │ ├── listeners │ │ ├── lobby │ │ │ ├── ClassicLobbyListener.java │ │ │ ├── AutoLobbyListener.java │ │ │ └── RotationLobbyListener.java │ │ ├── GoalsInventorySnapshot.java │ │ ├── WorldListener.java │ │ └── TeamListener.java │ │ ├── event │ │ ├── team │ │ │ ├── ObjectiveEvent.java │ │ │ └── ObjectiveUpdateEvent.java │ │ ├── match │ │ │ ├── MatchLoadEvent.java │ │ │ ├── MatchEvent.java │ │ │ ├── MatchTranscriptEvent.java │ │ │ ├── MatchStartEvent.java │ │ │ ├── MatchUnloadEvent.java │ │ │ ├── MatchUploadStatsEvent.java │ │ │ └── MatchCompleteEvent.java │ │ └── player │ │ │ ├── PlayerMatchEvent.java │ │ │ ├── PlayerTeamEvent.java │ │ │ ├── PlayerTeamLeaveEvent.java │ │ │ ├── PlayerMatchJoinEvent.java │ │ │ ├── PlayerMatchLeaveEvent.java │ │ │ └── PlayerTeamJoinEvent.java │ │ ├── goals │ │ ├── ScoreGoal.java │ │ ├── scoreboard │ │ │ ├── SurvivalObjective.java │ │ │ ├── ScoreObjective.java │ │ │ ├── BlockObjective.java │ │ │ └── AutoRefObjective.java │ │ ├── ScoreDeathmatchGoal.java │ │ ├── ScoreDummyGoal.java │ │ ├── SurvivalGoal.java │ │ ├── TimeGoal.java │ │ ├── CoreGoal.java │ │ ├── ScoreRegionGoal.java │ │ ├── AutoRefGoal.java │ │ └── BlockGoal.java │ │ ├── regions │ │ ├── PointRegion.java │ │ ├── CylinderRegion.java │ │ └── CuboidRegion.java │ │ └── AutoRefSpectator.java └── test │ └── java │ └── org │ └── mctourney │ └── autoreferee │ ├── RegionFlagCoverageTest.java │ ├── FindPlayerTest.java │ └── util │ └── ColorConverterTest.java ├── .gitignore ├── mapsync.sh ├── generate-colors.py ├── README.md └── pom.xml /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | 3 | jdk: 4 | - openjdk6 5 | -------------------------------------------------------------------------------- /src/main/resources/autoreferee.properties: -------------------------------------------------------------------------------- 1 | git-sha-1=${buildNumber} 2 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/util/commands/CommandHandler.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.util.commands; 2 | 3 | public abstract interface CommandHandler 4 | { 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/util/Metadatable.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.util; 2 | 3 | public interface Metadatable 4 | { 5 | public void addMetadata(String key, Object metadata); 6 | 7 | public Object getMetadata(String key); 8 | 9 | public boolean hasMetadata(String key); 10 | 11 | public Object removeMetadata(String key); 12 | 13 | public void clearMetadata(); 14 | } 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Eclipse 2 | /.classpath 3 | /.project 4 | /.settings 5 | 6 | # IntelliJ 7 | /.idea 8 | *.iml 9 | 10 | # we use maven! 11 | /build.xml 12 | 13 | # maven 14 | /target 15 | 16 | # vim 17 | .*.sw[a-p] 18 | *~ 19 | 20 | # AWS map repository 21 | /s3 22 | 23 | # various other potential build files 24 | /build 25 | /bin 26 | /dist 27 | /manifest.mf 28 | 29 | # Mac filesystem dust 30 | /.DS_Store 31 | -------------------------------------------------------------------------------- /mapsync.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | listfile=s3/maps/list.csv 4 | >$listfile 5 | 6 | echo "Generating $listfile" 7 | for zip in `ls s3/maps/*.zip` 8 | do 9 | file=`basename $zip` 10 | md5=`md5sum $zip | awk '{print $1}'` 11 | map=${file%%.zip} 12 | 13 | echo "Adding $map..." 14 | echo "${map/-v/;};$file;$md5" >> $listfile 15 | done 16 | 17 | s3cmd -P --delete-removed sync s3/maps s3://autoreferee/ 18 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/util/commands/CommandPermissionException.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.util.commands; 2 | 3 | import org.apache.commons.lang.StringUtils; 4 | 5 | public class CommandPermissionException extends RuntimeException 6 | { 7 | private static final long serialVersionUID = 1L; 8 | 9 | public CommandPermissionException(AutoRefCommand command, String reason) 10 | { super("Could not execute command '/" + StringUtils.join(command.name(), ' ') + "': " + reason); } 11 | } -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/AutoRefereeTools.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee; 2 | 3 | import java.io.File; 4 | 5 | import org.mctourney.autoreferee.util.commands.CommandDocumentationGenerator; 6 | 7 | public class AutoRefereeTools 8 | { 9 | public static void main(String[] args) 10 | { 11 | File docfile = new File("documentation.dat"); 12 | System.out.println("Generating documentation file: " + docfile.getAbsolutePath()); 13 | CommandDocumentationGenerator.generateDocumentationFile(docfile); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/util/NullChunkGenerator.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.util; 2 | 3 | import java.util.Random; 4 | 5 | import org.bukkit.World; 6 | import org.bukkit.generator.ChunkGenerator; 7 | 8 | public class NullChunkGenerator extends ChunkGenerator 9 | { 10 | private static final int WORLD_HEIGHT = 256; 11 | 12 | @Override 13 | public byte[][] generateBlockSections(World world, Random r, 14 | int x, int z, ChunkGenerator.BiomeGrid biomes) 15 | { return new byte[WORLD_HEIGHT / 16][]; } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/listeners/lobby/ClassicLobbyListener.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.listeners.lobby; 2 | 3 | import org.bukkit.entity.Player; 4 | 5 | import org.mctourney.autoreferee.AutoRefMap; 6 | import org.mctourney.autoreferee.AutoReferee; 7 | 8 | public class ClassicLobbyListener extends LobbyListener 9 | { 10 | public ClassicLobbyListener(AutoReferee plugin) 11 | { super(plugin); } 12 | 13 | @Override 14 | protected void lobbyLoadMap(Player player, AutoRefMap map) 15 | { _loadMap(player, map, null); } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/util/commands/CommandRegistrationException.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.util.commands; 2 | 3 | import java.lang.reflect.Method; 4 | 5 | public class CommandRegistrationException extends RuntimeException 6 | { 7 | private static final long serialVersionUID = 1L; 8 | 9 | public CommandRegistrationException(Method method, String reason) 10 | { 11 | super("Could not register the command method " + method.getName() + " in the class " + 12 | method.getDeclaringClass().getName() + ": " + reason); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/event/team/ObjectiveEvent.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.event.team; 2 | 3 | import org.bukkit.event.Event; 4 | 5 | import org.mctourney.autoreferee.goals.AutoRefGoal; 6 | 7 | public abstract class ObjectiveEvent extends Event 8 | { 9 | private AutoRefGoal goal; 10 | 11 | public ObjectiveEvent(AutoRefGoal goal) 12 | { 13 | this.goal = goal; 14 | } 15 | 16 | public AutoRefGoal getGoal() 17 | { return this.goal; } 18 | 19 | public Class getGoalType() 20 | { return this.goal.getClass(); } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/event/team/ObjectiveUpdateEvent.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.event.team; 2 | 3 | import org.bukkit.event.HandlerList; 4 | 5 | import org.mctourney.autoreferee.goals.AutoRefGoal; 6 | 7 | public class ObjectiveUpdateEvent extends ObjectiveEvent 8 | { 9 | private static final HandlerList handlers = new HandlerList(); 10 | 11 | public ObjectiveUpdateEvent(AutoRefGoal goal) 12 | { 13 | super(goal); 14 | } 15 | 16 | @Override 17 | public HandlerList getHandlers() 18 | { return handlers; } 19 | 20 | public static HandlerList getHandlerList() 21 | { return handlers; } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/resources/config.yml: -------------------------------------------------------------------------------- 1 | # AutoReferee Configuration 2 | config-version: 2 3 | console-log: true 4 | console-colors: true 5 | auto-update: true 6 | 7 | allow-ties: false 8 | time-limit: 0 9 | 10 | delay-seconds: 11 | ready: 15 12 | completed: 180 13 | 14 | # all paths relative to the server-root 15 | local-storage: 16 | match-summary: 17 | directory: plugins/AutoReferee/summary 18 | local-database: plugins/AutoReferee/autoref.sdb 19 | 20 | config-mode: 21 | tools: 22 | win-condition: GOLD_SPADE 23 | start-mechanism: GOLD_AXE 24 | protect-entities: GOLD_SWORD 25 | 26 | lobby: 27 | world: autoref-lobby 28 | mode: manual 29 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/util/commands/AutoRefPermission.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.util.commands; 2 | 3 | import org.mctourney.autoreferee.AutoRefMatch.Role; 4 | 5 | @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) 6 | @java.lang.annotation.Target(java.lang.annotation.ElementType.METHOD) 7 | 8 | public @interface AutoRefPermission 9 | { 10 | // permissions nodes required 11 | public String[] nodes() default {}; 12 | 13 | // AutoReferee role required (this role or higher) 14 | public Role role() default Role.NONE; 15 | 16 | // can console send this command? 17 | public boolean console() default true; 18 | } 19 | -------------------------------------------------------------------------------- /src/main/resources/map.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Competitive Map 5 | 1.x 6 | 7 | 8 | Creator1 9 | Creator2 10 | 11 | 12 | 13 | 14 | 15 | Left 16 | 17 | 18 | 19 | Right 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 8am 30 | 31 | 32 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/event/match/MatchLoadEvent.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.event.match; 2 | 3 | import org.bukkit.event.HandlerList; 4 | 5 | import org.mctourney.autoreferee.AutoRefMatch; 6 | 7 | /** 8 | * Called when a new map is loaded. 9 | * 10 | * @author authorblues 11 | */ 12 | public class MatchLoadEvent extends MatchEvent 13 | { 14 | private static final HandlerList handlers = new HandlerList(); 15 | 16 | public MatchLoadEvent(AutoRefMatch match) 17 | { 18 | super(match); 19 | } 20 | 21 | @Override 22 | public HandlerList getHandlers() 23 | { return handlers; } 24 | 25 | public static HandlerList getHandlerList() 26 | { return handlers; } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/event/match/MatchEvent.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.event.match; 2 | 3 | import org.bukkit.event.world.WorldEvent; 4 | 5 | import org.mctourney.autoreferee.AutoRefMatch; 6 | 7 | /** 8 | * Represents an event related to an {@link org.mctourney.autoreferee.AutoRefMatch} 9 | * 10 | * @author authorblues 11 | */ 12 | public abstract class MatchEvent extends WorldEvent 13 | { 14 | protected AutoRefMatch match; 15 | 16 | public MatchEvent(AutoRefMatch match) 17 | { 18 | super(match.getWorld()); 19 | this.match = match; 20 | } 21 | 22 | /** 23 | * Gets the match for this event. 24 | * @return match 25 | */ 26 | public AutoRefMatch getMatch() 27 | { return match; } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/util/commands/AutoRefCommand.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.util.commands; 2 | 3 | @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) 4 | @java.lang.annotation.Target(java.lang.annotation.ElementType.METHOD) 5 | 6 | public @interface AutoRefCommand 7 | { 8 | // name of command 9 | public String[] name(); 10 | 11 | // command description 12 | public String usage() default ""; 13 | 14 | // command description 15 | public String description() default ""; 16 | 17 | // number of arguments 18 | public int argmin() default 0; 19 | public int argmax() default Integer.MAX_VALUE; 20 | 21 | // options 22 | public String options() default ""; 23 | public String[] opthelp() default {}; 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/event/player/PlayerMatchEvent.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.event.player; 2 | 3 | import org.bukkit.entity.Player; 4 | import org.bukkit.event.player.PlayerEvent; 5 | 6 | import org.mctourney.autoreferee.AutoRefMatch; 7 | 8 | /** 9 | * Represents an event related to an {@link org.mctourney.autoreferee.AutoRefMatch} 10 | * 11 | * @author authorblues 12 | */ 13 | public abstract class PlayerMatchEvent extends PlayerEvent 14 | { 15 | private AutoRefMatch match; 16 | 17 | public PlayerMatchEvent(Player player, AutoRefMatch match) 18 | { 19 | super(player); 20 | this.match = match; 21 | } 22 | 23 | /** 24 | * Gets the match for this event. 25 | * @return match 26 | */ 27 | public AutoRefMatch getMatch() 28 | { return this.match; } 29 | } 30 | -------------------------------------------------------------------------------- /src/test/java/org/mctourney/autoreferee/RegionFlagCoverageTest.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee; 2 | 3 | import java.util.Set; 4 | 5 | import org.junit.Assert; 6 | import org.junit.Test; 7 | 8 | import org.mctourney.autoreferee.regions.AutoRefRegion; 9 | 10 | import com.google.common.collect.Sets; 11 | 12 | public class RegionFlagCoverageTest 13 | { 14 | @Test 15 | public void test() 16 | { 17 | Set optionsGiven, optionsComputed; 18 | 19 | optionsGiven = Sets.newHashSet(); 20 | for (char c : AutoRefRegion.Flag.OPTIONS.toCharArray()) 21 | optionsGiven.add(c); 22 | 23 | optionsComputed = Sets.newHashSet(); 24 | for (AutoRefRegion.Flag flag : AutoRefRegion.Flag.values()) 25 | optionsComputed.add(flag.getMark()); 26 | 27 | Assert.assertEquals(optionsGiven, optionsComputed); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/util/metrics/IncrementPlotter.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.util.metrics; 2 | 3 | import org.mcstats.Metrics; 4 | 5 | /** 6 | * Represents an incremental tracker for discrete events. 7 | * 8 | * @author mbaxter 9 | */ 10 | public class IncrementPlotter extends Metrics.Plotter 11 | { 12 | private final String name; 13 | private int value, last; 14 | 15 | public IncrementPlotter(String name) 16 | { 17 | this.name = name; 18 | this.value = this.last = 0; 19 | } 20 | 21 | @Override 22 | public String getColumnName() 23 | { return this.name; } 24 | 25 | @Override 26 | public int getValue() 27 | { return this.last = this.value; } 28 | 29 | public void increment() 30 | { ++this.value; } 31 | 32 | @Override 33 | public void reset() 34 | { this.value -= this.last; } 35 | } -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/util/metrics/PieChartGraph.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.util.metrics; 2 | 3 | import java.util.Map; 4 | import java.util.Set; 5 | 6 | import org.mcstats.Metrics; 7 | 8 | import com.google.common.collect.Maps; 9 | 10 | public class PieChartGraph 11 | { 12 | private Map items; 13 | 14 | public PieChartGraph(Metrics.Graph graph, Set choices) 15 | { 16 | this.items = Maps.newHashMap(); 17 | for (String choice : choices) 18 | { 19 | IncrementPlotter plotter = new IncrementPlotter(choice); 20 | items.put(choice, plotter); graph.addPlotter(plotter); 21 | } 22 | 23 | IncrementPlotter other = new IncrementPlotter("Other"); 24 | items.put(null, other); graph.addPlotter(other); 25 | } 26 | 27 | public void increment(String choice) 28 | { items.get(items.containsKey(choice) ? choice : null).increment(); } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/util/worldsearch/CallableGetSnapshots.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.util.worldsearch; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.concurrent.Callable; 6 | 7 | import org.bukkit.ChunkSnapshot; 8 | import org.bukkit.World; 9 | import org.bukkit.util.Vector; 10 | 11 | public class CallableGetSnapshots implements Callable> 12 | { 13 | private List coords; 14 | private World world; 15 | 16 | public CallableGetSnapshots(List coords, World world) 17 | { 18 | this.coords = coords; 19 | this.world = world; 20 | } 21 | 22 | @Override 23 | public List call() throws Exception 24 | { 25 | List ret = new ArrayList(); 26 | for (Vector v : coords) 27 | ret.add(world.getChunkAt(v.getBlockX(), v.getBlockZ()).getChunkSnapshot()); 28 | return ret; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/event/player/PlayerTeamEvent.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.event.player; 2 | 3 | import org.bukkit.entity.Player; 4 | import org.bukkit.event.HandlerList; 5 | import org.bukkit.event.player.PlayerEvent; 6 | 7 | import org.mctourney.autoreferee.AutoRefTeam; 8 | 9 | /** 10 | * Represents an event related to an {@link org.mctourney.autoreferee.AutoRefTeam} 11 | * 12 | * @author authorblues 13 | */ 14 | public abstract class PlayerTeamEvent extends PlayerEvent 15 | { 16 | private static final HandlerList handlers = new HandlerList(); 17 | private AutoRefTeam team; 18 | 19 | public PlayerTeamEvent(Player player, AutoRefTeam team) 20 | { 21 | super(player); 22 | this.team = team; 23 | } 24 | 25 | /** 26 | * Gets the team for this event. 27 | * @return team 28 | */ 29 | public AutoRefTeam getTeam() 30 | { return this.team; } 31 | 32 | @Override 33 | public HandlerList getHandlers() 34 | { return handlers; } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/event/match/MatchTranscriptEvent.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.event.match; 2 | 3 | import org.bukkit.event.HandlerList; 4 | import org.mctourney.autoreferee.AutoRefMatch; 5 | 6 | public class MatchTranscriptEvent extends MatchEvent 7 | { 8 | private static final HandlerList handlers = new HandlerList(); 9 | private AutoRefMatch.TranscriptEvent transcriptEntry; 10 | 11 | public MatchTranscriptEvent(AutoRefMatch match, AutoRefMatch.TranscriptEvent transcriptEntry) 12 | { super(match); this.transcriptEntry = transcriptEntry; } 13 | 14 | public AutoRefMatch.TranscriptEvent getEntry() 15 | { return this.transcriptEntry; } 16 | 17 | public AutoRefMatch.TranscriptEvent.EventType getEntryType() 18 | { return this.transcriptEntry == null ? null : this.transcriptEntry.getType(); } 19 | 20 | @Override 21 | public HandlerList getHandlers() 22 | { return handlers; } 23 | 24 | public static HandlerList getHandlerList() 25 | { return handlers; } 26 | } 27 | -------------------------------------------------------------------------------- /generate-colors.py: -------------------------------------------------------------------------------- 1 | import urllib.request 2 | import re 3 | 4 | # these colors are borrowed from webbukkit/DynmapCore 5 | COLOR_FILE = 'https://raw.github.com/webbukkit/DynmapCore/master/src/main/resources/extracted/colorschemes/default.txt' 6 | 7 | def check(line): 8 | parts = line.split() 9 | return len(parts) and re.match('\d+(:\d+)?', parts[0]) 10 | 11 | with urllib.request.urlopen(COLOR_FILE) as u: 12 | lines = [line.split() for line in u.read().decode('utf8').splitlines() if check(line)] 13 | 14 | materials = dict() 15 | for line in lines: 16 | info, r, g, b, *rest = line 17 | parts = info.split(':') 18 | 19 | mat = int(parts[0]) 20 | if mat not in materials: 21 | materials[mat] = dict() 22 | 23 | data = int(parts[1]) if len(parts) > 1 else -1 24 | materials[mat][data] = (r, g, b) 25 | 26 | for mat in sorted(materials.keys()): 27 | if len(materials[mat]) > 1: 28 | del materials[mat][-1] 29 | for data in sorted(materials[mat].keys()): 30 | r, g, b = materials[mat][data] 31 | print("%d %d %s %s %s" % (mat, data, r, g, b)) 32 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/goals/ScoreGoal.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.goals; 2 | 3 | import org.jdom2.Element; 4 | 5 | import org.mctourney.autoreferee.AutoRefMatch; 6 | import org.mctourney.autoreferee.AutoRefTeam; 7 | 8 | public abstract class ScoreGoal extends AutoRefGoal 9 | { 10 | protected Double targetScore = null; 11 | 12 | public ScoreGoal(AutoRefTeam team) 13 | { 14 | super(team); 15 | } 16 | 17 | public void setTargetScore(Double target) 18 | { this.targetScore = target; } 19 | 20 | public Double getTargetScore() 21 | { return this.targetScore; } 22 | 23 | public boolean isSatisfied(AutoRefMatch match) 24 | { return targetScore != null && this.getScore(match) >= this.getTargetScore(); } 25 | 26 | @Override 27 | protected AutoRefGoal getGoalSettings(AutoRefTeam team, Element elt) 28 | { 29 | if (elt.getAttribute("target") != null) 30 | try { this.setTargetScore(Double.parseDouble(elt.getAttributeValue("target"))); } 31 | catch (NumberFormatException e) { e.printStackTrace(); } 32 | 33 | return super.getGoalSettings(team, elt); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/test/java/org/mctourney/autoreferee/FindPlayerTest.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee; 2 | 3 | import org.mctourney.autoreferee.AutoRefTeam; 4 | import org.mctourney.autoreferee.AutoRefPlayer; 5 | 6 | import org.junit.Test; 7 | import org.junit.Assert; 8 | 9 | public class FindPlayerTest 10 | { 11 | @Test 12 | public void testNameLookup() 13 | { 14 | AutoRefTeam team = new AutoRefTeam(); 15 | 16 | AutoRefPlayer p1 = new AutoRefPlayer("jcll" , null); 17 | AutoRefPlayer p2 = new AutoRefPlayer("nosrepa" , null); 18 | AutoRefPlayer p3 = new AutoRefPlayer("coestar" , null); 19 | AutoRefPlayer p4 = new AutoRefPlayer("dewtroid", null); 20 | AutoRefPlayer pX = new AutoRefPlayer("jcllpony", null); 21 | 22 | team.addPlayer(p1); 23 | team.addPlayer(p2); 24 | 25 | Assert.assertNull(team.getPlayer("c")); 26 | Assert.assertNull(team.getPlayer("jcp")); 27 | 28 | team.addPlayer(p3); 29 | team.addPlayer(p4); 30 | 31 | Assert.assertEquals(p1, team.getPlayer("jc")); 32 | Assert.assertEquals(p2, team.getPlayer("nos")); 33 | Assert.assertEquals(p3, team.getPlayer("c")); 34 | 35 | Assert.assertNull(team.getPlayer("dewtroid!")); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/goals/scoreboard/SurvivalObjective.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.goals.scoreboard; 2 | 3 | import java.util.Set; 4 | 5 | import org.bukkit.scoreboard.Objective; 6 | import org.mctourney.autoreferee.AutoRefMatch.RespawnMode; 7 | import org.mctourney.autoreferee.AutoRefTeam; 8 | import org.mctourney.autoreferee.goals.SurvivalGoal; 9 | 10 | import com.google.common.collect.Sets; 11 | 12 | public class SurvivalObjective extends AutoRefObjective 13 | { 14 | public SurvivalObjective(Objective objective, AutoRefTeam team) 15 | { 16 | super(objective, team, team.getName(), 0); 17 | this.update(); 18 | } 19 | 20 | @Override 21 | public void update() 22 | { 23 | this.setName(String.format("%s", this.team.getName())); 24 | this.setValue(this.team.getPlayers().size()); 25 | } 26 | 27 | public static Set fromTeam(Objective objective, AutoRefTeam team) 28 | { 29 | Set objectives = Sets.newHashSet(); 30 | 31 | if (team.getMatch().getRespawnMode() != RespawnMode.ALLOW && 32 | !team.getTeamGoals(SurvivalGoal.class).isEmpty()) 33 | objectives.add(new SurvivalObjective(objective, team)); 34 | 35 | return objectives; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/util/midi/ToneUtil.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.util.midi; 2 | 3 | import org.bukkit.Note; 4 | import org.bukkit.Note.Tone; 5 | 6 | import javax.sound.midi.ShortMessage; 7 | 8 | /** 9 | * Utility for converting between different representations of a tone. 10 | * 11 | * @author authorblues 12 | */ 13 | public class ToneUtil 14 | { 15 | private static final byte BASE_NOTE = new Note(1, Tone.F, true).getId(); 16 | 17 | private static final int MIDI_BASE_FSHARP = 54; 18 | 19 | public static double noteToPitch(Note note) 20 | { 21 | double semitones = note.getId() - BASE_NOTE; 22 | return Math.pow(2.0, semitones / 12.0); 23 | } 24 | 25 | // converts midi events into Note objects 26 | public static Note midiToNote(ShortMessage smsg) 27 | { 28 | assert smsg.getCommand() == ShortMessage.NOTE_ON; 29 | int semitones = smsg.getData1() - MIDI_BASE_FSHARP % 12; 30 | return new Note(semitones % 24); 31 | } 32 | 33 | // converts midi events into pitch 34 | public static double midiToPitch(ShortMessage smsg) 35 | { 36 | return noteToPitch(midiToNote(smsg)); 37 | 38 | // assert smsg.getCommand() == ShortMessage.NOTE_ON; 39 | // int semitones = smsg.getData1() - MIDI_BASE_FSHARP; 40 | // return Math.pow(2.0, semitones / 12.0); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/event/player/PlayerTeamLeaveEvent.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.event.player; 2 | 3 | import org.bukkit.entity.Player; 4 | import org.bukkit.event.Cancellable; 5 | import org.bukkit.event.HandlerList; 6 | 7 | import org.mctourney.autoreferee.AutoRefTeam; 8 | 9 | /** 10 | * Called when a player leaves a team. 11 | * 12 | * @author authorblues 13 | */ 14 | public class PlayerTeamLeaveEvent extends PlayerTeamEvent implements Cancellable 15 | { 16 | private static final HandlerList handlers = new HandlerList(); 17 | private boolean cancelled = false; 18 | 19 | public PlayerTeamLeaveEvent(Player player, AutoRefTeam team) 20 | { 21 | super(player, team); 22 | } 23 | 24 | /** 25 | * Checks the cancelled state of the event. 26 | * @return true if the event has been cancelled, false otherwise 27 | */ 28 | public boolean isCancelled() 29 | { return this.cancelled; } 30 | 31 | /** 32 | * Sets the cancelled state of the event. 33 | * @param cancel true to cancel the event, false to uncancel the event 34 | */ 35 | public void setCancelled(boolean cancel) 36 | { this.cancelled = cancel; } 37 | 38 | @Override 39 | public HandlerList getHandlers() 40 | { return handlers; } 41 | 42 | public static HandlerList getHandlerList() 43 | { return handlers; } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/event/player/PlayerMatchJoinEvent.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.event.player; 2 | 3 | import org.bukkit.entity.Player; 4 | import org.bukkit.event.Cancellable; 5 | import org.bukkit.event.HandlerList; 6 | 7 | import org.mctourney.autoreferee.AutoRefMatch; 8 | 9 | /** 10 | * Called when a player joins a match. 11 | * 12 | * @author authorblues 13 | */ 14 | public class PlayerMatchJoinEvent extends PlayerMatchEvent implements Cancellable 15 | { 16 | private static final HandlerList handlers = new HandlerList(); 17 | private boolean cancelled = false; 18 | 19 | public PlayerMatchJoinEvent(Player player, AutoRefMatch match) 20 | { 21 | super(player, match); 22 | } 23 | 24 | /** 25 | * Checks the cancelled state of the event. 26 | * @return true if the event has been cancelled, false otherwise 27 | */ 28 | public boolean isCancelled() 29 | { return this.cancelled; } 30 | 31 | /** 32 | * Sets the cancelled state of the event. 33 | * @param cancel true to cancel the event, false to uncancel the event 34 | */ 35 | public void setCancelled(boolean cancel) 36 | { this.cancelled = cancel; } 37 | 38 | @Override 39 | public HandlerList getHandlers() 40 | { return handlers; } 41 | 42 | public static HandlerList getHandlerList() 43 | { return handlers; } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/event/player/PlayerMatchLeaveEvent.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.event.player; 2 | 3 | import org.bukkit.entity.Player; 4 | import org.bukkit.event.Cancellable; 5 | import org.bukkit.event.HandlerList; 6 | 7 | import org.mctourney.autoreferee.AutoRefMatch; 8 | 9 | /** 10 | * Called when a player leaves a match. 11 | * 12 | * @author authorblues 13 | */ 14 | public class PlayerMatchLeaveEvent extends PlayerMatchEvent implements Cancellable 15 | { 16 | private static final HandlerList handlers = new HandlerList(); 17 | private boolean cancelled = false; 18 | 19 | public PlayerMatchLeaveEvent(Player player, AutoRefMatch match) 20 | { 21 | super(player, match); 22 | } 23 | 24 | /** 25 | * Checks the cancelled state of the event. 26 | * @return true if the event has been cancelled, false otherwise 27 | */ 28 | public boolean isCancelled() 29 | { return this.cancelled; } 30 | 31 | /** 32 | * Sets the cancelled state of the event. 33 | * @param cancel true to cancel the event, false to uncancel the event 34 | */ 35 | public void setCancelled(boolean cancel) 36 | { this.cancelled = cancel; } 37 | 38 | @Override 39 | public HandlerList getHandlers() 40 | { return handlers; } 41 | 42 | public static HandlerList getHandlerList() 43 | { return handlers; } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/util/worldsearch/ObjectiveExhaustion.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.util.worldsearch; 2 | 3 | import java.util.Set; 4 | 5 | import org.mctourney.autoreferee.AutoRefPlayer; 6 | import org.mctourney.autoreferee.AutoRefTeam; 7 | import org.mctourney.autoreferee.AutoReferee; 8 | import org.mctourney.autoreferee.goals.AutoRefGoal; 9 | import org.mctourney.autoreferee.goals.AutoRefGoal.ItemStatus; 10 | import org.mctourney.autoreferee.util.BlockData; 11 | 12 | import com.google.common.collect.Sets; 13 | 14 | public class ObjectiveExhaustion 15 | { 16 | public static Set startSearch(AutoRefTeam team, AutoReferee plugin) 17 | { 18 | Set goals = Sets.newHashSet(); 19 | 20 | for (AutoRefGoal goal : team.getTeamGoals()) 21 | { 22 | if (!goal.hasItem()) continue; 23 | ItemStatus is = goal.getItemStatus(); 24 | if (is == ItemStatus.TARGET || is == ItemStatus.CARRYING) continue; 25 | goals.add(goal.getItem()); 26 | } 27 | if (goals.isEmpty()) return null; 28 | 29 | for (AutoRefPlayer player : team.getPlayers()) 30 | goals.removeAll(player.getCarrying().keySet()); 31 | 32 | if (goals.isEmpty()) return null; 33 | 34 | plugin.getServer().getScheduler().runTaskAsynchronously(plugin, new ObjectiveExhaustionMasterTask(team, goals)); 35 | return goals; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/goals/scoreboard/ScoreObjective.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.goals.scoreboard; 2 | 3 | import java.util.Set; 4 | 5 | import org.bukkit.scoreboard.Objective; 6 | 7 | import org.mctourney.autoreferee.AutoRefTeam; 8 | import org.mctourney.autoreferee.goals.AutoRefGoal; 9 | import org.mctourney.autoreferee.goals.ScoreGoal; 10 | 11 | import com.google.common.collect.Sets; 12 | 13 | public class ScoreObjective extends AutoRefObjective 14 | { 15 | public ScoreObjective(Objective objective, AutoRefTeam team, Set scoregoals) 16 | { 17 | super(objective, team, team.getName(), 0); 18 | this.goals.addAll(scoregoals); 19 | 20 | // update these objectives 21 | this.update(); 22 | } 23 | 24 | @Override 25 | public void update() 26 | { 27 | double totalscore = 0; 28 | for (AutoRefGoal goal : this.goals) 29 | totalscore += goal.getScore(this.team.getMatch()); 30 | 31 | this.setName(String.format("%s", this.team.getName())); 32 | this.setValue((int) totalscore); 33 | } 34 | 35 | public static Set fromTeam(Objective objective, AutoRefTeam team) 36 | { 37 | Set objectives = Sets.newHashSet(); 38 | 39 | Set scoregoals = team.getTeamGoals(ScoreGoal.class); 40 | if (!scoregoals.isEmpty()) objectives.add(new ScoreObjective(objective, team, scoregoals)); 41 | 42 | return objectives; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/util/LocationUtil.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.util; 2 | 3 | import org.bukkit.Location; 4 | import org.bukkit.World; 5 | 6 | public abstract class LocationUtil 7 | { 8 | public static String toBlockCoords(Location loc) 9 | { return String.format("%d,%d,%d", loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); } 10 | 11 | public static String toBlockCoordsWithYaw(Location loc) 12 | { return String.format("%s,%d", toBlockCoords(loc), (int)loc.getYaw()); } 13 | 14 | public static String toCoords(Location loc) 15 | { return String.format("%.3f,%.3f,%.3f", loc.getX(), loc.getY(), loc.getZ()); } 16 | 17 | public static Location fromCoords(World world, String coords) 18 | { 19 | try 20 | { 21 | String[] values = coords.split(","); 22 | Location ret = new Location(world, parseDouble(values[0]), 23 | parseDouble(values[1]), parseDouble(values[2])); 24 | 25 | if (values.length > 3) ret.setYaw(Float.parseFloat(values[3])); 26 | if (values.length > 4) ret.setPitch(Float.parseFloat(values[4])); 27 | return ret; 28 | } 29 | catch (NumberFormatException e) { return null; } 30 | } 31 | 32 | // simply here for utility 33 | private static double parseDouble(String v) 34 | { 35 | if (v.endsWith("oo") || v.endsWith("inf")) 36 | return v.startsWith("-") 37 | ? Double.NEGATIVE_INFINITY 38 | : Double.POSITIVE_INFINITY; 39 | return Double.parseDouble(v); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/test/java/org/mctourney/autoreferee/util/ColorConverterTest.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.util; 2 | 3 | import org.bukkit.Color; 4 | import org.junit.Assert; 5 | import org.junit.Test; 6 | 7 | public class ColorConverterTest 8 | { 9 | @Test 10 | public void testHexToColor() throws Exception 11 | { 12 | Assert.assertEquals(Color.fromRGB(255, 255, 255), ColorConverter.hexToColor("#ffffff")); 13 | Assert.assertEquals(Color.fromRGB(255, 0, 136), ColorConverter.hexToColor("#ff0088")); 14 | Assert.assertEquals(Color.fromRGB(222, 173, 0), ColorConverter.hexToColor("#dead00")); 15 | 16 | Assert.assertEquals(Color.fromRGB(160, 208, 48), ColorConverter.hexToColor("#ad3")); 17 | Assert.assertEquals(Color.fromRGB(192, 96, 192), ColorConverter.hexToColor("#c6c")); 18 | Assert.assertEquals(Color.fromRGB( 0, 112, 112), ColorConverter.hexToColor("#077")); 19 | } 20 | 21 | @Test 22 | public void testRgbToColor() throws Exception 23 | { 24 | Assert.assertEquals(Color.fromRGB(255, 255, 255), ColorConverter.rgbToColor("255,255,255")); 25 | Assert.assertEquals(Color.fromRGB(255, 0, 136), ColorConverter.rgbToColor("255,0,136")); 26 | Assert.assertEquals(Color.fromRGB(222, 173, 0), ColorConverter.rgbToColor("222,173,000")); 27 | 28 | Assert.assertEquals(Color.fromRGB(160, 208, 48), ColorConverter.rgbToColor("160/208/048")); 29 | Assert.assertEquals(Color.fromRGB(192, 96, 192), ColorConverter.rgbToColor("192 96 192")); 30 | Assert.assertEquals(Color.fromRGB( 0, 112, 112), ColorConverter.rgbToColor("000 112 112")); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/goals/ScoreDeathmatchGoal.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.goals; 2 | 3 | import org.bukkit.Location; 4 | import org.bukkit.entity.Player; 5 | 6 | import org.jdom2.Element; 7 | 8 | import org.mctourney.autoreferee.AutoRefMatch; 9 | import org.mctourney.autoreferee.AutoRefPlayer; 10 | import org.mctourney.autoreferee.AutoRefTeam; 11 | import org.mctourney.autoreferee.util.BlockData; 12 | 13 | public class ScoreDeathmatchGoal extends ScoreGoal 14 | { 15 | public ScoreDeathmatchGoal(AutoRefTeam team) 16 | { super(team); } 17 | 18 | private ScoreDeathmatchGoal(AutoRefTeam team, ScoreDeathmatchGoal goal) 19 | { this(team); } 20 | 21 | public ScoreDeathmatchGoal(AutoRefTeam team, Element elt) 22 | { super(team); } 23 | 24 | @Override 25 | public ScoreDeathmatchGoal copy() 26 | { return this.copy(this.owner); } 27 | 28 | @Override 29 | public ScoreDeathmatchGoal copy(AutoRefTeam team) 30 | { return new ScoreDeathmatchGoal(team, this); } 31 | 32 | public double getScore(AutoRefMatch match) 33 | { 34 | double score = 0.0; 35 | for (AutoRefPlayer apl : this.getOwner().getPlayers()) 36 | score += apl.getKills(); 37 | return score; 38 | } 39 | 40 | @Override 41 | public void updateReferee(Player ref) 42 | { 43 | } 44 | 45 | @Override 46 | public BlockData getItem() 47 | { return null; } 48 | 49 | @Override 50 | public Location getTarget() 51 | { return null; } 52 | 53 | @Override 54 | public Element toElement() 55 | { 56 | Element elt = new Element("deathmatch"); 57 | return elt; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/util/worldsearch/_Entry.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.util.worldsearch; 2 | 3 | import java.util.Map; 4 | 5 | public final class _Entry implements Map.Entry 6 | { 7 | private final K key; 8 | private V value; 9 | 10 | public _Entry(K key, V value) 11 | { 12 | this.key = key; 13 | this.value = value; 14 | } 15 | 16 | @Override 17 | public K getKey() 18 | { 19 | return key; 20 | } 21 | 22 | @Override 23 | public V getValue() 24 | { 25 | return value; 26 | } 27 | 28 | @Override 29 | public V setValue(V value) 30 | { 31 | V old = this.value; 32 | this.value = value; 33 | return old; 34 | } 35 | 36 | @Override 37 | public int hashCode() 38 | { 39 | final int prime = 31; 40 | int result = 1; 41 | result = prime * result + ((key == null) ? 0 : key.hashCode()); 42 | result = prime * result + ((value == null) ? 0 : value.hashCode()); 43 | return result; 44 | } 45 | 46 | @Override 47 | public boolean equals(Object obj) 48 | { 49 | if (this == obj) return true; 50 | if (obj == null) return false; 51 | if (!(obj instanceof _Entry)) return false; 52 | _Entry other = (_Entry) obj; 53 | if (key == null) 54 | if (other.key != null) return false; 55 | else if (!key.equals(other.key)) return false; 56 | 57 | if (value == null) 58 | if (other.value != null) return false; 59 | else if (!value.equals(other.value)) return false; 60 | return true; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/event/match/MatchStartEvent.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.event.match; 2 | 3 | import org.bukkit.event.Cancellable; 4 | import org.bukkit.event.HandlerList; 5 | 6 | import org.mctourney.autoreferee.AutoRefMatch; 7 | 8 | /** 9 | * Called when a match is starting. 10 | * 11 | * @author authorblues 12 | */ 13 | public class MatchStartEvent extends MatchEvent implements Cancellable 14 | { 15 | public static enum Reason 16 | { 17 | READY, 18 | AUTOMATIC, 19 | UNKNOWN; 20 | } 21 | 22 | private static final HandlerList handlers = new HandlerList(); 23 | private boolean cancelled = false; 24 | private Reason reason = Reason.UNKNOWN; 25 | 26 | @Deprecated 27 | public MatchStartEvent(AutoRefMatch match) 28 | { this(match, Reason.UNKNOWN); } 29 | 30 | public MatchStartEvent(AutoRefMatch match, Reason reason) 31 | { 32 | super(match); 33 | this.reason = reason; 34 | } 35 | 36 | public Reason getReason() 37 | { return this.reason; } 38 | 39 | /** 40 | * Checks the cancelled state of the event. 41 | * @return true if the event has been cancelled, false otherwise 42 | */ 43 | public boolean isCancelled() 44 | { return this.cancelled; } 45 | 46 | /** 47 | * Sets the cancelled state of the event. 48 | * @param cancel true to cancel the event, false to uncancel the event 49 | */ 50 | public void setCancelled(boolean cancel) 51 | { this.cancelled = cancel; } 52 | 53 | @Override 54 | public HandlerList getHandlers() 55 | { return handlers; } 56 | 57 | public static HandlerList getHandlerList() 58 | { return handlers; } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/goals/scoreboard/BlockObjective.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.goals.scoreboard; 2 | 3 | import java.util.Set; 4 | 5 | import org.bukkit.scoreboard.Objective; 6 | 7 | import org.mctourney.autoreferee.AutoRefTeam; 8 | import org.mctourney.autoreferee.goals.AutoRefGoal; 9 | import org.mctourney.autoreferee.goals.BlockGoal; 10 | 11 | import com.google.common.collect.Sets; 12 | 13 | public class BlockObjective extends AutoRefObjective 14 | { 15 | public BlockObjective(Objective objective, AutoRefTeam team, Set blockgoals) 16 | { 17 | super(objective, team, team.getName(), 0); 18 | this.goals.addAll(blockgoals); 19 | 20 | // update these objectives 21 | this.update(); 22 | } 23 | 24 | @Override 25 | public void update() 26 | { 27 | int found = 0, placed = 0; 28 | for (AutoRefGoal goal : this.goals) switch (goal.getItemStatus()) 29 | { 30 | case TARGET: 31 | placed++; 32 | 33 | case CARRYING: 34 | case SEEN: 35 | found++; 36 | 37 | default: break; 38 | } 39 | 40 | this.setName(String.format("%s", this.team.getName())); 41 | // this.setName(String.format("%s (%d)", this.team.getName(), found)); 42 | this.setValue(placed); 43 | } 44 | 45 | public static Set fromTeam(Objective objective, AutoRefTeam team) 46 | { 47 | Set objectives = Sets.newHashSet(); 48 | 49 | Set blockgoals = team.getTeamGoals(BlockGoal.class); 50 | if (!blockgoals.isEmpty()) objectives.add(new BlockObjective(objective, team, blockgoals)); 51 | 52 | return objectives; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/resources/webstats/report.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | font-family: 'Open Sans', sans-serif; 4 | background: #eee; 5 | color: #444; 6 | } 7 | 8 | h3 { 9 | margin-bottom: 15px; 10 | } 11 | 12 | h4 { 13 | margin-bottom: 10px; 14 | } 15 | 16 | #match-detail table th { 17 | width: 9em; 18 | } 19 | 20 | .ar_rank { 21 | width: 20px; 22 | } 23 | 24 | #ar_header, 25 | #ar_content, 26 | #ar_footer { 27 | margin-top: 30px; 28 | padding: 20px 20px 0 20px; 29 | } 30 | 31 | #ar_header { 32 | background-position: right 50%; 33 | background-repeat: no-repeat; 34 | } 35 | 36 | #ar_content { 37 | background: #fff; 38 | border: 1px solid #ddd; 39 | border-radius: 10px; 40 | } 41 | 42 | #ar_footer { 43 | color: #999; 44 | text-align: center; 45 | } 46 | 47 | input[type=checkbox].player-toggle { 48 | margin-right: 3px; 49 | } 50 | 51 | .player:before, 52 | .block:before, 53 | .item:before { 54 | display: inline-block; 55 | content: ""; 56 | vertical-align: middle; 57 | width: 16px; 58 | height: 16px; 59 | margin-right: 3px; 60 | background-repeat: no-repeat; 61 | } 62 | 63 | .referee { font-weight: bold; } 64 | 65 | #match-details .player { 66 | color: black !important; 67 | } 68 | 69 | .team, .block { font-weight: bold; } 70 | 71 | .teammembers li { 72 | margin-bottom: 5px; 73 | } 74 | 75 | #event-filter { 76 | float: right; 77 | margin-top: 20px; 78 | } 79 | 80 | canvas#maptip { 81 | display: none; 82 | position: absolute; 83 | 84 | border: 1px solid black; 85 | background-color: #333; 86 | z-index: 999; 87 | 88 | -moz-border-radius: 10px; 89 | border-radius: 10px; 90 | } 91 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/event/match/MatchUnloadEvent.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.event.match; 2 | 3 | import org.bukkit.event.Cancellable; 4 | import org.bukkit.event.HandlerList; 5 | 6 | import org.mctourney.autoreferee.AutoRefMatch; 7 | 8 | /** 9 | * Called when a map is unloaded from the server. 10 | * 11 | * @author authorblues 12 | */ 13 | public class MatchUnloadEvent extends MatchEvent implements Cancellable 14 | { 15 | public static enum Reason 16 | { 17 | COMMAND, 18 | COMPLETE, 19 | EMPTY, 20 | UNKNOWN; 21 | } 22 | 23 | private static final HandlerList handlers = new HandlerList(); 24 | private boolean cancelled = false; 25 | private Reason reason = Reason.UNKNOWN; 26 | 27 | @Deprecated 28 | public MatchUnloadEvent(AutoRefMatch match) 29 | { this(match, Reason.UNKNOWN); } 30 | 31 | public MatchUnloadEvent(AutoRefMatch match, Reason reason) 32 | { 33 | super(match); 34 | this.reason = reason; 35 | } 36 | 37 | public Reason getReason() 38 | { return this.reason; } 39 | 40 | /** 41 | * Checks the cancelled state of the event. 42 | * @return true if the event has been cancelled, false otherwise 43 | */ 44 | public boolean isCancelled() 45 | { return this.cancelled; } 46 | 47 | /** 48 | * Sets the cancelled state of the event. 49 | * @param cancel true to cancel the event, false to uncancel the event 50 | */ 51 | public void setCancelled(boolean cancel) 52 | { this.cancelled = cancel; } 53 | 54 | @Override 55 | public HandlerList getHandlers() 56 | { return handlers; } 57 | 58 | public static HandlerList getHandlerList() 59 | { return handlers; } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/regions/PointRegion.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.regions; 2 | 3 | import java.util.Random; 4 | 5 | import org.bukkit.Location; 6 | 7 | import org.bukkit.World; 8 | import org.jdom2.Element; 9 | 10 | import org.mctourney.autoreferee.AutoRefMatch; 11 | import org.mctourney.autoreferee.util.LocationUtil; 12 | 13 | public class PointRegion extends AutoRefRegion 14 | { 15 | Location pos = null; 16 | 17 | public PointRegion(Location loc) 18 | { this.pos = loc.getBlock().getLocation(); this.yaw = (int)loc.getYaw(); } 19 | 20 | public PointRegion(AutoRefMatch match, Element e) 21 | { this(match.getWorld(), e); } 22 | 23 | public PointRegion(World world, Element e) 24 | { this(LocationUtil.fromCoords(world, e.getAttributeValue("pos"))); } 25 | 26 | public Element toElement() 27 | { 28 | return this.setRegionSettings(new Element("location") 29 | .setAttribute("pos", LocationUtil.toBlockCoords(pos))); 30 | } 31 | 32 | @Override 33 | public double distanceToRegion(Location loc) 34 | { return pos.distance(loc); } 35 | 36 | @Override 37 | public Location getRandomLocation(Random r) 38 | { return pos.clone().add(0.5, 0.0, 0.5); } 39 | 40 | @Override 41 | public CuboidRegion getBoundingCuboid() 42 | { return new CuboidRegion(pos, pos); } 43 | 44 | @Override 45 | public int hashCode() 46 | { return pos.hashCode(); } 47 | 48 | @Override 49 | public boolean equals(Object o) 50 | { return (o instanceof PointRegion) && hashCode() == o.hashCode(); } 51 | 52 | @Override 53 | public String toString() 54 | { return String.format("POINT(%s)", LocationUtil.toBlockCoords(pos)); } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/event/player/PlayerTeamJoinEvent.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.event.player; 2 | 3 | import org.bukkit.entity.Player; 4 | import org.bukkit.event.Cancellable; 5 | import org.bukkit.event.HandlerList; 6 | 7 | import org.mctourney.autoreferee.AutoRefTeam; 8 | 9 | /** 10 | * Called when a player joins a team. 11 | * 12 | * @author authorblues 13 | */ 14 | public class PlayerTeamJoinEvent extends PlayerTeamEvent implements Cancellable 15 | { 16 | public static enum Reason 17 | { 18 | MANUAL, 19 | AUTOMATIC, 20 | EXPECTED, 21 | UNKNOWN; 22 | } 23 | 24 | private static final HandlerList handlers = new HandlerList(); 25 | private boolean cancelled = false; 26 | private Reason reason = Reason.UNKNOWN; 27 | 28 | @Deprecated 29 | public PlayerTeamJoinEvent(Player player, AutoRefTeam team) 30 | { this(player, team, Reason.UNKNOWN); } 31 | 32 | public PlayerTeamJoinEvent(Player player, AutoRefTeam team, Reason reason) 33 | { 34 | super(player, team); 35 | this.reason = reason; 36 | } 37 | 38 | public Reason getReason() 39 | { return this.reason; } 40 | 41 | /** 42 | * Checks the cancelled state of the event. 43 | * @return true if the event has been cancelled, false otherwise 44 | */ 45 | public boolean isCancelled() 46 | { return this.cancelled; } 47 | 48 | /** 49 | * Sets the cancelled state of the event. 50 | * @param cancel true to cancel the event, false to uncancel the event 51 | */ 52 | public void setCancelled(boolean cancel) 53 | { this.cancelled = cancel; } 54 | 55 | @Override 56 | public HandlerList getHandlers() 57 | { return handlers; } 58 | 59 | public static HandlerList getHandlerList() 60 | { return handlers; } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/event/match/MatchUploadStatsEvent.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.event.match; 2 | 3 | import org.bukkit.event.Cancellable; 4 | import org.bukkit.event.HandlerList; 5 | 6 | import org.mctourney.autoreferee.AutoRefMatch; 7 | 8 | /** 9 | * Called when match statistics are generated and uploaded. 10 | * 11 | * @author authorblues 12 | */ 13 | public class MatchUploadStatsEvent extends MatchEvent implements Cancellable 14 | { 15 | private static final HandlerList handlers = new HandlerList(); 16 | private boolean cancelled = false; 17 | private String webstats = null; 18 | 19 | public MatchUploadStatsEvent(AutoRefMatch match, String webstats) 20 | { 21 | super(match); 22 | this.webstats = webstats; 23 | } 24 | 25 | /** 26 | * Returns the webstats generated by the server. 27 | * @return web stats in HTML format 28 | */ 29 | public String getWebstats() 30 | { return this.webstats; } 31 | 32 | /** 33 | * Sets the webstats to be saved and uploaded. 34 | * @param webstats web stats in HTML format 35 | */ 36 | public void setWebstats(String webstats) 37 | { this.webstats = webstats; } 38 | 39 | /** 40 | * Checks the cancelled state of the event. 41 | * @return true if the event has been cancelled, false otherwise 42 | */ 43 | public boolean isCancelled() 44 | { return this.cancelled; } 45 | 46 | /** 47 | * Sets the cancelled state of the event. 48 | * @param cancel true to cancel the event, false to uncancel the event 49 | */ 50 | public void setCancelled(boolean cancel) 51 | { this.cancelled = cancel; } 52 | 53 | @Override 54 | public HandlerList getHandlers() 55 | { return handlers; } 56 | 57 | public static HandlerList getHandlerList() 58 | { return handlers; } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/event/match/MatchCompleteEvent.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.event.match; 2 | 3 | import org.bukkit.event.Cancellable; 4 | import org.bukkit.event.HandlerList; 5 | 6 | import org.mctourney.autoreferee.AutoRefMatch; 7 | import org.mctourney.autoreferee.AutoRefTeam; 8 | 9 | /** 10 | * Called when a match is ending. 11 | * 12 | * @author authorblues 13 | */ 14 | public class MatchCompleteEvent extends MatchEvent implements Cancellable 15 | { 16 | private static final HandlerList handlers = new HandlerList(); 17 | private boolean cancelled = false; 18 | private AutoRefTeam winner = null; 19 | 20 | public MatchCompleteEvent(AutoRefMatch match, AutoRefTeam winner) 21 | { 22 | super(match); 23 | this.winner = winner; 24 | } 25 | 26 | /** 27 | * Returns the winning team for this match. 28 | * @return winning team, null if a tie or no winner 29 | */ 30 | public AutoRefTeam getWinner() 31 | { return this.winner; } 32 | 33 | /** 34 | * Sets the winning team for this match. 35 | * @param winner winning team 36 | */ 37 | public void setWinner(AutoRefTeam winner) 38 | { this.winner = winner; } 39 | 40 | /** 41 | * Checks the cancelled state of the event. 42 | * @return true if the event has been cancelled, false otherwise 43 | */ 44 | public boolean isCancelled() 45 | { return this.cancelled; } 46 | 47 | /** 48 | * Sets the cancelled state of the event. 49 | * @param cancel true to cancel the event, false to uncancel the event 50 | */ 51 | public void setCancelled(boolean cancel) 52 | { this.cancelled = cancel; } 53 | 54 | @Override 55 | public HandlerList getHandlers() 56 | { return handlers; } 57 | 58 | public static HandlerList getHandlerList() 59 | { return handlers; } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/resources/examples/default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Direct Fire 4 | 1.1 5 | 6 | Vechs 7 | 8 | 9 | 10 | 11 | 12 | Right 13 | 14 | 15 | 16 | 17 | 18 | Left 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | Right 32 | 33 | 34 | 35 | Left 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | true 54 | true 55 | 56 | 57 | 58 | 59 | HARD 60 | 61 | 62 | 8am 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/util/worldsearch/WorkerValidateResults.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.util.worldsearch; 2 | 3 | import java.util.Set; 4 | 5 | import org.bukkit.scheduler.BukkitRunnable; 6 | import org.bukkit.util.Vector; 7 | import org.mctourney.autoreferee.util.BlockData; 8 | 9 | import com.google.common.collect.Sets; 10 | 11 | /** 12 | * Consumes: ObjectiveExhaustionMasterTask.found
13 | * Output: ObjectiveExhaustionMasterTask.searching
14 | * Output: ObjectiveExhaustionMasterTask.results
15 | * Cancellation: Handled by master 16 | * 17 | * Check whether the team would be able to access each result. If the result is 18 | * accessible, it is removed from the search goals and announced. 19 | * 20 | * @author riking 21 | */ 22 | public class WorkerValidateResults extends BukkitRunnable 23 | { 24 | private final ObjectiveExhaustionMasterTask master; 25 | 26 | public WorkerValidateResults(ObjectiveExhaustionMasterTask task) 27 | { 28 | master = task; 29 | } 30 | 31 | @Override 32 | public void run() 33 | { 34 | synchronized (master._LOCK_RESULTS) { 35 | if (master.found.isEmpty()) return; 36 | 37 | _Entry entry; 38 | Set newSearch = Sets.newHashSet(master.searching); 39 | while ((entry = master.found.poll()) != null) 40 | { 41 | Vector vec = entry.getValue(); 42 | if (master.team.canEnter(vec.toLocation(master.team.getMatch().getWorld()))) 43 | { 44 | BlockData data = entry.getKey(); 45 | newSearch.remove(data); 46 | // No safety - read-once 47 | master.results.put(data, vec); 48 | } 49 | } 50 | 51 | if (!newSearch.equals(master.searching)) 52 | { 53 | // Safety: Copy-on-write 54 | master.searching = newSearch; 55 | } 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/goals/ScoreDummyGoal.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.goals; 2 | 3 | import org.bukkit.Location; 4 | import org.bukkit.entity.Player; 5 | 6 | import org.mctourney.autoreferee.AutoRefMatch; 7 | import org.mctourney.autoreferee.AutoRefTeam; 8 | import org.mctourney.autoreferee.util.BlockData; 9 | 10 | import org.jdom2.Element; 11 | 12 | public class ScoreDummyGoal extends ScoreGoal 13 | { 14 | private final String goalname; 15 | private double score = 0.0; 16 | 17 | public ScoreDummyGoal(AutoRefTeam team, String name) 18 | { 19 | super(team); this.goalname = name; 20 | } 21 | 22 | public ScoreDummyGoal(AutoRefTeam team, Element elt) 23 | { this(team, elt.getAttributeValue("name")); } 24 | 25 | public ScoreDummyGoal(AutoRefTeam team, ScoreDummyGoal scoreDummyGoal) 26 | { this(team, scoreDummyGoal.getName()); } 27 | 28 | public String getName() 29 | { return goalname; } 30 | 31 | public double getScore(AutoRefMatch match) 32 | { return this.score; } 33 | 34 | public void setScore(double score) 35 | { this.score = score; } 36 | 37 | @Override 38 | public ScoreDummyGoal copy() 39 | { return this.copy(this.owner); } 40 | 41 | @Override 42 | public ScoreDummyGoal copy(AutoRefTeam team) 43 | { return new ScoreDummyGoal(team, this); } 44 | 45 | @Override 46 | public void updateReferee(Player ref) 47 | { 48 | } 49 | 50 | @Override 51 | public BlockData getItem() 52 | { return null; } 53 | 54 | @Override 55 | public Location getTarget() 56 | { return null; } 57 | 58 | @Override 59 | public String toString() 60 | { return "DUMMY[" + this.goalname + "=" + this.getTargetScore() + "]"; } 61 | 62 | @Override 63 | public Element toElement() 64 | { 65 | Element elt = new Element("dummy"); 66 | elt.setAttribute("name", this.goalname); 67 | return elt; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/util/ArmorPoints.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.util; 2 | 3 | import org.bukkit.Material; 4 | import org.bukkit.entity.Player; 5 | import org.bukkit.inventory.ItemStack; 6 | import org.bukkit.inventory.PlayerInventory; 7 | 8 | public abstract class ArmorPoints 9 | { 10 | public static int fromMaterial(Material mat) 11 | { 12 | switch (mat) 13 | { 14 | // leather armor 15 | case LEATHER_HELMET: return 1; 16 | case LEATHER_CHESTPLATE: return 3; 17 | case LEATHER_LEGGINGS: return 2; 18 | case LEATHER_BOOTS: return 1; 19 | 20 | // gold armor 21 | case GOLD_HELMET: return 2; 22 | case GOLD_CHESTPLATE: return 5; 23 | case GOLD_LEGGINGS: return 3; 24 | case GOLD_BOOTS: return 1; 25 | 26 | // chainmail armor 27 | case CHAINMAIL_HELMET: return 2; 28 | case CHAINMAIL_CHESTPLATE: return 5; 29 | case CHAINMAIL_LEGGINGS: return 4; 30 | case CHAINMAIL_BOOTS: return 1; 31 | 32 | // iron armor 33 | case IRON_HELMET: return 2; 34 | case IRON_CHESTPLATE: return 6; 35 | case IRON_LEGGINGS: return 5; 36 | case IRON_BOOTS: return 2; 37 | 38 | // diamond armor 39 | case DIAMOND_HELMET: return 3; 40 | case DIAMOND_CHESTPLATE: return 8; 41 | case DIAMOND_LEGGINGS: return 6; 42 | case DIAMOND_BOOTS: return 3; 43 | 44 | // non-armor (or not listed above) 45 | default: return 0; 46 | } 47 | } 48 | 49 | public static int fromItemStack(ItemStack item) 50 | { return fromMaterial(item.getType()); } 51 | 52 | public static int fromPlayerInventory(PlayerInventory inv) 53 | { 54 | int armorPoints = 0; 55 | for (ItemStack item : inv.getArmorContents()) 56 | if (item != null){ 57 | armorPoints += ArmorPoints.fromItemStack(item); 58 | } 59 | return armorPoints; 60 | } 61 | 62 | public static int fromPlayer(Player pl) 63 | { return fromPlayerInventory(pl.getInventory()); } 64 | } 65 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AutoReferee [![Travis Build Status for AutoReferee](https://secure.travis-ci.org/rmct/AutoReferee.png?branch=master)](http://travis-ci.org/#!/rmct/AutoReferee) 2 | 3 | ## [Competitive Minecraft Made Easy!](http://rmct.github.io/AutoReferee) 4 | 5 | [Follow us on dev.bukkit.org](http://dev.bukkit.org/server-mods/autoreferee/)! 6 | 7 | Join us for support at [#autoreferee](http://webchat.freenode.net?channels=autoreferee) on freenode. 8 | 9 | **AutoReferee**, in cooperation with [_RMCT_](http://www.reddit.com/r/mctourney) and [_Major League Mining_](http://www.majorleaguemining.net/): A plugin to automatically referee Race for Wool (and other competitive Minecraft) matches. Automatically handles maps, teams, regions, end conditions, match statistics, and much more. 10 | 11 | **Mapmakers:** Once you have built your map and [configured it for use with Autoreferee](http://github.com/rmct/AutoReferee/wiki/How-to-Configure-a-Map), the plugin will place a special configuration file directly into your world folder for you to package and distribute with your map. The configuration file configures AutoReferee automatically when your map is loaded. Please refer to the documentation regarding this configuration file. 12 | 13 | _Note:_ This plugin uses [WorldEdit](http://wiki.sk89q.com/wiki/WorldEdit) for map configuration. Server operators need not run WorldEdit on their server, but to configure a map for use with **AutoReferee**, WorldEdit is required. 14 | 15 | [![Plugin Statistics via mcstats.org](http://api.mcstats.org/signature/AutoReferee.png)](http://mcstats.org/plugin/AutoReferee) 16 | 17 | --- 18 | 19 | If you like AutoReferee, [consider donating a few dollars to help pay for map serving and hosting](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=authorblues%40gmail%2ecom&lc=US&item_name=AutoReferee¤cy_code=USD&bn=PP%2dDonationsBF%3abtn_donate_LG%2egif%3aNonHosted). Money raised will go directly to sustaining this plugin. 20 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/util/worldsearch/Unsafe_InspectVillagerTrades.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.util.worldsearch; 2 | 3 | import java.lang.reflect.Field; 4 | import java.lang.reflect.Method; 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | import org.bukkit.entity.Villager; 9 | import org.bukkit.inventory.ItemStack; 10 | 11 | import com.google.common.collect.Lists; 12 | 13 | /** 14 | * FIXME https://github.com/Bukkit/Bukkit/pull/921 15 | * 16 | * @author riking 17 | */ 18 | class Unsafe_InspectVillagerTrades 19 | { 20 | public static List getTradeResults(Villager vil) throws Exception, Error 21 | { 22 | Object internalVillager = vil.getClass().getDeclaredMethod("getHandle", (Class) null).invoke(vil, (Object[]) null); 23 | Class internalEntityHumanClass = Class.forName("net.minecraft.server.v1_6_R2.EntityHuman"); 24 | ArrayList merchantRecipeList = (ArrayList) internalVillager.getClass().getDeclaredMethod("getOffers", internalEntityHumanClass).invoke(internalVillager, new Object[] {null}); 25 | 26 | if (merchantRecipeList.size() == 0) return Lists.newArrayList(); 27 | List ret = Lists.newArrayListWithCapacity(merchantRecipeList.size()); 28 | 29 | Field itemField = merchantRecipeList.get(0).getClass().getField("sellingItem"); 30 | Class internalItemClass = Class.forName("net.minecraft.server.v1_6_R2.ItemStack"); 31 | Method getStackMethod = Class.forName("org.bukkit.craftbukkit.v1_6_R2.inventory.CraftItemStack").getDeclaredMethod("asBukkitCopy", internalItemClass); 32 | for (Object o : merchantRecipeList) 33 | { 34 | Object internalItemStack = itemField.get(o); 35 | if (!internalItemStack.getClass().equals(internalItemClass)) continue; 36 | Object bukkitItemStack = getStackMethod.invoke(null, internalItemStack); 37 | if (!ItemStack.class.isAssignableFrom(bukkitItemStack.getClass())) 38 | { 39 | new RuntimeException("asBukkitCopy() did not return a Bukkit ItemStack..? Investigate.").printStackTrace(); 40 | continue; 41 | } 42 | ret.add((ItemStack) bukkitItemStack); 43 | } 44 | return ret; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/resources/webstats/report.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function(){ 2 | $(".player-toggle").attr('checked', true).change(function(){ 3 | $('tr.transcript-event.type-player-event').hide(); 4 | $(".player-toggle").each(function(i, e){ 5 | if ($(e).is(':checked')) 6 | $('tr.transcript-event.type-player-event.player-' + $(e).data('player')).show(); 7 | }); 8 | }); 9 | 10 | $("#event-filter").change(function(e){ 11 | $(".transcript-event").toggle(this.value == ""); 12 | $(".transcript-event.type-" + this.value).show(); 13 | }); 14 | }); 15 | 16 | var mapImage = new Image; 17 | mapImage.src = map.image; 18 | 19 | var tip = $("canvas#maptip"); 20 | var ctx = tip.get(0).getContext('2d'); 21 | var tip_hide_task; 22 | 23 | ctx.imageSmoothingEnabled = false; 24 | ctx.webkitImageSmoothingEnabled = false; 25 | ctx.mozImageSmoothingEnabled = false; 26 | 27 | function drawFace(ctx, player) 28 | { 29 | var face = new Image; 30 | face.src = 'http://minotar.net/avatar/' + player + '/16.png'; 31 | ctx.drawImage(face, -8, -8); 32 | } 33 | 34 | ($(".transcript-event[data-location]") 35 | .mouseenter(function(mouse){ 36 | var coords = $(this).data('location').split(','); 37 | var x = parseInt(coords[0]) - map.x, z = parseInt(coords[2]) - map.z; 38 | 39 | ctx.save(); ctx.setTransform(1, 0, 0, 1, 0, 0); 40 | ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); ctx.restore(); 41 | 42 | ctx.save(); ctx.translate(ctx.canvas.width/2, ctx.canvas.height/2); 43 | ctx.save(); ctx.scale(4, 4); ctx.drawImage(mapImage, -x, -z); ctx.restore(); 44 | 45 | var player = $(this).data('player'); 46 | if (player) drawFace(ctx, player); ctx.restore(); 47 | 48 | clearInterval(tip_hide_task); tip.fadeIn(300); 49 | }) 50 | .mouseleave(function(mouse){ 51 | tip_hide_task = setTimeout(function(){ tip.stop(true).fadeOut(300); }, 100); 52 | }) 53 | ); 54 | 55 | $(document).mousemove(function(mouse){ 56 | tip.css({ 57 | left: mouse.pageX + (mouse.clientX < $(window).width() /2 ? 10 : -(tip.width() + 10)), 58 | top: mouse.pageY + (mouse.clientY < $(window).height()/2 ? 10 : -(tip.height() + 10)), 59 | }); 60 | }); -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/goals/SurvivalGoal.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.goals; 2 | 3 | import org.bukkit.Location; 4 | import org.bukkit.entity.Player; 5 | 6 | import org.jdom2.Element; 7 | 8 | import org.mctourney.autoreferee.AutoRefMatch; 9 | import org.mctourney.autoreferee.AutoRefTeam; 10 | import org.mctourney.autoreferee.util.BlockData; 11 | 12 | public class SurvivalGoal extends AutoRefGoal 13 | { 14 | public SurvivalGoal(AutoRefTeam team) 15 | { super(team); } 16 | 17 | private SurvivalGoal(AutoRefTeam team, SurvivalGoal goal) 18 | { this(team); } 19 | 20 | public SurvivalGoal(AutoRefTeam team, Element elt) 21 | { super(team); } 22 | 23 | @Override 24 | public SurvivalGoal copy() 25 | { return this.copy(this.owner); } 26 | 27 | @Override 28 | public SurvivalGoal copy(AutoRefTeam team) 29 | { return new SurvivalGoal(team, this); } 30 | 31 | public Element toElement() 32 | { return new Element("survive"); } 33 | 34 | @Override 35 | public String toString() 36 | { return "SURVIVE"; } 37 | 38 | @Override 39 | public boolean isSatisfied(AutoRefMatch match) 40 | { 41 | for (AutoRefTeam team : match.getTeams()) 42 | if (team != this.getOwner()) 43 | if (hasSurvived(team)) return false; 44 | return true; 45 | } 46 | 47 | public static boolean hasSurvived(AutoRefTeam team) 48 | { 49 | boolean practice = team.getMatch().isPracticeMode(); 50 | return !team.getPlayers().isEmpty() 51 | || (practice && team.getCachedPlayers().isEmpty()); 52 | } 53 | 54 | @Override 55 | public boolean canBeCompleted(AutoRefMatch match) 56 | { return SurvivalGoal.hasSurvived(this.getOwner()); } 57 | 58 | @Override 59 | public double getScore(AutoRefMatch match) 60 | { return this.getOwner().getPlayers().size() * 250.0; } 61 | 62 | @Override 63 | public void updateReferee(Player ref) 64 | { 65 | AutoRefMatch.messageReferee(ref, "team", getOwner().getName(), 66 | "goal", "survive", Integer.toString(getOwner().getPlayers().size())); 67 | } 68 | 69 | @Override 70 | public BlockData getItem() { return null; } 71 | 72 | @Override 73 | public Location getTarget() { return null; } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/util/BookUtil.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.util; 2 | 3 | import java.util.Map; 4 | 5 | import org.bukkit.ChatColor; 6 | 7 | import com.google.common.collect.Maps; 8 | 9 | import org.apache.commons.lang3.StringUtils; 10 | 11 | /** 12 | * Utility for writing books using BookMeta. 13 | * 14 | * @author authorblues 15 | */ 16 | public class BookUtil 17 | { 18 | private static final int LINE_WIDTH = 115; 19 | 20 | private static final int NUM_LINES = 13; 21 | 22 | private static Map charWidth = Maps.newHashMap(); 23 | static 24 | { 25 | charWidth.put(' ', 3); 26 | charWidth.put('i', 1); 27 | charWidth.put('I', 3); 28 | charWidth.put('l', 2); 29 | 30 | charWidth.put('.', 1); 31 | charWidth.put(',', 1); 32 | charWidth.put('<', 4); 33 | charWidth.put('>', 4); 34 | charWidth.put(':', 1); 35 | charWidth.put(';', 1); 36 | charWidth.put('\'', 2); 37 | charWidth.put('"', 4); 38 | charWidth.put('[', 4); 39 | charWidth.put(']', 4); 40 | charWidth.put('{', 4); 41 | charWidth.put('}', 4); 42 | charWidth.put('|', 4); 43 | 44 | charWidth.put('`', 1); 45 | charWidth.put('~', 6); 46 | charWidth.put('!', 1); 47 | charWidth.put('@', 6); 48 | charWidth.put('*', 4); 49 | charWidth.put('(', 4); 50 | charWidth.put(')', 4); 51 | } 52 | 53 | private static int getCharWidth(char c, boolean bold) 54 | { 55 | int w = charWidth.containsKey(c) ? charWidth.get(c) : 5; 56 | if (bold) w += 1; 57 | 58 | return w; 59 | } 60 | 61 | public static String makePage(String ...lines) 62 | { return StringUtils.join(lines, "\n" + ChatColor.BLACK + ChatColor.RESET); } 63 | 64 | public static String center(String text) 65 | { 66 | int w = 0; 67 | 68 | boolean isBold = false; 69 | for (int i = 0; i < text.length(); ++i) 70 | { 71 | char c = text.charAt(i); 72 | if (c == ChatColor.COLOR_CHAR) 73 | isBold = text.charAt(++i) == ChatColor.BOLD.getChar(); 74 | else w += 1 + getCharWidth(c, isBold); 75 | } 76 | 77 | int repeat = (LINE_WIDTH - w) / (2 * (charWidth.get(' ') + 1)); 78 | return StringUtils.repeat(' ', repeat < 0 ? 0 : repeat) + text; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/regions/CylinderRegion.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.regions; 2 | 3 | import java.util.Random; 4 | 5 | import org.bukkit.Location; 6 | import org.bukkit.World; 7 | 8 | import org.jdom2.Element; 9 | 10 | import org.mctourney.autoreferee.AutoRefMatch; 11 | import org.mctourney.autoreferee.util.LocationUtil; 12 | 13 | public class CylinderRegion extends AutoRefRegion 14 | { 15 | public double x, y, z, h; 16 | public double r; 17 | 18 | public World world; 19 | 20 | public CylinderRegion(Location base, double height, double radius) 21 | { 22 | this.world = base.getWorld(); 23 | this.x = base.getBlockX() + 0.5; 24 | this.y = base.getBlockY(); 25 | this.z = base.getBlockZ() + 0.5; 26 | 27 | this.h = height; 28 | this.r = radius; 29 | } 30 | 31 | public CylinderRegion(AutoRefMatch match, Element elt) 32 | { this(match.getWorld(), elt); } 33 | 34 | public CylinderRegion(World world, Element elt) 35 | { 36 | this(LocationUtil.fromCoords(world, elt.getAttributeValue("base")), 37 | Double.parseDouble(elt.getAttributeValue("height")), 38 | Double.parseDouble(elt.getAttributeValue("radius"))); 39 | } 40 | 41 | @Override 42 | public double distanceToRegion(Location loc) 43 | { 44 | return multimax(0, y - loc.getY(), loc.getY() - (y + h), 45 | new Location(world, x, loc.getY(), z).distance(loc) - r); 46 | } 47 | 48 | public Location getBase() 49 | { return new Location(world, x, y, z); } 50 | 51 | @Override 52 | public Location getRandomLocation(Random r) 53 | { 54 | double t = 2 * Math.PI * r.nextDouble(); 55 | double u = r.nextDouble() * r.nextDouble(); 56 | double d = (u > 1.0 ? 2.0 - u : u) * this.r; 57 | double y = this.y + r.nextDouble() * h; 58 | 59 | // for explanation: http://stackoverflow.com/a/5838055 60 | return new Location(world, x + d * Math.cos(t), y, z + d * Math.sin(t)); 61 | } 62 | 63 | @Override 64 | public CuboidRegion getBoundingCuboid() 65 | { return new CuboidRegion(world, x-r, x+r, y, y+h, z-r, z+r); } 66 | 67 | @Override 68 | public Element toElement() 69 | { 70 | return this.setRegionSettings(new Element("cylinder") 71 | .setAttribute("base", LocationUtil.toBlockCoords(this.getBase())) 72 | .setAttribute("height", Double.toString(h)) 73 | .setAttribute("radius", Double.toString(r))); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/util/worldsearch/WorkerContainerSearch.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.util.worldsearch; 2 | 3 | import java.util.Set; 4 | 5 | import org.bukkit.Location; 6 | import org.bukkit.World; 7 | import org.bukkit.block.BlockState; 8 | import org.bukkit.block.Chest; 9 | import org.bukkit.inventory.Inventory; 10 | import org.bukkit.inventory.InventoryHolder; 11 | import org.bukkit.inventory.ItemStack; 12 | import org.bukkit.scheduler.BukkitRunnable; 13 | import org.bukkit.util.Vector; 14 | import org.mctourney.autoreferee.util.BlockData; 15 | 16 | /** 17 | * Consumes: ObjectiveExhaustionMasterTask.foundContainers
18 | * Output: ObjectiveExhaustionMasterTask.found
19 | * Cancellation: Handled by master 20 | * 21 | * Checks containers for the goals, and adds the results to the found field. 22 | * 23 | * @author kane 24 | */ 25 | public class WorkerContainerSearch extends BukkitRunnable 26 | { 27 | private ObjectiveExhaustionMasterTask master; 28 | 29 | public WorkerContainerSearch(ObjectiveExhaustionMasterTask task) 30 | { 31 | master = task; 32 | } 33 | 34 | @Override 35 | public void run() 36 | { 37 | if (master.contchunks.isEmpty()) return; 38 | 39 | World world = master.team.getMatch().getWorld(); 40 | Location loc = new Location(world, 0, 0, 0); 41 | Set goals = master.searching; 42 | for (int i = 0; i < 15; i++) // 15 chunks per run 43 | { 44 | Vector vec = master.entitychunks.poll(); 45 | if (vec == null) { this.cancel(); return; } 46 | BlockState[] containers = world.getChunkAt(vec.getBlockX(), vec.getBlockZ()).getTileEntities(); // actually chunk-coords 47 | 48 | for (BlockState state : containers) 49 | { 50 | if (state instanceof InventoryHolder) 51 | { 52 | Inventory inv = ((InventoryHolder) state).getInventory(); 53 | if (state instanceof Chest) 54 | inv = ((Chest) state).getBlockInventory(); 55 | checkInventory(inv, goals, state.getLocation(loc)); 56 | } 57 | // TODO: spawners 58 | } 59 | } 60 | } 61 | 62 | private void checkInventory(Inventory inv, Set goals, Location loc) 63 | { 64 | for (ItemStack item : inv.getContents()) 65 | { 66 | BlockData bd = BlockData.fromItemStack(item); 67 | for (BlockData data : goals) 68 | if (data.equals(bd)) 69 | master.found.add(new _Entry(data, loc.toVector())); 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/util/midi/NoteBlockReceiver.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.util.midi; 2 | 3 | import javax.sound.midi.InvalidMidiDataException; 4 | import javax.sound.midi.MidiMessage; 5 | import javax.sound.midi.Receiver; 6 | import javax.sound.midi.ShortMessage; 7 | import java.io.IOException; 8 | import java.util.Map; 9 | import java.util.Set; 10 | 11 | import org.bukkit.Sound; 12 | import org.bukkit.entity.Player; 13 | 14 | import com.google.common.collect.Maps; 15 | 16 | /** 17 | * Midi Receiver for processing note events. 18 | * 19 | * @author authorblues 20 | */ 21 | public class NoteBlockReceiver implements Receiver 22 | { 23 | private static final float VOLUME_RANGE = 10.0f; 24 | 25 | private final Set listeners; 26 | private final Map channelPatches; 27 | 28 | public NoteBlockReceiver(Set listeners) throws InvalidMidiDataException, IOException 29 | { 30 | this.listeners = listeners; 31 | this.channelPatches = Maps.newHashMap(); 32 | } 33 | 34 | @Override 35 | public void send(MidiMessage m, long time) 36 | { 37 | if (m instanceof ShortMessage) 38 | { 39 | ShortMessage smessage = (ShortMessage) m; 40 | int chan = smessage.getChannel(); 41 | 42 | switch (smessage.getCommand()) 43 | { 44 | case ShortMessage.PROGRAM_CHANGE: 45 | int patch = smessage.getData1(); 46 | channelPatches.put(chan, patch); 47 | break; 48 | 49 | case ShortMessage.NOTE_ON: 50 | this.playNote(smessage); 51 | break; 52 | 53 | case ShortMessage.NOTE_OFF: 54 | break; 55 | } 56 | } 57 | } 58 | 59 | public void playNote(ShortMessage message) 60 | { 61 | // if this isn't a NOTE_ON message, we can't play it 62 | if (ShortMessage.NOTE_ON != message.getCommand()) return; 63 | 64 | // get pitch and volume from the midi message 65 | float pitch = (float) ToneUtil.midiToPitch(message); 66 | float volume = VOLUME_RANGE * (message.getData2() / 127.0f); 67 | 68 | // get the correct instrument 69 | Integer patch = channelPatches.get(message.getChannel()); 70 | Sound instrument = Sound.NOTE_PIANO; 71 | if (patch != null) instrument = MidiUtil.patchToInstrument(patch); 72 | 73 | for (Player player : listeners) 74 | player.playSound(player.getLocation(), instrument, volume, pitch); 75 | } 76 | 77 | @Override 78 | public void close() 79 | { 80 | listeners.clear(); 81 | channelPatches.clear(); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/goals/TimeGoal.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.goals; 2 | 3 | import org.bukkit.Location; 4 | import org.bukkit.entity.Player; 5 | 6 | import org.jdom2.Element; 7 | 8 | import org.mctourney.autoreferee.AutoRefMatch; 9 | import org.mctourney.autoreferee.AutoRefTeam; 10 | import org.mctourney.autoreferee.util.BlockData; 11 | 12 | import java.util.regex.Matcher; 13 | import java.util.regex.Pattern; 14 | 15 | public class TimeGoal extends AutoRefGoal 16 | { 17 | private long seconds = Long.MAX_VALUE; 18 | 19 | public TimeGoal(AutoRefTeam team, long seconds) 20 | { super(team); this.seconds = seconds; } 21 | 22 | private TimeGoal(AutoRefTeam team, TimeGoal goal) 23 | { this(team, goal.seconds); } 24 | 25 | public TimeGoal(AutoRefTeam team, Element elt) 26 | { this(team, parseTime(elt.getTextTrim())); } 27 | 28 | @Override 29 | public TimeGoal copy() 30 | { return this.copy(this.owner); } 31 | 32 | @Override 33 | public TimeGoal copy(AutoRefTeam team) 34 | { return new TimeGoal(team, this); } 35 | 36 | @Override 37 | public boolean isSatisfied(AutoRefMatch match) 38 | { return match.getElapsedSeconds() > this.seconds; } 39 | 40 | @Override 41 | public void updateReferee(Player ref) 42 | { 43 | AutoRefMatch.messageReferee(ref, "team", getOwner().getName(), 44 | "goal", "time", Long.toString(seconds)); 45 | } 46 | 47 | @Override 48 | public BlockData getItem() { return null; } 49 | 50 | @Override 51 | public Location getTarget() { return null; } 52 | 53 | @Override 54 | public Element toElement() 55 | { return new Element("time").setText(printTime(seconds)); } 56 | 57 | public static String printTime(long sec) 58 | { 59 | long min = sec / 60L, hrs = min / 60L; 60 | return String.format("%d:%02d:%02d", hrs, min%60L, sec%60L); 61 | } 62 | 63 | public static long parseTime(String time) 64 | { 65 | Pattern pattern = Pattern.compile("(((\\d*):)?(\\d{1,2}):)?(\\d{1,2})", Pattern.CASE_INSENSITIVE); 66 | Matcher match = pattern.matcher(time); 67 | 68 | // if the time matches the format 69 | if (match.matches()) try 70 | { 71 | int hrs = match.group(3) == null ? 0 : Integer.parseInt(match.group(3)); 72 | int min = match.group(4) == null ? 0 : Integer.parseInt(match.group(4)); 73 | int sec = match.group(5) == null ? 0 : Integer.parseInt(match.group(5)); 74 | return sec + 60L*(min + 60L*hrs); 75 | } 76 | catch (NumberFormatException e) { } 77 | 78 | // fallback: return an impossibly large time value 79 | return Long.MAX_VALUE; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/util/commands/CommandDocumentationGenerator.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.util.commands; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.lang.reflect.Method; 6 | import java.util.Collections; 7 | import java.util.List; 8 | import java.util.Set; 9 | 10 | import org.apache.commons.io.FileUtils; 11 | import org.apache.commons.lang3.StringUtils; 12 | 13 | import com.google.common.collect.Lists; 14 | import com.google.common.collect.Sets; 15 | 16 | public class CommandDocumentationGenerator 17 | { 18 | @SuppressWarnings("unchecked") 19 | private static Set> commandHandlers = Sets.newHashSet 20 | ( org.mctourney.autoreferee.commands.PlayerCommands.class 21 | , org.mctourney.autoreferee.commands.SpectatorCommands.class 22 | , org.mctourney.autoreferee.commands.AdminCommands.class 23 | , org.mctourney.autoreferee.commands.ConfigurationCommands.class 24 | , org.mctourney.autoreferee.commands.PracticeCommands.class 25 | ); 26 | 27 | public static void generateDocumentationFile(File file) 28 | { 29 | List commandLines = Lists.newArrayList(); 30 | for (Class handler : commandHandlers) 31 | for (Method method : handler.getDeclaredMethods()) 32 | { 33 | AutoRefCommand cmd = method.getAnnotation(AutoRefCommand.class); 34 | AutoRefPermission perm = method.getAnnotation(AutoRefPermission.class); 35 | 36 | if (cmd != null && !cmd.description().isEmpty()) 37 | { 38 | String usage = cmd.argmax() > 0 ? " " : ""; 39 | if (!cmd.usage().isEmpty()) usage = cmd.usage(); 40 | 41 | String c = StringUtils.join(cmd.name(), ' '); 42 | usage = usage.replace("", "/" + c); 43 | 44 | if (usage.contains("|")) System.err.println(String.format( 45 | "Usage string for '/%s' contains a '|'", StringUtils.join(cmd.name(), ' '))); 46 | 47 | commandLines.add(String.format("%s|%s|%s|%s|%d|%d|%s|%s", 48 | // command execution 49 | c, 50 | 51 | // options list (to be parsed) 52 | cmd.options(), 53 | 54 | // options help info, if any 55 | StringUtils.join(cmd.opthelp(), '#'), 56 | 57 | // necessary permissions nodes 58 | StringUtils.join(perm.nodes(), ','), 59 | 60 | // permission level required 61 | perm.role().ordinal(), 62 | 63 | // can command be used from console? 64 | perm.console() ? 1 : 0, 65 | 66 | // text description (must be last) 67 | cmd.description(), 68 | 69 | // usage string 70 | usage 71 | )); 72 | } 73 | } 74 | 75 | Collections.sort(commandLines); 76 | 77 | try { FileUtils.writeLines(file, commandLines); } 78 | catch (IOException e) { e.printStackTrace(); } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/goals/CoreGoal.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.goals; 2 | 3 | import org.bukkit.Location; 4 | import org.bukkit.entity.Player; 5 | import org.bukkit.event.block.BlockFromToEvent; 6 | 7 | import org.jdom2.Element; 8 | 9 | import org.mctourney.autoreferee.AutoRefMatch; 10 | import org.mctourney.autoreferee.AutoRefTeam; 11 | import org.mctourney.autoreferee.regions.AutoRefRegion; 12 | import org.mctourney.autoreferee.util.BlockData; 13 | 14 | public class CoreGoal extends AutoRefGoal 15 | { 16 | private boolean broken; 17 | private AutoRefRegion region; 18 | private long range = 0L; 19 | 20 | public CoreGoal(AutoRefTeam team, AutoRefRegion region, long range) 21 | { super(team); this.region = region; this.range = range; } 22 | 23 | public CoreGoal(AutoRefTeam team, AutoRefRegion region) 24 | { this(team, region, 0L); } 25 | 26 | private CoreGoal(AutoRefTeam team, CoreGoal goal) 27 | { this(team, goal.region, goal.range); } 28 | 29 | public CoreGoal(AutoRefTeam team, Element elt) 30 | { 31 | super(team); 32 | this.region = AutoRefRegion.fromElement(team.getMatch(), elt.getChildren().get(0)); 33 | 34 | if (elt.getAttribute("range") != null) 35 | try { this.range = Long.parseLong(elt.getAttributeValue("range").trim()); } 36 | catch (NumberFormatException e) { e.printStackTrace(); } 37 | } 38 | 39 | @Override 40 | public CoreGoal copy() 41 | { return this.copy(this.owner); } 42 | 43 | @Override 44 | public CoreGoal copy(AutoRefTeam team) 45 | { return new CoreGoal(team, this); } 46 | 47 | public long getRange() 48 | { return this.range; } 49 | 50 | public void setRange(long range) 51 | { this.range = range; } 52 | 53 | public void checkSatisfied(BlockFromToEvent event) 54 | { 55 | final Location fm = event.getBlock().getLocation(); 56 | final Location to = event.getToBlock().getLocation(); 57 | 58 | if (region != null && region.distanceToRegion(fm) <= range && 59 | region.distanceToRegion(to) > range) broken = true; 60 | } 61 | 62 | @Override 63 | public boolean isSatisfied(AutoRefMatch match) 64 | { return broken; } 65 | 66 | @Override 67 | public String toString() 68 | { 69 | return "CORE"; 70 | } 71 | 72 | @Override 73 | public void updateReferee(Player ref) 74 | { 75 | AutoRefMatch.messageReferee(ref, "team", getOwner().getName(), 76 | "goal", "core", region.toString(), Boolean.toString(broken)); 77 | } 78 | 79 | @Override 80 | public BlockData getItem() { return null; } 81 | 82 | @Override 83 | public Location getTarget() { return null; } 84 | 85 | @Override 86 | public Element toElement() 87 | { 88 | if (region == null) 89 | throw new IllegalStateException("Not a valid CoreGoal: Requires a valid region."); 90 | 91 | Element elt = new Element("core"); 92 | if (range > 0L) elt.setAttribute("range", Long.toString(range)); 93 | elt.addContent(region.toElement()); 94 | return elt; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/util/MapImageGenerator.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.util; 2 | 3 | import java.awt.image.RenderedImage; 4 | import java.awt.image.BufferedImage; 5 | import java.awt.image.WritableRaster; 6 | import java.io.File; 7 | import java.io.IOException; 8 | import java.io.InputStreamReader; 9 | import java.util.Map; 10 | 11 | import org.bukkit.Material; 12 | import org.bukkit.World; 13 | import org.bukkit.block.Block; 14 | 15 | import org.apache.commons.codec.binary.Base64; 16 | import org.apache.commons.io.FileUtils; 17 | 18 | import com.google.common.collect.Maps; 19 | import com.google.common.io.LineReader; 20 | 21 | import org.mctourney.autoreferee.AutoReferee; 22 | 23 | public class MapImageGenerator 24 | { 25 | private static Map blockColors; 26 | static 27 | { 28 | blockColors = Maps.newHashMap(); 29 | LineReader blocks = new LineReader(new InputStreamReader( 30 | AutoReferee.getInstance().getResource("colors.csv"))); 31 | 32 | try 33 | { 34 | String line; while ((line = blocks.readLine()) != null) 35 | { 36 | String[] parts = line.split("\\s+"); 37 | if (parts.length == 5) try 38 | { 39 | BlockData blockdata = new BlockData(Material.getMaterial(Integer.parseInt(parts[0])), 40 | Integer.valueOf(parts[1]).byteValue()); 41 | blockColors.put(blockdata, new int[]{ Integer.parseInt(parts[2]), 42 | Integer.parseInt(parts[3]), Integer.parseInt(parts[4]), 255 }); 43 | } 44 | catch (NumberFormatException e) 45 | { e.printStackTrace(); } 46 | } 47 | } catch (IOException e) 48 | { e.printStackTrace(); } 49 | } 50 | 51 | public static RenderedImage generateFromWorld(World world, int min_x, int max_x, int min_z, int max_z) 52 | { 53 | int w = max_x - min_x + 1; 54 | int h = max_z - min_z + 1; 55 | 56 | BufferedImage buffer = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); 57 | WritableRaster raster = buffer.getRaster(); 58 | 59 | for (int x = 0; x < w; ++x) 60 | for (int z = 0; z < h; ++z) 61 | raster.setPixel(x, z, getPixelAt(world, min_x + x, min_z + z)); 62 | 63 | return buffer; 64 | } 65 | 66 | private static int[] getPixelAt(World world, int x, int z) 67 | { 68 | Block block = getHighestBlockAt(world, x, z); 69 | int[] color = blockColors.get(BlockData.fromBlock(block)); 70 | return color == null ? new int[]{ 0, 0, 0, 0 } : color; 71 | } 72 | 73 | private static Block getHighestBlockAt(World world, int x, int z) 74 | { return world.getHighestBlockAt(x, z).getRelative(0, -1, 0); } 75 | 76 | public static String imageToDataURI(File file, String type) 77 | { 78 | try 79 | { 80 | // convert image to a data URI using base64 81 | return String.format("data:%s;base64,%s", type, 82 | Base64.encodeBase64String(FileUtils.readFileToByteArray(file)).replaceAll("\\s+", "")); 83 | } 84 | catch (IOException e) { e.printStackTrace(); return null; } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/goals/ScoreRegionGoal.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.goals; 2 | 3 | import java.util.Set; 4 | 5 | import org.bukkit.Location; 6 | import org.bukkit.World; 7 | import org.bukkit.entity.Player; 8 | 9 | import org.mctourney.autoreferee.AutoRefMatch; 10 | import org.mctourney.autoreferee.AutoRefTeam; 11 | import org.mctourney.autoreferee.regions.AutoRefRegion; 12 | import org.mctourney.autoreferee.regions.CuboidRegion; 13 | import org.mctourney.autoreferee.util.BlockData; 14 | import org.mctourney.autoreferee.util.LocationUtil; 15 | 16 | import org.jdom2.Element; 17 | 18 | import com.google.common.collect.Sets; 19 | 20 | public class ScoreRegionGoal extends ScoreGoal 21 | { 22 | protected final Set regions = Sets.newHashSet(); 23 | protected Location tpto = null; 24 | 25 | protected double score = 0; 26 | 27 | public ScoreRegionGoal(AutoRefTeam team, AutoRefRegion ...regions) 28 | { 29 | super(team); 30 | this.regions.addAll(Sets.newHashSet(regions)); 31 | } 32 | 33 | public ScoreRegionGoal(AutoRefTeam team, Element elt) 34 | { 35 | this(team); 36 | for (Element child : elt.getChildren()) 37 | { 38 | AutoRefRegion reg = AutoRefRegion.fromElement(team.getMatch(), child); 39 | if (reg != null) this.regions.add(reg); 40 | } 41 | } 42 | 43 | public ScoreRegionGoal(AutoRefTeam team, ScoreRegionGoal scoreRegionGoal) 44 | { this(team, scoreRegionGoal.regions.toArray(new AutoRefRegion[]{})); } 45 | 46 | @Override 47 | protected AutoRefGoal getGoalSettings(AutoRefTeam team, Element elt) 48 | { 49 | World world = team.getMatch().getWorld(); 50 | if (elt.getAttribute("tp") != null) 51 | tpto = LocationUtil.fromCoords(world, elt.getAttributeValue("tp")); 52 | 53 | return super.getGoalSettings(team, elt); 54 | } 55 | 56 | @Override 57 | public ScoreRegionGoal copy() 58 | { return this.copy(this.owner); } 59 | 60 | @Override 61 | public ScoreRegionGoal copy(AutoRefTeam team) 62 | { return new ScoreRegionGoal(team, this); } 63 | 64 | @Override 65 | public void updateReferee(Player ref) 66 | { 67 | } 68 | 69 | public double getScore(AutoRefMatch match) 70 | { return this.score; } 71 | 72 | public void addScore(double v) 73 | { this.score += v; } 74 | 75 | @Override 76 | public BlockData getItem() 77 | { return null; } 78 | 79 | @Override 80 | public Location getTarget() 81 | { 82 | CuboidRegion cube = null; 83 | for (AutoRefRegion reg : this.regions) 84 | cube = AutoRefRegion.combine(cube, reg); 85 | return cube == null ? null : cube.getGroundedCenter(); 86 | } 87 | 88 | @Override 89 | public String toString() 90 | { return "REGIONGOAL"; } 91 | 92 | @Override 93 | public Element toElement() 94 | { 95 | Element elt = new Element("scorezone"); 96 | for (AutoRefRegion reg : regions) 97 | elt.addContent(reg.toElement()); 98 | return elt; 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/main/resources/examples/kits.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Direct Fire 4 | 1.1 5 | 6 | Vechs 7 | 8 | 9 | 10 | 11 | 12 | 13 | Right 14 | 15 | 16 | 17 | 18 | 19 | Left 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | Right 33 | 34 | 35 | 36 | Left 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | true 55 | true 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 | HARD 95 | 96 | 97 | 8am 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /src/main/resources/plugin.yml: -------------------------------------------------------------------------------- 1 | name: AutoReferee 2 | main: org.mctourney.autoreferee.AutoReferee 3 | version: 2.8.4 4 | author: "authorblues, net" 5 | load: startup 6 | 7 | softdepend: 8 | - WorldEdit 9 | 10 | commands: 11 | autoref: 12 | aliases: [ar, autoreferee] 13 | description: AutoReferee configuration 14 | usage: / [] [args...] 15 | zone: 16 | description: Set a region's ownership 17 | usage: / |start 18 | zones: 19 | description: Show a list of all zones 20 | usage: / 21 | matchinfo: 22 | aliases: [info, minfo, mi] 23 | description: Show info about current match 24 | usage: / 25 | joinmatch: 26 | description: Join another player's match 27 | usage: / 28 | listmatches: 29 | aliases: [matchlist, matches] 30 | description: List all matches available on the server 31 | usage: / 32 | leavematch: 33 | aliases: [lobby] 34 | description: Leave the current match 35 | usage: / 36 | setaccess: 37 | description: Set access type of the current match 38 | usage: / 39 | jointeam: 40 | aliases: [join, j] 41 | description: Set player's team 42 | usage: / [] [] 43 | leaveteam: 44 | aliases: leave 45 | description: Remove player's team 46 | usage: / [] 47 | ready: 48 | description: Mark team as ready to play 49 | usage: / -tfyn 50 | viewinventory: 51 | aliases: vi 52 | description: View the inventory of the player 53 | usage: / [-p] 54 | artp: 55 | aliases: [atp] 56 | description: Teleport spectators safely 57 | usage: / [] 58 | announce: 59 | aliases: [a, ann] 60 | description: Make an announcement to players and streamers 61 | usage: / 62 | broadcast: 63 | aliases: [b, bcast] 64 | description: Make a broadcast to players and streamers 65 | usage: / 66 | notify: 67 | aliases: [n] 68 | description: Notify streamers and referees of a matter of interest 69 | usage: / 70 | scoreboard: 71 | description: Replacement for Bukkit's /scoreboard command 72 | usage: / ... 73 | time: 74 | description: Replacement for Minecraft's /time command 75 | usage: / [set, add] 76 | 77 | permissions: 78 | autoreferee.*: 79 | description: Access to all AutoReferee features 80 | default: op 81 | children: 82 | autoreferee.admin: true 83 | autoreferee.admin: 84 | description: AutoReferee administrators 85 | default: false 86 | children: 87 | autoreferee.configure: true 88 | autoreferee.referee: true 89 | autoreferee.configure: 90 | description: AutoReferee configuration 91 | default: false 92 | autoreferee.streamer: 93 | description: AutoReferee streamer 94 | default: false 95 | children: 96 | autoreferee.referee: true 97 | autoreferee.referee: 98 | description: AutoReferee referees 99 | default: false 100 | children: 101 | autoreferee.player: true 102 | autoreferee.player: 103 | description: AutoReferee players 104 | default: true 105 | children: 106 | bukkit.command.kill: false 107 | -------------------------------------------------------------------------------- /src/main/resources/colors.csv: -------------------------------------------------------------------------------- 1 | 1 -1 120 120 120 2 | 2 -1 117 176 73 3 | 3 -1 134 96 67 4 | 4 -1 115 115 115 5 | 5 -1 157 128 79 6 | 6 -1 120 120 120 7 | 7 -1 84 84 84 8 | 8 -1 38 92 255 9 | 9 -1 38 92 255 10 | 10 -1 255 90 0 11 | 11 -1 255 90 0 12 | 12 -1 218 210 158 13 | 13 -1 136 126 126 14 | 14 -1 143 140 125 15 | 15 -1 136 130 127 16 | 16 -1 115 115 115 17 | 17 0 102 81 51 18 | 17 1 75 44 24 19 | 17 2 191 191 191 20 | 17 3 75 44 24 21 | 18 -1 60 192 41 22 | 19 -1 193 193 65 23 | 20 -1 255 255 255 24 | 21 -1 23 68 196 25 | 22 -1 23 68 196 26 | 23 -1 96 96 96 27 | 24 -1 218 210 158 28 | 25 -1 125 91 38 29 | 26 -1 200 20 20 30 | 27 -1 150 134 102 31 | 28 -1 150 134 102 32 | 29 -1 157 128 79 33 | 30 -1 138 145 145 34 | 31 -1 97 156 53 35 | 32 -1 75 44 24 36 | 33 -1 157 128 79 37 | 34 -1 157 128 79 38 | 35 0 222 222 222 39 | 35 1 204 111 48 40 | 35 2 166 66 175 41 | 35 3 91 121 185 42 | 35 4 170 158 24 43 | 35 5 51 165 42 44 | 35 6 190 115 135 45 | 35 7 58 58 58 46 | 35 8 138 145 145 47 | 35 9 34 102 131 48 | 35 10 113 47 171 49 | 35 11 34 44 134 50 | 35 12 75 44 24 51 | 35 13 49 67 21 52 | 35 14 143 39 36 53 | 35 15 24 20 20 54 | 37 -1 255 255 0 55 | 38 -1 255 0 0 56 | 39 -1 204 153 120 57 | 40 -1 255 43 43 58 | 41 -1 232 245 46 59 | 42 -1 191 191 191 60 | 43 0 200 200 200 61 | 43 1 218 210 158 62 | 43 2 157 128 79 63 | 43 3 115 115 115 64 | 43 4 170 86 62 65 | 43 5 200 200 200 66 | 43 6 200 200 200 67 | 44 0 200 200 200 68 | 44 1 218 210 158 69 | 44 2 157 128 79 70 | 44 3 115 115 115 71 | 44 4 170 86 62 72 | 44 5 200 200 200 73 | 44 6 200 200 200 74 | 44 8 200 200 200 75 | 44 9 218 210 158 76 | 44 10 157 128 79 77 | 44 11 115 115 115 78 | 44 12 170 86 62 79 | 44 13 200 200 200 80 | 44 14 200 200 200 81 | 45 -1 170 86 62 82 | 46 -1 160 83 65 83 | 47 -1 125 91 38 84 | 48 -1 115 115 115 85 | 49 -1 26 11 43 86 | 50 -1 159 127 80 87 | 51 -1 255 170 30 88 | 52 -1 0 150 110 89 | 53 4 0 0 0 90 | 54 -1 125 91 38 91 | 55 -1 240 30 30 92 | 56 -1 129 140 143 93 | 57 -1 45 166 152 94 | 58 -1 114 88 56 95 | 59 -1 146 192 0 96 | 60 -1 95 58 30 97 | 61 -1 96 96 96 98 | 62 -1 96 96 96 99 | 63 -1 111 91 54 100 | 64 -1 136 109 67 101 | 65 -1 181 140 64 102 | 66 -1 150 134 102 103 | 67 -1 115 115 115 104 | 68 -1 111 91 54 105 | 69 -1 111 91 54 106 | 70 -1 120 120 120 107 | 71 -1 191 191 191 108 | 72 -1 111 91 54 109 | 73 -1 131 107 107 110 | 74 -1 131 107 107 111 | 75 -1 159 127 80 112 | 76 -1 159 127 80 113 | 77 -1 120 120 120 114 | 78 -1 255 255 255 115 | 79 -1 83 113 163 116 | 80 -1 250 250 250 117 | 81 -1 25 120 25 118 | 82 -1 151 157 169 119 | 83 -1 193 234 150 120 | 84 -1 125 91 38 121 | 85 -1 127 98 49 122 | 86 -1 255 115 0 123 | 87 -1 166 89 89 124 | 88 -1 133 109 94 125 | 89 -1 249 212 156 126 | 90 -1 140 0 196 127 | 91 -1 255 115 0 128 | 92 -1 234 234 234 129 | 93 -1 159 127 80 130 | 94 -1 159 127 80 131 | 95 -1 125 91 38 132 | 96 -1 111 91 54 133 | 97 -1 120 120 120 134 | 98 -1 120 120 120 135 | 99 -1 204 153 120 136 | 100 -1 255 43 43 137 | 101 -1 191 191 191 138 | 102 -1 255 255 255 139 | 103 -1 193 193 65 140 | 104 -1 146 192 0 141 | 105 -1 146 192 0 142 | 106 -1 60 192 41 143 | 107 -1 127 98 49 144 | 108 -1 170 86 62 145 | 109 -1 120 120 120 146 | 110 -1 110 98 104 147 | 111 -1 117 176 73 148 | 112 -1 166 89 89 149 | 113 -1 166 89 89 150 | 114 -1 166 89 89 151 | 115 -1 142 19 21 152 | 116 -1 88 23 22 153 | 117 -1 114 114 114 154 | 118 -1 74 74 74 155 | 119 -1 26 11 43 156 | 120 -1 113 133 104 157 | 121 -1 224 226 169 158 | 122 -1 26 11 43 159 | 123 -1 125 106 78 160 | 124 -1 249 212 156 161 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/util/QueryUtil.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.util; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.io.OutputStreamWriter; 6 | import java.io.StringWriter; 7 | import java.io.UnsupportedEncodingException; 8 | import java.net.HttpURLConnection; 9 | import java.net.URL; 10 | import java.net.URLConnection; 11 | import java.net.URLEncoder; 12 | import java.util.Map; 13 | import java.util.Set; 14 | 15 | import com.google.common.collect.Sets; 16 | import org.apache.commons.io.IOUtils; 17 | 18 | import org.apache.commons.lang.StringUtils; 19 | import org.mctourney.autoreferee.AutoReferee; 20 | 21 | public class QueryUtil 22 | { 23 | private static final String ENCODING = "UTF-8"; 24 | 25 | public static String getUserAgent() 26 | { 27 | AutoReferee instance = AutoReferee.getInstance(); 28 | String pluginName = instance.getDescription().getFullName(); 29 | return String.format("%s (%s)", pluginName, instance.getCommit()); 30 | } 31 | 32 | public static String syncGetQuery(String path, String params) throws IOException 33 | { return syncQuery(path, params, null); } 34 | 35 | public static String syncPostQuery(String path, String params) throws IOException 36 | { return syncQuery(path, null, params); } 37 | 38 | public static String syncPutQuery(String path, String params) throws IOException 39 | { return syncQuery(path, "PUT", null, params); } 40 | 41 | public static String syncQuery(String path, String getParams, String postParams) throws IOException 42 | { return syncQuery(path, null, getParams, postParams); } 43 | 44 | public static String syncQuery(String path, String method, String getParams, String postParams) throws IOException 45 | { 46 | OutputStreamWriter wr = null; 47 | InputStream rd = null; 48 | 49 | try 50 | { 51 | URL url = new URL(getParams == null ? path : String.format("%s?%s", path, getParams)); 52 | HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 53 | conn.setDoOutput(true); 54 | 55 | AutoReferee instance = AutoReferee.getInstance(); 56 | String pluginName = instance.getDescription().getFullName(); 57 | conn.setRequestProperty("User-Agent", String.format("%s (%s)", pluginName, instance.getCommit())); 58 | 59 | if (method != null) 60 | { 61 | conn.setRequestMethod(method); 62 | conn.addRequestProperty("Content-Type", "application/x-www-form-urlencoded"); 63 | } 64 | 65 | if (postParams != null) 66 | { 67 | wr = new OutputStreamWriter(conn.getOutputStream()); 68 | wr.write(postParams); wr.flush(); 69 | } 70 | 71 | StringWriter writer = new StringWriter(); 72 | IOUtils.copy(rd = conn.getInputStream(), writer); 73 | return writer.toString(); 74 | } 75 | 76 | // just drop out 77 | catch (IOException e) { throw e; } 78 | 79 | finally 80 | { 81 | try 82 | { 83 | // close the stream pointers 84 | if (wr != null) wr.close(); 85 | if (rd != null) rd.close(); 86 | } 87 | // meh. don't bother, if something goes wrong here. 88 | catch (Exception ignored) { } 89 | } 90 | } 91 | 92 | public static String prepareParams(Map paramMap) 93 | { 94 | Set params = Sets.newHashSet(); 95 | for (Map.Entry entry : paramMap.entrySet()) try 96 | { 97 | String val = URLEncoder.encode(entry.getValue(), ENCODING); 98 | params.add(String.format("%s=%s", entry.getKey(), val)); 99 | } 100 | catch (UnsupportedEncodingException e) 101 | { e.printStackTrace(); } 102 | 103 | return StringUtils.join(params, "&"); 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/goals/AutoRefGoal.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.goals; 2 | 3 | import java.lang.reflect.Constructor; 4 | import java.util.Map; 5 | 6 | import org.bukkit.Location; 7 | import org.bukkit.entity.Player; 8 | 9 | import org.jdom2.Element; 10 | 11 | import org.mctourney.autoreferee.AutoRefMatch; 12 | import org.mctourney.autoreferee.AutoRefTeam; 13 | import org.mctourney.autoreferee.util.BlockData; 14 | 15 | import com.google.common.collect.Maps; 16 | 17 | /** 18 | * Represents a condition for victory. 19 | * 20 | * @author authorblues 21 | */ 22 | public abstract class AutoRefGoal 23 | { 24 | public abstract boolean isSatisfied(AutoRefMatch match); 25 | public abstract void updateReferee(Player ref); 26 | 27 | public abstract BlockData getItem(); 28 | public abstract Location getTarget(); 29 | 30 | // for saving the data 31 | public abstract Element toElement(); 32 | 33 | // make a copy of this goal 34 | public abstract AutoRefGoal copy(); 35 | public abstract AutoRefGoal copy(AutoRefTeam team); 36 | 37 | /** 38 | * Represents the status of a tracked item. 39 | */ 40 | public static enum ItemStatus 41 | { 42 | NONE("none", 0.0), 43 | 44 | SEEN("found", 0.1), 45 | 46 | CARRYING("carry", 0.1), 47 | 48 | TARGET("target", 1000.0); 49 | 50 | private String msg; 51 | public double value; 52 | 53 | private ItemStatus(String m, double v) 54 | { msg = m; value = v; } 55 | 56 | @Override 57 | public String toString() 58 | { return msg; } 59 | } 60 | 61 | protected AutoRefTeam owner; 62 | private ItemStatus itemStatus = ItemStatus.NONE; 63 | 64 | public AutoRefGoal(AutoRefTeam team) 65 | { setOwner(team); } 66 | 67 | public void setOwner(AutoRefTeam team) 68 | { owner = team; } 69 | 70 | public AutoRefTeam getOwner() 71 | { return owner; } 72 | 73 | public boolean hasItem() 74 | { return getItem() != null; } 75 | 76 | public boolean canCraftItem() 77 | { return false; } 78 | 79 | public ItemStatus getItemStatus() 80 | { return itemStatus; } 81 | 82 | public void setItemStatus(ItemStatus s) 83 | { if (hasItem()) itemStatus = s; } 84 | 85 | public boolean hasTarget() 86 | { return getTarget() != null; } 87 | 88 | // default definition 89 | public double getScore(AutoRefMatch match) 90 | { return isSatisfied(match) ? 1000.0 : 0.0; } 91 | 92 | public boolean canBeCompleted(AutoRefMatch match) 93 | { return true; } 94 | 95 | protected AutoRefGoal getGoalSettings(AutoRefTeam team, Element elt) 96 | { 97 | return this; 98 | } 99 | 100 | private static Map> goalNames = Maps.newHashMap(); 101 | static 102 | { 103 | addGoalType("block", BlockGoal.class); 104 | addGoalType("core", CoreGoal.class); 105 | addGoalType("survive", SurvivalGoal.class); 106 | addGoalType("time", TimeGoal.class); 107 | addGoalType("deathmatch", ScoreDeathmatchGoal.class); 108 | addGoalType("dummy", ScoreDummyGoal.class); 109 | addGoalType("region", ScoreRegionGoal.class); 110 | } 111 | 112 | public static void addGoalType(String tag, Class cls) 113 | { goalNames.put(tag, cls); } 114 | 115 | public static AutoRefGoal fromElement(AutoRefTeam team, Element elt) 116 | { 117 | Class cls = goalNames.get(elt.getName()); 118 | if (cls == null) return null; 119 | 120 | try 121 | { 122 | Constructor cons = cls.getConstructor(AutoRefTeam.class, Element.class); 123 | return cons.newInstance(team, elt).getGoalSettings(team, elt); 124 | } 125 | catch (Exception e) { e.printStackTrace(); return null; } 126 | } 127 | } -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/util/worldsearch/WorkerAsyncSearchSnapshots.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.util.worldsearch; 2 | 3 | import java.util.Set; 4 | 5 | import org.apache.commons.lang.ArrayUtils; 6 | import org.apache.commons.lang.Validate; 7 | import org.bukkit.ChunkSnapshot; 8 | import org.bukkit.Material; 9 | import org.bukkit.scheduler.BukkitRunnable; 10 | import org.bukkit.util.Vector; 11 | import org.mctourney.autoreferee.util.BlockData; 12 | 13 | import com.google.common.collect.Sets; 14 | 15 | /** 16 | * Consumes: ObjectiveExhaustionMasterTask.snapshots
17 | * Output: ObjectiveExhaustionMasterTask.found
18 | * Output: ObjectiveExhaustionMasterTask.foundContainers
19 | * Cancellation: Self-cancels upon master.all_snapshots_added and queue empty 20 | * 21 | * Searches the ChunkSnapshots for the goal blocks. 22 | * 23 | * @author kane 24 | * 25 | */ 26 | public class WorkerAsyncSearchSnapshots extends BukkitRunnable 27 | { 28 | public volatile boolean finished = false; 29 | private ObjectiveExhaustionMasterTask master; 30 | 31 | public WorkerAsyncSearchSnapshots(ObjectiveExhaustionMasterTask task) 32 | { 33 | master = task; 34 | } 35 | 36 | @Override 37 | public void run() 38 | { 39 | // pre-clear, pass it on later 40 | boolean wasInterrupted = Thread.interrupted(); 41 | 42 | try 43 | { 44 | // Blocking run until everything's available 45 | while (!master.all_snapshots_added) 46 | { 47 | consume(master.snapshots.take()); 48 | } 49 | 50 | // Finish off by listening to special value 51 | ChunkSnapshot snap; 52 | while ((snap = master.snapshots.poll()) != null) 53 | { 54 | consume(snap); 55 | } 56 | } 57 | catch (IllegalArgumentException poisonSignal) 58 | { 59 | // thrown if null is recieved, which means we're done 60 | } 61 | catch (InterruptedException e) 62 | { 63 | e.printStackTrace(); 64 | wasInterrupted = true; 65 | } 66 | // Re-add null to the list, for the other workers to take 67 | master.snapshots.offer(null); 68 | 69 | finished = true; 70 | 71 | if (wasInterrupted) // pass it on 72 | Thread.currentThread().interrupt(); 73 | } 74 | 75 | private void consume(ChunkSnapshot snap) 76 | { 77 | Validate.notNull(snap); // send stop signal if poison-value 78 | 79 | Set goals = master.searching; // safe due to COW 80 | int[] interesting = buildInteresting(goals); 81 | 82 | int baseX = snap.getX() << 4; 83 | int baseZ = snap.getZ() << 4; 84 | 85 | for (int sy = 0; sy < 16; sy++) 86 | { 87 | if (snap.isSectionEmpty(sy)) 88 | continue; 89 | for (int py = sy << 4; py < (sy << 4) + 16; py++) 90 | for (int iz = 0; iz < 16; iz++) 91 | for (int ix = 0; ix < 16; ix++) 92 | { 93 | int block = snap.getBlockTypeId(ix, py, iz); 94 | if (ArrayUtils.contains(interesting, block)) 95 | { 96 | Vector pos = new Vector(baseX + ix, py, baseZ + iz); 97 | BlockData bd = new BlockData(Material.getMaterial(block), (byte) snap.getBlockData(ix, py, iz)); 98 | for (BlockData data : goals) 99 | if (data.equals(bd)) 100 | master.found.add(new _Entry(data, pos)); 101 | } 102 | } 103 | } 104 | } 105 | 106 | // Often this will just return the equivalent of new int[] { 35 } but whatever. 107 | private static int[] buildInteresting(Set goals) 108 | { 109 | Set filterGoals = Sets.newHashSet(); 110 | for (BlockData data : goals) 111 | { 112 | filterGoals.add(data.getMaterial().getId()); 113 | } 114 | return ArrayUtils.toPrimitive(filterGoals.toArray(new Integer[filterGoals.size()])); 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/AutoRefSpectator.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee; 2 | 3 | import org.bukkit.ChatColor; 4 | import org.bukkit.Location; 5 | import org.bukkit.entity.Player; 6 | import org.bukkit.potion.PotionEffect; 7 | import org.bukkit.potion.PotionEffectType; 8 | 9 | import org.mctourney.autoreferee.util.TeleportationUtil; 10 | 11 | public class AutoRefSpectator extends AutoRefPlayer 12 | { 13 | private AutoRefMatch match = null; 14 | private String cyclePlayer = null; 15 | 16 | private boolean nightVision = false; 17 | private boolean viewInventory = true; 18 | private boolean invisible = true; 19 | private boolean streamer; 20 | 21 | private Location prevLocation = null; 22 | 23 | public AutoRefSpectator(String name, AutoRefMatch match) 24 | { 25 | super(name, null); this.match = match; 26 | Player player = this.getPlayer(); 27 | 28 | this.streamer = player == null ? false 29 | : player.hasPermission("autoreferee.streamer"); 30 | } 31 | 32 | public AutoRefSpectator(Player player, AutoRefMatch match) 33 | { this(player.getName(), match); } 34 | 35 | public boolean isInvisible() 36 | { return invisible; } 37 | 38 | public void setInvisible(boolean vis) 39 | { this.invisible = vis; } 40 | 41 | public boolean isStreamer() 42 | { return streamer; } 43 | 44 | public void setStreamer(boolean b) 45 | { 46 | this.streamer = b; this.match.setupSpectators(this.getPlayer()); 47 | this.getPlayer().sendMessage(ChatColor.GREEN + "You are " + 48 | (this.streamer ? "now" : "no longer") + " in streamer mode!"); 49 | } 50 | 51 | @Override 52 | public AutoRefMatch getMatch() 53 | { return this.match; } 54 | 55 | public boolean hasNightVision() 56 | { return nightVision; } 57 | 58 | public void setNightVision(boolean b) 59 | { 60 | this.nightVision = b; 61 | if (this.hasClientMod()) AutoRefMatch.messageReferee(getPlayer(), 62 | "match", getMatch().getWorld().getName(), "nightvis", this.nightVision ? "1" : "0"); 63 | else this.applyNightVision(); 64 | } 65 | 66 | public void applyNightVision() 67 | { 68 | if (!isOnline() || this.hasClientMod()) return; 69 | getPlayer().removePotionEffect(PotionEffectType.NIGHT_VISION); 70 | 71 | PotionEffect nightvis = new PotionEffect(PotionEffectType.NIGHT_VISION, Integer.MAX_VALUE, 0); 72 | if (this.nightVision) getPlayer().addPotionEffect(nightvis); 73 | } 74 | 75 | public void cycleNextPlayer() 76 | { 77 | AutoRefMatch match = getMatch(); 78 | for (int i = 0; i < match.getPlayers().size(); ++i) 79 | { 80 | this.cyclePlayer = match.getCycleNextPlayer(this.cyclePlayer); 81 | AutoRefPlayer apl = match.getPlayer(this.cyclePlayer); 82 | 83 | if (apl != null) 84 | { 85 | Location tploc = TeleportationUtil.playerTeleport(apl); 86 | if (tploc != null) { getPlayer().teleport(tploc); break; } 87 | } 88 | } 89 | } 90 | 91 | public void cyclePrevPlayer() 92 | { 93 | AutoRefMatch match = getMatch(); 94 | for (int i = 0; i < match.getPlayers().size(); ++i) 95 | { 96 | this.cyclePlayer = match.getCyclePrevPlayer(this.cyclePlayer); 97 | AutoRefPlayer apl = match.getPlayer(this.cyclePlayer); 98 | 99 | if (apl != null) 100 | { 101 | Location tploc = TeleportationUtil.playerTeleport(apl); 102 | if (tploc != null) { getPlayer().teleport(tploc); break; } 103 | } 104 | } 105 | } 106 | 107 | public boolean canViewInventory() 108 | { return viewInventory; } 109 | 110 | public void setViewInventory(boolean vi) 111 | { this.viewInventory = vi; } 112 | 113 | public Location prevLocation() 114 | { return prevLocation; } 115 | 116 | public void setPrevLocation(Location loc) 117 | { this.prevLocation = loc; } 118 | } 119 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/listeners/lobby/AutoLobbyListener.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.listeners.lobby; 2 | 3 | import org.bukkit.entity.Player; 4 | 5 | import org.bukkit.event.EventHandler; 6 | import org.bukkit.event.EventPriority; 7 | import org.bukkit.scheduler.BukkitRunnable; 8 | import org.mctourney.autoreferee.AutoRefMap; 9 | import org.mctourney.autoreferee.AutoRefMatch; 10 | import org.mctourney.autoreferee.AutoRefTeam; 11 | import org.mctourney.autoreferee.AutoReferee; 12 | import org.mctourney.autoreferee.event.match.MatchStartEvent; 13 | import org.mctourney.autoreferee.event.player.PlayerMatchJoinEvent; 14 | import org.mctourney.autoreferee.event.player.PlayerTeamJoinEvent; 15 | 16 | public class AutoLobbyListener extends LobbyListener 17 | { 18 | public AutoLobbyListener(AutoReferee plugin) 19 | { 20 | super(plugin); 21 | AutoRefMatch.giveMatchInfoBooks = false; 22 | } 23 | 24 | @Override 25 | protected void lobbyLoadMap(Player player, AutoRefMap map) 26 | { 27 | AutoRefMatch match = findSuitableMatch(map); 28 | if (match != null) match.joinMatch(player); 29 | else _loadMap(player, map, null); 30 | } 31 | 32 | private AutoRefMatch findSuitableMatch(AutoRefMap map) 33 | { 34 | for (AutoRefMatch match : plugin.getMatches()) 35 | if (match.getCurrentState().isBeforeMatch() && map.equals(match.getMap())) 36 | return match; 37 | return null; 38 | } 39 | 40 | protected class PlayerJoinTask extends BukkitRunnable 41 | { 42 | private AutoRefMatch match; 43 | private Player player; 44 | 45 | public PlayerJoinTask(AutoRefMatch match, Player player) 46 | { this.match = match; this.player = player; } 47 | 48 | @Override 49 | public void run() 50 | { 51 | if (match.getCurrentState().isBeforeMatch() && match.getPlayerTeam(player) == null 52 | && !player.hasPermission("autoreferee.referee")) 53 | { 54 | match.joinTeam(player, match.getArbitraryTeam(), 55 | PlayerTeamJoinEvent.Reason.AUTOMATIC, false); 56 | } 57 | } 58 | } 59 | 60 | @EventHandler(priority=EventPriority.HIGHEST, ignoreCancelled=true) 61 | public void matchJoin(PlayerMatchJoinEvent event) 62 | { new PlayerJoinTask(event.getMatch(), event.getPlayer()).runTask(plugin); } 63 | 64 | private class MatchStarterTask extends BukkitRunnable 65 | { 66 | private final AutoRefMatch match; 67 | 68 | public MatchStarterTask(AutoRefMatch match) 69 | { this.match = match; } 70 | 71 | @Override 72 | public void run() 73 | { 74 | // starting a match is based purely on teams being filled 75 | boolean ready = true; 76 | for (AutoRefTeam t : match.getTeams()) 77 | ready &= t.getPlayers().size() >= t.getMaxSize(); 78 | if (ready) match.startMatch(MatchStartEvent.Reason.AUTOMATIC); 79 | } 80 | } 81 | 82 | @EventHandler(priority=EventPriority.HIGHEST, ignoreCancelled=true) 83 | public void teamJoin(PlayerTeamJoinEvent event) 84 | { 85 | AutoRefTeam team = event.getTeam(); 86 | if (team.getPlayers().size() >= team.getMaxSize()) 87 | event.setCancelled(true); 88 | 89 | // schedule a check to see if we need to start the match 90 | if (team.getMatch().getCurrentState().isBeforeMatch()) 91 | new MatchStarterTask(team.getMatch()).runTask(plugin); 92 | } 93 | 94 | @EventHandler(priority=EventPriority.HIGHEST, ignoreCancelled=true) 95 | public void matchStart(MatchStartEvent event) 96 | { 97 | // if the match is being manually started, let it happen(?) 98 | if (event.getReason() == MatchStartEvent.Reason.READY) return; 99 | 100 | boolean canStart = true; 101 | for (AutoRefTeam t : event.getMatch().getTeams()) 102 | canStart &= t.getPlayers().size() >= t.getMinSize(); 103 | if (!canStart) event.setCancelled(true); 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/goals/scoreboard/AutoRefObjective.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.goals.scoreboard; 2 | 3 | import java.util.Collections; 4 | import java.util.Set; 5 | 6 | import org.bukkit.Bukkit; 7 | import org.bukkit.ChatColor; 8 | import org.bukkit.OfflinePlayer; 9 | import org.bukkit.scoreboard.Objective; 10 | 11 | import org.mctourney.autoreferee.AutoRefTeam; 12 | import org.mctourney.autoreferee.goals.AutoRefGoal; 13 | 14 | import com.google.common.collect.Sets; 15 | 16 | public abstract class AutoRefObjective 17 | { 18 | protected Objective objective; 19 | protected OfflinePlayer title; 20 | 21 | protected AutoRefTeam team; 22 | protected Set goals; 23 | 24 | protected ChatColor color = null; 25 | protected String name; 26 | protected int value = 0; 27 | 28 | // does this objective need to be set non-zero still 29 | private boolean _needsZeroFix = true; 30 | 31 | public AutoRefObjective(Objective objective, AutoRefTeam team, String name, int value, ChatColor color) 32 | { 33 | // reference to the actual scoreboard objective where we drop our entries 34 | assert objective != null : "Objective cannot be null"; 35 | this.objective = objective; 36 | 37 | // save the owning team 38 | this.team = team; 39 | this.color = color; 40 | this.goals = Sets.newHashSet(); 41 | 42 | // objective name and value 43 | this.setName(name); 44 | this.setValue(value); 45 | } 46 | 47 | public AutoRefObjective(Objective objective, AutoRefTeam team, String name, int value) 48 | { this(objective, team, name, value, team.getColor()); } 49 | 50 | public abstract void update(); 51 | 52 | public void setName(String name) 53 | { 54 | this.name = name; 55 | 56 | // compute display name (color + name, truncated) 57 | String disp = (this.color == null ? "" : this.color.toString()) + name; 58 | if (disp.length() > 16) disp = disp.substring(0, 13) + "..."; 59 | 60 | // if we need to replace the title object, do so 61 | if (this.title == null || !this.title.getName().equals(disp)) 62 | { 63 | if (this.title != null) 64 | this.objective.getScoreboard().resetScores(this.title); 65 | this.title = Bukkit.getOfflinePlayer(disp); 66 | this._needsZeroFix = true; 67 | } 68 | 69 | // no matter what, update the score 70 | this.setValue(this.value); 71 | } 72 | 73 | public String getName() 74 | { return this.name; } 75 | 76 | public void setValue(int value) 77 | { 78 | this.value = value; 79 | 80 | // set to 1 first to try to force zeroes to show up 81 | if (this.value == 0 && this._needsZeroFix) 82 | this.objective.getScore(this.title).setScore(1); 83 | 84 | // set the correct value 85 | this._needsZeroFix = false; 86 | this.objective.getScore(this.title).setScore(this.value); 87 | } 88 | 89 | public int getValue() 90 | { return this.value; } 91 | 92 | public void setColor(ChatColor color) 93 | { 94 | if (color == ChatColor.RESET) color = null; 95 | this.color = color; this.setName(this.getName()); 96 | } 97 | 98 | public ChatColor getColor() 99 | { return this.color; } 100 | 101 | public Set getGoals() 102 | { return Collections.unmodifiableSet(goals); } 103 | 104 | @Override 105 | public String toString() 106 | { return String.format("%s[%s=%d]", this.getClass().getSimpleName(), this.getName(), this.getValue()); } 107 | 108 | public static Set fromTeam(Objective objective, AutoRefTeam team) 109 | { 110 | Set objectives = Sets.newHashSet(); 111 | 112 | objectives.addAll(BlockObjective.fromTeam(objective, team)); 113 | objectives.addAll(SurvivalObjective.fromTeam(objective, team)); 114 | objectives.addAll(ScoreObjective.fromTeam(objective, team)); 115 | 116 | return objectives; 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /src/main/resources/webstats/report.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | #title# | AutoReferee Match Report 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 |
26 | 27 | 28 |
29 |

AutoReferee Match Report

30 |

#title#

31 |
32 | 33 | 34 |
35 | 36 |
37 | 38 |
39 |

Match Summary

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 | #xtra-details# 71 | 72 |
Match Name:#title#
Map Name:#map#
Date:#date#
Match Length:#length#
Winners:#winners#
Referees:#referees#
Streamers:#streamers#
73 |
74 | 75 |
76 |

Teams

77 |
78 | #teams# 79 |
80 |
81 | 82 |
83 | 84 | 85 | 89 | 90 | 91 |

Match Log

92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | #transcript# 102 | 103 |
EventTime
104 | 105 |

Player Stats

106 |

Hover over headers for details.

107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | #plyr-stats# 120 | 121 |
RNameK/ADACCNemesis
122 |
123 | 124 | 125 | 129 | 130 |
131 |
132 | 133 | 134 | 135 | 136 | 140 | 141 | 142 | 143 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/util/midi/MidiUtil.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.util.midi; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.util.Set; 7 | 8 | import javax.sound.midi.InvalidMidiDataException; 9 | import javax.sound.midi.MidiSystem; 10 | import javax.sound.midi.MidiUnavailableException; 11 | import javax.sound.midi.Sequence; 12 | import javax.sound.midi.Sequencer; 13 | 14 | import org.bukkit.Sound; 15 | import org.bukkit.entity.Player; 16 | 17 | /** 18 | * Utility for playing midi files for players to hear. 19 | * 20 | * @author authorblues 21 | */ 22 | public class MidiUtil 23 | { 24 | private static void playMidi(Sequence seq, float tempo, Set listeners) 25 | throws InvalidMidiDataException, IOException, MidiUnavailableException 26 | { 27 | Sequencer sequencer = MidiSystem.getSequencer(false); 28 | sequencer.setSequence(seq); 29 | sequencer.open(); 30 | 31 | // slow it down just a bit 32 | sequencer.setTempoFactor(tempo); 33 | 34 | NoteBlockReceiver noteblockRecv = new NoteBlockReceiver(listeners); 35 | sequencer.getTransmitter().setReceiver(noteblockRecv); 36 | sequencer.start(); 37 | } 38 | 39 | public static void playMidi(File file, float tempo, Set listeners) 40 | throws InvalidMidiDataException, IOException, MidiUnavailableException 41 | { playMidi(MidiSystem.getSequence(file), tempo, listeners); } 42 | 43 | public static void playMidi(InputStream stream, float tempo, Set listeners) 44 | throws InvalidMidiDataException, IOException, MidiUnavailableException 45 | { playMidi(MidiSystem.getSequence(stream), tempo, listeners); } 46 | 47 | public static boolean playMidiQuietly(File file, float tempo, Set listeners) 48 | { 49 | try { MidiUtil.playMidi(file, tempo, listeners); } 50 | catch (MidiUnavailableException e) { e.printStackTrace(); return false; } 51 | catch (InvalidMidiDataException e) { e.printStackTrace(); return false; } 52 | catch (IOException e) { e.printStackTrace(); return false; } 53 | 54 | return true; 55 | } 56 | public static boolean playMidiQuietly(InputStream stream, float tempo, Set listeners) 57 | { 58 | try { MidiUtil.playMidi(stream, tempo, listeners); } 59 | catch (MidiUnavailableException e) { e.printStackTrace(); return false; } 60 | catch (InvalidMidiDataException e) { e.printStackTrace(); return false; } 61 | catch (IOException e) { e.printStackTrace(); return false; } 62 | 63 | return true; 64 | } 65 | 66 | public static boolean playMidiQuietly(File file, Set listeners) 67 | { return playMidiQuietly(file, 1.0f, listeners); } 68 | 69 | public static boolean playMidiQuietly(InputStream stream, Set listeners) 70 | { return playMidiQuietly(stream, 1.0f, listeners); } 71 | 72 | // provided by github.com/sk89q/craftbook 73 | private static final int[] instruments = { 74 | 0, 0, 0, 0, 0, 0, 0, 5, // 8 75 | 6, 0, 0, 0, 0, 0, 0, 0, // 16 76 | 0, 0, 0, 0, 0, 0, 0, 5, // 24 77 | 5, 5, 5, 5, 5, 5, 5, 5, // 32 78 | 6, 6, 6, 6, 6, 6, 6, 6, // 40 79 | 5, 5, 5, 5, 5, 5, 5, 2, // 48 80 | 5, 5, 5, 5, 0, 0, 0, 0, // 56 81 | 0, 0, 0, 0, 0, 0, 0, 0, // 64 82 | 0, 0, 0, 0, 0, 0, 0, 0, // 72 83 | 0, 0, 0, 0, 0, 0, 0, 0, // 80 84 | 0, 0, 0, 0, 0, 0, 0, 0, // 88 85 | 0, 0, 0, 0, 0, 0, 0, 0, // 96 86 | 0, 0, 0, 0, 0, 0, 0, 0, // 104 87 | 0, 0, 0, 0, 0, 0, 0, 0, // 112 88 | 1, 1, 1, 3, 1, 1, 1, 5, // 120 89 | 1, 1, 1, 1, 1, 2, 4, 3, // 128 90 | }; 91 | 92 | public static Sound patchToInstrument(int patch) 93 | { 94 | // look up the instrument matching the patch 95 | switch (instruments[patch]) 96 | { 97 | case 1: return Sound.NOTE_BASS_GUITAR; 98 | case 2: return Sound.NOTE_SNARE_DRUM; 99 | case 3: return Sound.NOTE_STICKS; 100 | case 4: return Sound.NOTE_BASS_DRUM; 101 | case 5: return Sound.NOTE_PLING; 102 | case 6: return Sound.NOTE_BASS; 103 | } 104 | 105 | // if no instrument match is found, use piano 106 | return Sound.NOTE_PIANO; 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/regions/CuboidRegion.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.regions; 2 | 3 | import java.util.Random; 4 | 5 | import org.bukkit.Location; 6 | import org.bukkit.World; 7 | 8 | import org.jdom2.Element; 9 | 10 | import org.mctourney.autoreferee.AutoRefMatch; 11 | import org.mctourney.autoreferee.util.LocationUtil; 12 | 13 | public class CuboidRegion extends AutoRefRegion 14 | { 15 | public double x1, y1, z1; 16 | public double x2, y2, z2; 17 | 18 | public World world; 19 | 20 | public CuboidRegion(Location v1, Location v2) 21 | { 22 | // if the two locations are from different worlds, quit 23 | assert v1.getWorld() == v2.getWorld(); 24 | 25 | world = v1.getWorld(); 26 | x1 = Math.min(v1.getX(), v2.getX()); x2 = Math.max(v1.getX(), v2.getX()); 27 | y1 = Math.min(v1.getY(), v2.getY()); y2 = Math.max(v1.getY(), v2.getY()); 28 | z1 = Math.min(v1.getZ(), v2.getZ()); z2 = Math.max(v1.getZ(), v2.getZ()); 29 | } 30 | 31 | public CuboidRegion(World world, double x1, double x2, double y1, double y2, double z1, double z2) 32 | { 33 | this.world = world; 34 | this.x1 = Math.min(x1, x2); this.x2 = Math.max(x1, x2); 35 | this.y1 = Math.min(y1, y2); this.y2 = Math.max(y1, y2); 36 | this.z1 = Math.min(z1, z2); this.z2 = Math.max(z1, z2); 37 | } 38 | 39 | public CuboidRegion(AutoRefMatch match, Element elt) 40 | { this(match.getWorld(), elt); } 41 | 42 | public CuboidRegion(World world, Element elt) 43 | { 44 | this( 45 | LocationUtil.fromCoords(world, elt.getAttributeValue("min")), 46 | LocationUtil.fromCoords(world, elt.getAttributeValue("max")) 47 | ); 48 | } 49 | 50 | public Element toElement() 51 | { 52 | return this.setRegionSettings(new Element("cuboid") 53 | .setAttribute("min", LocationUtil.toBlockCoords(this.getMinimumPoint())) 54 | .setAttribute("max", LocationUtil.toBlockCoords(this.getMaximumPoint()))); 55 | } 56 | 57 | @Override 58 | public int hashCode() 59 | { return getMinimumPoint().hashCode() ^ Integer.rotateLeft(getMaximumPoint().hashCode(), 16); } 60 | 61 | @Override 62 | public boolean equals(Object o) 63 | { return (o instanceof CuboidRegion) && hashCode() == o.hashCode(); } 64 | 65 | @Override 66 | public String toString() 67 | { 68 | return String.format("CUBOID(%s:%s), A=%d", 69 | LocationUtil.toBlockCoords(this.getMinimumPoint()), 70 | LocationUtil.toBlockCoords(this.getMaximumPoint()), 71 | (int)((x2-x1+1) * (y2-y1+1) * (z2-z1+1))); 72 | } 73 | 74 | public Location getMinimumPoint() 75 | { return new Location(world, x1, y1, z1); } 76 | 77 | public Location getMaximumPoint() 78 | { return new Location(world, x2, y2, z2); } 79 | 80 | public static CuboidRegion combine(CuboidRegion a, CuboidRegion b) 81 | { 82 | assert a.world == b.world; 83 | return new CuboidRegion(a.world, 84 | Math.min(a.x1, b.x1), Math.max(a.x2, b.x2), 85 | Math.min(a.y1, b.y1), Math.max(a.y2, b.y2), 86 | Math.min(a.z1, b.z1), Math.max(a.z2, b.z2)); 87 | } 88 | 89 | // distance from region, axially aligned (value less than actual distance, but 90 | // appropriate for measurements on cuboid regions) 91 | @Override 92 | public double distanceToRegion(Location v) 93 | { 94 | // garbage-in, garbage-out 95 | if (v == null || v.getWorld() != world) 96 | return Double.POSITIVE_INFINITY; 97 | 98 | double x = v.getX(), y = v.getY(), z = v.getZ(); 99 | Location mx = getMaximumPoint(), mn = getMinimumPoint(); 100 | 101 | // return maximum distance from this region 102 | // (max on all sides, axially-aligned) 103 | return CuboidRegion.multimax ( 0 104 | , mn.getX() - x, x - mx.getX() - 1 105 | , mn.getY() - y, y - mx.getY() - 1 106 | , mn.getZ() - z, z - mx.getZ() - 1 107 | ); 108 | } 109 | 110 | @Override 111 | public Location getRandomLocation(Random r) 112 | { 113 | return getMinimumPoint().add( 114 | (x2 - x1 + 1) * r.nextDouble(), 115 | (y2 - y1 + 1) * r.nextDouble(), 116 | (z2 - z1 + 1) * r.nextDouble()); 117 | } 118 | 119 | @Override 120 | public CuboidRegion getBoundingCuboid() { return this; } 121 | } 122 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/util/SportBukkitUtil.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.util; 2 | 3 | import java.lang.reflect.Method; 4 | 5 | import org.bukkit.Bukkit; 6 | import org.bukkit.ChatColor; 7 | import org.bukkit.Location; 8 | import org.bukkit.OfflinePlayer; 9 | import org.bukkit.entity.HumanEntity; 10 | import org.bukkit.entity.Player; 11 | 12 | public class SportBukkitUtil 13 | { 14 | private static boolean isSportBukkit = true; 15 | 16 | // custom methods, retrieved by reflection 17 | private static Method mAffectsSpawning = null; 18 | private static Method mCollidesWithEntities = null; 19 | private static Method mSetOverheadName = null; 20 | private static Method mOfflinePlayerLocation = null; 21 | 22 | static 23 | { 24 | // check server name 25 | isSportBukkit = "SportBukkit".equals(Bukkit.getName()); 26 | 27 | // reflect to get methods if this is SportBukkit 28 | if (isSportBukkit) try 29 | { 30 | // last_username's affects-spawning API from SportBukkit 31 | mAffectsSpawning = HumanEntity.class.getDeclaredMethod("setAffectsSpawning", boolean.class); 32 | 33 | // last_username's collides-with-entities API from SportBukkit 34 | mCollidesWithEntities = Player.class.getDeclaredMethod("setCollidesWithEntities", boolean.class); 35 | 36 | // anxuiz's set-overhead-name API from SportBukkit 37 | mSetOverheadName = Player.class.getDeclaredMethod("setOverheadName", String.class); 38 | 39 | // md_5's offlineUtil API from SportBukkit 40 | mOfflinePlayerLocation = OfflinePlayer.class.getDeclaredMethod("getLocation"); 41 | } 42 | catch (Exception e) { isSportBukkit = false; } 43 | } 44 | 45 | /** 46 | * Checks if AutoReferee is installed on a system supporting the SportBukkit API 47 | * 48 | * @return true if SportBukkit is installed, false otherwise 49 | * @see SportBukkit 50 | */ 51 | public static boolean hasSportBukkitApi() 52 | { return isSportBukkit; } 53 | 54 | /** 55 | * Sets whether player affects spawning via natural spawn and mob spawners. 56 | * Uses last_username's affects-spawning API from SportBukkit 57 | * 58 | * @param affectsSpawning Set whether player affects spawning 59 | * @see SportBukkit 60 | */ 61 | public static void setAffectsSpawning(Player player, boolean affectsSpawning) 62 | { 63 | if (mAffectsSpawning != null) try 64 | { mAffectsSpawning.invoke(player, affectsSpawning); } 65 | catch (Throwable ignored) { } 66 | } 67 | 68 | /** 69 | * Sets whether player collides with entities, including items and arrows. 70 | * Uses last_username's collides-with-entities API from SportBukkit 71 | * 72 | * @param collidesWithEntities Set whether player collides with entities 73 | * @see SportBukkit 74 | */ 75 | public static void setCollidesWithEntities(Player player, boolean collidesWithEntities) 76 | { 77 | if (mCollidesWithEntities != null) try 78 | { mCollidesWithEntities.invoke(player, collidesWithEntities); } 79 | catch (Throwable ignored) { } 80 | } 81 | 82 | /** 83 | * Sets the overhead name, allowing for ChatColor characters. 84 | * Uses anxuiz's set-overhead-name API from SportBukkit 85 | * 86 | * @param overheadName New string to display above player's head 87 | * @see SportBukkit 88 | * @deprecated use built-in scoreboards to change name colors 89 | */ 90 | @Deprecated 91 | public static void setOverheadName(Player player, String overheadName) 92 | { 93 | if (mSetOverheadName != null) try 94 | { mSetOverheadName.invoke(player, overheadName.trim() 95 | .replaceAll(ChatColor.RESET.toString(), "")); } 96 | catch (Throwable ignored) { } 97 | } 98 | 99 | /** 100 | * Gets the logged-out location of an OfflinePlayer 101 | * Uses md_5's offlineUtil API from SportBukkit 102 | * 103 | * @see SportBukkit 104 | */ 105 | public static Location getOfflinePlayerLocation(OfflinePlayer player) 106 | { 107 | if (mOfflinePlayerLocation != null) try 108 | { return (Location) mOfflinePlayerLocation.invoke(player); } 109 | catch (Exception e) { } return null; 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/util/AchievementPoints.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.util; 2 | 3 | import java.util.Map; 4 | 5 | import org.bukkit.Material; 6 | import org.bukkit.entity.EntityType; 7 | 8 | import com.google.common.collect.Maps; 9 | 10 | public enum AchievementPoints 11 | { 12 | KILL_PLAYER(100), 13 | DEATH(0), 14 | REVENGE(100), 15 | ARROW_HIT(3), 16 | 17 | OBJECTIVE_FOUND(300), 18 | OBJECTIVE_PLACE(100), 19 | 20 | PICKUP_BLOCK(1), 21 | MINE_COAL(2), 22 | SMELT_IRON(8), 23 | SMELT_GOLD(12), 24 | MINE_DIAMOND(25), 25 | 26 | CRAFT_ARMOR(25), 27 | CRAFT_TOOL(12), 28 | CRAFT_WEAPON(15), 29 | BREW_POTION(30), 30 | 31 | KILL_ZOMBIE(8), 32 | KILL_SKELETON(12), 33 | KILL_CREEPER(25), 34 | KILL_SPIDER(12), 35 | KILL_CAVE_SPIDER(12), 36 | KILL_ENDERMAN(20), 37 | KILL_SLIME(4), 38 | KILL_SILVERFISH(5), 39 | KILL_BLAZE(20), 40 | KILL_GHAST(20), 41 | KILL_PIGMAN(12), 42 | KILL_MAGMA_CUBE(5); 43 | 44 | public static final int POINTS = 100; 45 | 46 | private int value; 47 | 48 | private AchievementPoints(int v) 49 | { this.value = v; } 50 | 51 | public int getValue() 52 | { return this.value; } 53 | 54 | public static int ticksToPoints(int v) 55 | { return v / POINTS; } 56 | 57 | private static Map monsterKill = Maps.newEnumMap(EntityType.class); 58 | static 59 | { 60 | // the most dangerous game... 61 | monsterKill.put(EntityType.PLAYER, KILL_PLAYER); 62 | 63 | // all mobs for which we award points 64 | monsterKill.put(EntityType.ZOMBIE, KILL_ZOMBIE); 65 | monsterKill.put(EntityType.SKELETON, KILL_SKELETON); 66 | monsterKill.put(EntityType.CREEPER, KILL_CREEPER); 67 | monsterKill.put(EntityType.SPIDER, KILL_SPIDER); 68 | monsterKill.put(EntityType.CAVE_SPIDER, KILL_CAVE_SPIDER); 69 | monsterKill.put(EntityType.ENDERMAN, KILL_ENDERMAN); 70 | monsterKill.put(EntityType.SLIME, KILL_SLIME); 71 | monsterKill.put(EntityType.SILVERFISH, KILL_SILVERFISH); 72 | monsterKill.put(EntityType.BLAZE, KILL_BLAZE); 73 | monsterKill.put(EntityType.GHAST, KILL_GHAST); 74 | monsterKill.put(EntityType.PIG_ZOMBIE, KILL_PIGMAN); 75 | monsterKill.put(EntityType.MAGMA_CUBE, KILL_MAGMA_CUBE); 76 | } 77 | 78 | public static AchievementPoints getMonsterKill(EntityType entityType) 79 | { return monsterKill.get(entityType); } 80 | 81 | private static Map equipmentCraft = Maps.newEnumMap(Material.class); 82 | static 83 | { 84 | equipmentCraft.put(Material.STONE_SWORD, CRAFT_WEAPON); 85 | equipmentCraft.put(Material.IRON_SWORD, CRAFT_WEAPON); 86 | equipmentCraft.put(Material.GOLD_SWORD, CRAFT_WEAPON); 87 | equipmentCraft.put(Material.DIAMOND_SWORD, CRAFT_WEAPON); 88 | equipmentCraft.put(Material.BOW, CRAFT_WEAPON); 89 | 90 | equipmentCraft.put(Material.STONE_PICKAXE, CRAFT_TOOL); 91 | equipmentCraft.put(Material.STONE_AXE, CRAFT_TOOL); 92 | equipmentCraft.put(Material.STONE_SPADE, CRAFT_TOOL); 93 | equipmentCraft.put(Material.IRON_PICKAXE, CRAFT_TOOL); 94 | equipmentCraft.put(Material.IRON_AXE, CRAFT_TOOL); 95 | equipmentCraft.put(Material.IRON_SPADE, CRAFT_TOOL); 96 | equipmentCraft.put(Material.GOLD_PICKAXE, CRAFT_TOOL); 97 | equipmentCraft.put(Material.GOLD_AXE, CRAFT_TOOL); 98 | equipmentCraft.put(Material.GOLD_SPADE, CRAFT_TOOL); 99 | equipmentCraft.put(Material.DIAMOND_PICKAXE, CRAFT_TOOL); 100 | equipmentCraft.put(Material.DIAMOND_AXE, CRAFT_TOOL); 101 | equipmentCraft.put(Material.DIAMOND_SPADE, CRAFT_TOOL); 102 | 103 | equipmentCraft.put(Material.IRON_HELMET, CRAFT_ARMOR); 104 | equipmentCraft.put(Material.IRON_CHESTPLATE, CRAFT_ARMOR); 105 | equipmentCraft.put(Material.IRON_LEGGINGS, CRAFT_ARMOR); 106 | equipmentCraft.put(Material.IRON_BOOTS, CRAFT_ARMOR); 107 | equipmentCraft.put(Material.GOLD_HELMET, CRAFT_ARMOR); 108 | equipmentCraft.put(Material.GOLD_CHESTPLATE, CRAFT_ARMOR); 109 | equipmentCraft.put(Material.GOLD_LEGGINGS, CRAFT_ARMOR); 110 | equipmentCraft.put(Material.GOLD_BOOTS, CRAFT_ARMOR); 111 | equipmentCraft.put(Material.DIAMOND_HELMET, CRAFT_ARMOR); 112 | equipmentCraft.put(Material.DIAMOND_CHESTPLATE, CRAFT_ARMOR); 113 | equipmentCraft.put(Material.DIAMOND_LEGGINGS, CRAFT_ARMOR); 114 | equipmentCraft.put(Material.DIAMOND_BOOTS, CRAFT_ARMOR); 115 | } 116 | 117 | public static AchievementPoints getEquipmentCraft(Material material) 118 | { return equipmentCraft.get(material); } 119 | } 120 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/util/TeleportationUtil.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.util; 2 | 3 | import java.util.Set; 4 | import java.lang.Math; 5 | 6 | import org.bukkit.block.Block; 7 | import org.bukkit.entity.Entity; 8 | import org.bukkit.entity.LivingEntity; 9 | import org.bukkit.Material; 10 | import org.bukkit.Location; 11 | import org.bukkit.util.Vector; 12 | 13 | import com.google.common.collect.Sets; 14 | 15 | import org.mctourney.autoreferee.AutoRefPlayer; 16 | 17 | public class TeleportationUtil 18 | { 19 | private TeleportationUtil() 20 | { } 21 | 22 | public static Location locationTeleport(Location loc) 23 | { 24 | if (loc == null) return null; 25 | 26 | Location x, c = loc.clone(), best = c; 27 | double sqd, bsqd = -1.0; 28 | 29 | for (Vector vec : directions) 30 | { 31 | x = TeleportationUtil.checkDirection(c, vec); 32 | sqd = x.distanceSquared(best); 33 | if (sqd > bsqd) { bsqd = sqd; best = x; } 34 | } 35 | 36 | // return a location that is looking at the target 37 | Location dest = locationLookingAt(best, loc); 38 | return dest.distance(loc) < 1.0 ? null : dest; 39 | } 40 | 41 | public static Location blockTeleport(Block b) 42 | { return blockTeleport(b.getLocation()); } 43 | 44 | public static Location blockTeleport(Location loc) 45 | { return locationTeleport(loc.clone().add(0.5, 0.5, 0.5)); } 46 | 47 | public static Location entityTeleport(Entity e) 48 | { 49 | Location loc = e.getLocation().clone(); 50 | if (e instanceof LivingEntity) 51 | { 52 | LivingEntity live = (LivingEntity) e; 53 | loc.add(0, live.getEyeHeight(), 0); 54 | } 55 | return locationTeleport(loc); 56 | } 57 | 58 | public static Location playerTeleport(AutoRefPlayer apl) 59 | { 60 | if (apl == null) return null; 61 | if (apl.isOnline()) return entityTeleport(apl.getPlayer()); 62 | 63 | Location loc = apl.getLocation().clone(); 64 | return locationTeleport(loc); 65 | } 66 | 67 | private static Location locationLookingAt(Location base, Location target) 68 | { 69 | if (base == null || target == null) return base; 70 | 71 | double dx = base.getX() - target.getX(), 72 | dy = base.getY() - target.getY(), 73 | dz = base.getZ() - target.getZ(); 74 | 75 | double dist = Math.sqrt(dx*dx + dz*dz); 76 | 77 | Location res = base.clone(); 78 | res.setPitch((float)(Math.atan2(dy, dist)*180/Math.PI)); 79 | res.setYaw((float)(Math.atan2(dz, dx)*180/Math.PI) + 90.0f); 80 | 81 | return res; 82 | } 83 | 84 | private static Set passableBlocks = Sets.newHashSet 85 | ( Material.AIR 86 | , Material.DEAD_BUSH 87 | , Material.DIODE_BLOCK_ON 88 | , Material.DIODE_BLOCK_OFF 89 | , Material.LADDER 90 | , Material.LEVER 91 | , Material.LONG_GRASS 92 | , Material.MELON_STEM 93 | , Material.NETHER_STALK 94 | , Material.NETHER_WARTS 95 | , Material.POWERED_RAIL 96 | , Material.PUMPKIN_STEM 97 | , Material.RAILS 98 | , Material.RED_ROSE 99 | , Material.REDSTONE_TORCH_ON 100 | , Material.REDSTONE_TORCH_OFF 101 | , Material.REDSTONE_WIRE 102 | , Material.SAPLING 103 | , Material.SIGN 104 | , Material.SIGN_POST 105 | , Material.SNOW 106 | , Material.STATIONARY_WATER 107 | , Material.STONE_BUTTON 108 | , Material.STONE_PLATE 109 | , Material.TORCH 110 | , Material.TRIPWIRE 111 | , Material.TRIPWIRE_HOOK 112 | , Material.VINE 113 | , Material.WALL_SIGN 114 | , Material.WATER 115 | , Material.WATER_LILY 116 | , Material.WOOD_PLATE 117 | , Material.YELLOW_FLOWER 118 | ); 119 | 120 | public static boolean isBlockPassable(Block b) 121 | { return passableBlocks.contains(b.getType()); } 122 | 123 | public static boolean safeLocation(Location loc) 124 | { return isBlockPassable(loc.getBlock()) && 125 | isBlockPassable(loc.getBlock().getRelative(0, 1, 0)); } 126 | 127 | private static final int MAX_TELEPORT_DISTANCE = 4; 128 | private static Location checkDirection(Location loc, Vector v) 129 | { 130 | v = v.normalize(); 131 | int d = -1; 132 | 133 | // furthest we can stray in one direction 134 | // based on the rows preceeding 135 | int m = MAX_TELEPORT_DISTANCE; 136 | 137 | Location best = loc.clone(); 138 | for (int h = 0; h <= MAX_TELEPORT_DISTANCE && m > h; ++h) 139 | { 140 | // attempt up to M blocks away from the center 141 | Location c = loc.clone().add(0, h, 0); 142 | int k; for (k = 1; k <= m; ++k) 143 | { 144 | // the next location we are checking 145 | Location nc = c.add(v); 146 | 147 | // if this block is impassable, dec k before quitting 148 | if (!isBlockPassable(nc.getBlock())) { --k; break; } 149 | 150 | // update c if the block is passable 151 | else c = nc; 152 | } 153 | 154 | // we only got to row k, don't exceed this in future passes 155 | if (k < m) m = k; 156 | 157 | // if this is farther away than any previously, save it 158 | // only allow locations below a grade of 45deg 159 | if (h > 0 && k >= h && k + h > d) { d = k + h; best = c; } 160 | } 161 | 162 | return best; 163 | } 164 | 165 | private static Set directions = Sets.newHashSet 166 | ( new Vector( 0, 0, 1) 167 | , new Vector( 0, 0, -1) 168 | , new Vector( 1, 0, 0) 169 | , new Vector(-1, 0, 0) 170 | ); 171 | } 172 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/util/ColorConverter.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.util; 2 | 3 | import java.util.Map; 4 | 5 | import org.bukkit.ChatColor; 6 | import org.bukkit.Color; 7 | import org.bukkit.DyeColor; 8 | 9 | import com.google.common.collect.Maps; 10 | 11 | public abstract class ColorConverter 12 | { 13 | private static Map dyeChatMap; 14 | static 15 | { 16 | dyeChatMap = Maps.newHashMap(); 17 | dyeChatMap.put(DyeColor.BLACK, ChatColor.DARK_GRAY); 18 | dyeChatMap.put(DyeColor.BLUE, ChatColor.DARK_BLUE); 19 | dyeChatMap.put(DyeColor.BROWN, ChatColor.GOLD); 20 | dyeChatMap.put(DyeColor.CYAN, ChatColor.AQUA); 21 | dyeChatMap.put(DyeColor.GRAY, ChatColor.GRAY); 22 | dyeChatMap.put(DyeColor.GREEN, ChatColor.DARK_GREEN); 23 | dyeChatMap.put(DyeColor.LIGHT_BLUE, ChatColor.BLUE); 24 | dyeChatMap.put(DyeColor.LIME, ChatColor.GREEN); 25 | dyeChatMap.put(DyeColor.MAGENTA, ChatColor.LIGHT_PURPLE); 26 | dyeChatMap.put(DyeColor.ORANGE, ChatColor.GOLD); 27 | dyeChatMap.put(DyeColor.PINK, ChatColor.LIGHT_PURPLE); 28 | dyeChatMap.put(DyeColor.PURPLE, ChatColor.DARK_PURPLE); 29 | dyeChatMap.put(DyeColor.RED, ChatColor.DARK_RED); 30 | dyeChatMap.put(DyeColor.SILVER, ChatColor.GRAY); 31 | dyeChatMap.put(DyeColor.WHITE, ChatColor.WHITE); 32 | dyeChatMap.put(DyeColor.YELLOW, ChatColor.YELLOW); 33 | } 34 | 35 | public static ChatColor dyeToChat(DyeColor dclr) 36 | { 37 | if (dyeChatMap.containsKey(dclr)) 38 | return dyeChatMap.get(dclr); 39 | return ChatColor.MAGIC; 40 | } 41 | 42 | private static Map chatHexMap; 43 | static 44 | { 45 | chatHexMap = Maps.newHashMap(); 46 | chatHexMap.put(ChatColor.BLACK, "#000"); 47 | chatHexMap.put(ChatColor.DARK_BLUE, "#00a"); 48 | chatHexMap.put(ChatColor.DARK_GREEN, "#0a0"); 49 | chatHexMap.put(ChatColor.DARK_AQUA, "#0aa"); 50 | chatHexMap.put(ChatColor.DARK_RED, "#a00"); 51 | chatHexMap.put(ChatColor.DARK_PURPLE, "#a0a"); 52 | chatHexMap.put(ChatColor.GOLD, "#fa0"); 53 | chatHexMap.put(ChatColor.GRAY, "#999"); 54 | chatHexMap.put(ChatColor.DARK_GRAY, "#555"); 55 | chatHexMap.put(ChatColor.BLUE, "#55f"); 56 | chatHexMap.put(ChatColor.GREEN, "#5c5"); 57 | chatHexMap.put(ChatColor.AQUA, "#5cc"); 58 | chatHexMap.put(ChatColor.RED, "#f55"); 59 | chatHexMap.put(ChatColor.LIGHT_PURPLE, "#f5f"); 60 | chatHexMap.put(ChatColor.YELLOW, "#cc5"); 61 | chatHexMap.put(ChatColor.WHITE, "#aaa"); 62 | } 63 | 64 | public static String chatToHex(ChatColor clr) 65 | { 66 | if (chatHexMap.containsKey(clr)) 67 | return chatHexMap.get(clr); 68 | return "#000"; 69 | } 70 | 71 | private static Map dyeHexMap; 72 | static 73 | { 74 | dyeHexMap = Maps.newHashMap(); 75 | dyeHexMap.put(DyeColor.BLACK, "#181414"); 76 | dyeHexMap.put(DyeColor.BLUE, "#253193"); 77 | dyeHexMap.put(DyeColor.BROWN, "#56331c"); 78 | dyeHexMap.put(DyeColor.CYAN, "#267191"); 79 | dyeHexMap.put(DyeColor.GRAY, "#414141"); 80 | dyeHexMap.put(DyeColor.GREEN, "#364b18"); 81 | dyeHexMap.put(DyeColor.LIGHT_BLUE, "#6387d2"); 82 | dyeHexMap.put(DyeColor.LIME, "#39ba2e"); 83 | dyeHexMap.put(DyeColor.MAGENTA, "#be49c9"); 84 | dyeHexMap.put(DyeColor.ORANGE, "#ea7e35"); 85 | dyeHexMap.put(DyeColor.PINK, "#d98199"); 86 | dyeHexMap.put(DyeColor.PURPLE, "#7e34bf"); 87 | dyeHexMap.put(DyeColor.RED, "#9e2b27"); 88 | dyeHexMap.put(DyeColor.SILVER, "#a0a7a7"); 89 | dyeHexMap.put(DyeColor.WHITE, "#a4a4a4"); 90 | dyeHexMap.put(DyeColor.YELLOW, "#c2b51c"); 91 | } 92 | 93 | public static String dyeToHex(DyeColor clr) 94 | { 95 | if (dyeHexMap.containsKey(clr)) 96 | return dyeHexMap.get(clr); 97 | return "#000"; 98 | } 99 | 100 | public static Color hexToColor(String hex) 101 | { 102 | // get rid of typical hex color cruft 103 | if (hex.startsWith("#")) hex = hex.substring(1); 104 | if (hex.indexOf("x") != -1) hex = hex.substring(hex.indexOf("x")); 105 | 106 | // if the length isn't the standard 0xRRGGBB or 0xRGB, just quit 107 | if (hex.length() != 6 && hex.length() != 3) return null; 108 | 109 | // construct and return color object 110 | int sz = hex.length() / 3, mult = 1 << ((2 - sz)*4), x = 0; 111 | for (int i = 0, z = 0; z < hex.length(); ++i, z += sz) 112 | x |= (mult * Integer.parseInt(hex.substring(z, z+sz), 16)) << (i*8); 113 | return Color.fromBGR(x & 0xffffff); 114 | } 115 | 116 | public static Color rgbToColor(String rgb) 117 | { 118 | String parts[] = rgb.split("[^0-9]+"); 119 | if (parts.length < 3) return null; 120 | 121 | int x = 0, i; for (i = 0; i < 3; ++i) 122 | x |= Integer.parseInt(parts[i]) << (i*8); 123 | return Color.fromBGR(x & 0xffffff); 124 | } 125 | 126 | public static String generateColorTable() 127 | { 128 | StringBuilder str = new StringBuilder(); 129 | 130 | str.append(""); 131 | for (Map.Entry e : chatHexMap.entrySet()) 132 | str.append(String.format("" + 133 | "", e.getKey().name(), e.getValue())); 134 | str.append("
Chat ColorColor
%1$sTest String
"); 135 | 136 | str.append(""); 137 | for (Map.Entry e : dyeHexMap.entrySet()) 138 | str.append(String.format("" + 139 | "", e.getKey().name(), e.getValue())); 140 | str.append("
Dye ColorColor
%1$sTest String
"); 141 | 142 | return str.toString(); 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/util/worldsearch/WorkerEntitySearch.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.util.worldsearch; 2 | 3 | import java.util.List; 4 | import java.util.Set; 5 | 6 | import org.bukkit.Material; 7 | import org.bukkit.SkullType; 8 | import org.bukkit.World; 9 | import org.bukkit.entity.Boat; 10 | import org.bukkit.entity.Enderman; 11 | import org.bukkit.entity.Entity; 12 | import org.bukkit.entity.FallingBlock; 13 | import org.bukkit.entity.Item; 14 | import org.bukkit.entity.ItemFrame; 15 | import org.bukkit.entity.LivingEntity; 16 | import org.bukkit.entity.Minecart; 17 | import org.bukkit.entity.Sheep; 18 | import org.bukkit.entity.Skeleton; 19 | import org.bukkit.entity.Skeleton.SkeletonType; 20 | import org.bukkit.entity.Villager; 21 | import org.bukkit.entity.minecart.ExplosiveMinecart; 22 | import org.bukkit.entity.minecart.HopperMinecart; 23 | import org.bukkit.entity.minecart.PoweredMinecart; 24 | import org.bukkit.entity.minecart.SpawnerMinecart; 25 | import org.bukkit.entity.minecart.StorageMinecart; 26 | import org.bukkit.inventory.EntityEquipment; 27 | import org.bukkit.inventory.Inventory; 28 | import org.bukkit.inventory.InventoryHolder; 29 | import org.bukkit.inventory.ItemStack; 30 | import org.bukkit.material.MaterialData; 31 | import org.bukkit.scheduler.BukkitRunnable; 32 | import org.bukkit.util.Vector; 33 | import org.mctourney.autoreferee.util.BlockData; 34 | 35 | /** 36 | * Consumes: ObjectiveExhaustionMasterTask.entitychunks
37 | * Output: ObjectiveExhaustionMasterTask.found
38 | * Cancellation: Self, on depletion 39 | * 40 | * Searches each chunk for entities with the goal objects 41 | * 42 | * @author kane 43 | */ 44 | public class WorkerEntitySearch extends BukkitRunnable 45 | { 46 | ObjectiveExhaustionMasterTask master; 47 | 48 | public WorkerEntitySearch(ObjectiveExhaustionMasterTask task) 49 | { 50 | master = task; 51 | } 52 | 53 | @Override 54 | public void run() 55 | { 56 | World world = master.team.getMatch().getWorld(); 57 | Set goals = master.searching; 58 | for (int i = 0; i < 15; i++) // 15 chunks per run 59 | { 60 | Vector vec = master.entitychunks.poll(); 61 | if (vec == null) { this.cancel(); return; } 62 | Entity[] entities = world.getChunkAt(vec.getBlockX(), vec.getBlockZ()).getEntities(); // actually chunk-coords 63 | 64 | for (Entity ent : entities) 65 | { 66 | // Humans, Horses, Storage & Hopper Minecarts 67 | if (ent instanceof InventoryHolder) 68 | { 69 | Inventory inv = ((InventoryHolder) ent).getInventory(); 70 | for (ItemStack item : inv.getContents()) 71 | submitMatches(item, ent, goals); 72 | } 73 | 74 | // note: players get their armor checked here 75 | // the double-check on the held item doesn't really matter 76 | if (ent instanceof LivingEntity) 77 | { 78 | EntityEquipment eq = ((LivingEntity) ent).getEquipment(); 79 | for (ItemStack item : eq.getArmorContents()) 80 | { 81 | submitMatches(item, ent, goals); 82 | } 83 | submitMatches(eq.getItemInHand(), ent, goals); 84 | } 85 | 86 | // these 3 should be obvious 87 | if (ent instanceof FallingBlock) 88 | submitMatches(new BlockData(((FallingBlock) ent).getMaterial(), ((FallingBlock) ent).getBlockData()), ent, goals); 89 | if (ent instanceof Item) 90 | submitMatches(((Item) ent).getItemStack(), ent, goals); 91 | if (ent instanceof ItemFrame) 92 | submitMatches(((ItemFrame) ent).getItem(), ent, goals); 93 | 94 | 95 | // drops wood when destroyed 96 | if (ent instanceof Boat) 97 | submitMatches(new BlockData(Material.WOOD), ent, goals); 98 | // endermen can carry blocks...possibly into other lane? interesting, investigate later 99 | if (ent instanceof Enderman) 100 | { 101 | MaterialData carried = ((Enderman) ent).getCarriedMaterial(); 102 | submitMatches(new BlockData(carried.getItemType(), carried.getData()), ent, goals); 103 | } 104 | // break minecarts to get the blocks used to craft 105 | if (ent instanceof Minecart) 106 | { 107 | if (ent instanceof ExplosiveMinecart) 108 | submitMatches(new BlockData(Material.TNT), ent, goals); 109 | else if (ent instanceof HopperMinecart) 110 | submitMatches(new BlockData(Material.HOPPER), ent, goals); 111 | else if (ent instanceof PoweredMinecart) 112 | submitMatches(new BlockData(Material.FURNACE), ent, goals); 113 | // spawners can spawn entities with EntityEquipment on 114 | else if (ent instanceof SpawnerMinecart) 115 | { 116 | // XXX todo: spawners 117 | } 118 | else if (ent instanceof StorageMinecart) 119 | submitMatches(new BlockData(Material.CHEST), ent, goals); 120 | } 121 | // sheep can be sheared or killed for wool blocks 122 | if (ent instanceof Sheep) 123 | submitMatches(new BlockData(Material.WOOL, ((Sheep) ent).getColor().getWoolData()), ent, goals); 124 | // wither skele skulls 125 | if (ent instanceof Skeleton) 126 | { 127 | if (((Skeleton) ent).getSkeletonType() == SkeletonType.WITHER) 128 | submitMatches(new BlockData(Material.SKULL, (byte) SkullType.WITHER.ordinal()), ent, goals); 129 | } 130 | // trade for goal blocks 131 | if (ent instanceof Villager) 132 | { 133 | // FIXME https://github.com/Bukkit/Bukkit/pull/921 134 | try 135 | { 136 | List tradeResults = Unsafe_InspectVillagerTrades.getTradeResults((Villager) ent); 137 | for (ItemStack item : tradeResults) 138 | submitMatches(item, ent, goals); 139 | } 140 | catch (Throwable ignored) {} 141 | } 142 | } 143 | } 144 | } 145 | 146 | private void submitMatches(ItemStack item, Entity ent, Set goals) 147 | { 148 | if (item == null) 149 | return; 150 | BlockData found = BlockData.fromItemStack(item); 151 | submitMatches(found, ent, goals); 152 | } 153 | 154 | private void submitMatches(BlockData found, Entity ent, Set goals) 155 | { 156 | for (BlockData bd : goals) 157 | if (bd.equals(found)) 158 | master.found.add(new _Entry(bd, ent.getLocation().toVector())); 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/util/BlockData.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.util; 2 | 3 | import java.util.Map; 4 | 5 | import org.bukkit.ChatColor; 6 | import org.bukkit.DyeColor; 7 | import org.bukkit.Material; 8 | import org.bukkit.block.Block; 9 | import org.bukkit.inventory.Inventory; 10 | import org.bukkit.inventory.ItemStack; 11 | import org.bukkit.material.Colorable; 12 | 13 | import org.apache.commons.collections.map.DefaultedMap; 14 | 15 | /** 16 | * Represents a type of block, combined with any identifiable metadata. 17 | * 18 | * @author authorblues 19 | */ 20 | public class BlockData 21 | { 22 | // placeholder for a few common block data values 23 | public static final BlockData BEDROCK = new BlockData(Material.BEDROCK); 24 | public static final BlockData AIR = new BlockData(Material.AIR); 25 | 26 | private Material mat; 27 | 28 | /** 29 | * Gets the material type. 30 | */ 31 | public Material getMaterial() 32 | { return mat; } 33 | 34 | /** 35 | * Sets the material type. 36 | */ 37 | public void setMaterial(Material mat) 38 | { this.mat = mat; } 39 | 40 | private byte data; 41 | 42 | /** 43 | * Gets the metadata value. 44 | */ 45 | public byte getData() 46 | { return data; } 47 | 48 | /** 49 | * Sets the metadata value. 50 | */ 51 | public void setData(byte data) 52 | { this.data = data; } 53 | 54 | /** 55 | * Constructs a block data object with a material and metadata. 56 | * 57 | * @param material material type 58 | * @param data metadata value, or -1 if any metadata 59 | */ 60 | public BlockData(Material material, byte data) { setMaterial(material); setData(data); } 61 | 62 | /** 63 | * Constructs a block data object from an itemstack. 64 | */ 65 | public BlockData(ItemStack item) { this(item.getType(), item.getData().getData()); } 66 | 67 | /** 68 | * Constructs a block data object with a material and any metadata. 69 | * 70 | * @param material material type 71 | */ 72 | public BlockData(Material material) { this(material, (byte)-1); } 73 | 74 | @Override public int hashCode() 75 | { return getMaterial().hashCode(); } 76 | 77 | @Override public boolean equals(Object o) 78 | { 79 | // if the object is a mismatched type, its not equal 80 | if (o == null || !(o instanceof BlockData)) return false; 81 | 82 | // otherwise, check that the data is all equivalent 83 | BlockData ob = (BlockData) o; 84 | return ob.getMaterial().equals(getMaterial()) && this.dataMatches(ob); 85 | } 86 | 87 | private boolean dataMatches(BlockData ob) 88 | { return ob.getData() == getData() || ob.getData() == -1 || getData() == -1; } 89 | 90 | /** 91 | * Checks if the specified block matches this block data, taking metadata into account. 92 | * 93 | * @return true if block matches, otherwise false 94 | */ 95 | public boolean matchesBlock(Block block) 96 | { return block != null && this.equals(BlockData.fromBlock(block)); } 97 | 98 | public String serialize() 99 | { 100 | String s = Integer.toString(getMaterial().getId()); 101 | return getData() == -1 ? s : (s + "," + Integer.toString(getData())); 102 | } 103 | 104 | /** 105 | * Gets a human-readable name for this block data, without color. 106 | * 107 | * @return block data name 108 | */ 109 | public String getName() 110 | { return ChatColor.stripColor(getDisplayName()); } 111 | 112 | /** 113 | * Gets a human-readable name for this block data. 114 | * 115 | * @return colored block data name 116 | */ 117 | public String getDisplayName() 118 | { 119 | String bname = getMaterial().name().replaceAll("_+", " "); 120 | if ((getMaterial().getNewData((byte) 0) instanceof Colorable)) 121 | { 122 | DyeColor color = DyeColor.getByWoolData(getData()); 123 | ChatColor chatColor = ColorConverter.dyeToChat(color); 124 | 125 | String colorName = color.name().replaceAll("_+", " "); 126 | bname = chatColor + colorName + " " + bname + ChatColor.RESET; 127 | 128 | } 129 | return bname; 130 | } 131 | 132 | /** 133 | * Unserializes a block data object from a comma-seperated string. 134 | * 135 | * @param string serialized block data object 136 | * @return block data object 137 | */ 138 | public static BlockData unserialize(String string) 139 | { 140 | // format: mat[,data] 141 | String[] units = string.split(",", 2); 142 | 143 | try 144 | { 145 | // parse out the material (and potentially meta-data) 146 | Material mat = Material.getMaterial(Integer.parseInt(units[0])); 147 | byte data = units.length < 2 ? -1 : Byte.parseByte(units[1]); 148 | return new BlockData(mat, data); 149 | } 150 | 151 | // if there is a problem with parsing a material, assume the worst 152 | catch (NumberFormatException e) { return null; } 153 | } 154 | 155 | /** 156 | * Generates a block data object from a block. 157 | * 158 | * @param block block object 159 | * @return block data object 160 | */ 161 | public static BlockData fromBlock(Block block) 162 | { return new BlockData(block.getType(), block.getData()); } 163 | 164 | /** 165 | * Generates a block data object from an item stack. 166 | * 167 | * @param item item stack object 168 | * @return block data object 169 | */ 170 | public static BlockData fromItemStack(ItemStack item) 171 | { 172 | byte b = item.getData().getData(); 173 | return new BlockData(item.getType(), b); 174 | } 175 | 176 | /** 177 | * Generates a block data object from an inventory. If an inventory contains more than 178 | * one type of block, the block of the most quantity is returned. 179 | * 180 | * @param inv inventory object 181 | * @return block data object 182 | */ 183 | @SuppressWarnings("unchecked") 184 | public static BlockData fromInventory(Inventory inv) 185 | { 186 | Map count = new DefaultedMap(0); 187 | for (ItemStack item : inv) if (item != null) 188 | { 189 | BlockData bd = BlockData.fromItemStack(item); 190 | count.put(bd, item.getAmount() + count.get(bd)); 191 | } 192 | 193 | Map.Entry best = null; 194 | for (Map.Entry entry : count.entrySet()) 195 | if (best == null || entry.getValue() > best.getValue()) best = entry; 196 | 197 | return best == null ? null : best.getKey(); 198 | } 199 | } 200 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/listeners/lobby/RotationLobbyListener.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.listeners.lobby; 2 | 3 | import java.util.Collections; 4 | import java.util.List; 5 | import java.io.IOException; 6 | import java.io.File; 7 | 8 | import org.bukkit.Bukkit; 9 | import org.bukkit.ChatColor; 10 | import org.bukkit.command.CommandSender; 11 | import org.bukkit.entity.Player; 12 | import org.bukkit.event.EventHandler; 13 | import org.bukkit.event.EventPriority; 14 | import org.bukkit.event.player.PlayerChangedWorldEvent; 15 | import org.bukkit.event.player.PlayerJoinEvent; 16 | import org.bukkit.event.player.PlayerTeleportEvent; 17 | import org.bukkit.scheduler.BukkitRunnable; 18 | 19 | import org.mctourney.autoreferee.AutoRefMap; 20 | import org.mctourney.autoreferee.AutoRefMatch; 21 | import org.mctourney.autoreferee.AutoReferee; 22 | import org.mctourney.autoreferee.event.match.MatchCompleteEvent; 23 | import org.mctourney.autoreferee.event.match.MatchLoadEvent; 24 | import org.mctourney.autoreferee.event.match.MatchUnloadEvent; 25 | import org.mctourney.autoreferee.util.commands.AutoRefCommand; 26 | import org.mctourney.autoreferee.util.commands.AutoRefPermission; 27 | 28 | import com.google.common.collect.Lists; 29 | 30 | import org.apache.commons.cli.CommandLine; 31 | import org.apache.commons.io.FileUtils; 32 | 33 | public class RotationLobbyListener extends AutoLobbyListener 34 | { 35 | public static final File ROTATION_FILE = new File("rotation.txt"); 36 | 37 | private List rotation = Lists.newArrayList(); 38 | 39 | private int rotationCounter = 0; 40 | private AutoRefMatch currentMatch = null; 41 | private String currentMatchName = null; 42 | 43 | public RotationLobbyListener(AutoReferee plugin) 44 | { 45 | super(plugin); 46 | try 47 | { 48 | // loop through the map names in the rotation file to add to the list 49 | for (String mapname : FileUtils.readLines(ROTATION_FILE, "UTF-8")) 50 | { 51 | AutoRefMap map = AutoRefMap.getMap(mapname); 52 | if (map != null) rotation.add(map); 53 | } 54 | 55 | // shuffle the rotation 56 | Collections.shuffle(rotation); 57 | } 58 | catch (IOException e) { e.printStackTrace(); } 59 | 60 | // defer the task of loading the next map to the first server tick 61 | new BukkitRunnable() { @Override public void run() { loadNextMap(); } }.runTask(plugin); 62 | } 63 | 64 | @Override 65 | protected void lobbyLoadMap(Player player, AutoRefMap map) 66 | { 67 | if (currentMatch != null) 68 | currentMatch.joinMatch(player); 69 | } 70 | 71 | protected AutoRefMap getNextMap() 72 | { return rotation.get(rotationCounter % rotation.size()); } 73 | 74 | protected AutoRefMap loadNextMap() 75 | { 76 | // load up the map with a recognizable name 77 | this.currentMatchName = String.format("world-autoref-R%04d-%x", 78 | rotationCounter, System.currentTimeMillis()); 79 | 80 | AutoRefMap map = getNextMap(); ++rotationCounter; 81 | AutoRefMap.loadMap(Bukkit.getConsoleSender(), map, this.currentMatchName); 82 | return map; 83 | } 84 | 85 | @AutoRefCommand(name={"autoref", "nextmap"}, argmax=0, 86 | description="Get the next map in the rotation.") 87 | @AutoRefPermission(console=true, role=AutoRefMatch.Role.PLAYER) 88 | 89 | public boolean nextMap(CommandSender sender, AutoRefMatch match, String[] args, CommandLine options) 90 | { 91 | if (match != this.currentMatch) return false; 92 | 93 | AutoRefMap map = getNextMap(); 94 | sender.sendMessage(ChatColor.GREEN + "Next map is " + map.getVersionString()); 95 | return true; 96 | } 97 | 98 | @EventHandler(priority=EventPriority.MONITOR, ignoreCancelled=true) 99 | public void matchLoad(MatchLoadEvent event) 100 | { 101 | AutoRefMatch match = event.getMatch(); 102 | if (match.getWorld().getName().equals(this.currentMatchName)) 103 | { 104 | // update the current match BEFORE we unload 105 | AutoRefMatch prev = this.currentMatch; 106 | this.currentMatch = match; 107 | 108 | // if there was a match previously loaded, unload it 109 | if (prev != null) 110 | { 111 | for (Player player : prev.getWorld().getPlayers()) 112 | player.teleport(match.getPlayerSpawn(player)); 113 | prev.destroy(MatchUnloadEvent.Reason.COMPLETE); 114 | } 115 | } 116 | } 117 | 118 | @EventHandler(priority=EventPriority.HIGHEST, ignoreCancelled=true) 119 | public void playerLogin(PlayerJoinEvent event) 120 | { 121 | if (event.getPlayer().getWorld() == plugin.getLobbyWorld()) 122 | { 123 | this.currentMatch.joinMatch(event.getPlayer()); 124 | new PlayerJoinTask(this.currentMatch, event.getPlayer()).runTask(plugin); 125 | } 126 | } 127 | 128 | @EventHandler(priority=EventPriority.HIGHEST, ignoreCancelled=true) 129 | public void playerTeleport(PlayerTeleportEvent event) 130 | { 131 | if (event.getTo().getWorld() == plugin.getLobbyWorld()) 132 | { 133 | event.setTo(this.currentMatch.getPlayerSpawn(event.getPlayer())); 134 | new PlayerJoinTask(this.currentMatch, event.getPlayer()).runTask(plugin); 135 | } 136 | } 137 | 138 | @EventHandler(priority=EventPriority.HIGHEST, ignoreCancelled=true) 139 | public void playerChangeWorld(PlayerChangedWorldEvent event) 140 | { 141 | if (event.getPlayer().getWorld() == this.currentMatch.getWorld()) 142 | new PlayerJoinTask(this.currentMatch, event.getPlayer()).runTask(plugin); 143 | } 144 | 145 | @EventHandler(priority=EventPriority.MONITOR, ignoreCancelled=true) 146 | public void matchComplete(MatchCompleteEvent event) 147 | { 148 | if (event.getMatch() == this.currentMatch && AutoRefMatch.COMPLETED_SECONDS >= 15) 149 | new BukkitRunnable() 150 | { 151 | @Override 152 | public void run() 153 | { 154 | currentMatch.broadcast(ChatColor.GREEN + "Coming next: " + 155 | ChatColor.RESET + getNextMap().getVersionString()); 156 | } 157 | // announce the next match 5 seconds after the match ends 158 | }.runTaskLater(plugin, 5 * 20L); 159 | } 160 | 161 | @EventHandler(priority=EventPriority.HIGHEST, ignoreCancelled=true) 162 | public void matchUnload(MatchUnloadEvent event) 163 | { 164 | // if this is the current match in the rotation, defer unloading 165 | // until we load the next match and move everyone there 166 | if (event.getMatch() == this.currentMatch) 167 | { 168 | AutoRefMap map = loadNextMap(); 169 | currentMatch.broadcast(ChatColor.GREEN + "Now loading: " + 170 | ChatColor.RESET + map.getVersionString()); 171 | event.setCancelled(true); 172 | } 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/listeners/GoalsInventorySnapshot.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.listeners; 2 | 3 | import java.util.Collection; 4 | import java.util.HashMap; 5 | import java.util.Map; 6 | import java.util.Set; 7 | 8 | import com.google.common.collect.MapDifference; 9 | import com.google.common.collect.MapDifference.ValueDifference; 10 | import com.google.common.collect.Maps; 11 | 12 | import org.apache.commons.lang.Validate; 13 | import org.bukkit.ChatColor; 14 | import org.bukkit.block.Block; 15 | import org.bukkit.inventory.Inventory; 16 | import org.bukkit.inventory.ItemStack; 17 | import org.mctourney.autoreferee.util.BlockData; 18 | 19 | @SuppressWarnings("serial") 20 | public class GoalsInventorySnapshot extends HashMap 21 | { 22 | public GoalsInventorySnapshot() 23 | { 24 | super(); 25 | } 26 | 27 | public GoalsInventorySnapshot(ItemStack item, Set goals) 28 | { 29 | super(); 30 | BlockData target = BlockData.fromItemStack(item); 31 | for (BlockData goal : goals) 32 | if (goal.equals(target)) 33 | this.put(goal, item.getAmount()); 34 | } 35 | 36 | public GoalsInventorySnapshot(ItemStack item, BlockData goal) 37 | { 38 | super(); 39 | if (goal.equals(BlockData.fromItemStack(item))) 40 | this.put(goal, item.getAmount()); 41 | } 42 | 43 | public static GoalsInventorySnapshot fromItemsAndGoals(Collection items, Set goals) 44 | { 45 | GoalsInventorySnapshot ret = new GoalsInventorySnapshot(); 46 | for (BlockData goal : goals) 47 | { 48 | int count = itemSum(goal, items); 49 | ret.put(goal, count); 50 | } 51 | return ret; 52 | } 53 | 54 | public GoalsInventorySnapshot(Inventory inv, Set goals) 55 | { 56 | super(); 57 | ItemStack[] contents = inv.getContents(); 58 | for (BlockData goal : goals) 59 | { 60 | int count = itemSum(goal, contents); 61 | this.put(goal, count); 62 | } 63 | } 64 | 65 | public GoalsInventorySnapshot(Collection blocks, Set goals) 66 | { 67 | super(); 68 | for (BlockData goal : goals) 69 | { 70 | int count = blockCount(goal, blocks); 71 | this.put(goal, count); 72 | } 73 | } 74 | 75 | public GoalsInventorySnapshot(MapDifference diff) 76 | { 77 | super(); 78 | this.putAll(diff.entriesOnlyOnLeft()); 79 | for (Map.Entry entry : diff.entriesOnlyOnRight().entrySet()) 80 | { 81 | this.put(entry.getKey(), -entry.getValue()); 82 | } 83 | for (Map.Entry> entry : diff.entriesDiffering().entrySet()) 84 | { 85 | this.put(entry.getKey(), entry.getValue().leftValue() - entry.getValue().rightValue()); 86 | } 87 | } 88 | 89 | public static GoalsInventorySnapshot fromDiff(MapDifference diff, boolean leftSideOnly) 90 | { 91 | GoalsInventorySnapshot snap = new GoalsInventorySnapshot(); 92 | if (leftSideOnly) 93 | snap.putAll(diff.entriesOnlyOnLeft()); 94 | else 95 | snap.putAll(diff.entriesOnlyOnRight()); 96 | 97 | // Only positive differences 98 | for (Map.Entry> entry : diff.entriesDiffering().entrySet()) 99 | { 100 | int count; 101 | if (leftSideOnly) 102 | count = entry.getValue().leftValue() - entry.getValue().rightValue(); 103 | else 104 | count = entry.getValue().rightValue() - entry.getValue().leftValue(); 105 | 106 | if (count > 0) 107 | snap.put(entry.getKey(), count); 108 | } 109 | return snap; 110 | } 111 | 112 | public int getInt(BlockData key) 113 | { 114 | Integer val = get(key); 115 | if (val == null) return 0; 116 | 117 | return val; 118 | } 119 | 120 | @Override 121 | public Integer put(BlockData key, Integer value) 122 | { 123 | Validate.notNull(value, "Null integers are not permitted in GoalsInventorySnapshot"); 124 | // Convert all zeros to not-present 125 | if (value == 0) 126 | return this.remove(key); 127 | 128 | return super.put(key, value); 129 | } 130 | 131 | /** 132 | * This object is left in the return, the provided argument is the right. 133 | */ 134 | public MapDifference getDiff(GoalsInventorySnapshot other) 135 | { 136 | return Maps.difference(this, other); 137 | } 138 | 139 | public void addInPlace(GoalsInventorySnapshot other) 140 | { 141 | for (Map.Entry entry : other.entrySet()) 142 | addInPlace(entry.getKey(), entry.getValue()); 143 | } 144 | 145 | public void addInPlace(BlockData key, Integer value) 146 | { 147 | Validate.notNull(value); 148 | put(key, getInt(key) + value); 149 | } 150 | 151 | public void subtractInPlace(GoalsInventorySnapshot other) 152 | { 153 | for (Map.Entry entry : other.entrySet()) 154 | subtractInPlace(entry.getKey(), entry.getValue()); 155 | } 156 | 157 | public void subtractInPlace(BlockData key, Integer value) 158 | { 159 | Validate.notNull(value); 160 | put(key, getInt(key) - value); 161 | } 162 | 163 | private static int itemSum(BlockData data, ItemStack[] items) 164 | { 165 | int count = 0; 166 | for (ItemStack it : items) 167 | { 168 | if (it == null) continue; 169 | if (data.equals(BlockData.fromItemStack(it))) 170 | count += it.getAmount(); 171 | } 172 | return count; 173 | } 174 | 175 | private static int itemSum(BlockData data, Collection items) 176 | { 177 | int count = 0; 178 | for (ItemStack it : items) 179 | { 180 | if (it == null) continue; 181 | if (data.equals(BlockData.fromItemStack(it))) 182 | count += it.getAmount(); 183 | } 184 | return count; 185 | } 186 | 187 | private static int blockCount(BlockData data, Collection blocks) 188 | { 189 | int count = 0; 190 | for (Block block : blocks) 191 | { 192 | if (data.matchesBlock(block)) 193 | count++; 194 | } 195 | return count; 196 | } 197 | 198 | public String toString() 199 | { 200 | if (this.isEmpty()) return ""; 201 | StringBuilder sb = new StringBuilder(); 202 | boolean first = true; 203 | // Desired output: RED WOOL, GREEN WOOL, 5 x YELLOW WOOL, 20 x BLUE WOOL 204 | for (Map.Entry entry : this.entrySet()) 205 | { 206 | if (!first) 207 | { sb.append(", "); } 208 | else 209 | { first = false; } 210 | 211 | int count = entry.getValue(); 212 | if (count != 1) 213 | sb.append(ChatColor.YELLOW).append(Integer.toString(count)).append(" x ").append(ChatColor.RESET); 214 | sb.append(entry.getKey().getDisplayName()); 215 | sb.append(ChatColor.RESET); 216 | } 217 | return sb.toString(); 218 | } 219 | } 220 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/goals/BlockGoal.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.goals; 2 | 3 | import org.bukkit.Location; 4 | import org.bukkit.block.Block; 5 | import org.bukkit.entity.Player; 6 | import org.jdom2.Element; 7 | import org.mctourney.autoreferee.AutoRefMatch; 8 | import org.mctourney.autoreferee.AutoRefTeam; 9 | import org.mctourney.autoreferee.util.BlockData; 10 | import org.mctourney.autoreferee.util.LocationUtil; 11 | 12 | /** 13 | * Represents a block placement goal. 14 | * 15 | * @author authorblues 16 | */ 17 | public class BlockGoal extends AutoRefGoal 18 | { 19 | private Location loc; 20 | private BlockData blockdata; 21 | private int range; 22 | 23 | private String customName = null; 24 | private boolean canCraft = false; 25 | 26 | /** 27 | * Constructs a team's win condition. 28 | * 29 | * @param team owner of this win condition 30 | * @param loc target location for objective 31 | * @param blockdata objective block type 32 | * @param range maximum allowed distance from target 33 | */ 34 | public BlockGoal(AutoRefTeam team, Location loc, BlockData blockdata, int range) 35 | { super(team); this.loc = loc; this.blockdata = blockdata; this.range = range; } 36 | 37 | private BlockGoal(AutoRefTeam team, BlockGoal goal) 38 | { this(team, goal.loc, goal.blockdata, goal.range); } 39 | 40 | /** 41 | * Constructs a team's win condition. 42 | * 43 | * @param team owner of this win condition 44 | * @param loc target location for objective 45 | * @param blockdata objective block type 46 | */ 47 | public BlockGoal(AutoRefTeam team, Location loc, BlockData blockdata) 48 | { this(team, loc, blockdata, team.getMatch().getInexactRange()); } 49 | 50 | /** 51 | * Constructs a team's win condition. 52 | * 53 | * @param team owner of this win condition 54 | * @param block block to construct win condition from 55 | * @param range maximum allowed distance from target 56 | */ 57 | public BlockGoal(AutoRefTeam team, Block block, int range) 58 | { super(team); this.loc = block.getLocation(); this.blockdata = BlockData.fromBlock(block); this.range = range; } 59 | 60 | /** 61 | * Constructs a team's win condition. 62 | * 63 | * @param team owner of this win condition 64 | * @param block block to construct win condition from 65 | */ 66 | public BlockGoal(AutoRefTeam team, Block block) 67 | { this(team, block, team.getMatch().getInexactRange()); } 68 | 69 | public BlockGoal(AutoRefTeam team, Element elt) 70 | { 71 | super(team); 72 | 73 | this.loc = LocationUtil.fromCoords(team.getMatch().getWorld(), 74 | elt.getAttributeValue("pos")); 75 | this.blockdata = BlockData.unserialize(elt.getAttributeValue("id")); 76 | 77 | String arange = elt.getAttributeValue("range"); 78 | if (arange != null && !arange.isEmpty()) 79 | range = Integer.parseInt(arange); 80 | else range = team.getMatch().getInexactRange(); 81 | 82 | String acraft = elt.getAttributeValue("craftable"); 83 | this.canCraft = (acraft != null && Boolean.parseBoolean(acraft)); 84 | 85 | String text = elt.getTextTrim(); 86 | if (text != null && !text.isEmpty()) 87 | customName = text; 88 | } 89 | 90 | @Override 91 | public BlockGoal copy() 92 | { return this.copy(this.owner); } 93 | 94 | @Override 95 | public BlockGoal copy(AutoRefTeam team) 96 | { return new BlockGoal(team, this); } 97 | 98 | @Override 99 | public Element toElement() 100 | { 101 | Element elt = new Element("block"); 102 | 103 | if (this.customName != null) 104 | elt.setText(this.customName); 105 | 106 | elt.setAttribute("pos", LocationUtil.toBlockCoords(this.loc)); 107 | elt.setAttribute("id", this.blockdata.serialize()); 108 | 109 | if (this.range != getOwner().getMatch().getInexactRange()) 110 | elt.setAttribute("range", Integer.toString(this.range)); 111 | 112 | if (this.canCraft) 113 | elt.setAttribute("craftable", Boolean.toString(this.canCraft)); 114 | 115 | return elt; 116 | } 117 | 118 | @Override 119 | public boolean isSatisfied(AutoRefMatch match) 120 | { return null != blockInRange(blockdata, loc, range); } 121 | 122 | @Override 123 | public double getScore(AutoRefMatch match) 124 | { return getItemStatus().value; } 125 | 126 | /** 127 | * Checks if a given block type exists within a cube centered around a location. 128 | * 129 | * @param blockdata block type being searched for 130 | * @param loc center point of searchable cube 131 | * @param radius radius of searchable cube 132 | * @return location of a matching block within the region if one exists, otherwise null 133 | */ 134 | public static Location blockInRange(BlockData blockdata, Location loc, int radius) 135 | { 136 | Block b = loc.getBlock(); 137 | int h = loc.getWorld().getMaxHeight(); 138 | int by = loc.getBlockY(); 139 | 140 | for (int y = -radius; y <= radius; ++y) if (by + y >= 0 && by + y < h) 141 | for (int x = -radius; x <= radius; ++x) 142 | for (int z = -radius; z <= radius; ++z) 143 | { 144 | Block rel = b.getRelative(x, y, z); 145 | if (blockdata.matchesBlock(rel)) return rel.getLocation(); 146 | } 147 | 148 | return null; 149 | } 150 | 151 | /** 152 | * Checks if a given block type exists within a cube centered around a location. 153 | * 154 | * @param goal win condition object 155 | * @return location of a matching block within the region if one exists, otherwise null 156 | */ 157 | public static Location blockInRange(BlockGoal goal) 158 | { return blockInRange(goal.getItem(), goal.getTarget(), goal.getInexactRange()); } 159 | 160 | @Override 161 | public void updateReferee(Player ref) 162 | { 163 | String bd = getItem().serialize(); 164 | AutoRefMatch.messageReferee(ref, "team", getOwner().getName(), "goal", "+" + bd); 165 | AutoRefMatch.messageReferee(ref, "team", getOwner().getName(), "state", bd, 166 | getItemStatus().toString()); 167 | } 168 | 169 | /** 170 | * Gets the target location for this objective. 171 | */ 172 | @Override 173 | public Location getTarget() 174 | { return loc; } 175 | 176 | /** 177 | * Gets the block type for this objective. 178 | */ 179 | @Override 180 | public BlockData getItem() 181 | { return blockdata; } 182 | 183 | @Override 184 | public boolean canCraftItem() 185 | { return canCraft; } 186 | 187 | @Override 188 | public String toString() 189 | { 190 | String nm = customName == null ? blockdata.getDisplayName() : customName; 191 | return String.format("%s @ %s", nm, LocationUtil.toBlockCoords(loc)); 192 | } 193 | 194 | /** 195 | * Gets the maximum range this objective may be placed from its target. 196 | */ 197 | public int getInexactRange() 198 | { return range; } 199 | } 200 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/listeners/WorldListener.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.listeners; 2 | 3 | import org.bukkit.Bukkit; 4 | import org.bukkit.ChatColor; 5 | import org.bukkit.GameMode; 6 | import org.bukkit.Material; 7 | import org.bukkit.block.Block; 8 | import org.bukkit.command.BlockCommandSender; 9 | import org.bukkit.entity.Player; 10 | import org.bukkit.event.EventHandler; 11 | import org.bukkit.event.EventPriority; 12 | import org.bukkit.event.Listener; 13 | import org.bukkit.event.block.BlockFormEvent; 14 | import org.bukkit.event.block.BlockGrowEvent; 15 | import org.bukkit.event.player.PlayerChangedWorldEvent; 16 | import org.bukkit.event.player.PlayerJoinEvent; 17 | import org.bukkit.event.player.PlayerQuitEvent; 18 | import org.bukkit.event.server.ServerCommandEvent; 19 | import org.bukkit.event.world.WorldEvent; 20 | import org.bukkit.event.world.WorldLoadEvent; 21 | import org.bukkit.event.world.WorldInitEvent; 22 | import org.bukkit.event.world.WorldUnloadEvent; 23 | import org.bukkit.plugin.Plugin; 24 | 25 | import org.mctourney.autoreferee.AutoRefMatch; 26 | import org.mctourney.autoreferee.AutoReferee; 27 | import org.mctourney.autoreferee.util.PlayerUtil; 28 | 29 | public class WorldListener implements Listener 30 | { 31 | AutoReferee plugin = null; 32 | 33 | public WorldListener(Plugin p) 34 | { 35 | plugin = (AutoReferee) p; 36 | } 37 | 38 | @EventHandler 39 | public void worldInit(WorldInitEvent event) 40 | { checkLoadedWorld(event); } 41 | 42 | @EventHandler 43 | public void worldLoad(WorldLoadEvent event) 44 | { checkLoadedWorld(event); } 45 | 46 | private void checkLoadedWorld(WorldEvent event) 47 | { 48 | AutoRefMatch.setupWorld(event.getWorld(), false); 49 | } 50 | 51 | @EventHandler(priority=EventPriority.LOWEST) 52 | public void commandBlockCommandEvent(ServerCommandEvent event) 53 | { 54 | if (!(event.getSender() instanceof BlockCommandSender)) return; 55 | Block commandBlock = ((BlockCommandSender) event.getSender()).getBlock(); 56 | 57 | AutoRefMatch match = plugin.getMatch(commandBlock.getWorld()); 58 | if (match == null) return; 59 | 60 | if (event.getCommand().startsWith("say")) 61 | { 62 | match.broadcast(ChatColor.DARK_GRAY + "" + ChatColor.ITALIC + "[@] " + 63 | ChatColor.RESET + event.getCommand().substring(3).trim()); 64 | event.setCommand(""); return; 65 | } 66 | } 67 | 68 | @EventHandler(priority=EventPriority.HIGH, ignoreCancelled=true) 69 | public void playerJoin(PlayerJoinEvent event) 70 | { 71 | Player player = event.getPlayer(); 72 | 73 | // get the match for the world the player is logging into 74 | AutoRefMatch match = plugin.getMatch(player.getWorld()); 75 | 76 | // if there is no match here, or they aren't meant to play in this world, 77 | // check if there is a world they are expected in 78 | if (match == null || !match.isPlayer(player)) 79 | for (AutoRefMatch m : plugin.getMatches()) 80 | if (m.isPlayerExpected(player)) match = m; 81 | 82 | if (match != null) 83 | { 84 | // if we are logging in to the wrong world, teleport to the correct world 85 | if (player.getWorld() != match.getWorld()) match.joinMatch(player); 86 | else match.checkTeamsReady(); 87 | 88 | if (!match.getCurrentState().inProgress() || match.isPlayer(player)) 89 | match.broadcast(match.colorMessage(event.getJoinMessage())); 90 | event.setJoinMessage(null); 91 | 92 | match.sendMatchInfo(player); 93 | match.setupSpectators(player); 94 | 95 | // only clear inventories and give books if before match or not a player 96 | if (match.getCurrentState().isBeforeMatch() || !match.isPlayer(player)) 97 | { 98 | // give them a book with info about the match 99 | PlayerUtil.clearInventory(player); 100 | match.giveMatchInfoBook(player); 101 | } 102 | 103 | if (match.isReferee(player)) 104 | match.updateReferee(player); 105 | 106 | if (!player.hasPlayedBefore()) 107 | player.teleport(match.getPlayerSpawn(player)); 108 | } 109 | } 110 | 111 | @EventHandler 112 | public void playerQuit(PlayerQuitEvent event) 113 | { 114 | AutoRefMatch match = plugin.getMatch(event.getPlayer().getWorld()); 115 | if (match != null) 116 | { 117 | if (!match.getCurrentState().inProgress() || match.isPlayer(event.getPlayer())) 118 | match.broadcast(match.colorMessage(event.getQuitMessage())); 119 | event.setQuitMessage(null); 120 | 121 | // set the player back to the main scoreboard 122 | event.getPlayer().setScoreboard(Bukkit.getScoreboardManager().getMainScoreboard()); 123 | } 124 | } 125 | 126 | @EventHandler 127 | public void worldJoin(PlayerChangedWorldEvent event) 128 | { 129 | // update team ready information for both worlds 130 | AutoRefMatch matchFm = plugin.getMatch(event.getFrom()); 131 | if (matchFm != null) matchFm.checkTeamsReady(); 132 | 133 | Player player = event.getPlayer(); 134 | AutoRefMatch matchTo = plugin.getMatch(player.getWorld()); 135 | 136 | if (matchTo != null) 137 | { 138 | matchTo.checkTeamsReady(); 139 | matchTo.sendMatchInfo(player); 140 | matchTo.setupSpectators(player); 141 | 142 | if (matchTo.isReferee(player)) 143 | matchTo.updateReferee(player); 144 | 145 | // give them a book with info about the match 146 | PlayerUtil.clearInventory(player); 147 | matchTo.giveMatchInfoBook(player); 148 | } 149 | 150 | // if this is leaving a match, leave its team 151 | if (matchFm != null) 152 | matchFm.leaveTeam(player, false); 153 | 154 | // if they are leaving AutoReferee-managed worlds 155 | if (matchFm != null && matchTo == null) 156 | { 157 | matchFm.setSpectatorMode(player, false); 158 | PlayerUtil.setGameMode(player, GameMode.SURVIVAL); 159 | 160 | // set the player back to the main scoreboard 161 | player.setScoreboard(Bukkit.getScoreboardManager().getMainScoreboard()); 162 | } 163 | } 164 | 165 | @EventHandler(priority=EventPriority.MONITOR, ignoreCancelled=true) 166 | public void worldUnload(WorldUnloadEvent event) 167 | { 168 | AutoRefMatch match = plugin.getMatch(event.getWorld()); 169 | if (match == null) return; 170 | 171 | match.saveWorldConfiguration(); 172 | plugin.clearMatch(match); 173 | } 174 | 175 | @EventHandler 176 | public void blockForm(BlockFormEvent event) 177 | { 178 | // we are really only interested in stopping ice from forming here 179 | AutoRefMatch match = plugin.getMatch(event.getBlock().getWorld()); 180 | if (match != null && !match.getCurrentState().inProgress() 181 | && event.getNewState().getType() == Material.ICE) 182 | { event.setCancelled(true); return; } 183 | } 184 | 185 | @EventHandler 186 | public void blockGrow(BlockGrowEvent event) 187 | { 188 | AutoRefMatch match = plugin.getMatch(event.getBlock().getWorld()); 189 | if (match != null && !match.getCurrentState().inProgress()) 190 | { event.setCancelled(true); return; } 191 | } 192 | } 193 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/util/PlayerUtil.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.util; 2 | 3 | import java.util.Map; 4 | 5 | import org.bukkit.GameMode; 6 | import org.bukkit.entity.Player; 7 | import org.bukkit.inventory.Inventory; 8 | import org.bukkit.inventory.PlayerInventory; 9 | import org.bukkit.potion.PotionEffect; 10 | import org.bukkit.potion.PotionEffectType; 11 | 12 | import com.google.common.collect.Maps; 13 | 14 | import org.apache.commons.lang.WordUtils; 15 | import org.bukkit.scheduler.BukkitRunnable; 16 | import org.mctourney.autoreferee.AutoReferee; 17 | 18 | public class PlayerUtil 19 | { 20 | /** 21 | * Heals the player and resets hunger, saturation, and exhaustion. 22 | */ 23 | public static void restore(Player player) 24 | { 25 | PlayerUtil.heal(player); 26 | PlayerUtil.feed(player); 27 | } 28 | 29 | /** 30 | * Heals the player and resets hunger, saturation, and exhaustion. 31 | */ 32 | public static void heal(Player player) 33 | { 34 | player.setHealth( 20 ); // 10 hearts 35 | } 36 | 37 | /** 38 | * Heals the player and resets hunger, saturation, and exhaustion. 39 | */ 40 | public static void feed(Player player) 41 | { 42 | player.setFoodLevel ( 20 ); // full food 43 | player.setSaturation( 5 ); // saturation depletes hunger 44 | player.setExhaustion( 0 ); // exhaustion depletes saturation 45 | } 46 | 47 | /** 48 | * Clears the player's inventory, including armor slots. 49 | */ 50 | public static void clearInventory(Player player) 51 | { 52 | // clear the player's inventory 53 | PlayerInventory inv = player.getInventory(); 54 | inv.clear(); 55 | 56 | // clear the armor slots seperately 57 | inv.setHelmet(null); 58 | inv.setChestplate(null); 59 | inv.setLeggings(null); 60 | inv.setBoots(null); 61 | } 62 | 63 | /** 64 | * Resets player's experience and levels. 65 | */ 66 | public static void resetXP(Player player) 67 | { 68 | // reset the player's level 69 | player.setLevel(0); 70 | player.setExp(0.0f); 71 | } 72 | 73 | /** 74 | * Removes potion and beacon effects from the player. 75 | */ 76 | public static void removeStatusEffects(Player player) 77 | { 78 | // remove all potion effects 79 | for (PotionEffect effect : player.getActivePotionEffects()) 80 | player.removePotionEffect(effect.getType()); 81 | } 82 | 83 | /** 84 | * Clears player's ender chest 85 | */ 86 | public static void clearEnderChest(Player player) 87 | { 88 | // clear the ender chest 89 | Inventory enderChest = player.getEnderChest(); 90 | enderChest.clear(); 91 | } 92 | 93 | /** 94 | * Clears player's bed spawn 95 | */ 96 | public static void clearBedSpawn(Player player) 97 | { 98 | player.setBedSpawnLocation(null, true); 99 | } 100 | 101 | /** 102 | * Performs all PlayerUtil actions on this player. 103 | */ 104 | public static void reset(Player player) 105 | { 106 | // restore the player to full health, hunger, etc 107 | restore(player); 108 | 109 | // clear their entire inventory 110 | clearInventory(player); 111 | 112 | // reset levels and experience 113 | resetXP(player); 114 | 115 | // remove potion and beacon effects 116 | removeStatusEffects(player); 117 | } 118 | 119 | private static class BufferedGameModeChangeTask extends BukkitRunnable 120 | { 121 | private static Map players = Maps.newHashMap(); 122 | 123 | private Player player; 124 | private GameMode gamemode = null; 125 | private Boolean flight = null; 126 | 127 | private BufferedGameModeChangeTask(Player player) 128 | { this.player = player; } 129 | 130 | public static BufferedGameModeChangeTask change(Player player, GameMode gm) 131 | { return BufferedGameModeChangeTask.change(player, gm, null); } 132 | 133 | public static BufferedGameModeChangeTask change(Player player, GameMode gm, Boolean flight) 134 | { 135 | BufferedGameModeChangeTask task = players.get(player.getName()); 136 | if (task == null) 137 | { 138 | players.put(player.getName(), 139 | task = new BufferedGameModeChangeTask(player)); 140 | task.runTaskLater(AutoReferee.getInstance(), 2L); 141 | } 142 | 143 | task.gamemode = gm; 144 | task.flight = flight; 145 | return task; 146 | } 147 | 148 | @Override 149 | public void run() 150 | { 151 | if (this.gamemode != null) 152 | player.setGameMode(this.gamemode); 153 | if (this.flight != null) 154 | player.setAllowFlight(this.flight); 155 | players.remove(player.getName()); 156 | } 157 | } 158 | 159 | /** 160 | * Changes the players gamemode on the next server tick. Buffers gamemode changes. 161 | * @param player player 162 | * @param gamemode new gamemode 163 | */ 164 | public static void setGameMode(Player player, GameMode gamemode) 165 | { BufferedGameModeChangeTask.change(player, gamemode); } 166 | 167 | /** 168 | * Changes the players gamemode on the next server tick. Buffers gamemode changes. 169 | * @param player player 170 | * @param gamemode new gamemode 171 | * @param flight allow flight 172 | */ 173 | public static void setGameMode(Player player, GameMode gamemode, boolean flight) 174 | { BufferedGameModeChangeTask.change(player, gamemode, flight); } 175 | 176 | public static void setSpectatorSettings(Player player, boolean spec, GameMode pgm) 177 | { 178 | // gamemode is the obvious issue 179 | PlayerUtil.setGameMode(player, spec ? GameMode.SPECTATOR : pgm); 180 | 181 | // basic player settings depending on role 182 | player.setAllowFlight(spec); 183 | player.setCanPickupItems(!spec); 184 | } 185 | 186 | private static Map statusNames = Maps.newHashMap(); 187 | static 188 | { 189 | statusNames.put(PotionEffectType.DAMAGE_RESISTANCE, "Resistance"); 190 | statusNames.put(PotionEffectType.INCREASE_DAMAGE, "Strength"); 191 | statusNames.put(PotionEffectType.JUMP, "Jump Boost"); 192 | statusNames.put(PotionEffectType.SLOW, "Slowness"); 193 | statusNames.put(PotionEffectType.FAST_DIGGING, "Haste"); 194 | statusNames.put(PotionEffectType.SLOW_DIGGING, "Mining Fatigue"); 195 | } 196 | 197 | private static String[] roman = {"I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X"}; 198 | 199 | /** 200 | * Generates a human-readable string for the status effect. 201 | */ 202 | public static String getStatusEffectName(PotionEffect effect) 203 | { 204 | int time = effect.getDuration() / 20; 205 | PotionEffectType type = effect.getType(); 206 | int amp = effect.getAmplifier(); 207 | 208 | String name = statusNames.containsKey(type) ? statusNames.get(type) : 209 | WordUtils.capitalizeFully(type.getName().toLowerCase().replace('_', ' ')); 210 | if (amp >= 0) name += " " + (amp < roman.length ? roman[amp] : (1 + amp)); 211 | 212 | return String.format("%s (%d:%02d)", name, time/60, time%60); 213 | } 214 | 215 | public static boolean hasClientMod(Player player) 216 | { 217 | if (player == null) return false; 218 | return player.getListeningPluginChannels().contains(AutoReferee.REFEREE_PLUGIN_CHANNEL); 219 | } 220 | } 221 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/util/worldsearch/ObjectiveExhaustionMasterTask.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.util.worldsearch; 2 | 3 | import java.util.List; 4 | import java.util.Map; 5 | import java.util.Set; 6 | import java.util.concurrent.ConcurrentLinkedQueue; 7 | import java.util.concurrent.ExecutionException; 8 | import java.util.concurrent.Future; 9 | import java.util.concurrent.LinkedBlockingQueue; 10 | 11 | import org.bukkit.Bukkit; 12 | import org.bukkit.ChatColor; 13 | import org.bukkit.ChunkSnapshot; 14 | import org.bukkit.Location; 15 | import org.bukkit.World; 16 | import org.bukkit.entity.Player; 17 | import org.bukkit.scheduler.BukkitRunnable; 18 | import org.bukkit.util.Vector; 19 | import org.mctourney.autoreferee.AutoRefMatch; 20 | import org.mctourney.autoreferee.AutoRefTeam; 21 | import org.mctourney.autoreferee.AutoReferee; 22 | import org.mctourney.autoreferee.regions.AutoRefRegion; 23 | import org.mctourney.autoreferee.regions.CuboidRegion; 24 | import org.mctourney.autoreferee.util.BlockData; 25 | import org.mctourney.autoreferee.util.LocationUtil; 26 | 27 | import com.google.common.collect.ImmutableSet; 28 | import com.google.common.collect.Lists; 29 | import com.google.common.collect.Maps; 30 | import com.google.common.collect.Queues; 31 | import com.google.common.collect.Sets; 32 | 33 | public class ObjectiveExhaustionMasterTask implements Runnable 34 | { 35 | public final AutoReferee plugin = AutoReferee.getInstance(); 36 | public final AutoRefTeam team; 37 | 38 | // Safety strategy: Immutable set 39 | public final Set originalSearch; 40 | 41 | // Safety strategy: Copy on write 42 | public volatile Set searching; 43 | 44 | // Safety strategy: Single writer, stop before reading by using lock 45 | public Map results = Maps.newHashMap(); 46 | public final Object _LOCK_RESULTS = new Object(); 47 | 48 | /** 49 | * A stop-flag for the chunk snapshot worker threads. 50 | */ 51 | public volatile boolean all_snapshots_added; 52 | public ConcurrentLinkedQueue entitychunks = Queues.newConcurrentLinkedQueue(); 53 | public ConcurrentLinkedQueue contchunks = Queues.newConcurrentLinkedQueue(); 54 | public LinkedBlockingQueue snapshots = Queues.newLinkedBlockingQueue(); 55 | public ConcurrentLinkedQueue<_Entry> found = Queues.newConcurrentLinkedQueue(); 56 | 57 | private WorkerEntitySearch entSearcher; 58 | private WorkerContainerSearch containerSearcher; 59 | private List searchers; 60 | private WorkerValidateResults resultChecker; 61 | 62 | public ObjectiveExhaustionMasterTask(AutoRefTeam team, Set goals) 63 | { 64 | this.team = team; 65 | this.searching = goals; 66 | originalSearch = ImmutableSet.copyOf(goals); 67 | } 68 | 69 | @Override 70 | // REMINDER: This is run async! 71 | public void run() 72 | { 73 | boolean interrupted = Thread.interrupted(); 74 | 75 | List chunks = Lists.newArrayList(getChunkVectors()); 76 | 77 | // Start entity searcher 78 | entitychunks.addAll(chunks); 79 | entSearcher = new WorkerEntitySearch(this); 80 | entSearcher.runTaskTimer(plugin, 0, 3); 81 | 82 | // Start container searcher 83 | contchunks.addAll(chunks); 84 | containerSearcher = new WorkerContainerSearch(this); 85 | containerSearcher.runTaskTimer(plugin, 1, 3); 86 | 87 | // Start up chunk snapshot searchers 88 | // TODO pick a count 89 | searchers = Lists.newLinkedList(); 90 | WorkerAsyncSearchSnapshots tmp_searcher = new WorkerAsyncSearchSnapshots(this); 91 | tmp_searcher.runTaskAsynchronously(plugin); 92 | searchers.add(tmp_searcher); 93 | tmp_searcher = new WorkerAsyncSearchSnapshots(this); 94 | tmp_searcher.runTaskAsynchronously(plugin); 95 | searchers.add(tmp_searcher); 96 | tmp_searcher = new WorkerAsyncSearchSnapshots(this); 97 | tmp_searcher.runTaskAsynchronously(plugin); 98 | searchers.add(tmp_searcher); 99 | 100 | // Start result checker 101 | resultChecker = new WorkerValidateResults(this); 102 | resultChecker.runTaskTimer(plugin, 2, 3); 103 | 104 | for (int i = 0; i < chunks.size(); i += 10) 105 | { 106 | if (checkComplete()) 107 | { cleanup(); return; } 108 | 109 | int max = Math.max(chunks.size() - 1, i + 10); 110 | List sublist = chunks.subList(i, max); 111 | Future> future = Bukkit.getScheduler().callSyncMethod(plugin, new CallableGetSnapshots(sublist, team.getMatch().getWorld())); 112 | List value; 113 | try 114 | { 115 | // Do the get inside the loop to rate-limit. 116 | value = future.get(); 117 | } 118 | catch (ExecutionException e) 119 | { e.printStackTrace(); quit(e.toString(), interrupted); return; } 120 | catch (InterruptedException e) 121 | { e.printStackTrace(); quit("thread interrupted", true); return; } 122 | 123 | // Memory consistency: variable set happens-before adding of final snapshots 124 | if (i + 10 >= chunks.size()) 125 | all_snapshots_added = true; 126 | snapshots.addAll(value); 127 | } 128 | chunks = null; // drop 129 | snapshots.add(null); // poison-value, signal to stop trying to take 130 | 131 | while (true) 132 | { 133 | try 134 | { 135 | Thread.sleep(50); 136 | } 137 | catch (InterruptedException e) 138 | { interrupted = true; } 139 | 140 | if (checkComplete()) 141 | { 142 | cleanup(); 143 | return; 144 | } 145 | } 146 | } 147 | 148 | private void cleanup() 149 | { 150 | // Cancel timer tasks first 151 | tryCancel(entSearcher); 152 | tryCancel(containerSearcher); 153 | tryCancel(resultChecker); 154 | 155 | // Prepare all the "done" signals 156 | all_snapshots_added = true; 157 | snapshots.clear(); 158 | snapshots.add(null); 159 | for (WorkerAsyncSearchSnapshots searcher : searchers) 160 | { 161 | tryCancel(searcher); 162 | } 163 | } 164 | 165 | private void tryCancel(BukkitRunnable r) 166 | { 167 | try { r.cancel(); } 168 | catch (IllegalStateException ignored) { } 169 | } 170 | 171 | // unsafe 172 | private void quit(String message, boolean interrupted) 173 | { 174 | for (Player p : team.getMatch().getReferees()) 175 | p.sendMessage(ChatColor.RED + "The exhaustion search for " + team.getDisplayName() + " was stopped: " + ChatColor.DARK_RED + message); 176 | 177 | if (interrupted) 178 | Thread.currentThread().interrupt(); 179 | } 180 | 181 | private Set getChunkVectors() 182 | { 183 | Set chunks = Sets.newHashSet(); 184 | Set regions = team.getRegions(); 185 | for (AutoRefRegion region : regions) 186 | { 187 | addChunks(chunks, region.getBoundingCuboid()); 188 | } 189 | return chunks; 190 | } 191 | 192 | private void addChunks(Set chunks, CuboidRegion bound) 193 | { 194 | int czmax = (int) Math.floor(bound.z2) >> 4; 195 | int czmin = (int) Math.floor(bound.z1) >> 4; 196 | int cxmax = (int) Math.floor(bound.x2) >> 4; 197 | for (int cx = (int) Math.floor(bound.x1) >> 4; cx < cxmax; cx++) 198 | for (int cz = czmin; cz < czmax; cz++) 199 | chunks.add(new Vector(cx, 0, cz)); 200 | } 201 | 202 | private boolean checkComplete() 203 | { 204 | if (searching.isEmpty()) 205 | { 206 | synchronized (_LOCK_RESULTS) { 207 | // make results safe to read 208 | resultChecker.cancel(); 209 | } 210 | // Schedule announce, return true 211 | Bukkit.getScheduler().runTask(plugin, new Runnable() { public void run() 212 | { 213 | AutoRefMatch match = team.getMatch(); 214 | World world = match.getWorld(); 215 | StringBuilder sb = new StringBuilder(); 216 | sb.append(ChatColor.GREEN).append("Objective search for ").append(team.getDisplayName()).append(ChatColor.GREEN).append(" complete."); 217 | sb.append('\n'); 218 | for (BlockData bd : originalSearch) 219 | { 220 | Location loc = results.get(bd).toLocation(world); 221 | sb.append(bd.getDisplayName()).append(ChatColor.GRAY).append(" is at ").append(ChatColor.RED).append(LocationUtil.toBlockCoords(loc)); 222 | sb.append('\n'); 223 | } 224 | String[] message = sb.toString().split("\n"); 225 | for (Player p : match.getSpectators()) 226 | p.sendMessage(message); 227 | } }); 228 | return true; 229 | } 230 | return false; 231 | } 232 | } 233 | -------------------------------------------------------------------------------- /src/main/java/org/mctourney/autoreferee/listeners/TeamListener.java: -------------------------------------------------------------------------------- 1 | package org.mctourney.autoreferee.listeners; 2 | 3 | import java.util.Iterator; 4 | import java.util.Set; 5 | 6 | import org.bukkit.ChatColor; 7 | import org.bukkit.GameMode; 8 | import org.bukkit.Location; 9 | import org.bukkit.World; 10 | import org.bukkit.block.Sign; 11 | import org.bukkit.entity.Player; 12 | import org.bukkit.event.EventHandler; 13 | import org.bukkit.event.EventPriority; 14 | import org.bukkit.event.Listener; 15 | import org.bukkit.event.block.Action; 16 | import org.bukkit.event.player.AsyncPlayerChatEvent; 17 | import org.bukkit.event.player.PlayerCommandPreprocessEvent; 18 | import org.bukkit.event.player.PlayerGameModeChangeEvent; 19 | import org.bukkit.event.player.PlayerInteractEvent; 20 | import org.bukkit.event.player.PlayerLoginEvent; 21 | import org.bukkit.event.player.PlayerQuitEvent; 22 | import org.bukkit.event.player.PlayerRespawnEvent; 23 | import org.bukkit.plugin.Plugin; 24 | 25 | import org.mctourney.autoreferee.AutoRefMatch; 26 | import org.mctourney.autoreferee.AutoRefPlayer; 27 | import org.mctourney.autoreferee.AutoRefTeam; 28 | import org.mctourney.autoreferee.AutoReferee; 29 | import org.mctourney.autoreferee.AutoRefMatch.Role; 30 | import org.mctourney.autoreferee.event.player.PlayerTeamJoinEvent; 31 | 32 | public class TeamListener implements Listener 33 | { 34 | AutoReferee plugin = null; 35 | 36 | public TeamListener(Plugin p) 37 | { plugin = (AutoReferee) p; } 38 | 39 | @EventHandler(priority=EventPriority.HIGHEST) 40 | public void chatMessage(AsyncPlayerChatEvent event) 41 | { 42 | // typical chat message format, swap out with colored version 43 | Player speaker = event.getPlayer(); 44 | AutoRefMatch match = plugin.getMatch(speaker.getWorld()); 45 | 46 | // restrict listeners to being in the same match (not world). 47 | // this should avoid messing up multi-world chat on multipurpose servers 48 | Iterator iter = event.getRecipients().iterator(); 49 | while (iter.hasNext()) 50 | { 51 | Player listener = iter.next(); 52 | 53 | if (plugin.getMatch(listener.getWorld()) != match) 54 | { iter.remove(); continue; } 55 | } 56 | 57 | // if the speaker isn't in a match, that's all we can do 58 | if (match == null) return; 59 | 60 | AutoRefTeam speakerTeam = match.getPlayerTeam(speaker); 61 | if (speakerTeam != null) 62 | { 63 | ChatColor teamColor = speakerTeam.getColor(); 64 | event.setFormat("<" + teamColor + "%s" + ChatColor.RESET + "> %s"); 65 | } 66 | else event.setFormat("<%s> %s"); 67 | modifyChatRecipients(match, speaker, event.getRecipients()); 68 | } 69 | 70 | @EventHandler(priority=EventPriority.HIGHEST) 71 | public void commandPreProcess(PlayerCommandPreprocessEvent event) 72 | { 73 | String message = event.getMessage(); 74 | if (message.startsWith("/me ")) 75 | event.setMessage("/autoref me " + message.substring(4)); 76 | } 77 | 78 | public static void modifyChatRecipients(AutoRefMatch match, Player speaker, Set recipients) 79 | { 80 | AutoRefTeam speakerTeam = match.getPlayerTeam(speaker); 81 | Role speakerRole = match.getRole(speaker); 82 | boolean practiceMode = match.isPracticeMode(); 83 | 84 | Iterator iter = recipients.iterator(); 85 | if (!match.getCurrentState().isBeforeMatch()) while (iter.hasNext()) 86 | { 87 | Player listener = iter.next(); 88 | 89 | // if listener is a streamer and the speaker is a non-streamer spectator, hide it 90 | if (match.isStreamer(listener) && speakerTeam == null && speakerRole != Role.STREAMER) 91 | { iter.remove(); continue; } 92 | 93 | // if listener is on a team, and speaker is a spectator, hide message (unless practice mode) 94 | if (!practiceMode && speakerTeam == null && match.getPlayerTeam(listener) != null) 95 | { iter.remove(); continue; } 96 | } 97 | } 98 | 99 | @EventHandler 100 | public void playerRespawn(PlayerRespawnEvent event) 101 | { 102 | World world = event.getPlayer().getWorld(); 103 | AutoRefMatch match = plugin.getMatch(world); 104 | 105 | if (match != null && match.isPlayer(event.getPlayer())) 106 | { 107 | // does this player have a bed spawn? 108 | boolean hasBed = event.getPlayer().getBedSpawnLocation() != null; 109 | 110 | // if the player attempts to respawn in a different world, bring them back 111 | Location respawnLocation = event.getRespawnLocation(); 112 | boolean changeRespawn = !hasBed || respawnLocation.getWorld() != match.getWorld() || 113 | match.inStartRegion(respawnLocation); 114 | if (changeRespawn) event.setRespawnLocation(match.getPlayerSpawn(event.getPlayer())); 115 | 116 | // setup respawn for the player 117 | match.getPlayer(event.getPlayer()).respawn(); 118 | } 119 | } 120 | 121 | @EventHandler(priority=EventPriority.HIGHEST) 122 | public void playerLogin(PlayerLoginEvent event) 123 | { 124 | Player player = event.getPlayer(); 125 | 126 | // if this player needs to be in a specific world, put them there 127 | AutoRefTeam team = plugin.getExpectedTeam(player); 128 | AutoRefMatch match = plugin.getMatch(player.getWorld()); 129 | 130 | if (team != null) 131 | { 132 | team.join(player, PlayerTeamJoinEvent.Reason.EXPECTED); 133 | match = team.getMatch(); 134 | } 135 | 136 | if (match != null && match.isPlayer(player)) 137 | match.messageReferees("player", player.getName(), "login"); 138 | } 139 | 140 | @EventHandler(priority=EventPriority.MONITOR) 141 | public void playerQuit(PlayerQuitEvent event) 142 | { 143 | Player player = event.getPlayer(); 144 | AutoRefMatch match = plugin.getMatch(player.getWorld()); 145 | if (match == null) return; 146 | 147 | // leave the team, if necessary 148 | AutoRefTeam team = plugin.getTeam(player); 149 | if (team != null) match.messageReferees("player", player.getName(), "logout"); 150 | if (team != null && !match.getCurrentState().inProgress()) team.leave(player); 151 | 152 | AutoRefPlayer apl = match.getPlayer(player); 153 | if (apl != null && player.getLocation() != null) 154 | apl.setLastLogoutLocation(player.getLocation()); 155 | 156 | // if this player was damaged recently (during the match), notify 157 | if (match.getCurrentState().inProgress() && apl != null && !apl.isDead() && apl.wasDamagedRecently()) 158 | { 159 | String message = apl.getDisplayName() + ChatColor.GRAY + " logged out during combat " + 160 | String.format("with %2.1f hearts remaining", apl.getPlayer().getHealth() / 2.0); 161 | for (Player ref : match.getReferees(true)) ref.sendMessage(message); 162 | } 163 | } 164 | 165 | @EventHandler(priority=EventPriority.HIGHEST) 166 | public void signCommand(PlayerInteractEvent event) 167 | { 168 | Player player = event.getPlayer(); 169 | AutoRefMatch match = plugin.getMatch(player.getWorld()); 170 | 171 | if (event.hasBlock() && event.getClickedBlock().getState() instanceof Sign) 172 | { 173 | String[] lines = ((Sign) event.getClickedBlock().getState()).getLines(); 174 | if (lines[0] == null || !"[AutoReferee]".equals(lines[0])) return; 175 | 176 | if (match != null && match.getCurrentState().isBeforeMatch() && 177 | match.inStartRegion(event.getClickedBlock().getLocation())) 178 | { 179 | // execute the command on the sign (and hope like hell that AutoReferee picks it up) 180 | if (event.getAction() == Action.RIGHT_CLICK_BLOCK) 181 | player.performCommand(ChatColor.stripColor(lines[1] + " " + lines[2]).trim()); 182 | event.setCancelled(true); 183 | } 184 | } 185 | } 186 | 187 | @EventHandler(priority=EventPriority.HIGHEST) 188 | public void changeGamemode(PlayerGameModeChangeEvent event) 189 | { 190 | Player player = event.getPlayer(); 191 | AutoRefMatch match = plugin.getMatch(player.getWorld()); 192 | 193 | // if there is a match currently in progress on this world... 194 | if (match != null && !match.isPracticeMode() && 195 | match.getCurrentState().inProgress()) 196 | { 197 | // cancel the gamemode change if the player is a participant 198 | if (event.getNewGameMode() == GameMode.CREATIVE && 199 | match.isPlayer(player) && !player.hasPermission("autoreferee.admin")) 200 | { 201 | player.sendMessage(ChatColor.RED + 202 | "Cannot change gamemode outside of practice mode!"); 203 | event.setCancelled(true); 204 | } 205 | } 206 | } 207 | } 208 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 6 | 8 | 4.0.0 9 | 10 | org.mctourney.autoreferee 11 | AutoReferee 12 | 2.8.4 13 | AutoReferee Core Plugin 14 | https://www.reddit.com/r/mctourney 15 | Bukkit plugin for automatically refereeing competitive Minecraft matches. 16 | 17 | 18 | UTF-8 19 | 1.8.8-R0.1-SNAPSHOT 20 | 1.6 21 | 22 | 23 | 24 | scm:git:git://github.com/rmct/AutoReferee.git 25 | https://github.com/rmct/AutoReferee 26 | scm:git:git@github.com:rmct/AutoReferee.git 27 | 28 | 29 | 30 | 31 | spigot-repo 32 | https://hub.spigotmc.org/nexus/content/repositories/snapshots/ 33 | 34 | 35 | sk89q-mvn2 36 | http://mvn2.sk89q.com/repo 37 | 38 | 39 | Plugin Metrics 40 | http://repo.mcstats.org/content/repositories/public 41 | 42 | 43 | 44 | 45 | 46 | 47 | com.sk89q 48 | worldedit 49 | 5.3 50 | 51 | 52 | org.spout 53 | spoutapi 54 | 55 | 56 | org.spout 57 | vanilla 58 | 59 | 60 | 61 | 62 | 63 | 64 | org.bukkit 65 | bukkit 66 | ${bukkit.version} 67 | provided 68 | 69 | 70 | 71 | commons-io 72 | commons-io 73 | 2.0.1 74 | 75 | 76 | 77 | junit 78 | junit 79 | 4.8.1 80 | test 81 | 82 | 83 | 84 | org.apache.commons 85 | commons-lang3 86 | 3.1 87 | 88 | 89 | 90 | com.google.guava 91 | guava 92 | 14.0 93 | 94 | 95 | 96 | commons-collections 97 | commons-collections 98 | 3.2.2 99 | 100 | 101 | 102 | com.google.code.gson 103 | gson 104 | 2.2.2 105 | 106 | 107 | 108 | commons-cli 109 | commons-cli 110 | 1.2 111 | 112 | 113 | 114 | commons-codec 115 | commons-codec 116 | 1.4 117 | 118 | 119 | 120 | org.jdom 121 | jdom2 122 | 2.0.4 123 | 124 | 125 | 126 | org.mcstats.bukkit 127 | metrics 128 | R7 129 | compile 130 | 131 | 132 | 133 | 134 | ${basedir}/src/main/java 135 | 136 | 137 | 138 | 139 | . 140 | true 141 | ${basedir}/src/main/resources/ 142 | 143 | plugin.yml 144 | colors.csv 145 | autoreferee.properties 146 | 147 | 148 | 149 | defaults/ 150 | true 151 | ${basedir}/src/main/resources/ 152 | 153 | map.xml 154 | config.yml 155 | 156 | 157 | 158 | webstats/ 159 | false 160 | ${basedir}/src/main/resources/webstats 161 | 162 | 163 | 164 | 165 | 166 | org.codehaus.mojo 167 | buildnumber-maven-plugin 168 | 1.1 169 | 170 | 171 | validate 172 | 173 | create 174 | 175 | 176 | 177 | 178 | 179 | 180 | org.codehaus.mojo 181 | exec-maven-plugin 182 | 1.2.1 183 | 184 | 185 | 186 | java 187 | 188 | 189 | 190 | 191 | org.mctourney.autoreferee.AutoRefereeTools 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | org.apache.maven.plugins 200 | maven-jar-plugin 201 | 2.3.2 202 | 203 | 204 | 205 | true 206 | org.mctourney.autoreferee.AutoRefereeTools 207 | 208 | 209 | 210 | 211 | 212 | 213 | org.apache.maven.plugins 214 | maven-surefire-plugin 215 | 2.11 216 | 217 | 218 | 219 | org.apache.maven.plugins 220 | maven-compiler-plugin 221 | 2.3.2 222 | 223 | ${java.target.version} 224 | ${java.target.version} 225 | true 226 | true 227 | true 228 | 229 | 230 | 231 | 232 | org.apache.maven.plugins 233 | maven-shade-plugin 234 | 1.7 235 | 236 | 237 | package 238 | 239 | shade 240 | 241 | 242 | true 243 | 244 | 245 | org.apache.commons:commons-lang3 246 | commons-io:commons-io 247 | commons-codec:commons-codec 248 | commons-cli:commons-cli 249 | commons-collections:commons-collections 250 | com.google.code.gson:gson 251 | org.jdom:jdom2 252 | org.mcstats.bukkit:metrics 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | --------------------------------------------------------------------------------