From d468faaadb9e732b6fbebcfc772633b6f7c2d29b Mon Sep 17 00:00:00 2001 From: WegFetZ Date: Thu, 18 Dec 2014 19:24:59 +0100 Subject: [PATCH] add WorldGuard support --- .../soundcenter/client/MainLoop.java | 13 ++ .../client/audio/AudioManager.java | 12 +- .../soundcenter/client/data/Database.java | 40 +++- .../gui/actions/StationsTabActions.java | 10 +- .../client/gui/dialogs/EditStationDialog.java | 2 +- .../gui/renderer/RegionListCellRenderer.java | 4 +- .../client/gui/tabs/StationsTab.java | 2 +- .../client/network/tcp/TcpProtocol.java | 1 + .../client/util/IntersectionDetection.java | 194 +++++++++++++----- 9 files changed, 211 insertions(+), 67 deletions(-) diff --git a/SoundCenterClient/src/com/soundcenter/soundcenter/client/MainLoop.java b/SoundCenterClient/src/com/soundcenter/soundcenter/client/MainLoop.java index 24d8f60..c4b6da0 100644 --- a/SoundCenterClient/src/com/soundcenter/soundcenter/client/MainLoop.java +++ b/SoundCenterClient/src/com/soundcenter/soundcenter/client/MainLoop.java @@ -31,6 +31,7 @@ public void run() { if (location != null && App.audioManager.isMusicActive()) { HashMap boxesInRange = IntersectionDetection.getBoxesInRange(location); HashMap areasInRange = IntersectionDetection.getAreasInRange(location); + List wgRegionsInRange = IntersectionDetection.getWGRegionsInRange(location); List biomesInRange = IntersectionDetection.getBiomeInRange(location); List worldsInRange = IntersectionDetection.getWorldInRange(location); @@ -64,6 +65,18 @@ public void run() { App.audioManager.updatePlayer(GlobalConstants.TYPE_AREA, id, dist); } + /* update wgRegion players */ + for (Entry entry : App.audioManager.wgRegionPlayers.entrySet()) { + id = entry.getKey(); + + if (!wgRegionsInRange.contains(id)) { + App.audioManager.stopPlayer(GlobalConstants.TYPE_WGREGION, id, false); + } + } + for (short wgRegionId : wgRegionsInRange) { + App.audioManager.updatePlayer(GlobalConstants.TYPE_WGREGION, wgRegionId, 0); + } + /* update biome players */ for (Entry entry : App.audioManager.biomePlayers.entrySet()) { id = entry.getKey(); diff --git a/SoundCenterClient/src/com/soundcenter/soundcenter/client/audio/AudioManager.java b/SoundCenterClient/src/com/soundcenter/soundcenter/client/audio/AudioManager.java index 3e885a8..e2c677f 100644 --- a/SoundCenterClient/src/com/soundcenter/soundcenter/client/audio/AudioManager.java +++ b/SoundCenterClient/src/com/soundcenter/soundcenter/client/audio/AudioManager.java @@ -25,6 +25,7 @@ public class AudioManager { public ConcurrentHashMap boxPlayers = new ConcurrentHashMap(); public ConcurrentHashMap biomePlayers = new ConcurrentHashMap(); public ConcurrentHashMap worldPlayers = new ConcurrentHashMap(); + public ConcurrentHashMap wgRegionPlayers = new ConcurrentHashMap(); public ConcurrentHashMap voicePlayers = new ConcurrentHashMap(); public PlayerController globalPlayer = null; @@ -95,7 +96,7 @@ public void updatePlayer(byte type, short id, double dist) { } else { volumeManager.setPlayerVolume(controller, (byte) 100); } - } else if (type == GlobalConstants.TYPE_WORLD || type == GlobalConstants.TYPE_BIOME) { + } else if (type == GlobalConstants.TYPE_WORLD || type == GlobalConstants.TYPE_BIOME || type == GlobalConstants.TYPE_WGREGION) { volumeManager.setPlayerVolume(controller, (byte) 100); } } @@ -137,7 +138,7 @@ public boolean isPlayingGlobally() { public boolean playersOverlap() { //ceck if there is more than one player (excluding speex players) - int players = (areaPlayers.size() + boxPlayers.size() + biomePlayers.size() + worldPlayers.size()); + int players = (areaPlayers.size() + boxPlayers.size() + biomePlayers.size() + worldPlayers.size() + wgRegionPlayers.size()); return players > 1 || (players == 1 && globalPlayer != null); } @@ -270,6 +271,10 @@ public void run() { PlayerController controller = entry.getValue(); controller.close(true); } + for (Entry entry : wgRegionPlayers.entrySet()) { + PlayerController controller = entry.getValue(); + controller.close(true); + } if (globalPlayer != null) { globalPlayer.close(true); @@ -279,6 +284,7 @@ public void run() { boxPlayers.clear(); biomePlayers.clear(); worldPlayers.clear(); + wgRegionPlayers.clear(); globalPlayer = null; if (App.gui != null) { App.gui.controller.setPlayButtonText("Play Globally"); @@ -305,6 +311,8 @@ private ConcurrentHashMap getPlayerMap(byte type) { return biomePlayers; case GlobalConstants.TYPE_WORLD: return worldPlayers; + case GlobalConstants.TYPE_WGREGION: + return wgRegionPlayers; case GlobalConstants.TYPE_VOICE: return voicePlayers; default: diff --git a/SoundCenterClient/src/com/soundcenter/soundcenter/client/data/Database.java b/SoundCenterClient/src/com/soundcenter/soundcenter/client/data/Database.java index be0eddc..a6e60aa 100644 --- a/SoundCenterClient/src/com/soundcenter/soundcenter/client/data/Database.java +++ b/SoundCenterClient/src/com/soundcenter/soundcenter/client/data/Database.java @@ -9,6 +9,7 @@ import javax.swing.DefaultComboBoxModel; import javax.swing.DefaultListModel; + import com.soundcenter.soundcenter.client.App; import com.soundcenter.soundcenter.client.Client; import com.soundcenter.soundcenter.lib.data.GlobalConstants; @@ -28,12 +29,14 @@ public class Database implements Serializable{ public ConcurrentHashMap boxes = new ConcurrentHashMap(); public ConcurrentHashMap biomes = new ConcurrentHashMap(); public ConcurrentHashMap worlds = new ConcurrentHashMap(); + public ConcurrentHashMap wgRegions = new ConcurrentHashMap(); public ConcurrentHashMap songs = new ConcurrentHashMap(); private ConcurrentHashMap areaModels = new ConcurrentHashMap(); private ConcurrentHashMap boxModels = new ConcurrentHashMap(); private ConcurrentHashMap biomeModels = new ConcurrentHashMap(); private ConcurrentHashMap worldModels = new ConcurrentHashMap(); + private ConcurrentHashMap wgRegionModels = new ConcurrentHashMap(); private ConcurrentHashMap songModels = new ConcurrentHashMap(); private DefaultListModel availableBiomesModel = new DefaultListModel(); @@ -45,6 +48,7 @@ public class Database implements Serializable{ public List mutedBoxes = new ArrayList(); public List mutedBiomes = new ArrayList(); public List mutedWorlds = new ArrayList(); + public List mutedWGRegions = new ArrayList(); private List permissions = new ArrayList(); @@ -83,6 +87,9 @@ public void addStation(Station station) { case GlobalConstants.TYPE_WORLD: item = "Worlds"; removeAvailableWorld(station.getName()); + break; + case GlobalConstants.TYPE_WGREGION: + item = "WorldGuard Regions"; } updateStationsTab(station.getOwner(), item, model); } @@ -115,10 +122,12 @@ public Station removeStation(byte type, short id, boolean updateAvailables) { public void removeStation(Station station, boolean updateAvailables) { ConcurrentHashMap stationMap = getStationMap(station.getType()); ConcurrentHashMap modelMap = getModelMap(station.getType()); - - if (stationMap != null && modelMap != null) { - stationMap.remove(station); - + + if (stationMap != null) { + stationMap.remove(station.getId()); + + } + if (modelMap != null) { DefaultListModel model = null; if (modelMap.containsKey(station.getOwner())) { model = modelMap.get(station.getOwner()); @@ -133,6 +142,9 @@ public void removeStation(Station station, boolean updateAvailables) { case GlobalConstants.TYPE_BOX: item = "Boxes"; break; + case GlobalConstants.TYPE_WGREGION: + item = "WorldGuard Regions"; + break; case GlobalConstants.TYPE_BIOME: item = "Biomes"; if (updateAvailables) { @@ -159,6 +171,8 @@ private ConcurrentHashMap getStationMap(byte type) { return biomes; case GlobalConstants.TYPE_WORLD: return worlds; + case GlobalConstants.TYPE_WGREGION: + return wgRegions; default: return null; } @@ -174,6 +188,8 @@ private ConcurrentHashMap getModelMap(byte type) { return biomeModels; case GlobalConstants.TYPE_WORLD: return worldModels; + case GlobalConstants.TYPE_WGREGION: + return wgRegionModels; default: return null; } @@ -191,6 +207,12 @@ public DefaultListModel getBoxModel(String player) { } + /* --------------------------- WGREGIONS -------------------------- */ + public DefaultListModel getWGRegionModel(String player) { + return wgRegionModels.get(player); + } + + /* --------------------------- BIOMES -------------------------- */ public DefaultListModel getBiomeModel(String player) { return biomeModels.get(player); @@ -289,6 +311,9 @@ public void removeSongFromStations(String path) { for (Entry entry : worlds.entrySet()) { entry.getValue().removeSong(path); } + for (Entry entry : wgRegions.entrySet()) { + entry.getValue().removeSong(path); + } } public void addSongToUpload(File song) { @@ -347,6 +372,8 @@ public List getMutedList(byte type) { return mutedBiomes; case GlobalConstants.TYPE_WORLD: return mutedWorlds; + case GlobalConstants.TYPE_WGREGION: + return mutedWGRegions; default: return null; } @@ -424,6 +451,10 @@ public void reset() { DefaultListModel model = entry.getValue(); model.removeAllElements(); } + for (Entry entry : wgRegionModels.entrySet()) { + DefaultListModel model = entry.getValue(); + model.removeAllElements(); + } for (Entry entry : songModels.entrySet()) { DefaultListModel model = entry.getValue(); model.removeAllElements(); @@ -442,6 +473,7 @@ public void reset() { boxModels.clear(); biomeModels.clear(); worldModels.clear(); + wgRegionModels.clear(); songModels.clear(); permissions.clear(); diff --git a/SoundCenterClient/src/com/soundcenter/soundcenter/client/gui/actions/StationsTabActions.java b/SoundCenterClient/src/com/soundcenter/soundcenter/client/gui/actions/StationsTabActions.java index 67f538a..a52bf69 100644 --- a/SoundCenterClient/src/com/soundcenter/soundcenter/client/gui/actions/StationsTabActions.java +++ b/SoundCenterClient/src/com/soundcenter/soundcenter/client/gui/actions/StationsTabActions.java @@ -20,6 +20,7 @@ import com.soundcenter.soundcenter.lib.data.Region; import com.soundcenter.soundcenter.lib.data.Song; import com.soundcenter.soundcenter.lib.data.Station; +import com.soundcenter.soundcenter.lib.data.WGRegion; import com.soundcenter.soundcenter.lib.tcp.TcpOpcodes; public class StationsTabActions { @@ -56,6 +57,10 @@ public static void stationChooserSelected() { renderer = new RegionListCellRenderer(); if (Client.database.permissionGranted("sc.set.world")) addButtonEnabled = true; + + } else if(type.equals("WorldGuard Regions")) { + model = Client.database.getWGRegionModel(player); + renderer = new RegionListCellRenderer(); } if (model != null && renderer != null) { @@ -164,10 +169,13 @@ public static void editStationDialogApplyButtonPressed(EditStationDialog dialog) } else if (type == GlobalConstants.TYPE_WORLD) { station = new Region(oldStation.getId(), oldStation.getOwner(), oldStation.getName(), type); + + } else if (type == GlobalConstants.TYPE_WGREGION) { + station = new WGRegion(oldStation.getId(), oldStation.getOwner(), oldStation.getName(), oldStation.getMin(), oldStation.getMax(), oldStation.getPoints()); } try { - if (type != GlobalConstants.TYPE_WORLD && type != GlobalConstants.TYPE_BIOME) { + if (type == GlobalConstants.TYPE_AREA || type == GlobalConstants.TYPE_BOX) { int range = Integer.parseInt(dialog.rangeField.getText()); station.setRange(range); } diff --git a/SoundCenterClient/src/com/soundcenter/soundcenter/client/gui/dialogs/EditStationDialog.java b/SoundCenterClient/src/com/soundcenter/soundcenter/client/gui/dialogs/EditStationDialog.java index d1dea15..ba54cfe 100644 --- a/SoundCenterClient/src/com/soundcenter/soundcenter/client/gui/dialogs/EditStationDialog.java +++ b/SoundCenterClient/src/com/soundcenter/soundcenter/client/gui/dialogs/EditStationDialog.java @@ -124,7 +124,7 @@ public void stateChanged(ChangeEvent e) { pane.setLayout(new BoxLayout(pane, BoxLayout.Y_AXIS)); pane.setBorder(new EmptyBorder(new Insets(10, 10, 10, 10))); - if (type == GlobalConstants.TYPE_BIOME || type == GlobalConstants.TYPE_WORLD) { + if (type == GlobalConstants.TYPE_BIOME || type == GlobalConstants.TYPE_WORLD || type == GlobalConstants.TYPE_WGREGION) { Box nameBox = Box.createHorizontalBox(); JLabel nameTitleLabel = new JLabel("Name: "); nameTitleLabel.setPreferredSize(new Dimension(100, 20)); diff --git a/SoundCenterClient/src/com/soundcenter/soundcenter/client/gui/renderer/RegionListCellRenderer.java b/SoundCenterClient/src/com/soundcenter/soundcenter/client/gui/renderer/RegionListCellRenderer.java index 763f5c5..f62057a 100644 --- a/SoundCenterClient/src/com/soundcenter/soundcenter/client/gui/renderer/RegionListCellRenderer.java +++ b/SoundCenterClient/src/com/soundcenter/soundcenter/client/gui/renderer/RegionListCellRenderer.java @@ -12,7 +12,9 @@ import javax.swing.JPanel; import javax.swing.ListCellRenderer; import javax.swing.UIManager; + import com.soundcenter.soundcenter.lib.data.Region; +import com.soundcenter.soundcenter.lib.data.Station; public class RegionListCellRenderer extends JPanel implements ListCellRenderer { @@ -20,7 +22,7 @@ public class RegionListCellRenderer extends JPanel implements ListCellRenderer { public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { - Region region = (Region) value; + Station region = (Station) value; this.removeAll(); diff --git a/SoundCenterClient/src/com/soundcenter/soundcenter/client/gui/tabs/StationsTab.java b/SoundCenterClient/src/com/soundcenter/soundcenter/client/gui/tabs/StationsTab.java index bf22871..ac3553a 100644 --- a/SoundCenterClient/src/com/soundcenter/soundcenter/client/gui/tabs/StationsTab.java +++ b/SoundCenterClient/src/com/soundcenter/soundcenter/client/gui/tabs/StationsTab.java @@ -26,7 +26,7 @@ public class StationsTab extends JPanel { public JComboBox playerComboBox = new JComboBox(); - public JComboBox typeComboBox = new JComboBox(new String[]{"Areas", "Boxes", "Biomes", "Worlds"}); + public JComboBox typeComboBox = new JComboBox(new String[]{"Areas", "Boxes", "Biomes", "Worlds", "WorldGuard Regions"}); public JList stationList = new JList(); diff --git a/SoundCenterClient/src/com/soundcenter/soundcenter/client/network/tcp/TcpProtocol.java b/SoundCenterClient/src/com/soundcenter/soundcenter/client/network/tcp/TcpProtocol.java index 7bbef6a..cbf2ed2 100644 --- a/SoundCenterClient/src/com/soundcenter/soundcenter/client/network/tcp/TcpProtocol.java +++ b/SoundCenterClient/src/com/soundcenter/soundcenter/client/network/tcp/TcpProtocol.java @@ -167,6 +167,7 @@ public static boolean processPacket(TcpPacket packet) { App.audioManager.stopPlayer(type, id, true); Client.database.removeStation(type, id, true); + return true; } else if (cmd == TcpOpcodes.CL_DATA_CMD_DELETE_SONG) { diff --git a/SoundCenterClient/src/com/soundcenter/soundcenter/client/util/IntersectionDetection.java b/SoundCenterClient/src/com/soundcenter/soundcenter/client/util/IntersectionDetection.java index 41a37e3..53e399c 100644 --- a/SoundCenterClient/src/com/soundcenter/soundcenter/client/util/IntersectionDetection.java +++ b/SoundCenterClient/src/com/soundcenter/soundcenter/client/util/IntersectionDetection.java @@ -9,9 +9,10 @@ import com.soundcenter.soundcenter.client.Client; import com.soundcenter.soundcenter.lib.data.SCLocation; import com.soundcenter.soundcenter.lib.data.Station; +import com.soundcenter.soundcenter.lib.data.WGRegion; public class IntersectionDetection { - + public static List getBiomeInRange(SCLocation loc) { List matches = new ArrayList(); for (Entry entry : Client.database.biomes.entrySet()) { @@ -22,7 +23,7 @@ public static List getBiomeInRange(SCLocation loc) { } return matches; } - + public static List getWorldInRange(SCLocation loc) { List matches = new ArrayList(); for (Entry entry : Client.database.worlds.entrySet()) { @@ -33,60 +34,70 @@ public static List getWorldInRange(SCLocation loc) { } return matches; } - + public static HashMap getBoxesInRange(SCLocation loc) { HashMap matches = new HashMap(); - - for (Map.Entry entry : Client.database.boxes.entrySet()) - { - short id = entry.getKey(); - Station box = entry.getValue(); - SCLocation center = box.getLocation(); - try { - //check if location is roughly in rangeof the box, before calculating exact distance - if (locIsNear(center, loc, box.getRange())) { - double distance = center.distance(loc); - - /* if in range of box, add box id and distance to list */ - if (!isNaN(distance) && distance <= box.getRange()) { - matches.put(id, distance); - } - } - } catch (IllegalArgumentException e) {} - } - + + for (Map.Entry entry : Client.database.boxes.entrySet()) { + short id = entry.getKey(); + Station box = entry.getValue(); + SCLocation center = box.getLocation(); + try { + // check if location is roughly in rangeof the box, before + // calculating exact distance + if (locIsNear(center, loc, box.getRange())) { + double distance = center.distance(loc); + + /* if in range of box, add box id and distance to list */ + if (!isNaN(distance) && distance <= box.getRange()) { + matches.put(id, distance); + } + } + } catch (IllegalArgumentException e) { + } + } + return matches; } - + public static HashMap getAreasInRange(SCLocation loc) { HashMap matches = new HashMap(); - - for (Map.Entry entry : Client.database.areas.entrySet()) - { - short id = entry.getKey(); - Station area = entry.getValue(); - double distance = distToAreaBorder(loc, area, false); - - /* if in area, add area id and distance to border to list */ - if (distance > 0) { - matches.put(id, distance); - } - } + + for (Map.Entry entry : Client.database.areas.entrySet()) { + short id = entry.getKey(); + Station area = entry.getValue(); + double distance = distToAreaBorder(loc, area, false); + + /* if in area, add area id and distance to border to list */ + if (distance > 0) { + matches.put(id, distance); + } + } return matches; } - + + public static List getWGRegionsInRange(SCLocation loc) { + List matches = new ArrayList(); + for (Entry entry : Client.database.wgRegions.entrySet()) { + WGRegion wgRegion = (WGRegion) entry.getValue(); + if (locInWGRegion(loc, wgRegion)) { + matches.add(wgRegion.getId()); + } + } + return matches; + } + private static double distToAreaBorder(SCLocation loc, Station area, Boolean calcDistIfOutside) { - + if (!loc.getWorld().equals(area.getWorld())) return -1; - + double dist = 0; boolean contains = false; - + SCLocation min = area.getMin(); SCLocation max = area.getMax(); - - + // check if cuboid contains loc boolean betweenX = false; boolean betweenY = false; @@ -97,19 +108,19 @@ private static double distToAreaBorder(SCLocation loc, Station area, Boolean cal betweenY = true; if ((loc.getZ() <= max.getZ()) && (loc.getZ() >= min.getZ())) betweenZ = true; - if(betweenX && betweenZ && betweenY) + if (betweenX && betweenZ && betweenY) contains = true; - + if (contains || calcDistIfOutside) { - //calculate distance to borders + // calculate distance to borders double distX = Math.min(Math.abs(min.getX() - loc.getX()), Math.abs(max.getX() - loc.getX())); double distY = Math.min(Math.abs(min.getY() - loc.getY()), Math.abs(max.getY() - loc.getY())); double distZ = Math.min(Math.abs(min.getZ() - loc.getZ()), Math.abs(max.getZ() - loc.getZ())); - - //get minimum distance + + // get minimum distance if (contains) dist = Math.min(Math.min(distX, distY), Math.min(distZ, Math.min(distX, distY))); - + else { if (betweenX && betweenY) dist = distZ; @@ -125,28 +136,97 @@ else if (betweenZ) dist = Math.sqrt(Math.pow(distX, 2) + Math.pow(distY, 2)); else dist = Math.sqrt(Math.pow(distX, 2) + Math.pow(distY, 2) + Math.pow(distZ, 2)); - - //use negative distance for points from outside + + // use negative distance for points from outside dist = -dist; } - } - + } + return dist; } - + + /* this method is copied from + * https://github.com/sk89q/WorldGuard/blob/master/src/main/java/com/sk89q/worldguard/protection/regions/ProtectedPolygonalRegion.java + * to move the expensive calculation for WorldGuard regions away from the server to the client + */ + private static boolean locInWGRegion(SCLocation loc, WGRegion region) { + if (!loc.getWorld().equalsIgnoreCase(region.getWorld())) { + return false; + } + + SCLocation min = region.getMin(); + SCLocation max = region.getMax(); + + int X = loc.getBlockX(); + int Y = loc.getBlockY(); + int Z = loc.getBlockZ(); + + if (Y < min.getBlockY() || Y > max.getBlockY()) { + return false; + } + + // check roughly before doing exact calculation + if (X < min.getBlockX() || X > max.getBlockX() || Z < min.getBlockZ() || Z > max.getBlockZ()) { + return false; + } + boolean inside = false; + int npoints = region.getPoints().size(); + int xNew, zNew; + int xOld, zOld; + int x1, z1; + int x2, z2; + long crossproduct; + int i; + xOld = region.getPoints().get(npoints - 1).getBlockX(); + zOld = region.getPoints().get(npoints - 1).getBlockZ(); + + for (i = 0; i < npoints; i++) { + xNew = region.getPoints().get(i).getBlockX(); + zNew = region.getPoints().get(i).getBlockZ(); + // Check for corner + if (xNew == X && zNew == Z) { + return true; + } + if (xNew > xOld) { + x1 = xOld; + x2 = xNew; + z1 = zOld; + z2 = zNew; + } else { + x1 = xNew; + x2 = xOld; + z1 = zNew; + z2 = zOld; + } + if (x1 <= X && X <= x2) { + crossproduct = ((long) Z - (long) z1) * (long) (x2 - x1) - ((long) z2 - (long) z1) * (long) (X - x1); + if (crossproduct == 0) { + if ((z1 <= Z) == (Z <= z2)) + return true; // on edge + } else if (crossproduct < 0 && (x1 != X)) { + inside = !inside; + } + } + xOld = xNew; + zOld = zNew; + } + + return inside; + } + private static boolean locIsNear(SCLocation loc1, SCLocation loc2, int range) { if (loc1.getWorld().equals(loc2.getWorld())) { - //check if location are near each other - if ((Math.abs(loc1.getX()-loc2.getX()) <= range) && (Math.abs(loc1.getY()-loc2.getY()) <= range) - && (Math.abs(loc1.getZ()-loc2.getZ()) <= range)) { + // check if location are near each other + if ((Math.abs(loc1.getX() - loc2.getX()) <= range) && (Math.abs(loc1.getY() - loc2.getY()) <= range) + && (Math.abs(loc1.getZ() - loc2.getZ()) <= range)) { return true; } } return false; } - + private static boolean isNaN(double x) { return x != x; } - + }