├── .classpath ├── Example.java ├── Readme.md ├── bin └── de │ └── sebpas │ └── replay │ ├── RePlayer$1.class │ ├── RePlayer.class │ ├── Recorder$1.class │ ├── Recorder.class │ ├── ReplaySystem.class │ ├── command │ └── CommandReplay.class │ ├── event │ ├── RecordingStartEvent.class │ ├── RecordingStoppedEvent.class │ ├── ReplayStartEvent.class │ └── ReplayStoppedEvent.class │ ├── filesystem │ └── FileManager.class │ ├── npc │ └── NPC.class │ ├── recorder │ └── listener │ │ ├── InteractListener.class │ │ ├── MoveListener.class │ │ └── SpawnDespawnListener.class │ └── util │ ├── InventoryUtilities.class │ ├── ItemUtilities.class │ ├── PlayingPlayer$1.class │ ├── PlayingPlayer.class │ ├── Reflections.class │ └── ReplayStoppedEvent.class ├── plugin.yml ├── spigot.jar └── src └── de └── sebpas └── replay ├── RePlayer.java ├── Recorder.java ├── ReplaySystem.java ├── command └── CommandReplay.java ├── event ├── RecordingStartEvent.java ├── RecordingStoppedEvent.java ├── ReplayStartEvent.java └── ReplayStoppedEvent.java ├── filesystem └── FileManager.java ├── npc └── NPC.java ├── recorder └── listener │ ├── InteractListener.java │ ├── MoveListener.java │ └── SpawnDespawnListener.java └── util ├── InventoryUtilities.java ├── ItemUtilities.java ├── PlayingPlayer.java ├── Reflections.java └── ReplayStoppedEvent.java /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | 3 | import org.bukkit.entity.Player; 4 | 5 | import de.sebpas.replay.RePlayer; 6 | import de.sebpas.replay.ReplaySystem; 7 | 8 | public class Example { 9 | /** start recording */ 10 | public void startRecording(){ 11 | ReplaySystem.getInstance().start(); 12 | } 13 | /** 14 | * stop recording: 15 | */ 16 | public void stopRecording(){ 17 | ReplaySystem.getInstance().stop(); 18 | } 19 | /** 20 | * replay file file to player p and stop it 21 | * @param file 22 | * @param p 23 | */ 24 | public void replayFile(String file, Player p){ 25 | RePlayer replayer = new RePlayer(file, p); 26 | replayer.start(); 27 | 28 | //velocity 29 | 30 | replayer.setVelocity(0.25D); 31 | 32 | // pause and continue it 33 | 34 | replayer.pause(); 35 | 36 | replayer.continueReplay(); 37 | 38 | // jump to 60 seconds (20 * 60 ticks) 39 | 40 | replayer.setCurrentTick(20 * 60); 41 | 42 | // stop 43 | 44 | replayer.stop(); 45 | } 46 | /** 47 | * Events: de.sebpas.event (package) 48 | * 49 | * - RecordingStartEvent 50 | * - RecordingStoppedEvent 51 | * - ReplayStartEvent 52 | * - ReplayStoppedEvent 53 | * http://www.youtube.com/c/thepnlpchannel may be helpful too! (Video called 'ReplayAPI - Tutorial' (in german) 54 | */ 55 | } 56 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # ReplayAPI - Development paused :( I am sorry 2 | ReplayAPI a plugin for Bukkit / Spigot to record and replay ingame action 3 | 4 | IMPORTANT: Here is a newer version of this project - still not continued but way better than this one: 5 | https://bitbucket.org/thepn/replayapi/src/master/src/de/sebpas/replay/filesystem/serializable/ 6 | 7 | Languages: english and german 8 | 9 | Why use this plugin: 10 | - No network, sql or bungeecord needed 11 | - create own plugins or features using the api 12 | - open source :D 13 | 14 | # Ingame Commands 15 | 16 | - /replay play - plays a captured gameplay 17 | - /replay stop - stops the replay 18 | - /rplstart - starts capturing 19 | - /rplstop - stops capturing 20 | - /replay time - jumps to the wished time (eg. /replay time 1:30 to go to 1 minute and 30 seconds 21 | 22 | # API documentation: 23 | API examples can be found here 24 | -------------------------------------------------------------------------------- /bin/de/sebpas/replay/RePlayer$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pscln/ReplayAPI/4ad4152dc4c4fdfb65084f0beaeb4452f63fcf61/bin/de/sebpas/replay/RePlayer$1.class -------------------------------------------------------------------------------- /bin/de/sebpas/replay/RePlayer.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pscln/ReplayAPI/4ad4152dc4c4fdfb65084f0beaeb4452f63fcf61/bin/de/sebpas/replay/RePlayer.class -------------------------------------------------------------------------------- /bin/de/sebpas/replay/Recorder$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pscln/ReplayAPI/4ad4152dc4c4fdfb65084f0beaeb4452f63fcf61/bin/de/sebpas/replay/Recorder$1.class -------------------------------------------------------------------------------- /bin/de/sebpas/replay/Recorder.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pscln/ReplayAPI/4ad4152dc4c4fdfb65084f0beaeb4452f63fcf61/bin/de/sebpas/replay/Recorder.class -------------------------------------------------------------------------------- /bin/de/sebpas/replay/ReplaySystem.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pscln/ReplayAPI/4ad4152dc4c4fdfb65084f0beaeb4452f63fcf61/bin/de/sebpas/replay/ReplaySystem.class -------------------------------------------------------------------------------- /bin/de/sebpas/replay/command/CommandReplay.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pscln/ReplayAPI/4ad4152dc4c4fdfb65084f0beaeb4452f63fcf61/bin/de/sebpas/replay/command/CommandReplay.class -------------------------------------------------------------------------------- /bin/de/sebpas/replay/event/RecordingStartEvent.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pscln/ReplayAPI/4ad4152dc4c4fdfb65084f0beaeb4452f63fcf61/bin/de/sebpas/replay/event/RecordingStartEvent.class -------------------------------------------------------------------------------- /bin/de/sebpas/replay/event/RecordingStoppedEvent.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pscln/ReplayAPI/4ad4152dc4c4fdfb65084f0beaeb4452f63fcf61/bin/de/sebpas/replay/event/RecordingStoppedEvent.class -------------------------------------------------------------------------------- /bin/de/sebpas/replay/event/ReplayStartEvent.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pscln/ReplayAPI/4ad4152dc4c4fdfb65084f0beaeb4452f63fcf61/bin/de/sebpas/replay/event/ReplayStartEvent.class -------------------------------------------------------------------------------- /bin/de/sebpas/replay/event/ReplayStoppedEvent.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pscln/ReplayAPI/4ad4152dc4c4fdfb65084f0beaeb4452f63fcf61/bin/de/sebpas/replay/event/ReplayStoppedEvent.class -------------------------------------------------------------------------------- /bin/de/sebpas/replay/filesystem/FileManager.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pscln/ReplayAPI/4ad4152dc4c4fdfb65084f0beaeb4452f63fcf61/bin/de/sebpas/replay/filesystem/FileManager.class -------------------------------------------------------------------------------- /bin/de/sebpas/replay/npc/NPC.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pscln/ReplayAPI/4ad4152dc4c4fdfb65084f0beaeb4452f63fcf61/bin/de/sebpas/replay/npc/NPC.class -------------------------------------------------------------------------------- /bin/de/sebpas/replay/recorder/listener/InteractListener.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pscln/ReplayAPI/4ad4152dc4c4fdfb65084f0beaeb4452f63fcf61/bin/de/sebpas/replay/recorder/listener/InteractListener.class -------------------------------------------------------------------------------- /bin/de/sebpas/replay/recorder/listener/MoveListener.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pscln/ReplayAPI/4ad4152dc4c4fdfb65084f0beaeb4452f63fcf61/bin/de/sebpas/replay/recorder/listener/MoveListener.class -------------------------------------------------------------------------------- /bin/de/sebpas/replay/recorder/listener/SpawnDespawnListener.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pscln/ReplayAPI/4ad4152dc4c4fdfb65084f0beaeb4452f63fcf61/bin/de/sebpas/replay/recorder/listener/SpawnDespawnListener.class -------------------------------------------------------------------------------- /bin/de/sebpas/replay/util/InventoryUtilities.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pscln/ReplayAPI/4ad4152dc4c4fdfb65084f0beaeb4452f63fcf61/bin/de/sebpas/replay/util/InventoryUtilities.class -------------------------------------------------------------------------------- /bin/de/sebpas/replay/util/ItemUtilities.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pscln/ReplayAPI/4ad4152dc4c4fdfb65084f0beaeb4452f63fcf61/bin/de/sebpas/replay/util/ItemUtilities.class -------------------------------------------------------------------------------- /bin/de/sebpas/replay/util/PlayingPlayer$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pscln/ReplayAPI/4ad4152dc4c4fdfb65084f0beaeb4452f63fcf61/bin/de/sebpas/replay/util/PlayingPlayer$1.class -------------------------------------------------------------------------------- /bin/de/sebpas/replay/util/PlayingPlayer.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pscln/ReplayAPI/4ad4152dc4c4fdfb65084f0beaeb4452f63fcf61/bin/de/sebpas/replay/util/PlayingPlayer.class -------------------------------------------------------------------------------- /bin/de/sebpas/replay/util/Reflections.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pscln/ReplayAPI/4ad4152dc4c4fdfb65084f0beaeb4452f63fcf61/bin/de/sebpas/replay/util/Reflections.class -------------------------------------------------------------------------------- /bin/de/sebpas/replay/util/ReplayStoppedEvent.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pscln/ReplayAPI/4ad4152dc4c4fdfb65084f0beaeb4452f63fcf61/bin/de/sebpas/replay/util/ReplayStoppedEvent.class -------------------------------------------------------------------------------- /plugin.yml: -------------------------------------------------------------------------------- 1 | name: ReplayAPI 2 | main: de.sebpas.replay.ReplaySystem 3 | version: 1.0 4 | authors: [SPMinecraftWorld, thepn,] 5 | commands: 6 | rplstart: 7 | usage: /start 8 | description: starts the replay recorder 9 | rplstop: 10 | usage: /stop 11 | description: stops the replay recorder 12 | replay: 13 | permissions: 14 | replay.*: 15 | description: Erlaubt Zugriff auf alle Befehle des Replay - Plugins. 16 | children: 17 | replay.command: true 18 | replay.command: 19 | default: op -------------------------------------------------------------------------------- /spigot.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pscln/ReplayAPI/4ad4152dc4c4fdfb65084f0beaeb4452f63fcf61/spigot.jar -------------------------------------------------------------------------------- /src/de/sebpas/replay/RePlayer.java: -------------------------------------------------------------------------------- 1 | package de.sebpas.replay; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | import java.util.List; 6 | import java.util.Map; 7 | 8 | import net.md_5.bungee.api.ChatColor; 9 | 10 | import org.bukkit.Bukkit; 11 | import org.bukkit.GameMode; 12 | import org.bukkit.Location; 13 | import org.bukkit.Material; 14 | import org.bukkit.Sound; 15 | import org.bukkit.entity.Player; 16 | import org.bukkit.inventory.ItemStack; 17 | 18 | import de.sebpas.replay.event.ReplayStartEvent; 19 | import de.sebpas.replay.npc.NPC; 20 | import de.sebpas.replay.util.PlayingPlayer; 21 | 22 | public class RePlayer { 23 | private double lastTick; 24 | private Map players; 25 | private List tickList; 26 | private double currentTick; 27 | private double velocity = 1; 28 | private boolean isRunning = false; 29 | 30 | /** NPC stuff */ 31 | private List npcs = new ArrayList(); 32 | 33 | /** thread stuff */ 34 | private int taskID; 35 | private Runnable task = new Runnable() { 36 | 37 | @Override 38 | public void run() { 39 | if(isRunning){ 40 | // if(currentTick - lastTick > 1 && lastTick % 1 == 0){ 41 | double ticks = Math.floor(currentTick - lastTick); 42 | System.out.println("Last tick: " + lastTick + ", current: " + currentTick + ", ticks to run: " + ticks); 43 | for(int j = 0; j < ticks; j++){ 44 | System.out.println("running: " + j + " / " + ticks + " ticks!"); 45 | for(String s : getCurrentStringList((int) lastTick + j)){ 46 | if(s.split(";").length == 1) 47 | break; 48 | String name = s.split(";")[2]; 49 | String uuid = s.split(";")[1]; 50 | if(!isExisting(s.split(";")[2])){ 51 | double x = 0, y = 0, z = 0; 52 | float yaw = 0, pitch = 0; 53 | String[] temp = s.split(";")[3].replace("moved:", "").split(","); 54 | try{ 55 | x = Double.parseDouble(temp[0]); 56 | y = Double.parseDouble(temp[1]); 57 | z = Double.parseDouble(temp[2]); 58 | 59 | yaw = Float.parseFloat(temp[3]); 60 | pitch = Float.parseFloat(temp[4]); 61 | }catch(Exception e){ 62 | x = 0; 63 | y = 255; 64 | z = 0; 65 | yaw = 45; 66 | pitch = 0; 67 | } 68 | NPC npc = new NPC(uuid, name, new Location(((Player) players.keySet().toArray()[0]).getWorld(), x, y, z, yaw, pitch), (Player) players.keySet().toArray()[0]); 69 | npcs.add(npc); 70 | npc.spawn(); 71 | }else if(s.split(";")[3].startsWith("moved:")){ /** movement */ 72 | double x = 0, y = 0, z = 0; 73 | float yaw = 0, pitch = 0; 74 | String[] temp = s.split(";")[3].replace("moved:", "").split(","); 75 | x = Double.parseDouble(temp[0]); 76 | y = Double.parseDouble(temp[1]); 77 | z = Double.parseDouble(temp[2]); 78 | 79 | yaw = Float.parseFloat(temp[3]); 80 | pitch = Float.parseFloat(temp[4]); 81 | 82 | if(currentTick % 2 != 0){ 83 | float yawR = (float) Math.toRadians(yaw); 84 | x = -Math.sin(yawR); 85 | z = Math.cos(yawR); 86 | } 87 | 88 | double speed = 4.3D; 89 | 90 | if(s.split(";").length == 4 && getNPCByName(name).isBlocking() || getNPCByName(name).isSneaking() || getNPCByName(name).isSprinting()) 91 | getNPCByName(name).resetMovement(); 92 | 93 | if(s.split(";").length == 5){ 94 | if(s.split(";")[4].equalsIgnoreCase("sprint")) 95 | getNPCByName(name).sprint(); 96 | if(s.split(";")[4].equalsIgnoreCase("sneak")){ 97 | getNPCByName(name).sneak(); 98 | speed /= 3D; 99 | } 100 | if(s.split(";")[4].equalsIgnoreCase("block")){ 101 | getNPCByName(name).block(); 102 | speed /= 4D; 103 | } 104 | } 105 | 106 | if(s.split(";").length == 6){ 107 | if(s.split(";")[4].equalsIgnoreCase("block")) 108 | getNPCByName(name).block(); 109 | } 110 | 111 | getNPCByName(name).look(yaw, pitch); 112 | getNPCByName(name).move(x * (speed / 20), y - getNPCByName(name).getLocation().getY(), z * (speed / 20), yaw, pitch); 113 | 114 | if(currentTick % 2 == 0) 115 | getNPCByName(name).teleport(new Location(((Player) players.keySet().toArray()[0]).getWorld(), x, y, z, yaw, pitch)); 116 | }else if(s.split(";").length == 1) 117 | break; 118 | 119 | if(s.split(";")[3].startsWith("swing")) /** swinging the item in hand */ { 120 | getNPCByName(name).swingArm(); 121 | }else if(s.split(";")[3].startsWith("dmg")) /** damage animation */ { 122 | getNPCByName(name).damageAnimation(); 123 | }else if(s.split(";")[3].startsWith("armr")) /** armor content updating */ { 124 | String[] temp = s.split(";")[3].replace("armr:", "").split(","); 125 | ItemStack[] armor = new ItemStack[4]; 126 | for(int i = 0; i < temp.length; i++){ 127 | armor[i] = new ItemStack(Material.getMaterial(temp[i])); 128 | } 129 | getNPCByName(name).updateItems(getNPCByName(name).getItemInHand(), armor[3], armor[2], armor[1], armor[0]); 130 | }else if(s.split(";")[3].startsWith("itmhnd")) /** item in hand */ { 131 | getNPCByName(name).updateItems(new ItemStack(Material.getMaterial(s.split(";")[3].replace("itmhnd:", ""))), getNPCByName(name).getArmorContents()[0], getNPCByName(name).getArmorContents()[1], getNPCByName(name).getArmorContents()[2], getNPCByName(name).getArmorContents()[3]); 132 | }else if(s.split(";")[3].startsWith("lggdin")) /** joined the game */ { 133 | double x = 0, y = 0, z = 0; 134 | String[] temp = s.split(";")[3].replace("lggdin:", "").split(","); 135 | try{ 136 | x = Double.parseDouble(temp[0]); 137 | y = Double.parseDouble(temp[1]); 138 | z = Double.parseDouble(temp[2]); 139 | }catch(Exception e){ 140 | x = 0; 141 | y = 255; 142 | z = 0; 143 | } 144 | 145 | sendChatMessageToAll(s.split(";")[4]); 146 | getNPCByName(name).spawn(new Location(((Player) players.keySet().toArray()[0]).getWorld(), x, y, z)); 147 | }else if(s.split(";")[3].startsWith("lggdout")) /** left the game */ { 148 | sendChatMessageToAll(s.split(";")[4]); 149 | getNPCByName(name).deSpawn(); 150 | }else if(s.split(";")[3].startsWith("died")) /** died */ { 151 | sendChatMessageToAll(s.split(";")[4]); 152 | getNPCByName(name).deSpawn(); 153 | }else if(s.split(";")[3].startsWith("rspn")) /** respawned */ { 154 | double x = 0, y = 0, z = 0; 155 | String[] temp = s.split(";")[3].replace("rspn:", "").split(","); 156 | try{ 157 | x = Double.parseDouble(temp[0]); 158 | y = Double.parseDouble(temp[1]); 159 | z = Double.parseDouble(temp[2]); 160 | }catch(Exception e){ 161 | x = 0; 162 | y = 255; 163 | z = 0; 164 | } 165 | 166 | sendChatMessageToAll(s.split(";")[4]); 167 | getNPCByName(name).spawn(new Location(((Player) players.keySet().toArray()[0]).getWorld(), x, y, z)); 168 | }else if(s.split(";")[3].startsWith("cht")) /** chat message sent */ { 169 | for(Player p : players.keySet()) 170 | p.sendMessage(ChatColor.translateAlternateColorCodes('&', s.split(";")[4])); 171 | } 172 | } 173 | lastTick = Math.floor(currentTick); 174 | } 175 | 176 | /** tick decrease */ 177 | currentTick += velocity; 178 | } 179 | for(Player p : players.keySet()){ 180 | p.setExp((float) currentTick / (float) getLastTick()); 181 | if(currentTick % 20 == 0) 182 | p.setLevel((int) currentTick / 20); 183 | p.setHealth(20D); 184 | p.setFoodLevel(20); 185 | } 186 | if(currentTick > getLastTick() || players.isEmpty()) 187 | stop(); 188 | 189 | } 190 | }; 191 | 192 | public void pause(){ 193 | this.isRunning = false; 194 | } 195 | 196 | public void continueReplay(){ 197 | this.isRunning = true; 198 | } 199 | 200 | public RePlayer(String file, Player player){ 201 | this.currentTick = 0; 202 | this.players = new HashMap(); 203 | this.players.put(player, new PlayingPlayer(player)); 204 | tickList = ReplaySystem.getInstance().getFileManager().readFile(file + ".rpl"); 205 | if(!tickList.isEmpty()) 206 | ReplaySystem.getInstance().addPlayer(this); 207 | } 208 | 209 | public RePlayer(String file, Map players){ 210 | this.currentTick = 0; 211 | this.players = players; 212 | tickList = ReplaySystem.getInstance().getFileManager().readFile(file + ".rpl"); 213 | if(!tickList.isEmpty()) 214 | ReplaySystem.getInstance().addPlayer(this); 215 | } 216 | 217 | @SuppressWarnings("deprecation") 218 | public void start(){ 219 | this.isRunning = true; 220 | Bukkit.getPluginManager().callEvent(new ReplayStartEvent(this)); 221 | if(tickList == null){ 222 | for(Player p : this.players.keySet()){ 223 | p.sendMessage(ChatColor.translateAlternateColorCodes('&', ReplaySystem.getInstance().getErrorPrefix() + " &3Fehler beim lesen der Datei!")); 224 | } 225 | return; 226 | } 227 | for(Player p : this.players.keySet()){ 228 | p.setGameMode(GameMode.ADVENTURE); 229 | p.setAllowFlight(true); 230 | p.setFlying(true); 231 | p.setHealth(20D); 232 | p.setFoodLevel(20); 233 | p.sendMessage(ChatColor.translateAlternateColorCodes('&', ReplaySystem.getInstance().getPrefix() + "&3Replay gestartet!")); 234 | } 235 | taskID = Bukkit.getScheduler().scheduleAsyncRepeatingTask(ReplaySystem.getInstance(), task, 1L, 1L); 236 | } 237 | 238 | public void stop(){ 239 | this.isRunning = false; 240 | Bukkit.getScheduler().cancelTask(taskID); 241 | for(NPC n : npcs) 242 | n.deSpawn(); 243 | for(Player p : this.players.keySet()){ 244 | p.playSound(p.getLocation(), Sound.LEVEL_UP, 1, 1); 245 | this.getPlayers().get(p).throwIntoGame(p, true); 246 | p.sendMessage(ChatColor.translateAlternateColorCodes('&', ReplaySystem.getInstance().getPrefix() + " &3Das Replay ist beendet. Du hast das Replay verlassen.")); 247 | } 248 | ReplaySystem.getInstance().onPlayerStopped(this); 249 | } 250 | 251 | /** 252 | * ONLY use while stopping plugin 253 | */ 254 | public void stopWithoutTask(){ 255 | this.isRunning = false; 256 | Bukkit.getScheduler().cancelTask(taskID); 257 | for(NPC n : npcs) 258 | n.deSpawn(); 259 | for(Player p : this.players.keySet()){ 260 | p.playSound(p.getLocation(), Sound.LEVEL_UP, 1, 1); 261 | this.getPlayers().get(p).throwIntoGame(p, false); 262 | p.sendMessage(ChatColor.translateAlternateColorCodes('&', ReplaySystem.getInstance().getPrefix() + " &3Das Replay ist beendet. Du hast das Replay verlassen.")); 263 | } 264 | ReplaySystem.getInstance().onPlayerStopped(this); 265 | } 266 | 267 | @Deprecated 268 | /** 269 | * use RePlayer.stop() instead 270 | * @param p 271 | */ 272 | public void removePlayer(Player p){ 273 | this.players.remove(p); 274 | p.sendMessage(ChatColor.translateAlternateColorCodes('&', ReplaySystem.getInstance().getPrefix() + " &3Du hast das Replay verlassen.")); 275 | this.stop(); 276 | } 277 | 278 | public double getVelocity() { 279 | return velocity; 280 | } 281 | public void setVelocity(double velocity) { 282 | this.velocity = velocity; 283 | } 284 | public double getCurrentTick() { 285 | return currentTick; 286 | } 287 | public boolean setCurrentTick(double currentTick) { 288 | if(currentTick >= this.getLastTick() || currentTick < 0) 289 | return false; 290 | this.currentTick = currentTick; 291 | this.lastTick = currentTick -= velocity; 292 | return true; 293 | } 294 | public Map getPlayers() { 295 | return players; 296 | } 297 | public boolean isRunning() { 298 | return isRunning; 299 | } 300 | private int getLastTick(){ 301 | int max = 0; 302 | for(String s : tickList){ 303 | if(Integer.parseInt(s.split(";")[0]) > max) 304 | max = Integer.parseInt(s.split(";")[0]); 305 | } 306 | return max; 307 | } 308 | 309 | private List getCurrentStringList(int tick){ 310 | List rtn = new ArrayList(); 311 | for(String s : tickList){ 312 | if(Integer.parseInt(s.split(";")[0]) == tick) 313 | rtn.add(s); 314 | } 315 | return rtn; 316 | } 317 | private boolean isExisting(String name){ 318 | for(NPC n : this.npcs){ 319 | if(n.getName().equalsIgnoreCase(name)) 320 | return true; 321 | } 322 | return false; 323 | } 324 | public NPC getNPCByName(String name){ 325 | for(NPC n : npcs){ 326 | if(n.getName().equalsIgnoreCase(name)) 327 | return n; 328 | } 329 | return null; 330 | } 331 | 332 | public List getNpcs() { 333 | return npcs; 334 | } 335 | private void sendChatMessageToAll(String msg){ 336 | for(Player p : this.players.keySet()) 337 | p.sendMessage(ChatColor.translateAlternateColorCodes('&', msg)); 338 | } 339 | } 340 | -------------------------------------------------------------------------------- /src/de/sebpas/replay/Recorder.java: -------------------------------------------------------------------------------- 1 | package de.sebpas.replay; 2 | 3 | import org.bukkit.Bukkit; 4 | import org.bukkit.entity.Player; 5 | 6 | import de.sebpas.replay.event.RecordingStartEvent; 7 | import de.sebpas.replay.event.RecordingStoppedEvent; 8 | import de.sebpas.replay.recorder.listener.InteractListener; 9 | import de.sebpas.replay.recorder.listener.MoveListener; 10 | import de.sebpas.replay.recorder.listener.SpawnDespawnListener; 11 | import de.sebpas.replay.util.InventoryUtilities; 12 | 13 | public class Recorder{ 14 | private ReplaySystem plugin; 15 | private boolean isRecording = false; 16 | 17 | private Runnable runnable = new Runnable() { 18 | 19 | @Override 20 | public void run() { 21 | if(Bukkit.getOnlinePlayers().size() != 0) 22 | plugin.addTick(); 23 | } 24 | }; 25 | 26 | public Recorder(ReplaySystem plugin){ 27 | this.plugin = plugin; 28 | Bukkit.getPluginManager().registerEvents(new MoveListener(plugin), plugin); 29 | Bukkit.getPluginManager().registerEvents(new InteractListener(plugin), plugin); 30 | Bukkit.getPluginManager().registerEvents(new SpawnDespawnListener(plugin), plugin); 31 | Bukkit.getScheduler().runTaskTimerAsynchronously(plugin, runnable, 1L, 1L); 32 | } 33 | /** starts capturing */ 34 | public void recorde(){ 35 | Bukkit.getPluginManager().callEvent(new RecordingStartEvent()); 36 | this.isRecording = true; 37 | for(Player p : Bukkit.getOnlinePlayers()){ 38 | addString(plugin.getHandledTicks() + ";" + p.getUniqueId() + ";" + p.getName() + ";moved:" + p.getLocation().getX() + "," + p.getLocation().getY() + "," + p.getLocation().getZ()+ "," + p.getLocation().getYaw() + "," + p.getLocation().getPitch() + ";" + ";"); 39 | InventoryUtilities.saveArmor(p, plugin); 40 | this.addString(plugin.getHandledTicks() + ";" + p.getUniqueId() + ";" + p.getName() + ";itmhnd:" + p.getItemInHand().getType()); 41 | } 42 | } 43 | /** stops capturing */ 44 | public void stop(){ 45 | this.addString(plugin.getHandledTicks() + ""); 46 | Bukkit.getPluginManager().callEvent(new RecordingStoppedEvent()); 47 | this.isRecording = false; 48 | } 49 | 50 | public boolean isRecording(){ 51 | return this.isRecording; 52 | } 53 | /** adds a string to the file the replay will be saved in */ 54 | public void addString(String s){ 55 | if(isRecording()) 56 | this.plugin.getFileManager().appendString(s); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/de/sebpas/replay/ReplaySystem.java: -------------------------------------------------------------------------------- 1 | package de.sebpas.replay; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import org.bukkit.Bukkit; 7 | import org.bukkit.ChatColor; 8 | import org.bukkit.entity.HumanEntity; 9 | import org.bukkit.entity.Player; 10 | import org.bukkit.plugin.java.JavaPlugin; 11 | 12 | import de.sebpas.replay.command.CommandReplay; 13 | import de.sebpas.replay.event.ReplayStoppedEvent; 14 | import de.sebpas.replay.filesystem.FileManager; 15 | import de.sebpas.replay.util.PlayingPlayer; 16 | 17 | public class ReplaySystem extends JavaPlugin{ 18 | private int ranTicks = 0; 19 | private FileManager fileSystem; 20 | private Recorder recorder; 21 | 22 | private static ReplaySystem instance = null; 23 | 24 | /** list of all replayers */ 25 | private List replayers = new ArrayList(); 26 | 27 | /** plugin prefixes */ 28 | private static String prefix = "&8[&3Replay&8]: &r"; 29 | private static String error = "&8[&cReplay&8]: &c"; 30 | 31 | 32 | /** 33 | * Bukkit methods 34 | */ 35 | 36 | @Override 37 | public void onEnable() { 38 | System.out.println("[Replay]: Enabled!"); 39 | this.fileSystem = new FileManager(); 40 | this.recorder = new Recorder(this); 41 | 42 | this.getCommand("rplstart").setExecutor(new CommandReplay(this)); 43 | this.getCommand("rplstop").setExecutor(new CommandReplay(this)); 44 | this.getCommand("replay").setExecutor(new CommandReplay(this)); 45 | 46 | this.getServer().getPluginManager().registerEvents(new PlayingPlayer(), this); 47 | 48 | instance = this; 49 | } 50 | @Override 51 | public void onDisable() { 52 | if(recorder.isRecording()){ 53 | this.stop(); 54 | } 55 | for(RePlayer r : replayers) 56 | r.stopWithoutTask(); 57 | } 58 | 59 | /** returns a new instance of this main class */ 60 | public static ReplaySystem getInstance(){ 61 | return instance; 62 | } 63 | 64 | public void start(){ 65 | this.ranTicks = 0; 66 | this.fileSystem.reset(); 67 | this.recorder.recorde(); 68 | } 69 | 70 | public void stop(){ 71 | this.recorder.stop(); 72 | this.ranTicks = 0; 73 | this.fileSystem.save(); 74 | } 75 | 76 | /** returns the amount of recorded ticks */ 77 | public int getHandledTicks(){ 78 | return this.ranTicks; 79 | } 80 | 81 | /** sends a message to all players and the console */ 82 | public static void sendBroadcast(String msg){ 83 | Bukkit.broadcastMessage(ChatColor.translateAlternateColorCodes('&', prefix + msg)); 84 | } 85 | 86 | /** sends an error message to all players and the console */ 87 | public static void sendBroadcastError(String msg){ 88 | Bukkit.broadcastMessage(ChatColor.translateAlternateColorCodes('&', error + msg)); 89 | } 90 | public String getPrefix(){ 91 | return prefix; 92 | } 93 | public String getErrorPrefix(){ 94 | return error; 95 | } 96 | 97 | /** the tick counter */ 98 | public void addTick(){ 99 | ++ ranTicks; 100 | } 101 | 102 | /** returns the filemanager */ 103 | public FileManager getFileManager(){ 104 | return fileSystem; 105 | } 106 | 107 | /** returns the recording thread */ 108 | public Recorder getRecorder(){ 109 | return this.recorder; 110 | } 111 | /** returns true if the player is already watching a replay */ 112 | public boolean isAlreadyInReplay(Player p){ 113 | for(RePlayer r : replayers) 114 | if(r.getPlayers().containsKey(p)) 115 | return true; 116 | return false; 117 | } 118 | 119 | public void addPlayer(RePlayer p){ 120 | this.replayers.add(p); 121 | } 122 | 123 | public void onPlayerStopped(RePlayer p){ 124 | this.replayers.remove(p); 125 | synchronized (p) { 126 | this.getServer().getPluginManager().callEvent(new ReplayStoppedEvent(p)); 127 | } 128 | } 129 | public RePlayer getPlayersRePlayer(Player p){ 130 | for(RePlayer r : replayers){ 131 | if(r.getPlayers().containsKey(p)) 132 | return r; 133 | } 134 | return null; 135 | } 136 | public RePlayer getPlayersRePlayer(HumanEntity p){ 137 | for(RePlayer r : replayers){ 138 | for(Player t : r.getPlayers().keySet()) 139 | if(t.getName().equals(p.getName())) 140 | return r; 141 | } 142 | return null; 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /src/de/sebpas/replay/command/CommandReplay.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pscln/ReplayAPI/4ad4152dc4c4fdfb65084f0beaeb4452f63fcf61/src/de/sebpas/replay/command/CommandReplay.java -------------------------------------------------------------------------------- /src/de/sebpas/replay/event/RecordingStartEvent.java: -------------------------------------------------------------------------------- 1 | package de.sebpas.replay.event; 2 | 3 | import org.bukkit.event.Event; 4 | import org.bukkit.event.HandlerList; 5 | 6 | public class RecordingStartEvent extends Event{ 7 | private static final HandlerList handlers = new HandlerList(); 8 | public RecordingStartEvent(){} 9 | 10 | @Override 11 | public HandlerList getHandlers() { 12 | return handlers; 13 | } 14 | public static HandlerList getHandlerList(){ 15 | return handlers; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/de/sebpas/replay/event/RecordingStoppedEvent.java: -------------------------------------------------------------------------------- 1 | package de.sebpas.replay.event; 2 | 3 | import org.bukkit.event.Event; 4 | import org.bukkit.event.HandlerList; 5 | 6 | public class RecordingStoppedEvent extends Event{ 7 | private static final HandlerList handlers = new HandlerList(); 8 | public RecordingStoppedEvent(){} 9 | 10 | @Override 11 | public HandlerList getHandlers() { 12 | return handlers; 13 | } 14 | public static HandlerList getHandlerList(){ 15 | return handlers; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/de/sebpas/replay/event/ReplayStartEvent.java: -------------------------------------------------------------------------------- 1 | package de.sebpas.replay.event; 2 | 3 | import org.bukkit.event.Event; 4 | import org.bukkit.event.HandlerList; 5 | 6 | import de.sebpas.replay.RePlayer; 7 | 8 | public class ReplayStartEvent extends Event{ 9 | private static final HandlerList handlers = new HandlerList(); 10 | 11 | private RePlayer replayer; 12 | 13 | public ReplayStartEvent(RePlayer replayer){ 14 | this.replayer = replayer; 15 | } 16 | 17 | @Override 18 | public HandlerList getHandlers() { 19 | return handlers; 20 | } 21 | public static HandlerList getHandlerList(){ 22 | return handlers; 23 | } 24 | public RePlayer getRePlayer(){ 25 | return replayer; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/de/sebpas/replay/event/ReplayStoppedEvent.java: -------------------------------------------------------------------------------- 1 | package de.sebpas.replay.event; 2 | 3 | import org.bukkit.event.Event; 4 | import org.bukkit.event.HandlerList; 5 | 6 | import de.sebpas.replay.RePlayer; 7 | 8 | public class ReplayStoppedEvent extends Event{ 9 | private static final HandlerList handlers = new HandlerList(); 10 | 11 | private RePlayer replayer; 12 | 13 | public ReplayStoppedEvent(RePlayer replayer){ 14 | this.replayer = replayer; 15 | } 16 | 17 | @Override 18 | public HandlerList getHandlers() { 19 | return handlers; 20 | } 21 | public static HandlerList getHandlerList(){ 22 | return handlers; 23 | } 24 | public RePlayer getRePlayer(){ 25 | return replayer; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/de/sebpas/replay/filesystem/FileManager.java: -------------------------------------------------------------------------------- 1 | package de.sebpas.replay.filesystem; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.File; 5 | import java.io.FileNotFoundException; 6 | import java.io.FileReader; 7 | import java.io.IOException; 8 | import java.io.PrintWriter; 9 | import java.text.SimpleDateFormat; 10 | import java.util.ArrayList; 11 | import java.util.Date; 12 | import java.util.List; 13 | 14 | import de.sebpas.replay.ReplaySystem; 15 | 16 | public class FileManager { 17 | private String fileContent = ""; 18 | private File file; 19 | private PrintWriter writer; 20 | public FileManager(){ 21 | 22 | } 23 | 24 | public synchronized boolean save(){ 25 | Date date = new Date(); 26 | SimpleDateFormat format = new SimpleDateFormat("YY-MM-D-H-m-s"); 27 | file = new File("plugins/Replays/", format.format(date) + ".rpl"); 28 | if(!file.exists()) 29 | try { 30 | file.createNewFile(); 31 | } catch (IOException e1) { 32 | ReplaySystem.sendBroadcastError(e1.getMessage()); 33 | e1.printStackTrace(); 34 | } 35 | try { 36 | writer = new PrintWriter(file); 37 | } catch (FileNotFoundException e) { 38 | ReplaySystem.sendBroadcastError(e.getMessage()); 39 | e.printStackTrace(); 40 | return false; 41 | } 42 | writer.print(fileContent); 43 | System.out.println("[Replay] Saving..." + fileContent); 44 | writer.flush(); 45 | writer.close(); 46 | return true; 47 | } 48 | public synchronized List readFile(String name){ 49 | List rtn = new ArrayList(); 50 | try { 51 | BufferedReader reader = new BufferedReader(new FileReader(new File("plugins/Replays/", name))); 52 | String t; 53 | while((t = reader.readLine()) != null) 54 | rtn.add(t); 55 | reader.close(); 56 | return rtn; 57 | } catch (FileNotFoundException e) { 58 | ReplaySystem.sendBroadcastError(e.getMessage()); 59 | } catch (IOException e) { 60 | ReplaySystem.sendBroadcastError(e.getMessage()); 61 | e.printStackTrace(); 62 | } 63 | return null; 64 | } 65 | public void reset(){ 66 | this.fileContent = ""; 67 | } 68 | public void appendString(String s){ 69 | fileContent += s + "\n"; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/de/sebpas/replay/npc/NPC.java: -------------------------------------------------------------------------------- 1 | package de.sebpas.replay.npc; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | import java.util.UUID; 6 | 7 | import net.minecraft.server.v1_8_R2.DataWatcher; 8 | import net.minecraft.server.v1_8_R2.MathHelper; 9 | import net.minecraft.server.v1_8_R2.PacketPlayOutAnimation; 10 | import net.minecraft.server.v1_8_R2.PacketPlayOutEntity.PacketPlayOutEntityLook; 11 | import net.minecraft.server.v1_8_R2.PacketPlayOutEntity.PacketPlayOutRelEntityMoveLook; 12 | import net.minecraft.server.v1_8_R2.PacketPlayOutEntityDestroy; 13 | import net.minecraft.server.v1_8_R2.PacketPlayOutEntityEquipment; 14 | import net.minecraft.server.v1_8_R2.PacketPlayOutEntityHeadRotation; 15 | import net.minecraft.server.v1_8_R2.PacketPlayOutEntityMetadata; 16 | import net.minecraft.server.v1_8_R2.PacketPlayOutEntityTeleport; 17 | import net.minecraft.server.v1_8_R2.PacketPlayOutNamedEntitySpawn; 18 | import net.minecraft.server.v1_8_R2.PacketPlayOutPlayerInfo; 19 | import net.minecraft.server.v1_8_R2.PacketPlayOutPlayerInfo.EnumPlayerInfoAction; 20 | import net.minecraft.server.v1_8_R2.WorldSettings.EnumGamemode; 21 | 22 | import org.bukkit.Bukkit; 23 | import org.bukkit.Location; 24 | import org.bukkit.Sound; 25 | import org.bukkit.craftbukkit.v1_8_R2.inventory.CraftItemStack; 26 | import org.bukkit.craftbukkit.v1_8_R2.util.CraftChatMessage; 27 | import org.bukkit.entity.Player; 28 | import org.bukkit.inventory.ItemStack; 29 | 30 | import com.mojang.authlib.GameProfile; 31 | 32 | import de.sebpas.replay.util.Reflections; 33 | 34 | public class NPC extends Reflections{ 35 | private int ID; 36 | private Location location; 37 | private GameProfile profile; 38 | private String name; 39 | private Player player; 40 | 41 | /** movement */ 42 | private boolean isSneaking = false; 43 | private boolean isSprinting = false; 44 | private boolean isBlocking = false; 45 | 46 | /** items (armor, item in hand etc) */ 47 | private ItemStack helmet; 48 | private ItemStack chestplate; 49 | private ItemStack leggins; 50 | private ItemStack boots; 51 | private ItemStack handHeld; 52 | 53 | /** 54 | * @param name 55 | * @param loc 56 | */ 57 | public NPC(String uuid, String name, Location loc){ 58 | this.ID = (int) Math.ceil(Math.random() * 1000) + 2000; 59 | profile = new GameProfile(UUID.fromString(uuid), name); 60 | this.location = loc; 61 | this.name = name; 62 | } 63 | public NPC(String uuid, String name, Location loc, Player player){ 64 | this.ID = (int) Math.ceil(Math.random() * 1000) + 2000; 65 | profile = new GameProfile(UUID.fromString(uuid), name); 66 | this.location = loc; 67 | this.player = player; 68 | this.name = name; 69 | } 70 | /** spawns this npc */ 71 | public void spawn(){ 72 | this.spawn(location); 73 | } 74 | /** spawns this npc at location location */ 75 | public void spawn(Location location){ 76 | PacketPlayOutNamedEntitySpawn packet = new PacketPlayOutNamedEntitySpawn(); 77 | setValue(packet, "a", ID); 78 | setValue(packet, "b", profile.getId()); 79 | setValue(packet, "c", (int) MathHelper.floor(location.getX() * 32.0D)); 80 | setValue(packet, "d", (int) MathHelper.floor(location.getY() * 32.0D)); 81 | setValue(packet, "e", (int) MathHelper.floor(location.getZ() * 32.0D)); 82 | 83 | setValue(packet, "f", (byte) ((int) (location.getYaw() * 256.0F / 360.0F))); 84 | setValue(packet, "g", (byte) ((int) (location.getYaw() * 256.0F / 360.0F))); 85 | 86 | setValue(packet, "h", 0); 87 | 88 | DataWatcher w = new DataWatcher(null); 89 | w.a(10, (byte) 127); 90 | w.a(6, (float) 20); 91 | setValue(packet, "i", w); 92 | this.sendTablistPacket(); 93 | if(player != null) 94 | sendPacket(packet, player); 95 | else 96 | sendPacket(packet); 97 | } 98 | 99 | /** tp to location loc */ 100 | public void teleport(Location loc) { 101 | PacketPlayOutEntityTeleport tp = new PacketPlayOutEntityTeleport(); 102 | setValue(tp, "a", Integer.valueOf(this.ID)); 103 | setValue(tp, "b", Integer.valueOf((int)(loc.getX() * 32.0D))); 104 | setValue(tp, "c", Integer.valueOf((int)(loc.getY() * 32.0D))); 105 | setValue(tp, "d", Integer.valueOf((int)(loc.getZ() * 32.0D))); 106 | setValue(tp, "e", Byte.valueOf(toAngle(loc.getYaw()))); 107 | setValue(tp, "f", Byte.valueOf(toAngle(loc.getPitch()))); 108 | this.location = loc; 109 | if(player != null) 110 | sendPacket(tp, player); 111 | else 112 | sendPacket(tp); 113 | } 114 | 115 | /** let this npc sneak */ 116 | public void sneak(){ 117 | this.isSneaking = true; 118 | this.isBlocking = false; 119 | this.isSprinting = false; 120 | DataWatcher w = new DataWatcher(null); 121 | w.a(0, (byte) 2); 122 | w.a(1, (short) 0); 123 | w.a(8, (byte) 0); 124 | PacketPlayOutEntityMetadata packet = new PacketPlayOutEntityMetadata(this.ID, w, true); 125 | if(player != null) 126 | sendPacket(packet, player); 127 | else 128 | sendPacket(packet); 129 | } 130 | 131 | /** resets the sprinting, sneaking [...] values */ 132 | public void resetMovement(){ 133 | this.isBlocking = false; 134 | this.isSneaking = false; 135 | this.isSprinting = false; 136 | DataWatcher w = new DataWatcher(null); 137 | w.a(0, (byte) 0); 138 | w.a(1, (short) 0); 139 | w.a(8, (byte) 0); 140 | PacketPlayOutEntityMetadata packet = new PacketPlayOutEntityMetadata(this.ID, w, true); 141 | if(player != null) 142 | sendPacket(packet, player); 143 | else 144 | sendPacket(packet); 145 | } 146 | 147 | /** let this npc sprint */ 148 | public void sprint(){ 149 | this.isSprinting = true; 150 | this.isBlocking = false; 151 | this.isSneaking = false; 152 | DataWatcher w = new DataWatcher(null); 153 | w.a(0, (byte) 8); 154 | w.a(1, (short) 0); 155 | w.a(8, (byte) 0); 156 | PacketPlayOutEntityMetadata packet = new PacketPlayOutEntityMetadata(this.ID, w, true); 157 | if(player != null) 158 | sendPacket(packet, player); 159 | else 160 | sendPacket(packet); 161 | } 162 | 163 | /** blocks with sword, bow or consumables */ 164 | public void block() { 165 | this.isBlocking = true; 166 | this.isSneaking = false; 167 | this.isSprinting = false; 168 | DataWatcher w = new DataWatcher(null); 169 | w.a(0, (byte) 16); 170 | w.a(1, (short) 0); 171 | w.a(6, (byte) 0); 172 | PacketPlayOutEntityMetadata packet = new PacketPlayOutEntityMetadata(this.ID, w, true); 173 | if(player != null) 174 | sendPacket(packet, player); 175 | else 176 | sendPacket(packet); 177 | } 178 | 179 | /** updates the inventory (esp. armor and item in hand) */ 180 | public void updateItems(ItemStack inHand, ItemStack boots, ItemStack leggins, ItemStack chestplate, ItemStack helmet){ 181 | if(inHand != null) 182 | this.handHeld = inHand; 183 | if(boots != null) 184 | this.boots = boots; 185 | if(leggins != null) 186 | this.leggins = leggins; 187 | if(chestplate != null) 188 | this.chestplate = chestplate; 189 | if(helmet != null) 190 | this.helmet = helmet; 191 | 192 | PacketPlayOutEntityEquipment[] packets = { new PacketPlayOutEntityEquipment(this.ID, 1, CraftItemStack.asNMSCopy(this.helmet)), new PacketPlayOutEntityEquipment(this.ID, 2, CraftItemStack.asNMSCopy(this.chestplate)), new PacketPlayOutEntityEquipment(this.ID, 3, CraftItemStack.asNMSCopy(this.leggins)), new PacketPlayOutEntityEquipment(this.ID, 4, CraftItemStack.asNMSCopy(this.boots)), new PacketPlayOutEntityEquipment(this.ID, 0, CraftItemStack.asNMSCopy(this.handHeld)) }; 193 | 194 | for(int i = 0; i < packets.length; i++) 195 | if(player != null) 196 | sendPacket(packets[i], player); 197 | else 198 | sendPacket(packets[i]); 199 | } 200 | 201 | /** sends a damage animation to all players */ 202 | public void damageAnimation(){ 203 | PacketPlayOutAnimation packet = new PacketPlayOutAnimation(); 204 | setValue(packet, "a", (int) this.ID); 205 | setValue(packet, "b", (int) 1); 206 | if(player != null){ 207 | sendPacket(packet, player); 208 | player.playSound(this.location, Sound.HURT_FLESH, 1, 2); 209 | } 210 | else{ 211 | sendPacket(packet); 212 | for(Player p : Bukkit.getOnlinePlayers()) 213 | p.playSound(this.location, Sound.HURT_FLESH, 1, 2); 214 | } 215 | } 216 | 217 | /** moves the npc with walking animation */ 218 | public void move(double x, double y, double z, float yaw, float pitch){ 219 | if(player != null) 220 | sendPacket(new PacketPlayOutRelEntityMoveLook(this.ID, (byte) toFxdPnt(x), (byte) toFxdPnt(y), (byte) toFxdPnt(z), toAngle(yaw), toAngle(pitch), true), player); 221 | else 222 | sendPacket(new PacketPlayOutRelEntityMoveLook(this.ID, (byte) toFxdPnt(x), (byte) toFxdPnt(y), (byte) toFxdPnt(z), toAngle(yaw), toAngle(pitch), true)); 223 | this.location.add(toFxdPnt(x) / 32D, toFxdPnt(y) / 32D, toFxdPnt(z) / 32D); 224 | this.location.setYaw(yaw); 225 | this.location.setPitch(pitch); 226 | } 227 | 228 | private int toFxdPnt(double value){ 229 | return (int) Math.floor(value * 32.0D); 230 | } 231 | 232 | public Location getLocation(){ 233 | return this.location; 234 | } 235 | 236 | /** changes players head rotation */ 237 | public void look(float yaw, float pitch){ 238 | PacketPlayOutEntityHeadRotation headRot = new PacketPlayOutEntityHeadRotation(); 239 | setValue(headRot, "a", this.ID); 240 | setValue(headRot, "b", toAngle(yaw)); 241 | 242 | if(player != null){ 243 | sendPacket(headRot); 244 | sendPacket(new PacketPlayOutEntityLook(this.ID, toAngle(yaw), toAngle(pitch), true), player); 245 | } 246 | else{ 247 | sendPacket(headRot); 248 | sendPacket(new PacketPlayOutEntityLook(this.ID, toAngle(yaw), toAngle(pitch), true), player); 249 | } 250 | this.location.setYaw(yaw); 251 | this.location.setPitch(pitch); 252 | } 253 | 254 | private byte toAngle(float value){ 255 | return (byte) ((int) (value * 256.0F / 360.0F)); 256 | } 257 | 258 | /** adds the npc to the target's tablist */ 259 | private void sendTablistPacket(){ 260 | PacketPlayOutPlayerInfo packet = new PacketPlayOutPlayerInfo(); 261 | PacketPlayOutPlayerInfo.PlayerInfoData data = packet.new PlayerInfoData(profile, 1, EnumGamemode.NOT_SET, CraftChatMessage.fromString(profile.getName())[0]); 262 | @SuppressWarnings("unchecked") 263 | List players = (List) getValue(packet, "b"); 264 | players.add(data); 265 | setValue(packet, "a", PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER); 266 | setValue(packet, "b", players); 267 | if(player != null) 268 | sendPacket(packet, player); 269 | else 270 | sendPacket(packet); 271 | } 272 | /** removes the npc from the target's tablist */ 273 | private void removeFromTablist(){ 274 | boolean isOnline = false; 275 | for(Player p : Bukkit.getOnlinePlayers()){ 276 | if(this.getName().equals(p.getName())) 277 | isOnline = true; 278 | } 279 | if(isOnline) 280 | return; 281 | PacketPlayOutPlayerInfo packet = new PacketPlayOutPlayerInfo(EnumPlayerInfoAction.REMOVE_PLAYER); 282 | setValue(packet, "b", Arrays.asList(packet.new PlayerInfoData(this.profile, 0, null, null))); 283 | if(player != null) 284 | sendPacket(packet, player); 285 | else 286 | sendPacket(packet); 287 | } 288 | /** kills this npc */ 289 | public void deSpawn(){ 290 | PacketPlayOutEntityDestroy packet = new PacketPlayOutEntityDestroy(this.ID); 291 | if(player != null) 292 | sendPacket(packet, player); 293 | else 294 | sendPacket(packet); 295 | this.removeFromTablist(); 296 | } 297 | 298 | /** plays the item use animation (hit or place blocks...) */ 299 | public void swingArm(){ 300 | PacketPlayOutAnimation packet18 = new PacketPlayOutAnimation(); 301 | setValue(packet18, "a", Integer.valueOf(this.ID)); 302 | setValue(packet18, "b", Integer.valueOf(0)); 303 | if(player != null) 304 | sendPacket(packet18, player); 305 | else 306 | sendPacket(packet18); 307 | } 308 | 309 | public String getName(){ 310 | return this.name; 311 | } 312 | public boolean isSneaking() { 313 | return isSneaking; 314 | } 315 | public boolean isSprinting() { 316 | return isSprinting; 317 | } 318 | public boolean isBlocking() { 319 | return isBlocking; 320 | } 321 | public ItemStack getItemInHand(){ 322 | return this.handHeld; 323 | } 324 | public ItemStack[] getArmorContents(){ 325 | return new ItemStack[]{ helmet, chestplate, leggins, boots }; 326 | } 327 | } 328 | -------------------------------------------------------------------------------- /src/de/sebpas/replay/recorder/listener/InteractListener.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pscln/ReplayAPI/4ad4152dc4c4fdfb65084f0beaeb4452f63fcf61/src/de/sebpas/replay/recorder/listener/InteractListener.java -------------------------------------------------------------------------------- /src/de/sebpas/replay/recorder/listener/MoveListener.java: -------------------------------------------------------------------------------- 1 | package de.sebpas.replay.recorder.listener; 2 | 3 | import org.bukkit.event.EventHandler; 4 | import org.bukkit.event.Listener; 5 | import org.bukkit.event.player.PlayerMoveEvent; 6 | 7 | import de.sebpas.replay.ReplaySystem; 8 | 9 | public class MoveListener implements Listener{ 10 | private ReplaySystem plugin; 11 | public MoveListener(ReplaySystem plugin){ 12 | this.plugin = plugin; 13 | } 14 | @EventHandler 15 | public void onMove(PlayerMoveEvent e){ 16 | plugin.getRecorder().addString(plugin.getHandledTicks() + ";" + e.getPlayer().getUniqueId() + ";" + e.getPlayer().getName() + ";moved:" + e.getTo().getX() + "," + e.getTo().getY() + "," + e.getTo().getZ() 17 | + "," + e.getTo().getYaw() + "," + e.getTo().getPitch() + ";" + (e.getPlayer().isSneaking() ? "sneak" : (e.getPlayer().isSprinting() ? "sprint" : "")) 18 | + ";" + (e.getPlayer().isBlocking() ? "block" : "")); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/de/sebpas/replay/recorder/listener/SpawnDespawnListener.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pscln/ReplayAPI/4ad4152dc4c4fdfb65084f0beaeb4452f63fcf61/src/de/sebpas/replay/recorder/listener/SpawnDespawnListener.java -------------------------------------------------------------------------------- /src/de/sebpas/replay/util/InventoryUtilities.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pscln/ReplayAPI/4ad4152dc4c4fdfb65084f0beaeb4452f63fcf61/src/de/sebpas/replay/util/InventoryUtilities.java -------------------------------------------------------------------------------- /src/de/sebpas/replay/util/ItemUtilities.java: -------------------------------------------------------------------------------- 1 | package de.sebpas.replay.util; 2 | 3 | import org.bukkit.Material; 4 | import org.bukkit.inventory.ItemStack; 5 | import org.bukkit.inventory.meta.ItemMeta; 6 | import org.bukkit.inventory.meta.SkullMeta; 7 | 8 | public class ItemUtilities { 9 | private ItemUtilities() {} 10 | 11 | public static ItemStack createItem(Material mat, int amount, int shortid, String displayname){ 12 | short s = (short) shortid; 13 | ItemStack i = new ItemStack(mat, amount, s); 14 | ItemMeta meta = i.getItemMeta(); 15 | meta.setDisplayName(displayname); 16 | i.setItemMeta(meta); 17 | return i; 18 | } 19 | /** 20 | * You need a player head? 21 | * @param mat 22 | * @param amount 23 | * @param shortid 24 | * @param name 25 | * @param displayname 26 | * @return skull of a specified player 27 | */ 28 | public static ItemStack createItem(int amount, String name, String displayname){ 29 | ItemStack item = new ItemStack(Material.SKULL_ITEM, amount, (short) 3); 30 | SkullMeta meta = (SkullMeta) item.getItemMeta(); 31 | meta.setDisplayName(displayname); 32 | meta.setOwner(name); 33 | item.setItemMeta(meta); 34 | return item; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/de/sebpas/replay/util/PlayingPlayer.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pscln/ReplayAPI/4ad4152dc4c4fdfb65084f0beaeb4452f63fcf61/src/de/sebpas/replay/util/PlayingPlayer.java -------------------------------------------------------------------------------- /src/de/sebpas/replay/util/Reflections.java: -------------------------------------------------------------------------------- 1 | package de.sebpas.replay.util; 2 | 3 | import java.lang.reflect.Field; 4 | 5 | import net.minecraft.server.v1_8_R2.Packet; 6 | 7 | import org.bukkit.Bukkit; 8 | import org.bukkit.craftbukkit.v1_8_R2.entity.CraftPlayer; 9 | import org.bukkit.entity.Player; 10 | 11 | import de.sebpas.replay.ReplaySystem; 12 | 13 | public class Reflections { 14 | 15 | public void setValue(Object obj, String name, Object value){ 16 | try{ 17 | Field field = obj.getClass().getDeclaredField(name); 18 | field.setAccessible(true); 19 | field.set(obj, value); 20 | }catch(Exception e){ 21 | ReplaySystem.sendBroadcastError(e.getMessage()); 22 | e.printStackTrace(); 23 | } 24 | } 25 | public Object getValue(Object obj, String name){ 26 | try{ 27 | Field field = obj.getClass().getDeclaredField(name); 28 | field.setAccessible(true); 29 | return field.get(obj); 30 | }catch(Exception e){ 31 | ReplaySystem.sendBroadcastError(e.getMessage()); 32 | e.printStackTrace(); 33 | } 34 | return null; 35 | } 36 | public void sendPacket(Packet packet, Player player){ 37 | ((CraftPlayer) player).getHandle().playerConnection.sendPacket(packet); 38 | } 39 | public void sendPacket(Packet packet){ 40 | for(Player p : Bukkit.getOnlinePlayers()){ 41 | this.sendPacket(packet, p); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/de/sebpas/replay/util/ReplayStoppedEvent.java: -------------------------------------------------------------------------------- 1 | package de.sebpas.replay.util; 2 | 3 | import org.bukkit.event.Event; 4 | import org.bukkit.event.HandlerList; 5 | 6 | import de.sebpas.replay.RePlayer; 7 | 8 | public class ReplayStoppedEvent extends Event{ 9 | private static final HandlerList handlers = new HandlerList(); 10 | 11 | private RePlayer replayer; 12 | 13 | public ReplayStoppedEvent(RePlayer replayer){ 14 | this.replayer = replayer; 15 | } 16 | 17 | @Override 18 | public HandlerList getHandlers() { 19 | return handlers; 20 | } 21 | public static HandlerList getHandlerList(){ 22 | return handlers; 23 | } 24 | public RePlayer getRePlayer(){ 25 | return replayer; 26 | } 27 | 28 | } 29 | --------------------------------------------------------------------------------