A fuck ton of changes

This commit is contained in:
ImHacking 2022-06-22 18:21:38 -04:00
parent 8d4f78755d
commit 7f292dffca
69 changed files with 3787 additions and 125 deletions

View File

@ -78,7 +78,7 @@
<dependency> <dependency>
<groupId>com.google.code.gson</groupId> <groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId> <artifactId>gson</artifactId>
<version>2.2.4</version> <version>2.9.0</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.avaje</groupId> <groupId>org.avaje</groupId>
@ -102,7 +102,7 @@
<dependency> <dependency>
<groupId>org.projectlombok</groupId> <groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId> <artifactId>lombok</artifactId>
<version>1.18.20</version> <version>1.18.22</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<!-- Thread Affinity --> <!-- Thread Affinity -->
@ -136,8 +136,6 @@
<!-- versions after this appear to be broken --> <!-- versions after this appear to be broken -->
<version>3.1</version> <version>3.1</version>
<configuration> <configuration>
<!-- we use the Eclipse compiler as it doesn't need a JDK -->
<compilerId>eclipse</compilerId>
<!-- source and target are ignored if this isn't true --> <!-- source and target are ignored if this isn't true -->
<optimize>true</optimize> <optimize>true</optimize>
</configuration> </configuration>

View File

@ -0,0 +1,5 @@
package net.techcable.tacospigot.event.entity;
public interface ChunkSnapshot {
}

View File

@ -121,4 +121,8 @@ public interface Chunk {
* @return true if the chunk has unloaded successfully, otherwise false * @return true if the chunk has unloaded successfully, otherwise false
*/ */
boolean unload(); boolean unload();
net.techcable.tacospigot.event.entity.ChunkSnapshot takeSnapshot();
void restoreSnapshot(net.techcable.tacospigot.event.entity.ChunkSnapshot snapshot);
} }

View File

@ -494,6 +494,23 @@ public interface World extends PluginMessageRecipient, Metadatable {
*/ */
public boolean setSpawnLocation(int x, int y, int z); public boolean setSpawnLocation(int x, int y, int z);
/**
* Sets the spawn location of the world
*
* @param x X coordinate
* @param y Y coordinate
* @param z Z coordinate
* @return True if it was successfully set.
*/
public boolean setSpawnLocation(double x, double y, double z, float yaw, float pitch);
/**
* Sets the spawn location of the world
*
* @param location Location of the spawn
* @return True if it was successfully set.
*/
public boolean setSpawnLocation(Location location);
/** /**
* Gets the relative in-game time of this world. * Gets the relative in-game time of this world.
* <p> * <p>

View File

@ -29,6 +29,12 @@
</parent> </parent>
<dependencies> <dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
<scope>provided</scope>
</dependency>
<dependency> <dependency>
<groupId>io.netty</groupId> <groupId>io.netty</groupId>
<artifactId>netty-all</artifactId> <artifactId>netty-all</artifactId>
@ -105,18 +111,23 @@
<artifactId>mockito-core</artifactId> <artifactId>mockito-core</artifactId>
<version>1.10.19</version> <version>1.10.19</version>
</dependency> </dependency>
<dependency>
<groupId>it.unimi.dsi</groupId>
<artifactId>fastutil</artifactId>
<version>8.1.0</version>
</dependency>
<dependency>
<groupId>net.jafama</groupId>
<artifactId>jafama</artifactId>
<version>2.3.2</version>
<scope>compile</scope>
</dependency>
<dependency> <dependency>
<groupId>org.hamcrest</groupId> <groupId>org.hamcrest</groupId>
<artifactId>hamcrest-library</artifactId> <artifactId>hamcrest-library</artifactId>
<version>1.3</version> <version>1.3</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
<scope>provided</scope>
</dependency>
<dependency> <dependency>
<groupId>com.velocitypowered</groupId> <groupId>com.velocitypowered</groupId>
<artifactId>velocity-native</artifactId> <artifactId>velocity-native</artifactId>
@ -228,31 +239,29 @@
</executions> </executions>
</plugin> </plugin>
<!-- Gotta go after shade plugin --> <!-- Gotta go after shade plugin -->
<plugin> <!-- <plugin>
<groupId>net.md-5</groupId> <groupId>net.md-5</groupId>
<artifactId>specialsource-maven-plugin</artifactId> <artifactId>specialsource-maven-plugin</artifactId>
<version>1.2.1</version> <version>1.2.1</version>
<executions> <executions>
<execution> <execution>
<phase>package</phase> <phase>package</phase>
<goals> <goals>
<goal>remap</goal> <goal>remap</goal>
</goals> </goals>
<configuration> <configuration>
<srgIn>${project.basedir}/deprecation-mappings.csrg</srgIn> <srgIn>${project.basedir}/deprecation-mappings.csrg</srgIn>
<accessIn>${project.basedir}/deprecation-mappings.at</accessIn> <accessIn>${project.basedir}/deprecation-mappings.at</accessIn>
</configuration> </configuration>
</execution> </execution>
</executions> </executions>
</plugin> </plugin>-->
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId> <artifactId>maven-compiler-plugin</artifactId>
<!-- versions after this appear to be broken --> <!-- versions after this appear to be broken -->
<version>3.8.1</version> <version>3.8.1</version>
<configuration> <configuration>
<!-- we use the Eclipse compiler as it doesn't need a JDK -->
<compilerId>eclipse</compilerId>
<!-- source and target are ignored if this isn't true --> <!-- source and target are ignored if this isn't true -->
<optimize>true</optimize> <optimize>true</optimize>
</configuration> </configuration>

View File

@ -0,0 +1,49 @@
package com.elevatemc.spigot.chunk;
import net.minecraft.server.NibbleArray;
public class ChunkSectionSnapshot {
private final int nonEmptyBlockCount;
private final int tickingBlockCount;
private final char[] blockIds;
private final NibbleArray emittedLight;
private final NibbleArray skyLight;
public ChunkSectionSnapshot(
int nonEmptyBlockCount,
int tickingBlockCount,
char[] blockIds,
NibbleArray emittedLight,
NibbleArray skyLight
) {
this.nonEmptyBlockCount = nonEmptyBlockCount;
this.tickingBlockCount = tickingBlockCount;
this.blockIds = blockIds;
this.emittedLight = emittedLight;
this.skyLight = skyLight;
}
public final int getNonEmptyBlockCount() {
return nonEmptyBlockCount;
}
public final int getTickingBlockCount() {
return tickingBlockCount;
}
public final char[] getBlockIds() {
return blockIds;
}
public final NibbleArray getEmittedLight() {
return emittedLight;
}
public final NibbleArray getSkyLight() {
return skyLight;
}
}

View File

@ -0,0 +1,22 @@
package com.elevatemc.spigot.chunk;
import net.minecraft.server.NBTTagCompound;
import net.techcable.tacospigot.event.entity.ChunkSnapshot;
import java.util.ArrayList;
import java.util.List;
public class CraftChunkSnapshot implements ChunkSnapshot {
private final ChunkSectionSnapshot[] sections = new ChunkSectionSnapshot[16];
private final List<NBTTagCompound> tileEntities = new ArrayList<>();
public ChunkSectionSnapshot[] getSections() {
return this.sections;
}
public List<NBTTagCompound> getTileEntities() {
return this.tileEntities;
}
}

View File

@ -0,0 +1,119 @@
package com.elevatemc.spigot.chunk;
import net.minecraft.server.*;
public class WeakChunkCache implements IBlockAccess {
private final int lowerChunkX;
private final int lowerChunkZ;
private final Chunk[][] chunks;
private boolean ownArray = false;
public WeakChunkCache(Chunk[][] chunks, int lowerChunkX, int lowerChunkZ) {
this.chunks = chunks;
this.lowerChunkX = lowerChunkX;
this.lowerChunkZ = lowerChunkZ;
}
public WeakChunkCache(World world, int chunkX, int chunkZ, int chunkRadius) {
this(world, chunkX - chunkRadius, chunkZ - chunkRadius, chunkX + chunkRadius, chunkZ + chunkRadius);
}
public WeakChunkCache(World world, int lowerChunkX, int lowerChunkZ, int upperChunkX, int upperChunkZ) {
this.lowerChunkX = lowerChunkX;
this.lowerChunkZ = lowerChunkZ;
this.chunks = new Chunk[upperChunkX - this.lowerChunkX + 1][upperChunkZ - this.lowerChunkZ + 1];
this.ownArray = true;
for (int chunkX = this.lowerChunkX; chunkX <= upperChunkX; ++chunkX) {
for (int chunkZ = this.lowerChunkZ; chunkZ <= upperChunkZ; ++chunkZ) {
this.chunks[chunkX - this.lowerChunkX][chunkZ - this.lowerChunkZ] = world.getChunkIfLoaded(chunkX, chunkZ);
}
}
}
public WeakChunkCache(World world, int lowerBlockX, int lowerBlockY, int lowerBlockZ, int upperBlockX, int upperBlockY, int upperBlockZ, int blockRadius) {
this(world, (lowerBlockX - blockRadius) >> 4,
(lowerBlockZ - blockRadius) >> 4,
(upperBlockX + blockRadius) >> 4,
(upperBlockZ + blockRadius) >> 4);
}
public IBlockData getData(BlockPosition blockPosition) {
if (blockPosition.getY() >= 0 && blockPosition.getY() < 256) {
int indexX = (blockPosition.getX() >> 4) - this.lowerChunkX;
int indexZ = (blockPosition.getZ() >> 4) - this.lowerChunkZ;
if (indexX >= 0 && indexX < this.chunks.length && indexZ >= 0 && indexZ < this.chunks[indexX].length) {
Chunk chunk = this.chunks[indexX][indexZ];
if (chunk != null) {
return chunk.getBlockData(blockPosition);
}
}
}
return null;
}
public boolean isLoaded(int x, int y, int z) {
int indexX = (x >> 4) - this.lowerChunkX;
int indexZ = (z >> 4) - this.lowerChunkZ;
if (indexX >= 0 && indexX < this.chunks.length && indexZ >= 0 && indexZ < this.chunks[indexX].length) {
return this.chunks[indexX][indexZ] != null;
}
return false;
}
public void clear() {
if(this.ownArray) {
for(int i = 0; i < this.chunks.length; i++) {
for(int j = 0; j < this.chunks[i].length; j++) {
this.chunks[i][j] = null;
}
}
}
}
@Override
public TileEntity getTileEntity(BlockPosition blockPosition) {
int indexX = (blockPosition.getX() >> 4) - this.lowerChunkX;
int indexZ = (blockPosition.getZ() >> 4) - this.lowerChunkZ;
Chunk chunk = this.chunks[indexX][indexZ];
if (chunk != null) {
return chunk.i(blockPosition);
}
return null;
}
@Override
public IBlockData getType(BlockPosition blockPosition) {
Block block = Blocks.AIR;
if (blockPosition.getY() >= 0 && blockPosition.getY() < 256) {
int indexX = (blockPosition.getX() >> 4) - this.lowerChunkX;
int indexZ = (blockPosition.getZ() >> 4) - this.lowerChunkZ;
if (indexX >= 0 && indexX < this.chunks.length && indexZ >= 0 && indexZ < this.chunks[indexX].length) {
Chunk chunk = this.chunks[indexX][indexZ];
if (chunk != null) {
block = chunk.getType(blockPosition);
}
}
}
return block.getBlockData();
}
@Override
public boolean isEmpty(BlockPosition blockPosition) {
return getType(blockPosition) != Blocks.AIR.getBlockData();
}
@Override
public int getBlockPower(BlockPosition blockposition, EnumDirection enumdirection) {
IBlockData iblockdata = this.getType(blockposition);
return iblockdata.getBlock().b(this, blockposition, iblockdata, enumdirection);
}
}

View File

@ -16,6 +16,7 @@ import java.lang.management.ManagementFactory;
import java.math.RoundingMode; import java.math.RoundingMode;
import java.text.DecimalFormat; import java.text.DecimalFormat;
public class TicksPerSecondCommand extends Command { public class TicksPerSecondCommand extends Command {
public TicksPerSecondCommand() { public TicksPerSecondCommand() {

View File

@ -2,18 +2,26 @@ package com.elevatemc.spigot;
import com.elevatemc.spigot.command.KnockbackCommand; import com.elevatemc.spigot.command.KnockbackCommand;
import com.elevatemc.spigot.command.TicksPerSecondCommand; import com.elevatemc.spigot.command.TicksPerSecondCommand;
import com.elevatemc.spigot.handler.MovementHandler;
import com.elevatemc.spigot.handler.PacketHandler;
import com.elevatemc.spigot.util.YamlConfig; import com.elevatemc.spigot.util.YamlConfig;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import org.bukkit.Bukkit;
import org.bukkit.command.Command; import org.bukkit.command.Command;
import com.elevatemc.spigot.knockback.KnockbackHandler; import com.elevatemc.spigot.knockback.KnockbackHandler;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
public class eSpigot { public class eSpigot {
private final Set<PacketHandler> packetHandlers = new HashSet<>();
private final Set<MovementHandler> movementHandlers = new HashSet<>();
public static final ScheduledExecutorService EXECUTOR_SERVICE = public static final ScheduledExecutorService EXECUTOR_SERVICE =
Executors.newSingleThreadScheduledExecutor(); Executors.newSingleThreadScheduledExecutor();
@ -45,6 +53,25 @@ public class eSpigot {
EXECUTOR_SERVICE.scheduleAtFixedRate(() -> MinecraftServer.getServer().aq().processFastPackets(), 5L, 5L, TimeUnit.MILLISECONDS); EXECUTOR_SERVICE.scheduleAtFixedRate(() -> MinecraftServer.getServer().aq().processFastPackets(), 5L, 5L, TimeUnit.MILLISECONDS);
} }
public void addPacketHandler(PacketHandler handler) {
Bukkit.getLogger().info("Adding packet handler: " + handler.getClass().getPackage().getName() + "." + handler.getClass().getSimpleName());
this.packetHandlers.add(handler);
}
public void addMovementHandler(MovementHandler handler) {
Bukkit.getLogger().info("Adding movement handler: " + handler.getClass().getPackage().getName() + "." + handler.getClass().getSimpleName());
this.movementHandlers.add(handler);
}
public Set<MovementHandler> getMovementHandlers() {
return this.movementHandlers;
}
public Set<PacketHandler> getPacketHandlers() {
return this.packetHandlers;
}
public YamlConfig getConfig() { public YamlConfig getConfig() {
return config; return config;
} }

View File

@ -0,0 +1,56 @@
package com.elevatemc.spigot.event;
import org.bukkit.block.Block;
import org.bukkit.entity.Item;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import java.util.List;
public class BlockDropItemsEvent extends Event implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private Block block;
private Player player;
private List<Item> toDrop;
private boolean cancelled = false;
public BlockDropItemsEvent(Block block, Player player, List<Item> toDrop) {
this.block = block;
this.player = player;
this.toDrop = toDrop;
}
public Block getBlock() {
return this.block;
}
public Player getPlayer() {
return this.player;
}
public List<Item> getToDrop() {
return this.toDrop;
}
@Override
public HandlerList getHandlers() {
return handlers;
}
public static HandlerList getHandlerList() {
return handlers;
}
@Override
public boolean isCancelled() {
return this.cancelled;
}
@Override
public void setCancelled(boolean cancel) {
this.cancelled = cancel;
}
}

View File

@ -0,0 +1,38 @@
package com.elevatemc.spigot.event;
import org.bukkit.entity.Player;
import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerEvent;
public class PlayerHealthChangeEvent extends PlayerEvent {
private static final HandlerList handlers = new HandlerList();
private final double previousHealth;
private final double newHealth;
public PlayerHealthChangeEvent(Player who, double previousHealth, double newHealth) {
super(who);
this.previousHealth = previousHealth;
this.newHealth = newHealth;
}
@Override
public HandlerList getHandlers() {
return handlers;
}
public static HandlerList getHandlerList() {
return handlers;
}
public double getPreviousHealth() {
return previousHealth;
}
public double getNewHealth() {
return newHealth;
}
}

View File

@ -0,0 +1,22 @@
package com.elevatemc.spigot.event;
import org.bukkit.entity.Player;
import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerEvent;
public class PlayerPearlRefundEvent extends PlayerEvent {
private static final HandlerList handlers = new HandlerList();
public PlayerPearlRefundEvent(final Player player) {
super(player);
}
@Override
public HandlerList getHandlers() {
return handlers;
}
public static HandlerList getHandlerList() {
return handlers;
}
}

View File

@ -0,0 +1,13 @@
package com.elevatemc.spigot.handler;
import net.minecraft.server.PacketPlayInFlying;
import org.bukkit.Location;
import org.bukkit.entity.Player;
public interface MovementHandler {
void handleUpdateLocation(Player player, Location to, Location from, PacketPlayInFlying packet);
void handleUpdateRotation(Player player, Location to, Location from, PacketPlayInFlying packet);
}

View File

@ -0,0 +1,17 @@
package com.elevatemc.spigot.handler;
import net.minecraft.server.Packet;
import net.minecraft.server.PlayerConnection;
public interface PacketHandler {
default void handleReceivedPacket(PlayerConnection connection, Packet<?> packet) {}
default void handleSentPacket(PlayerConnection connection, Packet<?> packet) {}
default boolean handleSentPacketCancellable(PlayerConnection connection, Packet<?> packet) {
return true;
}
}

View File

@ -0,0 +1,200 @@
package com.elevatemc.spigot.pathsearch;
import com.elevatemc.spigot.pathsearch.cache.SearchCacheEntry;
import com.elevatemc.spigot.pathsearch.cache.SearchCacheEntryEntity;
import com.elevatemc.spigot.pathsearch.cache.SearchCacheEntryPosition;
import com.elevatemc.spigot.pathsearch.jobs.PathSearchJob;
import com.elevatemc.spigot.pathsearch.jobs.PathSearchJobNavigationEntity;
import com.elevatemc.spigot.pathsearch.jobs.PathSearchJobNavigationPosition;
import com.elevatemc.spigot.pathsearch.jobs.PathSearchQueuingManager;
import net.minecraft.server.*;
import org.bukkit.util.BlockVector;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.UUID;
public class AsyncNavigation extends Navigation {
private HashMap<UUID, SearchCacheEntry> searchCache;
private HashMap<PositionPathSearchType, SearchCacheEntryPosition> positionSearchCache;
private static double minimumDistanceForOffloadingSquared = 0.0D;
private int cleanUpDelay = 0;
private PathSearchQueuingManager queuingManager;
public AsyncNavigation(EntityInsentient entityInsentient, World world) {
super(entityInsentient, world);
this.searchCache = new HashMap<>();
this.positionSearchCache = new HashMap<>();
this.queuingManager = new PathSearchQueuingManager();
}
private BlockVector createBlockVectorForPosition(int x, int y, int z) {
return new BlockVector(x, y, z);
}
private void issueSearch(Entity target, float range, boolean j, boolean k, boolean l, boolean m) {
this.queuingManager.queueSearch(new PathSearchJobNavigationEntity(this.b, target, range, j, k, l, m));
}
private void issueSearch(PositionPathSearchType type, BlockPosition blockPosition, float range, boolean j, boolean k, boolean l, boolean m) {
this.queuingManager.queueSearch(new PathSearchJobNavigationPosition(type, this.b, blockPosition, range, j, k, l, m));
}
@Override
public void cancelSearch(PathSearchJob pathSearch) {
this.queuingManager.checkLastSearchResult(pathSearch);
pathSearch.cleanup();
}
@Override
public void setSearchResult(PathSearchJobNavigationEntity pathSearch) {
this.queuingManager.checkLastSearchResult(pathSearch);
SearchCacheEntry entry = pathSearch.getCacheEntryValue();
if (entry != null && entry.didSearchSucceed()) {
synchronized (this.searchCache) {
UUID key = pathSearch.getCacheEntryKey();
this.searchCache.put(key, entry);
}
}
}
@Override
public void setSearchResult(PathSearchJobNavigationPosition pathSearch) {
this.queuingManager.checkLastSearchResult(pathSearch);
SearchCacheEntryPosition entry = pathSearch.getCacheEntryValue();
if (entry != null && entry.didSearchSucceed()) {
synchronized (this.positionSearchCache) {
PositionPathSearchType key = pathSearch.getCacheEntryKey();
this.positionSearchCache.put(key, entry);
}
}
}
@Override
public PathEntity a(BlockPosition blockPosition) {
return this.a(PositionPathSearchType.ANYOTHER, blockPosition.getX(), blockPosition.getY(), blockPosition.getZ());
}
@Override
public boolean a(PositionPathSearchType type, double d0, double d1, double d2, double d3) {
PathEntity pathentity = this.a(type, (double) MathHelper.floor(d0), (double) ((int) d1), (double) MathHelper.floor(d2));
return this.a(pathentity, d3);
}
@Override
public PathEntity a(Entity entity) {
if (!this.offloadSearches() || this.b.h(entity) < minimumDistanceForOffloadingSquared) {
return super.a(entity);
}
if (!this.b()) {
return null;
}
SearchCacheEntry entry = null;
UUID id = entity.getUniqueID();
synchronized (this.searchCache) {
if (this.searchCache.containsKey(id)) {
entry = this.searchCache.get(id);
}
}
PathEntity resultPath = null;
if (entry != null) {
resultPath = entry.getAdjustedPathEntity();
if (!entry.isStillValid()) {
this.issueSearch(entity, this.i(), this.a.getB(), this.a.getC(), this.a.getD(), this.a.getE());
}
}
if (entry == null && !this.queuingManager.hasAsyncSearchIssued()) {
resultPath = super.a(entity);
if (resultPath != null) {
entry = new SearchCacheEntryEntity(this.b, entity, resultPath);
synchronized (this.searchCache) {
SearchCacheEntry oldEntry = this.searchCache.put(id, entry);
if (oldEntry != null) {
oldEntry.cleanup();
}
}
}
}
return resultPath;
}
@Override
public PathEntity a(PositionPathSearchType type, double d0, double d1, double d2) {
if (!this.offloadSearches() || this.b.e(d0, d1, d2) < minimumDistanceForOffloadingSquared) {
return super.a(d0, d1, d2);
}
if (!this.b()) {
return null;
}
int x = MathHelper.floor(d0);
int y = (int) d1;
int z = MathHelper.floor(d2);
SearchCacheEntryPosition entry = null;
synchronized (this.positionSearchCache) {
if (this.positionSearchCache.containsKey(type)) {
entry = this.positionSearchCache.get(type);
}
}
PathEntity resultPath = null;
if (entry != null) {
resultPath = entry.getAdjustedPathEntity();
if (!entry.isStillValid()) {
this.issueSearch(type, new BlockPosition(x, y, z), this.i(), this.a.getB(), this.a.getC(), this.a.getD(), this.a.getE());
}
}
if (entry == null && !this.queuingManager.hasAsyncSearchIssued()) {
resultPath = super.a(d0, d1, d2);
if (resultPath != null) {
entry = new SearchCacheEntryPosition(this.b, x, y, z, resultPath);
synchronized (this.positionSearchCache) {
SearchCacheEntry oldEntry = this.positionSearchCache.put(type, entry);
if (oldEntry != null) {
oldEntry.cleanup();
}
}
}
}
return resultPath;
}
@Override
public void cleanUpExpiredSearches() {
if (++this.cleanUpDelay > 100) {
this.cleanUpDelay = 0;
synchronized (this.searchCache) {
Iterator<Map.Entry<UUID, SearchCacheEntry>> iter = this.searchCache.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry<UUID, SearchCacheEntry> entry = iter.next();
if (entry.getValue().hasExpired()) {
iter.remove();
}
}
}
synchronized (this.positionSearchCache) {
Iterator<Map.Entry<PositionPathSearchType, SearchCacheEntryPosition>> iter2 = this.positionSearchCache.entrySet().iterator();
while (iter2.hasNext()) {
Map.Entry<PositionPathSearchType, SearchCacheEntryPosition> entry = iter2.next();
if (entry.getValue().hasExpired()) {
iter2.remove();
}
}
}
}
}
private boolean offloadSearches() {
return true;
}
}

View File

@ -0,0 +1,25 @@
package com.elevatemc.spigot.pathsearch;
import net.minecraft.server.*;
public class AsyncPathfinder extends Pathfinder {
private IBlockAccess iblockaccess;
public AsyncPathfinder(IBlockAccess iblockaccess) {
super(new AsyncPathfinderNormal(iblockaccess));
this.iblockaccess = iblockaccess;
}
@Override
public PathEntity a(IBlockAccess var1, Entity var2, Entity var3, float var4) {
return super.a(iblockaccess, var2, var3, var4);
}
@Override
public PathEntity a(IBlockAccess var1, Entity var2, BlockPosition var3, float var4) {
return super.a(iblockaccess, var2, var3, var4);
}
}

View File

@ -0,0 +1,20 @@
package com.elevatemc.spigot.pathsearch;
import net.minecraft.server.Entity;
import net.minecraft.server.IBlockAccess;
import net.minecraft.server.PathfinderNormal;
public class AsyncPathfinderNormal extends PathfinderNormal {
private IBlockAccess iblockaccess;
public AsyncPathfinderNormal(IBlockAccess iblockaccess) {
this.iblockaccess = iblockaccess;
}
@Override
public void a(IBlockAccess iblockaccess, Entity entity) {
super.a(this.iblockaccess, entity);
}
}

View File

@ -0,0 +1,101 @@
package com.elevatemc.spigot.pathsearch;
import com.elevatemc.spigot.pathsearch.jobs.PathSearchJob;
import com.elevatemc.spigot.threading.NamePriorityThreadFactory;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.*;
public class PathSearchThrottlerThread extends ThreadPoolExecutor {
private int queueLimit;
private LinkedHashMap<PathSearchJob, PathSearchJob> filter;
private HashSet<Integer> activeSearchHashes;
private static PathSearchThrottlerThread instance;
public PathSearchThrottlerThread(int poolSize) {
super(poolSize, poolSize, 1L, TimeUnit.MINUTES, new LinkedBlockingQueue<Runnable>(), new NamePriorityThreadFactory(Thread.MIN_PRIORITY, "eSpigot_PathFinder"));
instance = this;
adjustPoolSize(poolSize);
this.filter = new LinkedHashMap<>();
this.activeSearchHashes = new HashSet<>();
}
public boolean queuePathSearch(PathSearchJob newJob) {
boolean jobHasBeenQueued = false;
if(newJob != null) {
synchronized(this.filter) {
if(this.filter.containsKey(newJob) || this.filter.size() < 1000) {
jobHasBeenQueued = true;
PathSearchJob previousJob = this.filter.put(newJob, newJob);
if(previousJob != null) {
previousJob.cancel();
}
}
}
if(!jobHasBeenQueued) {
newJob.cancel();
}
}
PathSearchJob jobToExecute = null;
synchronized(this.filter) {
Iterator<Map.Entry<PathSearchJob, PathSearchJob>> iter = this.filter.entrySet().iterator();
while(iter.hasNext() && this.getQueue().size() < this.queueLimit) {
jobToExecute = iter.next().getValue();
if(!this.activeSearchHashes.contains(jobToExecute.getSearchHash())) {
iter.remove();
if(jobToExecute != null) {
this.activeSearchHashes.add(jobToExecute.getSearchHash());
this.submit(jobToExecute);
}
if(newJob != null) {
break;
}
}
}
}
return jobHasBeenQueued;
}
@Override
public void shutdown() {
this.getQueue().clear();
super.shutdown();
}
@Override
protected void afterExecute(Runnable runnable, Throwable throwable) {
super.afterExecute(runnable, throwable);
if(runnable instanceof FutureTask) {
FutureTask<PathSearchJob> task = (FutureTask<PathSearchJob>) runnable;
PathSearchJob job = null;
try {
job = task.get();
} catch (InterruptedException e) {
} catch (ExecutionException e) {
}
if(job != null) {
synchronized(this.filter) {
this.activeSearchHashes.remove(job.getSearchHash());
}
}
}
this.queuePathSearch(null);
}
public static void adjustPoolSize(int size) {
if(instance != null) {
if(size > instance.getMaximumPoolSize()) {
instance.setMaximumPoolSize(size);
instance.setCorePoolSize(size);
} else if(size < instance.getMaximumPoolSize()) {
instance.setCorePoolSize(size);
instance.setMaximumPoolSize(size);
}
instance.queueLimit = size * 8;
}
}
}

View File

@ -0,0 +1,18 @@
package com.elevatemc.spigot.pathsearch;
public enum PositionPathSearchType {
ANYOTHER,
AVOIDPLAYER,
FLEESUN,
JUMPONBLOCK,
MOVEINDOORS,
MOVETHROUGHVILLAGE,
MOVETOWARDSRESTRICTION,
MOVETOWARDSTARGET,
PANIC,
PLAY,
RANDOMSTROLL,
TAME;
}

View File

@ -0,0 +1,78 @@
package com.elevatemc.spigot.pathsearch.cache;
import net.minecraft.server.*;
import org.bukkit.util.BlockVector;
public class SearchCacheEntry {
protected long tick;
protected BlockVector positionStart;
protected BlockVector positionTarget;
protected EntityInsentient entity;
private PathEntity path;
public SearchCacheEntry(EntityInsentient entity, PathEntity path) {
this.entity = entity;
this.positionStart = this.getEntityPosition(this.entity);
this.path = path;
this.tick = this.getCurrentTick();
}
protected int getCurrentTick() {
return MinecraftServer.currentTick;
}
protected BlockVector getEntityPosition(Entity entity) {
return new BlockVector(entity.locX, entity.locY, entity.locZ);
}
protected BlockVector getTargetPosition(int x, int y, int z) {
return new BlockVector(x, y, z);
}
public boolean isStillValid() {
return false;
}
public PathEntity getPathEntity() {
return this.path;
}
public boolean hasExpired() {
return !this.entity.isAlive() || (this.getCurrentTick() - this.tick) > 200;
}
public boolean didSearchSucceed() {
return this.path != null;
}
public boolean shouldBeRefreshed() {
return (this.getCurrentTick() - this.tick) > 5;
}
public PathEntity getAdjustedPathEntity() {
if(this.path != null && (this.path.e() < this.path.d() - 1)) {
PathPoint pathpoint = this.path.a(this.path.e());
double currentDist = this.entity.e(pathpoint.a, pathpoint.b, pathpoint.c);
while(this.path.e() < this.path.d() - 1) {
pathpoint = this.path.a(this.path.e() + 1);
double nextDist = this.entity.e(pathpoint.a, pathpoint.b, pathpoint.c);
if(nextDist < currentDist) {
currentDist = nextDist;
this.path.a();
} else {
break;
}
}
}
return this.path;
}
public void cleanup() {
this.positionStart = null;
this.positionTarget = null;
this.entity = null;
this.path = null;
}
}

View File

@ -0,0 +1,38 @@
package com.elevatemc.spigot.pathsearch.cache;
import net.minecraft.server.Entity;
import net.minecraft.server.EntityInsentient;
import net.minecraft.server.PathEntity;
import org.bukkit.util.BlockVector;
public class SearchCacheEntryEntity extends SearchCacheEntry {
private Entity target;
public SearchCacheEntryEntity(EntityInsentient entity, Entity target, PathEntity path) {
super(entity, path);
this.target = target;
this.positionTarget = this.getEntityPosition(this.target);
}
@Override
public boolean isStillValid() {
if (this.getCurrentTick() - this.tick > 20) {
return false;
}
BlockVector bvStart = this.getEntityPosition(this.entity);
BlockVector bvTarget = this.getEntityPosition(this.target);
return bvStart.equals(this.positionStart) && bvTarget.equals(this.positionTarget);
}
@Override
public void cleanup() {
super.cleanup();
this.target = null;
}
}

View File

@ -0,0 +1,29 @@
package com.elevatemc.spigot.pathsearch.cache;
import net.minecraft.server.EntityInsentient;
import net.minecraft.server.PathEntity;
import org.bukkit.util.BlockVector;
public class SearchCacheEntryPosition extends SearchCacheEntry {
public SearchCacheEntryPosition(EntityInsentient entity, int x, int y, int z, PathEntity path) {
super(entity, path);
this.positionTarget = this.getTargetPosition(x, y, z);
}
@Override
public boolean isStillValid() {
if (this.getCurrentTick() - this.tick > 20) {
return false;
}
BlockVector bvStart = this.getEntityPosition(this.entity);
return bvStart.equals(this.positionStart);
}
public boolean targetEquals(BlockVector bv) {
return this.positionTarget.equals(bv);
}
}

View File

@ -0,0 +1,73 @@
package com.elevatemc.spigot.pathsearch.jobs;
import com.elevatemc.spigot.chunk.WeakChunkCache;
import com.elevatemc.spigot.pathsearch.cache.SearchCacheEntry;
import net.minecraft.server.EntityInsentient;
import net.minecraft.server.MathHelper;
import net.minecraft.server.PathEntity;
import java.util.concurrent.Callable;
public abstract class PathSearchJob implements Callable<PathSearchJob> {
protected EntityInsentient entity;
protected WeakChunkCache chunkCache;
protected boolean issued;
protected float range;
protected boolean b1, b2, b3, b4;
protected PathEntity pathEntity;
protected int hash;
public PathSearchJob(EntityInsentient entity, float range, boolean b1, boolean b2, boolean b3, boolean b4) {
this.entity = entity;
this.range = range;
this.b1 = b1;
this.b2 = b2;
this.b3 = b3;
this.b4 = b4;
this.issued = false;
this.hash = entity.getUniqueID().hashCode();
this.createChunkCache();
}
private void createChunkCache() {
int x = MathHelper.floor(this.entity.locX);
int y = MathHelper.floor(this.entity.locY);
int z = MathHelper.floor(this.entity.locZ);
int radius = (int) (this.range + 8.0F);
int xMinor = x - radius;
int yMinor = y - radius;
int zMinor = z - radius;
int xMajor = x + radius;
int yMajor = y + radius;
int zMajor = z + radius;
this.chunkCache = new WeakChunkCache(this.entity.world, xMinor, yMinor, zMinor, xMajor, yMajor, zMajor, 0);
}
public void cleanup() {
this.entity = null;
this.chunkCache = null;
this.pathEntity = null;
}
public int getSearchHash() {
return this.hash;
}
@Override
public int hashCode() {
return this.hash;
}
public abstract Object getCacheEntryKey();
public abstract SearchCacheEntry getCacheEntryValue();
public abstract void cancel();
protected boolean isEntityStillValid() {
return this.entity != null && this.entity.valid && this.entity.isAlive();
}
}

View File

@ -0,0 +1,61 @@
package com.elevatemc.spigot.pathsearch.jobs;
import com.elevatemc.spigot.pathsearch.AsyncPathfinder;
import com.elevatemc.spigot.pathsearch.cache.SearchCacheEntry;
import com.elevatemc.spigot.pathsearch.cache.SearchCacheEntryEntity;
import net.minecraft.server.Entity;
import net.minecraft.server.EntityCreature;
public class PathSearchJobEntity extends PathSearchJob {
private Entity target;
public PathSearchJobEntity(EntityCreature entity, Entity target, float range, boolean b1, boolean b2, boolean b3, boolean b4) {
super(entity, range, b1, b2, b3, b4);
this.target = target;
}
@Override
public PathSearchJob call() throws Exception {
if(!this.isEntityStillValid()) {
this.cancel();
} else if(!this.issued) {
this.issued = true;
this.pathEntity = (new AsyncPathfinder(this.chunkCache)).a(this.chunkCache, entity, this.target, this.range);
((EntityCreature) this.entity).setSearchResult(this, this.target, this.pathEntity);
this.cleanup();
}
return this;
}
@Override
public void cleanup() {
super.cleanup();
this.target = null;
}
@Override
public Object getCacheEntryKey() {
return this.entity.getUniqueID();
}
@Override
public SearchCacheEntry getCacheEntryValue() {
return new SearchCacheEntryEntity(this.entity, this.target, this.pathEntity);
}
@Override
public void cancel() {
((EntityCreature) this.entity).cancelSearch(this);
}
@Override
public boolean equals(Object o) {
if (!(o instanceof PathSearchJobEntity)) {
return false;
}
return this.getSearchHash() == ((PathSearchJobEntity)o).getSearchHash();
}
}

View File

@ -0,0 +1,62 @@
package com.elevatemc.spigot.pathsearch.jobs;
import com.elevatemc.spigot.pathsearch.AsyncPathfinder;
import com.elevatemc.spigot.pathsearch.cache.SearchCacheEntry;
import com.elevatemc.spigot.pathsearch.cache.SearchCacheEntryEntity;
import net.minecraft.server.Entity;
import net.minecraft.server.EntityInsentient;
import java.util.UUID;
public class PathSearchJobNavigationEntity extends PathSearchJob {
private Entity target;
public PathSearchJobNavigationEntity(EntityInsentient entity, Entity target, float range, boolean b1, boolean b2, boolean b3, boolean b4) {
super(entity, range, b1, b2, b3, b4);
this.target = target;
}
@Override
public PathSearchJob call() throws Exception {
if (!this.isEntityStillValid()) {
this.cancel();
} else if (!this.issued) {
this.issued = true;
this.pathEntity = (new AsyncPathfinder(this.chunkCache)).a(this.chunkCache, entity, this.target, this.range);
this.entity.getNavigation().setSearchResult(this);
this.cleanup();
}
return this;
}
@Override
public void cleanup() {
super.cleanup();
this.target = null;
}
public UUID getCacheEntryKey() {
return this.target.getUniqueID();
}
public SearchCacheEntry getCacheEntryValue() {
return new SearchCacheEntryEntity(this.entity, this.target, this.pathEntity);
}
@Override
public void cancel() {
this.entity.getNavigation().cancelSearch(this);
}
@Override
public boolean equals(Object o) {
if (o == null || !(o instanceof PathSearchJobNavigationEntity)) {
return false;
}
return this.getSearchHash() == ((PathSearchJobNavigationEntity) o).getSearchHash();
}
}

View File

@ -0,0 +1,65 @@
package com.elevatemc.spigot.pathsearch.jobs;
import com.elevatemc.spigot.pathsearch.AsyncPathfinder;
import com.elevatemc.spigot.pathsearch.PositionPathSearchType;
import com.elevatemc.spigot.pathsearch.cache.SearchCacheEntryPosition;
import net.minecraft.server.BlockPosition;
import net.minecraft.server.EntityInsentient;
public class PathSearchJobNavigationPosition extends PathSearchJob {
private BlockPosition blockPosition;
private PositionPathSearchType type;
public PathSearchJobNavigationPosition(PositionPathSearchType type, EntityInsentient entity, BlockPosition blockPosition, float range, boolean b1, boolean b2, boolean b3, boolean b4) {
super(entity, range, b1, b2, b3, b4);
this.type = type;
this.blockPosition = blockPosition;
}
@Override
public PathSearchJob call() throws Exception {
if(!this.isEntityStillValid()) {
this.cancel();
} else if(!this.issued) {
this.issued = true;
this.pathEntity = (new AsyncPathfinder(this.chunkCache)).a(this.chunkCache, entity, blockPosition, range);
this.entity.getNavigation().setSearchResult(this);
this.cleanup();
}
return this;
}
public PositionPathSearchType getCacheEntryKey() {
return this.type;
}
public SearchCacheEntryPosition getCacheEntryValue() {
return new SearchCacheEntryPosition(this.entity, blockPosition.getX(), blockPosition.getY(), blockPosition.getZ(), this.pathEntity);
}
@Override
public int hashCode() {
return this.type.hashCode() ^
(this.getSearchHash() << 4);
}
@Override
public boolean equals(Object o) {
if(o == null || !(o instanceof PathSearchJobNavigationPosition)) {
return false;
}
PathSearchJobNavigationPosition other = (PathSearchJobNavigationPosition) o;
return this.type.equals(
other.type) &&
this.getSearchHash() ==
other.getSearchHash();
}
@Override
public void cancel() {
this.entity.getNavigation().cancelSearch(this);
}
}

View File

@ -0,0 +1,66 @@
package com.elevatemc.spigot.pathsearch.jobs;
import com.elevatemc.spigot.pathsearch.AsyncPathfinder;
import com.elevatemc.spigot.pathsearch.PositionPathSearchType;
import com.elevatemc.spigot.pathsearch.cache.SearchCacheEntry;
import com.elevatemc.spigot.pathsearch.cache.SearchCacheEntryPosition;
import net.minecraft.server.BlockPosition;
import net.minecraft.server.EntityCreature;
public class PathSearchJobPosition extends PathSearchJob {
private BlockPosition blockPosition;
private PositionPathSearchType type;
public PathSearchJobPosition(EntityCreature entity, BlockPosition blockPosition, float range, boolean b1, boolean b2, boolean b3, boolean b4) {
super(entity, range, b1, b2, b3, b4);
this.type = PositionPathSearchType.ANYOTHER;
this.blockPosition = blockPosition;
}
@Override
public PathSearchJob call() throws Exception {
if(!this.isEntityStillValid()) {
this.cancel();
} else if(!this.issued) {
this.issued = true;
this.pathEntity = (new AsyncPathfinder(this.chunkCache)).a(this.chunkCache, entity, blockPosition, range);
((EntityCreature)this.entity).setSearchResult(this, this.pathEntity);
this.cleanup();
}
return this;
}
@Override
public Object getCacheEntryKey() {
return this.type;
}
@Override
public SearchCacheEntry getCacheEntryValue() {
return new SearchCacheEntryPosition(this.entity, this.blockPosition.getX(), this.blockPosition.getY(), this.blockPosition.getZ(), this.pathEntity);
}
@Override
public int hashCode() {
return this.type.hashCode() ^ (this.getSearchHash() << 4);
}
@Override
public boolean equals(Object o) {
if(o == null || !(o instanceof PathSearchJobPosition)) {
return false;
}
PathSearchJobPosition other = (PathSearchJobPosition) o;
return this.type.equals(
other.type) &&
this.getSearchHash() == other.getSearchHash();
}
@Override
public void cancel() {
((EntityCreature) this.entity).cancelSearch(this);
}
}

View File

@ -0,0 +1,30 @@
package com.elevatemc.spigot.pathsearch.jobs;
import com.elevatemc.spigot.threading.ThreadingManager;
public class PathSearchQueuingManager {
private PathSearchJob lastQueuedJob;
public PathSearchQueuingManager() {
this.lastQueuedJob = null;
}
public synchronized boolean hasAsyncSearchIssued() {
return this.lastQueuedJob != null;
}
public synchronized void queueSearch(PathSearchJob job) {
if (ThreadingManager.queuePathSearch(job)) {
this.lastQueuedJob = job;
}
}
public synchronized void checkLastSearchResult(PathSearchJob pathSearch) {
if (this.lastQueuedJob == pathSearch) {
this.lastQueuedJob = null;
}
}
}

View File

@ -0,0 +1,85 @@
package com.elevatemc.spigot.threading;
import net.jafama.FastMath;
import java.lang.ref.WeakReference;
import java.util.Iterator;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
public class NamePriorityThreadFactory implements ThreadFactory {
private final int priority;
private int idCounter = 0;
private String name = "gSpigotThread";
private boolean isDaemon = false;
private Queue<WeakReference<Thread>> createdThreadList;
public NamePriorityThreadFactory(int priority) {
this.priority = FastMath.min(FastMath.max(priority, Thread.MIN_PRIORITY), Thread.MAX_PRIORITY);
}
public NamePriorityThreadFactory(int priority, String name) {
this(priority);
this.name = name;
}
public NamePriorityThreadFactory(String name) {
this(Thread.NORM_PRIORITY);
this.name = name;
}
public NamePriorityThreadFactory setDaemon(boolean daemon) {
this.isDaemon = daemon;
return this;
}
public NamePriorityThreadFactory setLogThreads(boolean log) {
if (log) {
if (this.createdThreadList == null) {
this.createdThreadList = new ConcurrentLinkedQueue<WeakReference<Thread>>();
}
} else {
this.createdThreadList = null;
}
return this;
}
@Override
public Thread newThread(Runnable runnable) {
Thread thread = Executors.defaultThreadFactory().newThread(runnable);
thread.setPriority(this.priority);
thread.setName(this.name + "-" + idCounter);
thread.setDaemon(this.isDaemon);
if (this.createdThreadList != null) {
this.createdThreadList.add(new WeakReference<>(thread));
}
idCounter++;
return thread;
}
public int getActiveCount() {
if (this.createdThreadList != null) {
Iterator<WeakReference<Thread>> iter = this.createdThreadList.iterator();
int count = 0;
while (iter.hasNext()) {
WeakReference<Thread> ref = iter.next();
Thread t = ref.get();
if (t == null) {
iter.remove();
} else if (t.isAlive()) {
count++;
}
}
return count;
}
return -1;
}
public Queue<WeakReference<Thread>> getThreadList() {
return this.createdThreadList;
}
}

View File

@ -0,0 +1,281 @@
package com.elevatemc.spigot.threading;
import com.elevatemc.spigot.pathsearch.PathSearchThrottlerThread;
import com.elevatemc.spigot.pathsearch.jobs.PathSearchJob;
import net.minecraft.server.NBTCompressedStreamTools;
import net.minecraft.server.NBTTagCompound;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.ref.WeakReference;
import java.util.ArrayDeque;
import java.util.Iterator;
import java.util.Queue;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
public class ThreadingManager {
private static ThreadingManager instance;
private final Logger log = LogManager.getLogger();
private PathSearchThrottlerThread pathSearchThrottler;
private ScheduledExecutorService timerService = Executors.newScheduledThreadPool(1, new NamePriorityThreadFactory(Thread.NORM_PRIORITY + 2, "eSpigot_TimerService"));
private TickCounter tickCounter = new TickCounter();
private NamePriorityThreadFactory cachedThreadPoolFactory;
private ExecutorService cachedThreadPool;
private ScheduledFuture<Object> tickTimerTask;
private TickTimer tickTimerObject;
private static int timerDelay = 45;
private TaskQueueWorker nbtFiles;
private TaskQueueWorker headConversions;
public ThreadingManager() {
instance = this;
this.pathSearchThrottler = new PathSearchThrottlerThread(2);
this.timerService.scheduleAtFixedRate(this.tickCounter, 1, 1000, TimeUnit.MILLISECONDS);
this.tickTimerObject = new TickTimer();
this.cachedThreadPoolFactory = new NamePriorityThreadFactory(Thread.currentThread().getPriority() - 1, "eSpigot_Async-Executor").setLogThreads(true).setDaemon(true);
this.cachedThreadPool = Executors.newCachedThreadPool(this.cachedThreadPoolFactory);
this.nbtFiles = this.createTaskQueueWorker();
this.headConversions = this.createTaskQueueWorker();
}
public void shutdown() {
this.pathSearchThrottler.shutdown();
this.timerService.shutdown();
this.cachedThreadPool.shutdown();
while((this.nbtFiles.isActive()) && !this.cachedThreadPool.isTerminated()) {
try {
this.cachedThreadPool.awaitTermination(10, TimeUnit.SECONDS);
log.warn("gSpigot is still waiting for NBT files to be written to disk. " + this.nbtFiles.getTaskCount() + " to go...");
} catch(InterruptedException e) {}
}
if(!this.cachedThreadPool.isTerminated()) {
this.cachedThreadPool.shutdownNow();
try {
this.cachedThreadPool.awaitTermination(10L, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(this.cachedThreadPoolFactory.getActiveCount() > 0) {
log.warn("gSpigot is still waiting for " + this.cachedThreadPoolFactory.getActiveCount() + " async threads to finish.");
Queue<WeakReference<Thread>> queue = this.cachedThreadPoolFactory.getThreadList();
Iterator<WeakReference<Thread>> iter = null;
if(queue != null) {
System.out.println("== List of async threads that did not terminate on their own == ");
iter = queue.iterator();
}
while(iter != null && iter.hasNext()) {
WeakReference<Thread> ref = iter.next();
Thread t = ref.get();
if(t == null) {
iter.remove();
} else if (t.isAlive()) {
StackTraceElement[] e = t.getStackTrace();
System.out.println(t.getName() + " - " + t.getState().toString());
for(StackTraceElement et: e) {
System.out.println(et.toString());
}
System.out.println("========================== ");
}
}
}
}
}
public static void saveNBTFileStatic(NBTTagCompound compound, File file) {
instance.saveNBTFile(compound, file);
}
public void saveNBTFile(NBTTagCompound compound, File file) {
this.nbtFiles.queueTask(new NBTFileSaver(compound, file));
}
private class NBTFileSaver implements Runnable {
private NBTTagCompound compound;
private File file;
public NBTFileSaver(NBTTagCompound compound, File file) {
this.compound = compound;
this.file = file;
}
public void run() {
FileOutputStream fileoutputstream = null;
try {
fileoutputstream = new FileOutputStream(this.file);
NBTCompressedStreamTools.a(this.compound, fileoutputstream);
} catch (Exception e) {
e.printStackTrace();
} finally {
if(fileoutputstream != null) {
try {
fileoutputstream.close();
} catch (IOException e) {}
}
}
this.compound = null;
this.file = null;
}
}
public static boolean queuePathSearch(PathSearchJob pathSearchJob) {
return instance.pathSearchThrottler.queuePathSearch(pathSearchJob);
}
public class TickCounter implements Runnable {
private ArrayDeque<Integer> ticksPerSecond;
private AtomicInteger ticksCounter;
public TickCounter() {
this.ticksPerSecond = new ArrayDeque<>();
this.ticksCounter = new AtomicInteger(0);
}
@Override
public void run() {
int lastCount = this.ticksCounter.getAndSet(0);
synchronized(this.ticksPerSecond) {
this.ticksPerSecond.addLast(lastCount);
if(this.ticksPerSecond.size() > 30) {
this.ticksPerSecond.removeFirst();
}
}
}
public void increaseTickCounter() {
this.ticksCounter.incrementAndGet();
}
public Integer[] getTicksPerSecond() {
synchronized(this.ticksPerSecond) {
return this.ticksPerSecond.toArray(new Integer[0]);
}
}
}
public static TickCounter getTickCounter() {
return instance.tickCounter;
}
public static void startTickTimerTask() {
instance.tickTimerTask = instance.timerService.schedule(instance.tickTimerObject, timerDelay, TimeUnit.MILLISECONDS);
}
public static void cancelTimerTask(float tickTime) {
if(checkTickTime(tickTime) && instance.tickTimerTask.cancel(false)) {
instance.tickTimerObject.tickFinishedEarly();
}
}
private static boolean checkTickTime(float tickTime) {
if(tickTime > 45.0F) {
if(timerDelay > 40) {
timerDelay--;
}
} else {
if(timerDelay < 45) {
timerDelay++;
}
return tickTime < 40.0F;
}
return false;
}
private class TickTimer implements Callable<Object> {
public Object call() {
this.tickIsGoingToFinishLate();
return null;
}
public void tickIsGoingToFinishLate() {
}
public void tickFinishedEarly() {
}
}
public static void execute(Runnable runnable) {
instance.cachedThreadPool.execute(runnable);
}
public static Future<?> submit(Runnable runnable) {
return instance.cachedThreadPool.submit(runnable);
}
public static Future<?> submit(Callable<?> callable) {
return instance.cachedThreadPool.submit(callable);
}
public static void queueHeadConversion(Runnable runnable) {
instance.headConversions.queueTask(runnable);
}
public static TaskQueueWorker createTaskQueue() {
return instance.createTaskQueueWorker();
}
public TaskQueueWorker createTaskQueueWorker() {
return new TaskQueueWorker(this.cachedThreadPool);
}
public class TaskQueueWorker implements Runnable {
private ConcurrentLinkedDeque<Runnable> taskQueue = new ConcurrentLinkedDeque<>();
private ExecutorService service;
private volatile boolean isActive = false;
public TaskQueueWorker(ExecutorService service) {
this.service = service;
}
@Override
public void run() {
Runnable task = null;
while(this.isActive = ((task = this.taskQueue.pollFirst()) != null)) {
try {
task.run();
} catch (Exception e) {
log.error("Thread " + Thread.currentThread().getName() + " encountered an exception: " + e.getMessage(), e);
}
}
}
public void queueTask(Runnable runnable) {
this.taskQueue.addLast(runnable);
if(!this.isActive) {
this.isActive = true;
this.service.execute(this);
}
}
public boolean isActive() {
if(!this.isActive && !this.taskQueue.isEmpty()) {
this.isActive = true;
this.service.execute(this);
}
return this.isActive;
}
public int getTaskCount() {
int count = this.taskQueue.size();
if(this.isActive) {
count++;
}
return count;
}
}
public static Executor getCommonThreadPool() {
return instance.cachedThreadPool;
}
}

View File

@ -0,0 +1,211 @@
package com.elevatemc.spigot.util;
import net.jafama.FastMath;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.configuration.serialization.ConfigurationSerializable;
import org.bukkit.entity.Entity;
import java.util.*;
public class Cuboid implements Iterable<Block>, Cloneable, ConfigurationSerializable {
protected String worldName;
public int lowerX;
public int lowerY;
public int lowerZ;
public int upperX;
public int upperY;
public int upperZ;
public Cuboid(Location loc1, Location loc2) {
if (loc1.getWorld() != loc2.getWorld()) {
throw new IllegalArgumentException("Locations must be on the same world");
}
this.worldName = loc1.getWorld().getName();
this.lowerX = FastMath.min(loc1.getBlockX(), loc2.getBlockX());
this.lowerY = FastMath.min(loc1.getBlockY(), loc2.getBlockY());
this.lowerZ = FastMath.min(loc1.getBlockZ(), loc2.getBlockZ());
this.upperX = FastMath.max(loc1.getBlockX(), loc2.getBlockX());
this.upperY = FastMath.max(loc1.getBlockY(), loc2.getBlockY());
this.upperZ = FastMath.max(loc1.getBlockZ(), loc2.getBlockZ());
}
public Cuboid(Cuboid cuboid) {
this.worldName = cuboid.worldName;
this.lowerX = cuboid.lowerX;
this.lowerY = cuboid.lowerY;
this.lowerZ = cuboid.lowerZ;
this.upperX = cuboid.upperX;
this.upperY = cuboid.upperY;
this.upperZ = cuboid.upperZ;
}
public Cuboid(Map<String, Object> map) {
this.worldName = (String) map.get("worldName");
this.lowerX = (int) map.get("x1");
this.lowerY = (int) map.get("y1");
this.lowerZ = (int) map.get("z1");
this.upperX = (int) map.get("x2");
this.upperY = (int) map.get("y2");
this.upperZ = (int) map.get("z2");
}
public World getWorld() {
World world = Bukkit.getWorld(this.worldName);
if (world == null) {
throw new IllegalStateException("World '" + this.worldName + "' is not loaded");
}
return world;
}
public Location getLowerNE() {
return new Location(this.getWorld(), this.lowerX, this.lowerY, this.lowerZ);
}
public Location getUpperSW() {
return new Location(this.getWorld(), this.upperX, this.upperY, this.upperZ);
}
public Location getCenter() {
return new Location(
this.getWorld(),
this.lowerX + (((this.upperX + 1) - this.lowerX) / 2.0),
this.lowerY + (((this.upperY + 1) - this.lowerY) / 2.0),
this.lowerZ + (((this.upperZ + 1) - this.lowerZ) / 2.0)
);
}
public int getSizeX() {
return this.upperX - this.lowerX + 1;
}
public int getSizeY() {
return this.upperY - this.lowerY + 1;
}
public int getSizeZ() {
return this.upperZ - this.lowerZ + 1;
}
public int getVolume() {
return this.getSizeX() * this.getSizeY() * this.getSizeZ();
}
public List<Chunk> getChunks() {
List<Chunk> results = new ArrayList<>();
World world = this.getWorld();
final int x1 = this.lowerX & -0x10;
final int x2 = this.upperX & -0x10;
final int z1 = this.lowerZ & -0x10;
final int z2 = this.upperZ & -0x10;
int x3 = x1;
while (x3 <= x2) {
int z3 = z1;
while (z3 <= z2) {
results.add(world.getChunkAt(x3 >> 4, z3 << 4));
z3 += 16;
}
x3 += 16;
}
return results;
}
public List<Block> getBlocks() {
List<Block> copy = new ArrayList<>();
for (Block block : this) {
copy.add(block);
}
return copy;
}
public boolean contains(int x, int y, int z) {
return x >= lowerX && x <= upperX && y >= lowerY && y <= upperY && z >= lowerZ && z <= upperZ;
}
public boolean contains(Location location) {
return worldName.equals(location.getWorld().getName()) && contains(location.getBlockX(), location.getBlockY(), location.getBlockZ());
}
public boolean contains(Block block) {
return contains(block.getLocation());
}
public boolean contains(Entity entity) {
return contains(entity.getLocation());
}
@Override
public Iterator<Block> iterator() {
return new CuboidIterator(this.getWorld(), this.lowerX, this.lowerY, this.lowerZ, this.upperX, this.upperY, this.upperZ);
}
@Override
public Map<String, Object> serialize() {
Map<String, Object> map = new HashMap<>();
map.put("worldName", this.worldName);
map.put("x1", this.lowerX);
map.put("y1", this.lowerY);
map.put("z1", this.lowerZ);
map.put("x2", this.upperX);
map.put("y2", this.upperY);
map.put("z2", this.upperZ);
return map;
}
static class CuboidIterator implements Iterator<Block> {
private final World world;
private final int baseX;
private final int baseY;
private final int baseZ;
private int x = 0;
private int y = 0;
private int z = 0;
private final int sizeX;
private final int sizeY;
private final int sizeZ;
public CuboidIterator(World world, int x1, int y1, int z1, int x2, int y2, int z2) {
this.world = world;
this.baseX = FastMath.min(x1, x2);
this.baseY = FastMath.min(y1, y2);
this.baseZ = FastMath.min(z1, z2);
this.sizeX = FastMath.abs(x2 - x1) + 1;
this.sizeY = FastMath.abs(y2 - y1) + 1;
this.sizeZ = FastMath.abs(z2 - z1) + 1;
}
@Override
public boolean hasNext() {
return this.x < this.sizeX && this.y < this.sizeY && this.z < this.sizeZ;
}
@Override
public Block next() {
Block block = this.world.getBlockAt(this.baseX + this.x, this.baseY + this.y, this.baseZ + this.z);
if (++this.x >= this.sizeX) {
this.x = 0;
if (++this.y >= this.sizeY) {
this.y = 0;
++this.z;
}
}
return block;
}
}
}

View File

@ -1,11 +1,18 @@
package net.minecraft.server; package net.minecraft.server;
import com.elevatemc.spigot.event.BlockDropItemsEvent;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.entity.CraftItem;
import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;
public class Block { public class Block {
public List<org.bukkit.entity.Item> droppedItemsCatcher;
private static final MinecraftKey a = new MinecraftKey("air"); private static final MinecraftKey a = new MinecraftKey("air");
public static final RegistryBlocks<MinecraftKey, Block> REGISTRY = new RegistryBlocks(Block.a); public static final RegistryBlocks<MinecraftKey, Block> REGISTRY = new RegistryBlocks(Block.a);
public static final RegistryID<IBlockData> d = new RegistryID(); public static final RegistryID<IBlockData> d = new RegistryID();
@ -342,7 +349,30 @@ public class Block {
} }
public final void b(World world, BlockPosition blockposition, IBlockData iblockdata, int i) { public final void b(World world, BlockPosition blockposition, IBlockData iblockdata, int i) {
this.dropNaturally(world, blockposition, iblockdata, 1.0F, i); if (this == Blocks.AIR) return;
if (this.droppedItemsCatcher == null) {
this.droppedItemsCatcher = new ArrayList<>(1);
this.dropNaturally(world, blockposition, iblockdata, 1.0F, i);
BlockDropItemsEvent dropItemsEvent = new BlockDropItemsEvent(world.getWorld().getBlockAt(
blockposition.getX(),
blockposition.getY(),
blockposition.getZ()), null, this.droppedItemsCatcher);
Bukkit.getPluginManager().callEvent(dropItemsEvent);
if (!dropItemsEvent.isCancelled() && dropItemsEvent.getToDrop() != null) {
for (final org.bukkit.entity.Item item : dropItemsEvent.getToDrop()) {
world.addEntity(((CraftItem) item).getHandle());
}
}
this.droppedItemsCatcher = null;
} else {
this.dropNaturally(world, blockposition, iblockdata, 1.0F, i);
}
} }
public void dropNaturally(World world, BlockPosition blockposition, IBlockData iblockdata, float f, int i) { public void dropNaturally(World world, BlockPosition blockposition, IBlockData iblockdata, float f, int i) {

View File

@ -42,7 +42,7 @@ public class Chunk {
private boolean done; private boolean done;
private boolean lit; private boolean lit;
private boolean p; private boolean p;
private boolean q; public boolean q;
private boolean r; private boolean r;
private long lastSaved; private long lastSaved;
private int t; private int t;
@ -828,7 +828,7 @@ public class Chunk {
return j >= this.heightMap[k << 4 | i]; return j >= this.heightMap[k << 4 | i];
} }
private TileEntity i(BlockPosition blockposition) { public TileEntity i(BlockPosition blockposition) {
Block block = this.getType(blockposition); Block block = this.getType(blockposition);
return !block.isTileEntity() ? null : ((IContainer) block).a(this.world, this.c(blockposition)); return !block.isTileEntity() ? null : ((IContainer) block).a(this.world, this.c(blockposition));

View File

@ -1,5 +1,7 @@
package net.minecraft.server; package net.minecraft.server;
import com.elevatemc.spigot.chunk.ChunkSectionSnapshot;
public class ChunkSection { public class ChunkSection {
private int yPos; private int yPos;
@ -8,7 +10,7 @@ public class ChunkSection {
private char[] blockIds; private char[] blockIds;
private NibbleArray emittedLight; private NibbleArray emittedLight;
private NibbleArray skyLight; private NibbleArray skyLight;
boolean isDirty; // PaperSpigot public boolean isDirty;
public ChunkSection(int i, boolean flag) { public ChunkSection(int i, boolean flag) {
this.yPos = i; this.yPos = i;
@ -58,7 +60,6 @@ public class ChunkSection {
} }
this.blockIds[j << 8 | k << 4 | i] = (char) Block.d.b(iblockdata); this.blockIds[j << 8 | k << 4 | i] = (char) Block.d.b(iblockdata);
isDirty = true; // PaperSpigot
} }
public Block b(int i, int j, int k) { public Block b(int i, int j, int k) {
@ -85,7 +86,6 @@ public class ChunkSection {
public void a(int i, int j, int k, int l) { public void a(int i, int j, int k, int l) {
this.skyLight.a(i, j, k, l); this.skyLight.a(i, j, k, l);
isDirty = true; // PaperSpigot
} }
public int d(int i, int j, int k) { public int d(int i, int j, int k) {
@ -94,7 +94,6 @@ public class ChunkSection {
public void b(int i, int j, int k, int l) { public void b(int i, int j, int k, int l) {
this.emittedLight.a(i, j, k, l); this.emittedLight.a(i, j, k, l);
isDirty = true; // PaperSpigot
} }
public int e(int i, int j, int k) { public int e(int i, int j, int k) {
@ -145,4 +144,23 @@ public class ChunkSection {
public void b(NibbleArray nibblearray) { public void b(NibbleArray nibblearray) {
this.skyLight = nibblearray; this.skyLight = nibblearray;
} }
public ChunkSectionSnapshot createSnapshot() {
return new ChunkSectionSnapshot(
nonEmptyBlockCount,
tickingBlockCount,
blockIds.clone(),
new NibbleArray(),
new NibbleArray()
);
}
public void restoreSnapshot(ChunkSectionSnapshot snap) {
nonEmptyBlockCount = snap.getNonEmptyBlockCount();
tickingBlockCount = snap.getTickingBlockCount();
blockIds = snap.getBlockIds().clone();
isDirty = true;
}
} }

View File

@ -85,7 +85,7 @@ public abstract class Entity implements ICommandListener {
public float M; public float M;
public float N; public float N;
public float fallDistance; public float fallDistance;
private int h; public int h; //Last ground Y
public double P; public double P;
public double Q; public double Q;
public double R; public double R;

View File

@ -3,6 +3,10 @@ package net.minecraft.server;
import java.util.UUID; import java.util.UUID;
// CraftBukkit start // CraftBukkit start
import com.elevatemc.spigot.pathsearch.jobs.PathSearchJob;
import com.elevatemc.spigot.pathsearch.jobs.PathSearchJobEntity;
import com.elevatemc.spigot.pathsearch.jobs.PathSearchJobPosition;
import com.elevatemc.spigot.pathsearch.jobs.PathSearchQueuingManager;
import org.bukkit.event.entity.EntityUnleashEvent; import org.bukkit.event.entity.EntityUnleashEvent;
// CraftBukkit end // CraftBukkit end
@ -15,6 +19,41 @@ public abstract class EntityCreature extends EntityInsentient {
private PathfinderGoal c; private PathfinderGoal c;
private boolean bm; private boolean bm;
// ImHacking start
private PathSearchQueuingManager queuingManager = new PathSearchQueuingManager();
private boolean searchIssued = false;
private PathEntity returnedPathEntity;
public boolean isSearchingForAPath() {
return this.queuingManager.hasAsyncSearchIssued();
}
public void cancelSearch(PathSearchJob pathSearch) {
this.queuingManager.checkLastSearchResult(pathSearch);
pathSearch.cleanup();
}
private void issueSearch(BlockPosition blockPosition, float range) {
this.queuingManager.queueSearch(new PathSearchJobPosition(this, blockPosition, range, true, false, false, true));
}
private void issueSearch(Entity target, float range) {
this.queuingManager.queueSearch(new PathSearchJobEntity(this, target, range, true, false, false, true));
}
public void setSearchResult(PathSearchJobEntity pathSearchJobEntity, Entity target, PathEntity pathentity) {
this.queuingManager.checkLastSearchResult(pathSearchJobEntity);
if (this.goalTarget != null && this.goalTarget.equals(target)) {
this.returnedPathEntity = pathentity;
}
}
public void setSearchResult(PathSearchJobPosition pathSearchJobPosition, PathEntity pathentity) {
this.queuingManager.checkLastSearchResult(pathSearchJobPosition);
this.returnedPathEntity = pathentity;
}
// ImHacking end
public EntityCreature(World world) { public EntityCreature(World world) {
super(world); super(world);
this.a = BlockPosition.ZERO; this.a = BlockPosition.ZERO;
@ -31,7 +70,7 @@ public abstract class EntityCreature extends EntityInsentient {
} }
public boolean cf() { public boolean cf() {
return !this.navigation.m(); return !this.getNavigation().m();
} }
public boolean cg() { public boolean cg() {

View File

@ -1,15 +1,37 @@
package net.minecraft.server; package net.minecraft.server;
// CraftBukkit start // CraftBukkit start
import com.elevatemc.spigot.event.PlayerPearlRefundEvent;
import com.google.common.collect.Sets;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.BlockFace;
import org.bukkit.craftbukkit.entity.CraftPlayer;
import org.bukkit.craftbukkit.event.CraftEventFactory; import org.bukkit.craftbukkit.event.CraftEventFactory;
import org.bukkit.event.player.PlayerTeleportEvent; import org.bukkit.event.player.PlayerTeleportEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.material.Gate;
import org.bukkit.material.Openable;
import org.bukkit.util.BlockIterator;
import org.bukkit.util.Vector;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;
// CraftBukkit end // CraftBukkit end
public class EntityEnderPearl extends EntityProjectile { public class EntityEnderPearl extends EntityProjectile {
private EntityLiving c; private EntityLiving c;
private Location teleportLocation;
private static final Set<Block> PROHIBITED_PEARL_BLOCKS = Sets.newHashSet(Block.getById(85), Block.getById(107));
public static List<String> pearlAbleType = Arrays.asList("STEP", "STAIR");
public static List<org.bukkit.Material> forwardTypes = Collections.singletonList(org.bukkit.Material.ENDER_PORTAL_FRAME);
public EntityEnderPearl(World world) { public EntityEnderPearl(World world) {
super(world); super(world);
this.loadChunks = world.paperSpigotConfig.loadUnloadedEnderPearls; // PaperSpigot this.loadChunks = world.paperSpigotConfig.loadUnloadedEnderPearls; // PaperSpigot
@ -21,80 +43,177 @@ public class EntityEnderPearl extends EntityProjectile {
this.loadChunks = world.paperSpigotConfig.loadUnloadedEnderPearls; // PaperSpigot this.loadChunks = world.paperSpigotConfig.loadUnloadedEnderPearls; // PaperSpigot
} }
protected void a(MovingObjectPosition movingobjectposition) { @Override
EntityLiving entityliving = this.getShooter(); protected void a(final MovingObjectPosition objectPosition) {
final EntityLiving entityliving = this.getShooter();
BlockPosition position = objectPosition.a();
if(position == null) {
position = new BlockPosition(this);
}
Block block = this.world.getType(position).getBlock();
if (movingobjectposition.entity != null) { if (block == Blocks.TRIPWIRE) {
if (movingobjectposition.entity == this.c) { return;
return; } else if (block == Blocks.FENCE_GATE) {
BlockIterator bi = null;
try {
Vector l = new Vector(this.locX, this.locY, this.locZ);
Vector l2 = new Vector(this.locX + this.motX, this.locY + this.motY, this.locZ + this.motZ);
Vector dir = new Vector(l2.getX() - l.getX(), l2.getY() - l.getY(), l2.getZ() - l.getZ()).normalize();
bi = new BlockIterator(this.world.getWorld(), l, dir, 0, 1);
} catch (IllegalStateException ex) {
// ignore
} }
movingobjectposition.entity.damageEntity(DamageSource.projectile(this, entityliving), 0.0F); if (bi != null) {
boolean open = true;
boolean hasSolidBlock = false;
while (bi.hasNext()) {
org.bukkit.block.Block b = bi.next();
if (b.getType().isSolid() && b.getType().isOccluding()) {
hasSolidBlock = true;
}
if (b.getState().getData() instanceof Gate && !((Gate) b.getState().getData()).isOpen()) {
open = false;
break;
}
}
if (open && !hasSolidBlock) {
return;
}
}
}
if (objectPosition.entity != null) {
if (objectPosition.entity == this.c) {
return;
}
objectPosition.entity.damageEntity(DamageSource.projectile(this, entityliving), 0.0f);
} }
// PaperSpigot start - Remove entities in unloaded chunks if (this.inUnloadedChunk && this.world.paperSpigotConfig.removeUnloadedEnderPearls) {
if (this.inUnloadedChunk && world.paperSpigotConfig.removeUnloadedEnderPearls) {
this.die(); this.die();
} }
// PaperSpigot end
for (int i = 0; i < 32; ++i) { for (int i = 0; i < 32; ++i) {
this.world.addParticle(EnumParticle.PORTAL, this.locX, this.locY + this.random.nextDouble() * 2.0D, this.locZ, this.random.nextGaussian(), 0.0D, this.random.nextGaussian(), new int[0]); this.world.addParticle(EnumParticle.PORTAL, this.locX, this.locY + this.random.nextDouble() * 2.0, this.locZ, this.random.nextGaussian(),
0.0, this.random.nextGaussian());
} }
if (!this.world.isClientSide) { if (!this.world.isClientSide) {
if (entityliving instanceof EntityPlayer) { if (entityliving instanceof EntityPlayer) {
EntityPlayer entityplayer = (EntityPlayer) entityliving; final EntityPlayer entityplayer = (EntityPlayer)entityliving;
if (entityplayer.playerConnection.a().g() && entityplayer.world == this.world && !entityplayer.isSleeping()) { if (entityplayer.playerConnection.a().g() && entityplayer.world == this.world && !entityplayer.isSleeping()) {
// CraftBukkit start - Fire PlayerTeleportEvent if (teleportLocation != null) {
org.bukkit.craftbukkit.entity.CraftPlayer player = entityplayer.getBukkitEntity(); CraftPlayer player = entityplayer.getBukkitEntity();
org.bukkit.Location location = getBukkitEntity().getLocation(); Location previousLocation = player.getLocation();
location.setPitch(player.getLocation().getPitch());
location.setYaw(player.getLocation().getYaw());
PlayerTeleportEvent teleEvent = new PlayerTeleportEvent(player, player.getLocation(), location, PlayerTeleportEvent.TeleportCause.ENDER_PEARL); teleportLocation.setYaw(previousLocation.getYaw());
Bukkit.getPluginManager().callEvent(teleEvent); teleportLocation.setPitch(previousLocation.getPitch());
if (!teleEvent.isCancelled() && !entityplayer.playerConnection.isDisconnected()) { // Fix an issue with the pearl actually not teleporting you into the exact Y it will
if (this.random.nextFloat() < 0.05F && this.world.getGameRules().getBoolean("doMobSpawning")) { // randomly/based of the pitch the Y would change, the closer to the thrower/thrown from
EntityEndermite entityendermite = new EntityEndermite(this.world); // will cause it to be higher, unless directly down
teleportLocation.setY((int) teleportLocation.getY());
entityendermite.a(true); PlayerTeleportEvent teleEvent = new PlayerTeleportEvent(player, player.getLocation(),
entityendermite.setPositionRotation(entityliving.locX, entityliving.locY, entityliving.locZ, entityliving.yaw, entityliving.pitch); teleportLocation, PlayerTeleportEvent.TeleportCause.ENDER_PEARL);
this.world.addEntity(entityendermite);
Bukkit.getPluginManager().callEvent(teleEvent);
if (!teleEvent.isCancelled() && !entityplayer.playerConnection.isDisconnected()) {
if (entityliving.au()) {
this.getShooter().mount(null);
}
entityplayer.playerConnection.teleport(teleEvent.getTo());
entityliving.fallDistance = 0.0F;
((Entity)entityliving).h = -1;
CraftEventFactory.entityDamage = this;
entityliving.damageEntity(DamageSource.FALL, 5.0F);
CraftEventFactory.entityDamage = null;
} }
} else {
if (entityliving.au()) { //ImHacking Add Player Pearl Refund
entityliving.mount((Entity) null); Bukkit.getPluginManager().callEvent(new PlayerPearlRefundEvent(entityplayer.getBukkitEntity()));
} // ImHacking (Give back the pearl since the teleport location was not made correctly)
player.getInventory().addItem(new ItemStack(org.bukkit.Material.ENDER_PEARL));
entityplayer.playerConnection.teleport(teleEvent.getTo());
entityliving.fallDistance = 0.0F;
CraftEventFactory.entityDamage = this;
entityliving.damageEntity(DamageSource.FALL, 5.0F);
CraftEventFactory.entityDamage = null;
} }
// CraftBukkit end
} }
} else if (entityliving != null) { } else if (entityliving != null) {
entityliving.enderTeleportTo(this.locX, this.locY, this.locZ); entityliving.enderTeleportTo(this.locX, this.locY, this.locZ);
entityliving.fallDistance = 0.0F; entityliving.fallDistance = 0.0f;
((Entity)entityliving).h = -1;
} }
this.die(); this.die();
} }
} }
@Override
public void t_() { public void t_() {
EntityLiving entityliving = this.getShooter(); final EntityLiving shooter = this.getShooter();
if (entityliving != null && entityliving instanceof EntityHuman && !entityliving.isAlive()) { // ImHacking Start - Prevent Pearling into blocks
// (This is a simple check to make sure
// that people can't make an impossible pearl through block
if (shooter != null && !shooter.isAlive()) {
this.die(); this.die();
} else { } else {
super.t_(); AxisAlignedBB boundingBox = AxisAlignedBB.a(this.locX - 0.3D, this.locY - 0.05D, this.locZ - 0.3D, this.locX + 0.3D, this.locY + 0.5D, this.locZ + 0.3D);
}
if (!this.world.boundingBoxContainsMaterials(this.getBoundingBox().grow(0.25D,
0D, 0.25D), PROHIBITED_PEARL_BLOCKS) && this.world.getCubes(this, boundingBox).isEmpty()) {
this.teleportLocation = getBukkitEntity().getLocation();
}
org.bukkit.block.Block block = this.world.getWorld().getBlockAt(MathHelper.floor(this.locX), MathHelper.floor(this.locY), MathHelper.floor(this.locZ));
org.bukkit.Material typeHere = this.world.getWorld().getBlockAt(MathHelper.floor(this.locX),
MathHelper.floor(this.locY), MathHelper.floor(this.locZ)).getType();
if (pearlAbleType.stream().anyMatch(it -> typeHere.name().contains(it))) {
this.teleportLocation = getBukkitEntity().getLocation();
}
if (shooter != null && forwardTypes.stream().anyMatch(it ->
block.getRelative(getDirection((EntityPlayer) shooter)).getType() == it)) {
this.teleportLocation = getBukkitEntity().getLocation();
}
if (typeHere == org.bukkit.Material.FENCE_GATE) {
if (((Openable) block.getState().getData()).isOpen()) {
this.teleportLocation = getBukkitEntity().getLocation();
}
}
if (shooter != null) {
final org.bukkit.block.Block newTrap = block.getRelative(getDirection((EntityPlayer) shooter)).getRelative(BlockFace.DOWN);
if (newTrap.getType() == org.bukkit.Material.COBBLE_WALL || newTrap.getType() == Material.FENCE) {
this.teleportLocation = newTrap.getLocation();
}
}
}
super.t_();
// ImHacking End
}
public static BlockFace getDirection(EntityPlayer entityPlayer) {
float yaw = entityPlayer.getBukkitEntity().getLocation().getYaw();
if (yaw < 0) {
yaw += 360;
}
if (yaw >= 315 || yaw < 45) {
return BlockFace.SOUTH;
} else if (yaw < 135) {
return BlockFace.WEST;
} else if (yaw < 225) {
return BlockFace.NORTH;
} else if (yaw < 315) {
return BlockFace.EAST;
}
return BlockFace.NORTH;
} }
} }

View File

@ -749,7 +749,7 @@ public class EntityHorse extends EntityAnimal implements IInventoryListener {
EntityHorse entityhorse = this.a(this, 16.0D); EntityHorse entityhorse = this.a(this, 16.0D);
if (entityhorse != null && this.h((Entity) entityhorse) > 4.0D) { if (entityhorse != null && this.h((Entity) entityhorse) > 4.0D) {
this.navigation.a((Entity) entityhorse); this.getNavigation().a(entityhorse);
} }
} }
} }

View File

@ -1,11 +1,14 @@
package net.minecraft.server; package net.minecraft.server;
import com.elevatemc.spigot.event.PlayerHealthChangeEvent;
import com.google.common.base.Charsets; import com.google.common.base.Charsets;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.mojang.authlib.GameProfile; import com.mojang.authlib.GameProfile;
import com.elevatemc.spigot.eSpigot; import com.elevatemc.spigot.eSpigot;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.entity.CraftHumanEntity; import org.bukkit.craftbukkit.entity.CraftHumanEntity;
import org.bukkit.craftbukkit.entity.CraftItem; import org.bukkit.craftbukkit.entity.CraftItem;
import org.bukkit.craftbukkit.entity.CraftPlayer;
import org.bukkit.craftbukkit.inventory.CraftItemStack; import org.bukkit.craftbukkit.inventory.CraftItemStack;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.entity.EntityCombustByEntityEvent; import org.bukkit.event.entity.EntityCombustByEntityEvent;
@ -1756,8 +1759,13 @@ public abstract class EntityHuman extends EntityLiving {
if (f < 0.0F) { if (f < 0.0F) {
f = 0.0F; f = 0.0F;
} }
float previous = getAbsorptionHearts(); // ImHacking
this.getDataWatcher().watch(17, Float.valueOf(f)); this.getDataWatcher().watch(17, Float.valueOf(f));
// ImHacking Start - Player Health Change Event
if (previous != f) {
Bukkit.getPluginManager().callEvent(new PlayerHealthChangeEvent(((CraftPlayer) getBukkitEntity()), previous, getHealth()));
}
// ImHacking End
} }
public boolean a(ChestLock chestlock) { public boolean a(ChestLock chestlock) {

View File

@ -5,6 +5,7 @@ import java.util.List;
import java.util.UUID; import java.util.UUID;
// CraftBukkit start // CraftBukkit start
import com.elevatemc.spigot.pathsearch.AsyncNavigation;
import org.bukkit.craftbukkit.event.CraftEventFactory; import org.bukkit.craftbukkit.event.CraftEventFactory;
import org.bukkit.craftbukkit.entity.CraftLivingEntity; import org.bukkit.craftbukkit.entity.CraftLivingEntity;
import org.bukkit.event.entity.EntityTargetLivingEntityEvent; import org.bukkit.event.entity.EntityTargetLivingEntityEvent;
@ -21,10 +22,10 @@ public abstract class EntityInsentient extends EntityLiving {
protected ControllerMove moveController; protected ControllerMove moveController;
protected ControllerJump g; protected ControllerJump g;
private EntityAIBodyControl b; private EntityAIBodyControl b;
protected NavigationAbstract navigation; private Navigation navigation;
public PathfinderGoalSelector goalSelector; public PathfinderGoalSelector goalSelector;
public PathfinderGoalSelector targetSelector; public PathfinderGoalSelector targetSelector;
private EntityLiving goalTarget; public EntityLiving goalTarget;
private EntitySenses bk; private EntitySenses bk;
private ItemStack[] equipment = new ItemStack[5]; private ItemStack[] equipment = new ItemStack[5];
public float[] dropChances = new float[5]; public float[] dropChances = new float[5];
@ -43,7 +44,7 @@ public abstract class EntityInsentient extends EntityLiving {
this.moveController = new ControllerMove(this); this.moveController = new ControllerMove(this);
this.g = new ControllerJump(this); this.g = new ControllerJump(this);
this.b = new EntityAIBodyControl(this); this.b = new EntityAIBodyControl(this);
this.navigation = this.b(world); this.navigation = new AsyncNavigation(this, world); // ImHacking
this.bk = new EntitySenses(this); this.bk = new EntitySenses(this);
for (int i = 0; i < this.dropChances.length; ++i) { for (int i = 0; i < this.dropChances.length; ++i) {
@ -76,7 +77,7 @@ public abstract class EntityInsentient extends EntityLiving {
return this.g; return this.g;
} }
public NavigationAbstract getNavigation() { public Navigation getNavigation() {
return this.navigation; return this.navigation;
} }

View File

@ -67,6 +67,8 @@ public abstract class EntityLiving extends Entity {
protected boolean aP; protected boolean aP;
protected int ticksFarFromPlayer; protected int ticksFarFromPlayer;
protected float aR; protected float aR;
public int lastGroundY; //lastGroundY
protected float aS; protected float aS;
protected float aT; protected float aT;
protected float aU; protected float aU;

View File

@ -1,5 +1,7 @@
package net.minecraft.server; package net.minecraft.server;
import org.bukkit.craftbukkit.entity.CraftPlayer;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
@ -13,6 +15,10 @@ public abstract class EntityProjectile extends Entity implements IProjectile {
public int shake; public int shake;
public EntityLiving shooter; public EntityLiving shooter;
public String shooterName; public String shooterName;
//ImHacking - Start
public CraftPlayer player;
//ImHacking - End
private int i; private int i;
private int ar; private int ar;

View File

@ -27,7 +27,7 @@ public class EntityRabbit extends EntityAnimal {
// CraftBukkit start - code from constructor // CraftBukkit start - code from constructor
public void initializePathFinderGoals(){ public void initializePathFinderGoals(){
this.navigation.a(2.5F); this.getNavigation().a(2.5F);
this.goalSelector.a(1, new PathfinderGoalFloat(this)); this.goalSelector.a(1, new PathfinderGoalFloat(this));
this.goalSelector.a(1, new EntityRabbit.PathfinderGoalRabbitPanic(this, 1.33D)); this.goalSelector.a(1, new EntityRabbit.PathfinderGoalRabbitPanic(this, 1.33D));
this.goalSelector.a(2, new PathfinderGoalTempt(this, 1.0D, Items.CARROT, false)); this.goalSelector.a(2, new PathfinderGoalTempt(this, 1.0D, Items.CARROT, false));
@ -123,7 +123,7 @@ public class EntityRabbit extends EntityAnimal {
if (!entityrabbit_controllerjumprabbit.c()) { if (!entityrabbit_controllerjumprabbit.c()) {
if (this.moveController.a() && this.bs == 0) { if (this.moveController.a() && this.bs == 0) {
PathEntity pathentity = this.navigation.j(); PathEntity pathentity = this.getNavigation().j();
Vec3D vec3d = new Vec3D(this.moveController.d(), this.moveController.e(), this.moveController.f()); Vec3D vec3d = new Vec3D(this.moveController.d(), this.moveController.e(), this.moveController.f());
if (pathentity != null && pathentity.e() < pathentity.d()) { if (pathentity != null && pathentity.e() < pathentity.d()) {

View File

@ -272,8 +272,8 @@ public class EntityWolf extends EntityTameableAnimal {
if (this.e((EntityLiving) entityhuman) && !this.world.isClientSide && !this.d(itemstack)) { if (this.e((EntityLiving) entityhuman) && !this.world.isClientSide && !this.d(itemstack)) {
this.bm.setSitting(!this.isSitting()); this.bm.setSitting(!this.isSitting());
this.aY = false; this.aY = false;
this.navigation.n(); this.getNavigation().n();
this.setGoalTarget((EntityLiving) null, TargetReason.FORGOT_TARGET, true); // CraftBukkit - reason this.setGoalTarget(null, TargetReason.FORGOT_TARGET, true); // CraftBukkit - reason
} }
} else if (itemstack != null && itemstack.getItem() == Items.BONE && !this.isAngry()) { } else if (itemstack != null && itemstack.getItem() == Items.BONE && !this.isAngry()) {
if (!entityhuman.abilities.canInstantlyBuild) { if (!entityhuman.abilities.canInstantlyBuild) {
@ -288,8 +288,8 @@ public class EntityWolf extends EntityTameableAnimal {
// CraftBukkit - added event call and isCancelled check. // CraftBukkit - added event call and isCancelled check.
if (this.random.nextInt(3) == 0 && !CraftEventFactory.callEntityTameEvent(this, entityhuman).isCancelled()) { if (this.random.nextInt(3) == 0 && !CraftEventFactory.callEntityTameEvent(this, entityhuman).isCancelled()) {
this.setTamed(true); this.setTamed(true);
this.navigation.n(); this.getNavigation().n();
this.setGoalTarget((EntityLiving) null, TargetReason.FORGOT_TARGET, true); this.setGoalTarget(null, TargetReason.FORGOT_TARGET, true);
this.bm.setSitting(true); this.bm.setSitting(true);
this.setHealth(this.getMaxHealth()); // CraftBukkit - 20.0 -> getMaxHealth() this.setHealth(this.getMaxHealth()); // CraftBukkit - 20.0 -> getMaxHealth()
this.setOwnerUUID(entityhuman.getUniqueID().toString()); this.setOwnerUUID(entityhuman.getUniqueID().toString());

View File

@ -0,0 +1,239 @@
package net.minecraft.server;
import com.elevatemc.spigot.pathsearch.PositionPathSearchType;
import com.elevatemc.spigot.pathsearch.jobs.PathSearchJob;
import com.elevatemc.spigot.pathsearch.jobs.PathSearchJobNavigationEntity;
import com.elevatemc.spigot.pathsearch.jobs.PathSearchJobNavigationPosition;
import net.jafama.FastMath;
import java.util.Iterator;
public class Navigation extends NavigationAbstract {
protected PathfinderNormal a;
private boolean f;
public Navigation(EntityInsentient var1, World var2) {
super(var1, var2);
}
// ImHacking start
public void setSearchResult(PathSearchJobNavigationEntity pathSearch) {
}
public void setSearchResult(PathSearchJobNavigationPosition pathSearch) {
}
public PathEntity a(PositionPathSearchType type, double d0, double d1, double d2) {
return this.a(d0, d1, d2);
}
public boolean a(PositionPathSearchType type, double d0, double d1, double d2, double d3) {
return this.a(d0, d1, d2, d3);
}
public void cleanUpExpiredSearches() {
}
public void cancelSearch(PathSearchJob pathSearch) {
}
// ImHacking end
protected Pathfinder a() {
this.a = new PathfinderNormal();
this.a.a(true);
return new Pathfinder(this.a);
}
protected boolean b() {
return this.b.onGround || this.h() && this.o() || this.b.au() && this.b instanceof EntityZombie && this.b.vehicle instanceof EntityChicken;
}
protected Vec3D c() {
return new Vec3D(this.b.locX, (double) this.p(), this.b.locZ);
}
private int p() {
if (this.b.V() && this.h()) {
int var1 = (int) this.b.getBoundingBox().b;
Block var2 = this.c.getType(new BlockPosition(MathHelper.floor(this.b.locX), var1, MathHelper.floor(this.b.locZ))).getBlock();
int var3 = 0;
do {
if (var2 != Blocks.FLOWING_WATER && var2 != Blocks.WATER) {
return var1;
}
++var1;
var2 = this.c.getType(new BlockPosition(MathHelper.floor(this.b.locX), var1, MathHelper.floor(this.b.locZ))).getBlock();
++var3;
} while (var3 <= 16);
return (int) this.b.getBoundingBox().b;
} else {
return (int) (this.b.getBoundingBox().b + 0.5D);
}
}
protected void d() {
super.d();
if (this.f) {
if (this.c.i(new BlockPosition(MathHelper.floor(this.b.locX), (int) (this.b.getBoundingBox().b + 0.5D), MathHelper.floor(this.b.locZ)))) {
return;
}
for (int var1 = 0; var1 < this.d.d(); ++var1) {
PathPoint var2 = this.d.a(var1);
if (this.c.i(new BlockPosition(var2.a, var2.b, var2.c))) {
this.d.b(var1 - 1);
return;
}
}
}
}
protected boolean a(Vec3D var1, Vec3D var2, int var3, int var4, int var5) {
int var6 = MathHelper.floor(var1.a);
int var7 = MathHelper.floor(var1.c);
double var8 = var2.a - var1.a;
double var10 = var2.c - var1.c;
double var12 = var8 * var8 + var10 * var10;
if (var12 < 1.0E-8D) {
return false;
} else {
double var14 = 1.0D / FastMath.sqrt(var12);
var8 *= var14;
var10 *= var14;
var3 += 2;
var5 += 2;
if (!this.a(var6, (int) var1.b, var7, var3, var4, var5, var1, var8, var10)) {
return false;
} else {
var3 -= 2;
var5 -= 2;
double var16 = 1.0D / FastMath.abs(var8);
double var18 = 1.0D / FastMath.abs(var10);
double var20 = (double) (var6 * 1) - var1.a;
double var22 = (double) (var7 * 1) - var1.c;
if (var8 >= 0.0D) {
++var20;
}
if (var10 >= 0.0D) {
++var22;
}
var20 /= var8;
var22 /= var10;
int var24 = var8 < 0.0D ? -1 : 1;
int var25 = var10 < 0.0D ? -1 : 1;
int var26 = MathHelper.floor(var2.a);
int var27 = MathHelper.floor(var2.c);
int var28 = var26 - var6;
int var29 = var27 - var7;
do {
if (var28 * var24 <= 0 && var29 * var25 <= 0) {
return true;
}
if (var20 < var22) {
var20 += var16;
var6 += var24;
var28 = var26 - var6;
} else {
var22 += var18;
var7 += var25;
var29 = var27 - var7;
}
} while (this.a(var6, (int) var1.b, var7, var3, var4, var5, var1, var8, var10));
return false;
}
}
}
private boolean a(int var1, int var2, int var3, int var4, int var5, int var6, Vec3D var7, double var8, double var10) {
int var12 = var1 - var4 / 2;
int var13 = var3 - var6 / 2;
if (!this.b(var12, var2, var13, var4, var5, var6, var7, var8, var10)) {
return false;
} else {
for (int var14 = var12; var14 < var12 + var4; ++var14) {
for (int var15 = var13; var15 < var13 + var6; ++var15) {
double var16 = (double) var14 + 0.5D - var7.a;
double var18 = (double) var15 + 0.5D - var7.c;
if (!(var16 * var8 + var18 * var10 < 0.0D)) {
Block var20 = this.c.getType(new BlockPosition(var14, var2 - 1, var15)).getBlock();
Material var21 = var20.getMaterial();
if (var21 == Material.AIR) {
return false;
}
if (var21 == Material.WATER && !this.b.V()) {
return false;
}
if (var21 == Material.LAVA) {
return false;
}
}
}
}
return true;
}
}
private boolean b(int var1, int var2, int var3, int var4, int var5, int var6, Vec3D var7, double var8, double var10) {
Iterator var12 = BlockPosition.a(new BlockPosition(var1, var2, var3), new BlockPosition(var1 + var4 - 1, var2 + var5 - 1, var3 + var6 - 1)).iterator();
while (var12.hasNext()) {
BlockPosition var13 = (BlockPosition) var12.next();
double var14 = (double) var13.getX() + 0.5D - var7.a;
double var16 = (double) var13.getZ() + 0.5D - var7.c;
if (!(var14 * var8 + var16 * var10 < 0.0D)) {
Block var18 = this.c.getType(var13).getBlock();
if (!var18.b(this.c, var13)) {
return false;
}
}
}
return true;
}
public void a(boolean var1) {
this.a.c(var1);
}
public boolean e() {
return this.a.e();
}
public void b(boolean var1) {
this.a.b(var1);
}
public void c(boolean var1) {
this.a.a(var1);
}
public boolean g() {
return this.a.b();
}
public void d(boolean var1) {
this.a.d(var1);
}
public boolean h() {
return this.a.d();
}
public void e(boolean var1) {
this.f = var1;
}
}

View File

@ -1,5 +1,10 @@
package net.minecraft.server; package net.minecraft.server;
import com.elevatemc.spigot.pathsearch.PositionPathSearchType;
import com.elevatemc.spigot.pathsearch.jobs.PathSearchJob;
import com.elevatemc.spigot.pathsearch.jobs.PathSearchJobNavigationEntity;
import com.elevatemc.spigot.pathsearch.jobs.PathSearchJobNavigationPosition;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;

View File

@ -1,5 +1,6 @@
package net.minecraft.server; package net.minecraft.server;
import com.elevatemc.spigot.eSpigot;
import com.elevatemc.spigot.util.CryptException; import com.elevatemc.spigot.util.CryptException;
import com.google.common.collect.Queues; import com.google.common.collect.Queues;
import com.google.common.util.concurrent.ThreadFactoryBuilder; import com.google.common.util.concurrent.ThreadFactoryBuilder;
@ -190,8 +191,17 @@ public class NetworkManager extends SimpleChannelInboundHandler<Packet> {
if (this.channel.isOpen()) { if (this.channel.isOpen()) {
try { try {
packet.a(this.m); packet.a(this.m);
if (this.m instanceof PlayerConnection) {
try {
eSpigot.getInstance().getPacketHandlers().forEach(packetHandler -> packetHandler.handleReceivedPacket((PlayerConnection) this.m, packet));
} catch (Exception e) {
e.printStackTrace();
}
}
} catch (CancelledPacketHandleException cancelledpackethandleexception) { } catch (CancelledPacketHandleException cancelledpackethandleexception) {
} };
} }
} }

View File

@ -0,0 +1,58 @@
package net.minecraft.server;
import java.io.IOException;
public class PacketPlayInUseEntity implements Packet<PacketListenerPlayIn> {
public int a;
public EnumEntityUseAction action;
public Vec3D c;
public PacketPlayInUseEntity() {
}
public void a(PacketDataSerializer packetdataserializer) throws IOException {
this.a = packetdataserializer.e();
this.action = packetdataserializer.a(EnumEntityUseAction.class);
if (this.action == PacketPlayInUseEntity.EnumEntityUseAction.INTERACT_AT) {
this.c = new Vec3D( packetdataserializer.readFloat(), packetdataserializer.readFloat(), packetdataserializer.readFloat());
}
}
public void b(PacketDataSerializer packetdataserializer) throws IOException {
packetdataserializer.b(this.a);
packetdataserializer.a(this.action);
if (this.action == PacketPlayInUseEntity.EnumEntityUseAction.INTERACT_AT) {
packetdataserializer.writeFloat((float)this.c.a);
packetdataserializer.writeFloat((float)this.c.b);
packetdataserializer.writeFloat((float)this.c.c);
}
}
public void a(PacketListenerPlayIn packetlistenerplayin) {
packetlistenerplayin.a(this);
}
public Entity a(World world) {
return world.a(this.a);
}
public EnumEntityUseAction a() {
return this.action;
}
public Vec3D b() {
return this.c;
}
public enum EnumEntityUseAction {
INTERACT,
ATTACK,
INTERACT_AT;
private EnumEntityUseAction() {
}
}
}

View File

@ -0,0 +1,46 @@
package net.minecraft.server;
import lombok.Getter;
import lombok.Setter;
import java.io.IOException;
@Getter
@Setter
public class PacketPlayOutAttachEntity implements Packet<PacketListenerPlayOut> {
public int a;
public int b;
public int c;
public PacketPlayOutAttachEntity() {}
public PacketPlayOutAttachEntity(int entity, int vehicle) {
a = 0;
b = entity;
c = vehicle;
}
public PacketPlayOutAttachEntity(int i, Entity entity, Entity entity1) {
this.a = i;
this.b = entity.getId();
this.c = entity1 != null ? entity1.getId() : -1;
}
public void a(PacketDataSerializer packetdataserializer) throws IOException {
this.b = packetdataserializer.readInt();
this.c = packetdataserializer.readInt();
this.a = packetdataserializer.readUnsignedByte();
}
public void b(PacketDataSerializer packetdataserializer) throws IOException {
packetdataserializer.writeInt(this.b);
packetdataserializer.writeInt(this.c);
packetdataserializer.writeByte(this.a);
}
public void a(PacketListenerPlayOut packetlistenerplayout) {
packetlistenerplayout.a(this);
}
}

View File

@ -0,0 +1,43 @@
package net.minecraft.server;
import lombok.Getter;
import lombok.Setter;
import java.io.IOException;
import java.util.List;
@Getter
@Setter
public class PacketPlayOutEntityMetadata implements Packet<PacketListenerPlayOut> {
public int a;
public List<DataWatcher.WatchableObject> b;
public PacketPlayOutEntityMetadata() {}
public PacketPlayOutEntityMetadata(int i, DataWatcher datawatcher, boolean flag) {
this.a = i;
if (flag) {
this.b = datawatcher.c();
} else {
this.b = datawatcher.b();
}
}
public void a(PacketDataSerializer packetdataserializer) throws IOException {
this.a = packetdataserializer.e();
this.b = DataWatcher.b(packetdataserializer);
}
public void b(PacketDataSerializer packetdataserializer) throws IOException {
packetdataserializer.b(this.a);
DataWatcher.a(this.b, packetdataserializer);
}
public void a(PacketListenerPlayOut packetlistenerplayout) {
packetlistenerplayout.a(this);
}
}

View File

@ -0,0 +1,312 @@
package net.minecraft.server;
import com.google.common.base.Objects;
import com.google.common.collect.Lists;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.properties.Property;
import lombok.Getter;
import lombok.Setter;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
@Getter @Setter
public class PacketPlayOutPlayerInfo implements Packet<PacketListenerPlayOut> {
public PacketPlayOutPlayerInfo.EnumPlayerInfoAction a;
public List<PacketPlayOutPlayerInfo.PlayerInfoData> b = Lists.newArrayList();
public PacketPlayOutPlayerInfo() {
}
public PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction packetplayoutplayerinfo_enumplayerinfoaction, EntityPlayer... aentityplayer) {
this.a = packetplayoutplayerinfo_enumplayerinfoaction;
EntityPlayer[] aentityplayer1 = aentityplayer;
int i = aentityplayer.length;
for (int j = 0; j < i; ++j) {
EntityPlayer entityplayer = aentityplayer1[j];
this.b.add(new PacketPlayOutPlayerInfo.PlayerInfoData(entityplayer.getProfile(),
entityplayer.ping, entityplayer.playerInteractManager.getGameMode(), entityplayer.getPlayerListName()));
}
}
public PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction packetplayoutplayerinfo_enumplayerinfoaction, List<PacketPlayOutPlayerInfo.PlayerInfoData> b) {
this.a = packetplayoutplayerinfo_enumplayerinfoaction;
this.b = b;
}
public static PacketPlayOutPlayerInfo addPlayer(EntityPlayer player) {
PacketPlayOutPlayerInfo packet = new PacketPlayOutPlayerInfo();
packet.a = EnumPlayerInfoAction.ADD_PLAYER;
PacketPlayOutPlayerInfo.PlayerInfoData playerInfoData =
new PacketPlayOutPlayerInfo.PlayerInfoData(player.getProfile(), player.ping,
player.playerInteractManager.getGameMode(), player.getPlayerListName());
packet.b.add(playerInfoData);
return packet;
}
public static PacketPlayOutPlayerInfo updatePing(EntityPlayer player) {
PacketPlayOutPlayerInfo packet = new PacketPlayOutPlayerInfo();
packet.a = EnumPlayerInfoAction.UPDATE_LATENCY;
PacketPlayOutPlayerInfo.PlayerInfoData playerInfoData =
new PacketPlayOutPlayerInfo.PlayerInfoData(player.getProfile(), player.ping,
player.playerInteractManager.getGameMode(), player.getPlayerListName());
packet.b.add(playerInfoData);
return packet;
}
public static PacketPlayOutPlayerInfo updateGamemode(EntityPlayer player) {
PacketPlayOutPlayerInfo packet = new PacketPlayOutPlayerInfo();
packet.a = EnumPlayerInfoAction.UPDATE_GAME_MODE;
PacketPlayOutPlayerInfo.PlayerInfoData playerInfoData =
new PacketPlayOutPlayerInfo.PlayerInfoData(player.getProfile(), player.ping,
player.playerInteractManager.getGameMode(), player.getPlayerListName());
packet.b.add(playerInfoData);
return packet;
}
public static PacketPlayOutPlayerInfo updateDisplayName(EntityPlayer player) {
PacketPlayOutPlayerInfo packet = new PacketPlayOutPlayerInfo();
packet.a = EnumPlayerInfoAction.UPDATE_DISPLAY_NAME;
PacketPlayOutPlayerInfo.PlayerInfoData playerInfoData =
new PacketPlayOutPlayerInfo.PlayerInfoData(player.getProfile(), player.ping,
player.playerInteractManager.getGameMode(), player.getPlayerListName());
packet.b.add(playerInfoData);
return packet;
}
public static PacketPlayOutPlayerInfo removePlayer(EntityPlayer player) {
PacketPlayOutPlayerInfo packet = new PacketPlayOutPlayerInfo();
packet.a = EnumPlayerInfoAction.REMOVE_PLAYER;
PacketPlayOutPlayerInfo.PlayerInfoData playerInfoData =
new PacketPlayOutPlayerInfo.PlayerInfoData(player.getProfile(), player.ping,
player.playerInteractManager.getGameMode(), player.getPlayerListName());
packet.b.add(playerInfoData);
return packet;
}
public void a(PacketDataSerializer packetdataserializer) throws IOException {
this.a = packetdataserializer.a(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.class);
int i = packetdataserializer.e();
for (int j = 0; j < i; ++j) {
GameProfile gameprofile = null;
int k = 0;
WorldSettings.EnumGamemode worldsettings_enumgamemode = null;
IChatBaseComponent ichatbasecomponent = null;
switch (PacketPlayOutPlayerInfo.SyntheticClass_1.a[this.a.ordinal()]) {
case 1:
gameprofile = new GameProfile(packetdataserializer.g(), packetdataserializer.c(16));
int l = packetdataserializer.e();
for (int i1 = 0; i1 < l; ++i1) {
String s = packetdataserializer.c(32767);
String s1 = packetdataserializer.c(32767);
if (packetdataserializer.readBoolean()) {
gameprofile.getProperties().put(s, new Property(s, s1, packetdataserializer.c(32767)));
} else {
gameprofile.getProperties().put(s, new Property(s, s1));
}
}
worldsettings_enumgamemode = WorldSettings.EnumGamemode.getById(packetdataserializer.e());
k = packetdataserializer.e();
if (packetdataserializer.readBoolean()) {
ichatbasecomponent = packetdataserializer.d();
}
break;
case 2:
gameprofile = new GameProfile(packetdataserializer.g(), null);
worldsettings_enumgamemode = WorldSettings.EnumGamemode.getById(packetdataserializer.e());
break;
case 3:
gameprofile = new GameProfile(packetdataserializer.g(), null);
k = packetdataserializer.e();
break;
case 4:
gameprofile = new GameProfile(packetdataserializer.g(), null);
if (packetdataserializer.readBoolean()) {
ichatbasecomponent = packetdataserializer.d();
}
break;
case 5:
gameprofile = new GameProfile(packetdataserializer.g(), null);
}
this.b.add(new PacketPlayOutPlayerInfo.PlayerInfoData(gameprofile, k, worldsettings_enumgamemode, ichatbasecomponent));
}
}
public void b(PacketDataSerializer packetdataserializer) throws IOException {
packetdataserializer.a((Enum) this.a);
packetdataserializer.b(this.b.size());
Iterator iterator = this.b.iterator();
while (iterator.hasNext()) {
PacketPlayOutPlayerInfo.PlayerInfoData packetplayoutplayerinfo_playerinfodata = (PacketPlayOutPlayerInfo.PlayerInfoData) iterator.next();
switch (PacketPlayOutPlayerInfo.SyntheticClass_1.a[this.a.ordinal()]) {
case 1:
packetdataserializer.a(packetplayoutplayerinfo_playerinfodata.a().getId());
packetdataserializer.a(packetplayoutplayerinfo_playerinfodata.a().getName());
packetdataserializer.b(packetplayoutplayerinfo_playerinfodata.a().getProperties().size());
Iterator iterator1 = packetplayoutplayerinfo_playerinfodata.a().getProperties().values().iterator();
while (iterator1.hasNext()) {
Property property = (Property) iterator1.next();
packetdataserializer.a(property.getName());
packetdataserializer.a(property.getValue());
if (property.hasSignature()) {
packetdataserializer.writeBoolean(true);
packetdataserializer.a(property.getSignature());
} else {
packetdataserializer.writeBoolean(false);
}
}
packetdataserializer.b(packetplayoutplayerinfo_playerinfodata.c().getId());
packetdataserializer.b(packetplayoutplayerinfo_playerinfodata.b());
if (packetplayoutplayerinfo_playerinfodata.d() == null) {
packetdataserializer.writeBoolean(false);
} else {
packetdataserializer.writeBoolean(true);
packetdataserializer.a(packetplayoutplayerinfo_playerinfodata.d());
}
break;
case 2:
packetdataserializer.a(packetplayoutplayerinfo_playerinfodata.a().getId());
packetdataserializer.b(packetplayoutplayerinfo_playerinfodata.c().getId());
break;
case 3:
packetdataserializer.a(packetplayoutplayerinfo_playerinfodata.a().getId());
packetdataserializer.b(packetplayoutplayerinfo_playerinfodata.b());
break;
case 4:
packetdataserializer.a(packetplayoutplayerinfo_playerinfodata.a().getId());
if (packetplayoutplayerinfo_playerinfodata.d() == null) {
packetdataserializer.writeBoolean(false);
} else {
packetdataserializer.writeBoolean(true);
packetdataserializer.a(packetplayoutplayerinfo_playerinfodata.d());
}
break;
case 5:
packetdataserializer.a(packetplayoutplayerinfo_playerinfodata.a().getId());
}
}
}
public void a(PacketListenerPlayOut packetlistenerplayout) {
packetlistenerplayout.a(this);
}
public String toString() {
return Objects.toStringHelper(this).add("action", this.a).add("entries", this.b).toString();
}
static class SyntheticClass_1 {
static final int[] a = new int[PacketPlayOutPlayerInfo.EnumPlayerInfoAction.values().length];
static {
try {
PacketPlayOutPlayerInfo.SyntheticClass_1.a[PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER.ordinal()] = 1;
} catch (NoSuchFieldError ignored) {
;
}
try {
PacketPlayOutPlayerInfo.SyntheticClass_1.a[PacketPlayOutPlayerInfo.EnumPlayerInfoAction.UPDATE_GAME_MODE.ordinal()] = 2;
} catch (NoSuchFieldError ignored) {
;
}
try {
PacketPlayOutPlayerInfo.SyntheticClass_1.a[PacketPlayOutPlayerInfo.EnumPlayerInfoAction.UPDATE_LATENCY.ordinal()] = 3;
} catch (NoSuchFieldError ignored) {
;
}
try {
PacketPlayOutPlayerInfo.SyntheticClass_1.a[PacketPlayOutPlayerInfo.EnumPlayerInfoAction.UPDATE_DISPLAY_NAME.ordinal()] = 4;
} catch (NoSuchFieldError ignored) {
;
}
try {
PacketPlayOutPlayerInfo.SyntheticClass_1.a[PacketPlayOutPlayerInfo.EnumPlayerInfoAction.REMOVE_PLAYER.ordinal()] = 5;
} catch (NoSuchFieldError ignored) {
;
}
}
}
public static class PlayerInfoData {
private final int b;
private final WorldSettings.EnumGamemode c;
private final GameProfile d;
private final IChatBaseComponent e;
public PlayerInfoData(GameProfile gameprofile, int i, WorldSettings.EnumGamemode worldsettings_enumgamemode, IChatBaseComponent ichatbasecomponent) {
this.d = gameprofile;
this.b = i;
this.c = worldsettings_enumgamemode;
this.e = ichatbasecomponent;
}
public GameProfile a() {
return this.d;
}
public int b() {
return this.b;
}
public WorldSettings.EnumGamemode c() {
return this.c;
}
public IChatBaseComponent d() {
return this.e;
}
public String toString() {
return Objects.toStringHelper(this)
.add("latency", this.b)
.add("gameMode", this.c)
.add("profile", this.d)
.add("displayName", this.e == null ? null : IChatBaseComponent.ChatSerializer.a(this.e)).toString();
}
}
public enum EnumPlayerInfoAction {
ADD_PLAYER, UPDATE_GAME_MODE, UPDATE_LATENCY, UPDATE_DISPLAY_NAME, REMOVE_PLAYER;
EnumPlayerInfoAction() {
}
}
// ImHacking start
public GameProfile getPlayer() {
return this.b.get(this.b.size() - 1).d;
}
// ImHacking end
}

View File

@ -0,0 +1,119 @@
package net.minecraft.server;
import com.google.common.collect.Lists;
import lombok.Getter;
import lombok.Setter;
import java.io.IOException;
import java.util.Collection;
import java.util.Iterator;
@Getter
@Setter
public class PacketPlayOutScoreboardTeam implements Packet<PacketListenerPlayOut> {
public String a = "";
public String b = "";
public String c = "";
public String d = "";
public String e;
public int f;
public Collection<String> g;
public int h;
public int i;
public PacketPlayOutScoreboardTeam() {
this.e = ScoreboardTeamBase.EnumNameTagVisibility.ALWAYS.e;
this.f = -1;
this.g = Lists.newArrayList();
}
public PacketPlayOutScoreboardTeam(ScoreboardTeam scoreboardteam, int i) {
this.e = ScoreboardTeamBase.EnumNameTagVisibility.ALWAYS.e;
this.f = -1;
this.g = Lists.newArrayList();
this.a = scoreboardteam.getName();
this.h = i;
if (i == 0 || i == 2) {
this.b = scoreboardteam.getDisplayName();
this.c = scoreboardteam.getPrefix();
this.d = scoreboardteam.getSuffix();
this.i = scoreboardteam.packOptionData();
this.e = scoreboardteam.getNameTagVisibility().e;
this.f = scoreboardteam.l().b();
}
if (i == 0) {
this.g.addAll(scoreboardteam.getPlayerNameSet());
}
}
public PacketPlayOutScoreboardTeam(ScoreboardTeam scoreboardteam, Collection<String> collection, int i) {
this.e = ScoreboardTeamBase.EnumNameTagVisibility.ALWAYS.e;
this.f = -1;
this.g = Lists.newArrayList();
if (i != 3 && i != 4) {
throw new IllegalArgumentException("Method must be join or leave for player constructor");
} else if (collection != null && !collection.isEmpty()) {
this.h = i;
this.a = scoreboardteam.getName();
this.g.addAll(collection);
} else {
throw new IllegalArgumentException("Players cannot be null/empty");
}
}
public void a(PacketDataSerializer packetdataserializer) throws IOException {
this.a = packetdataserializer.c(16);
this.h = packetdataserializer.readByte();
if (this.h == 0 || this.h == 2) {
this.b = packetdataserializer.c(32);
this.c = packetdataserializer.c(16);
this.d = packetdataserializer.c(16);
this.i = packetdataserializer.readByte();
this.e = packetdataserializer.c(32);
this.f = packetdataserializer.readByte();
}
if (this.h == 0 || this.h == 3 || this.h == 4) {
int i = packetdataserializer.e();
for (int j = 0; j < i; ++j) {
this.g.add(packetdataserializer.c(40));
}
}
}
public void b(PacketDataSerializer packetdataserializer) throws IOException {
packetdataserializer.a(this.a);
packetdataserializer.writeByte(this.h);
if (this.h == 0 || this.h == 2) {
packetdataserializer.a(this.b);
packetdataserializer.a(this.c);
packetdataserializer.a(this.d);
packetdataserializer.writeByte(this.i);
packetdataserializer.a(this.e);
packetdataserializer.writeByte(this.f);
}
if (this.h == 0 || this.h == 3 || this.h == 4) {
packetdataserializer.b(this.g.size());
Iterator iterator = this.g.iterator();
while (iterator.hasNext()) {
String s = (String) iterator.next();
packetdataserializer.a(s);
}
}
}
public void a(PacketListenerPlayOut packetlistenerplayout) {
packetlistenerplayout.a(this);
}
}

View File

@ -0,0 +1,168 @@
package net.minecraft.server;
import lombok.Getter;
import lombok.Setter;
import java.io.IOException;
@Getter
@Setter
public class PacketPlayOutSpawnEntity implements Packet<PacketListenerPlayOut> {
public int a;
public int b;
public int c;
public int d;
private int e;
private int f;
private int g;
private int h;
private int i;
private int j;
private int k;
public PacketPlayOutSpawnEntity() {}
public PacketPlayOutSpawnEntity(Entity entity, int i) {
this(entity, i, 0);
}
public PacketPlayOutSpawnEntity(Entity entity, int i, int j) {
this.a = entity.getId();
this.b = MathHelper.floor(entity.locX * 32.0D);
this.c = MathHelper.floor(entity.locY * 32.0D);
this.d = MathHelper.floor(entity.locZ * 32.0D);
this.h = MathHelper.d(entity.pitch * 256.0F / 360.0F);
this.i = MathHelper.d(entity.yaw * 256.0F / 360.0F);
this.j = i;
this.k = j;
if (j > 0) {
double d0 = entity.motX;
double d1 = entity.motY;
double d2 = entity.motZ;
double d3 = 3.9D;
if (d0 < -d3) {
d0 = -d3;
}
if (d1 < -d3) {
d1 = -d3;
}
if (d2 < -d3) {
d2 = -d3;
}
if (d0 > d3) {
d0 = d3;
}
if (d1 > d3) {
d1 = d3;
}
if (d2 > d3) {
d2 = d3;
}
this.e = (int) (d0 * 8000.0D);
this.f = (int) (d1 * 8000.0D);
this.g = (int) (d2 * 8000.0D);
}
}
public void a(PacketDataSerializer packetdataserializer) throws IOException {
this.a = packetdataserializer.e();
this.j = packetdataserializer.readByte();
this.b = packetdataserializer.readInt();
this.c = packetdataserializer.readInt();
this.d = packetdataserializer.readInt();
this.h = packetdataserializer.readByte();
this.i = packetdataserializer.readByte();
}
public void b(PacketDataSerializer packetdataserializer) throws IOException {
packetdataserializer.b(this.a);
packetdataserializer.writeByte(this.j);
switch (this.k) {
case 0: {
this.d -= 32;
this.i = 128;
break;
}
case 1: {
this.b += 32;
this.i = 64;
break;
}
case 2: {
this.d += 32;
this.i = 0;
break;
}
case 3: {
this.b -= 32;
this.i = 192;
break;
}
}
packetdataserializer.writeInt(this.b);
packetdataserializer.writeInt(this.c);
packetdataserializer.writeInt(this.d);
packetdataserializer.writeByte(this.h);
packetdataserializer.writeByte(this.i);
packetdataserializer.writeInt(this.k);
if (this.k > 0) {
packetdataserializer.writeShort(this.e);
packetdataserializer.writeShort(this.f);
packetdataserializer.writeShort(this.g);
}
}
public void b_old(PacketDataSerializer packetdataserializer) throws IOException {
packetdataserializer.b(this.a);
packetdataserializer.writeByte(this.j);
packetdataserializer.writeInt(this.b);
packetdataserializer.writeInt(this.c);
packetdataserializer.writeInt(this.d);
packetdataserializer.writeByte(this.h);
packetdataserializer.writeByte(this.i);
packetdataserializer.writeInt(this.k);
if (this.k > 0) {
packetdataserializer.writeShort(this.e);
packetdataserializer.writeShort(this.f);
packetdataserializer.writeShort(this.g);
}
}
public void a(PacketListenerPlayOut packetlistenerplayout) {
packetlistenerplayout.a(this);
}
public void a(int i) {
this.b = i;
}
public void b(int i) {
this.c = i;
}
public void c(int i) {
this.d = i;
}
public void d(int i) {
this.e = i;
}
public void e(int i) {
this.f = i;
}
public void f(int i) {
this.g = i;
}
}

View File

@ -0,0 +1,107 @@
package net.minecraft.server;
import lombok.Getter;
import lombok.Setter;
import java.io.IOException;
import java.util.List;
@Getter
@Setter
public class PacketPlayOutSpawnEntityLiving implements Packet<PacketListenerPlayOut> {
public int id;
public int type;
public int x;
public int y;
public int z;
public int motionX;
public int motionY;
public int motionZ;
public byte yaw;
public byte pitch;
public byte headYaw;
public DataWatcher l;
public List<DataWatcher.WatchableObject> m;
public PacketPlayOutSpawnEntityLiving() {}
public PacketPlayOutSpawnEntityLiving(EntityLiving entityliving) {
this.id = entityliving.getId();
this.type = (byte) EntityTypes.a(entityliving);
this.x = MathHelper.floor(entityliving.locX * 32.0D);
this.y = MathHelper.floor(entityliving.locY * 32.0D);
this.z = MathHelper.floor(entityliving.locZ * 32.0D);
this.yaw = (byte) ((int) (entityliving.yaw * 256.0F / 360.0F));
this.pitch = (byte) ((int) (entityliving.pitch * 256.0F / 360.0F));
this.headYaw = (byte) ((int) (entityliving.aK * 256.0F / 360.0F));
double d0 = 3.9D;
double d1 = entityliving.motX;
double d2 = entityliving.motY;
double d3 = entityliving.motZ;
if (d1 < -d0) {
d1 = -d0;
}
if (d2 < -d0) {
d2 = -d0;
}
if (d3 < -d0) {
d3 = -d0;
}
if (d1 > d0) {
d1 = d0;
}
if (d2 > d0) {
d2 = d0;
}
if (d3 > d0) {
d3 = d0;
}
this.motionX = (int) (d1 * 8000.0D);
this.motionY = (int) (d2 * 8000.0D);
this.motionZ = (int) (d3 * 8000.0D);
this.l = entityliving.getDataWatcher();
}
public void a(PacketDataSerializer packetdataserializer) throws IOException {
this.id = packetdataserializer.e();
this.type = packetdataserializer.readByte() & 255;
this.x = packetdataserializer.readInt();
this.y = packetdataserializer.readInt();
this.z = packetdataserializer.readInt();
this.yaw = packetdataserializer.readByte();
this.pitch = packetdataserializer.readByte();
this.headYaw = packetdataserializer.readByte();
this.motionX = packetdataserializer.readShort();
this.motionY = packetdataserializer.readShort();
this.motionZ = packetdataserializer.readShort();
this.m = DataWatcher.b(packetdataserializer);
}
public void b(PacketDataSerializer packetdataserializer) throws IOException {
packetdataserializer.b(this.id);
packetdataserializer.writeByte(this.type & 255);
packetdataserializer.writeInt(this.x);
packetdataserializer.writeInt(this.y);
packetdataserializer.writeInt(this.z);
packetdataserializer.writeByte(this.yaw);
packetdataserializer.writeByte(this.pitch);
packetdataserializer.writeByte(this.headYaw);
packetdataserializer.writeShort(this.motionX);
packetdataserializer.writeShort(this.motionY);
packetdataserializer.writeShort(this.motionZ);
this.l.a(packetdataserializer);
}
public void a(PacketListenerPlayOut packetlistenerplayout) {
packetlistenerplayout.a(this);
}
}

View File

@ -0,0 +1,51 @@
package net.minecraft.server;
import lombok.Getter;
import lombok.Setter;
import java.io.IOException;
@Getter
@Setter
public class PacketPlayOutSpawnEntityWeather implements Packet<PacketListenerPlayOut> {
private int a;
private int b;
private int c;
private int d;
private int e;
public PacketPlayOutSpawnEntityWeather() {}
public PacketPlayOutSpawnEntityWeather(Entity entity) {
this.a = entity.getId();
this.b = MathHelper.floor(entity.locX * 32.0D);
this.c = MathHelper.floor(entity.locY * 32.0D);
this.d = MathHelper.floor(entity.locZ * 32.0D);
if (entity instanceof EntityLightning) {
this.e = 1;
}
}
public void a(PacketDataSerializer packetdataserializer) throws IOException {
this.a = packetdataserializer.e();
this.e = packetdataserializer.readByte();
this.b = packetdataserializer.readInt();
this.c = packetdataserializer.readInt();
this.d = packetdataserializer.readInt();
}
public void b(PacketDataSerializer packetdataserializer) throws IOException {
packetdataserializer.b(this.a);
packetdataserializer.writeByte(this.e);
packetdataserializer.writeInt(this.b);
packetdataserializer.writeInt(this.c);
packetdataserializer.writeInt(this.d);
}
public void a(PacketListenerPlayOut packetlistenerplayout) {
packetlistenerplayout.a(this);
}
}

View File

@ -0,0 +1,87 @@
package net.minecraft.server;
import lombok.Getter;
import lombok.Setter;
import java.io.IOException;
@Getter
@Setter
public class PacketPlayOutWorldParticles implements Packet<PacketListenerPlayOut> {
public EnumParticle a;
public float b;
public float c;
public float d;
public float e;
public float f;
public float g;
public float h;
public int i;
public boolean j;
public int[] k;
public PacketPlayOutWorldParticles() {}
public PacketPlayOutWorldParticles(EnumParticle enumparticle, boolean flag, float f, float f1, float f2, float f3, float f4, float f5, float f6, int i, int... aint) {
this.a = enumparticle;
this.j = flag;
this.b = f;
this.c = f1;
this.d = f2;
this.e = f3;
this.f = f4;
this.g = f5;
this.h = f6;
this.i = i;
this.k = aint;
}
public void a(PacketDataSerializer packetdataserializer) throws IOException {
this.a = EnumParticle.a(packetdataserializer.readInt());
if (this.a == null) {
this.a = EnumParticle.BARRIER;
}
this.j = packetdataserializer.readBoolean();
this.b = packetdataserializer.readFloat();
this.c = packetdataserializer.readFloat();
this.d = packetdataserializer.readFloat();
this.e = packetdataserializer.readFloat();
this.f = packetdataserializer.readFloat();
this.g = packetdataserializer.readFloat();
this.h = packetdataserializer.readFloat();
this.i = packetdataserializer.readInt();
int i = this.a.d();
this.k = new int[i];
for (int j = 0; j < i; ++j) {
this.k[j] = packetdataserializer.e();
}
}
public void b(PacketDataSerializer packetdataserializer) throws IOException {
packetdataserializer.writeInt(this.a.c());
packetdataserializer.writeBoolean(this.j);
packetdataserializer.writeFloat(this.b);
packetdataserializer.writeFloat(this.c);
packetdataserializer.writeFloat(this.d);
packetdataserializer.writeFloat(this.e);
packetdataserializer.writeFloat(this.f);
packetdataserializer.writeFloat(this.g);
packetdataserializer.writeFloat(this.h);
packetdataserializer.writeInt(this.i);
int i = this.a.d();
for (int j = 0; j < i; ++j) {
packetdataserializer.b(this.k[j]);
}
}
public void a(PacketListenerPlayOut packetlistenerplayout) {
packetlistenerplayout.a(this);
}
}

View File

@ -216,4 +216,20 @@ public class PathfinderNormal extends PathfinderAbstract {
public boolean e() { public boolean e() {
return this.h; return this.h;
} }
public boolean getB() {
return this.f;
}
public boolean getC() {
return this.g;
}
public boolean getD() {
return this.i;
}
public boolean getE() {
return this.h;
}
} }

View File

@ -348,7 +348,13 @@ public class PlayerChunkMap {
public static int getFurthestViewableBlock(int i) { public static int getFurthestViewableBlock(int i) {
return i * 16 - 16; return i * 16 - 16;
} }
public void resend(int chunkX, int chunkZ) {
PlayerChunk chunk = this.a(chunkX, chunkZ, false);
if (chunk != null) {
chunk.resend();
}
}
class PlayerChunk { class PlayerChunk {
private final List<EntityPlayer> b = Lists.newArrayList(); private final List<EntityPlayer> b = Lists.newArrayList();
@ -372,7 +378,13 @@ public class PlayerChunkMap {
this.location = new ChunkCoordIntPair(i, j); this.location = new ChunkCoordIntPair(i, j);
PlayerChunkMap.this.a().chunkProviderServer.getChunkAt(i, j, loadedRunnable); // CraftBukkit PlayerChunkMap.this.a().chunkProviderServer.getChunkAt(i, j, loadedRunnable); // CraftBukkit
} }
public void resend() {
if (this.dirtyCount == 0) {
PlayerChunkMap.this.e.add(this);
}
this.dirtyCount = 64;
this.f = 0xFFFF;
}
public void a(final EntityPlayer entityplayer) { // CraftBukkit - added final to argument public void a(final EntityPlayer entityplayer) { // CraftBukkit - added final to argument
if (this.b.contains(entityplayer)) { if (this.b.contains(entityplayer)) {
PlayerChunkMap.a.debug("Failed to add player. {} already is in chunk {}, {}", new Object[] { entityplayer, Integer.valueOf(this.location.x), Integer.valueOf(this.location.z)}); PlayerChunkMap.a.debug("Failed to add player. {} already is in chunk {}, {}", new Object[] { entityplayer, Integer.valueOf(this.location.x), Integer.valueOf(this.location.z)});

View File

@ -1,5 +1,8 @@
package net.minecraft.server; package net.minecraft.server;
import com.elevatemc.spigot.eSpigot;
import com.elevatemc.spigot.handler.MovementHandler;
import com.elevatemc.spigot.handler.PacketHandler;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.primitives.Doubles; import com.google.common.primitives.Doubles;
import com.google.common.primitives.Floats; import com.google.common.primitives.Floats;
@ -263,6 +266,26 @@ public class PlayerConnection implements PacketListenerPlayIn, IUpdatePlayerList
double delta = Math.pow(this.lastPosX - to.getX(), 2) + Math.pow(this.lastPosY - to.getY(), 2) + Math.pow(this.lastPosZ - to.getZ(), 2); double delta = Math.pow(this.lastPosX - to.getX(), 2) + Math.pow(this.lastPosY - to.getY(), 2) + Math.pow(this.lastPosZ - to.getZ(), 2);
float deltaAngle = Math.abs(this.lastYaw - to.getYaw()) + Math.abs(this.lastPitch - to.getPitch()); float deltaAngle = Math.abs(this.lastYaw - to.getYaw()) + Math.abs(this.lastPitch - to.getPitch());
if (packetplayinflying.hasPos && delta > 0.0D && this.checkMovement && !this.player.dead) {
for (MovementHandler handler : eSpigot.getInstance().getMovementHandlers()) {
try {
handler.handleUpdateLocation(player, to, from, packetplayinflying);
} catch (Exception e) {
e.printStackTrace();
}
}
}
if (packetplayinflying.hasLook && deltaAngle > 0.0F && this.checkMovement && !this.player.dead) {
for (MovementHandler handler : eSpigot.getInstance().getMovementHandlers()) {
try {
handler.handleUpdateRotation(player, to, from, packetplayinflying);
} catch (Exception e) {
e.printStackTrace();
}
}
}
if ((delta > 1f / 256 || deltaAngle > 10f) && (this.checkMovement && !this.player.dead)) { if ((delta > 1f / 256 || deltaAngle > 10f) && (this.checkMovement && !this.player.dead)) {
this.lastPosX = to.getX(); this.lastPosX = to.getX();
this.lastPosY = to.getY(); this.lastPosY = to.getY();
@ -920,7 +943,12 @@ public class PlayerConnection implements PacketListenerPlayIn, IUpdatePlayerList
// CraftBukkit end // CraftBukkit end
try { try {
this.networkManager.handle(packet); // Loop through normal handlers
for (PacketHandler handler : eSpigot.getInstance().getPacketHandlers()) {
handler.handleSentPacket(this, packet);
}
this.networkManager.a((EnumProtocol) packet);
} catch (Throwable throwable) { } catch (Throwable throwable) {
CrashReport crashreport = CrashReport.a(throwable, "Sending packet"); CrashReport crashreport = CrashReport.a(throwable, "Sending packet");
CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Packet being sent"); CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Packet being sent");

View File

@ -890,10 +890,11 @@ public abstract class PlayerList {
} }
public void tick() { public void tick() {
if (++this.u > 600) { // ImHacking - Useless feature.
this.sendAll(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.UPDATE_LATENCY, this.players)); /*if (++this.u > 600) {
this.sendAll(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.UPDATE_LATENCY, (EntityPlayer) this.players));
this.u = 0; this.u = 0;
} }*/
} }

View File

@ -17,7 +17,7 @@ public abstract class TileEntity {
private static Map<String, Class<? extends TileEntity>> f = Maps.newHashMap(); private static Map<String, Class<? extends TileEntity>> f = Maps.newHashMap();
private static Map<Class<? extends TileEntity>, String> g = Maps.newHashMap(); private static Map<Class<? extends TileEntity>, String> g = Maps.newHashMap();
protected World world; protected World world;
protected BlockPosition position; public BlockPosition position;
protected boolean d; protected boolean d;
private int h; private int h;
protected Block e; protected Block e;

View File

@ -5,6 +5,7 @@ import com.google.common.collect.Lists;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.block.BlockState; import org.bukkit.block.BlockState;
import org.bukkit.craftbukkit.CraftServer; import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.craftbukkit.CraftWorld; import org.bukkit.craftbukkit.CraftWorld;
@ -2042,6 +2043,30 @@ public abstract class World implements IBlockAccess {
return false; return false;
} }
// ImHacking start
public boolean boundingBoxContainsMaterials(AxisAlignedBB boundingBox, Set<Block> matching) {
int i = MathHelper.floor(boundingBox.a);
int j = MathHelper.floor(boundingBox.d + 1.0D);
int k = MathHelper.floor(boundingBox.b);
int l = MathHelper.floor(boundingBox.e + 1.0D);
int i1 = MathHelper.floor(boundingBox.c);
int j1 = MathHelper.floor(boundingBox.f + 1.0D);
BlockPosition.MutableBlockPosition blockPosition = new BlockPosition.MutableBlockPosition();
for (int k1 = i; k1 < j; ++k1) {
for (int l1 = k; l1 < l; ++l1) {
for (int i2 = i1; i2 < j1; ++i2) {
if (matching.contains(this.getType(blockPosition.c(k1, l1, i2)).getBlock())) {
return true;
}
}
}
}
return false;
}
// ImHacking end
public boolean b(AxisAlignedBB axisalignedbb, Material material) { public boolean b(AxisAlignedBB axisalignedbb, Material material) {
int i = MathHelper.floor(axisalignedbb.a); int i = MathHelper.floor(axisalignedbb.a);
int j = MathHelper.floor(axisalignedbb.d + 1.0D); int j = MathHelper.floor(axisalignedbb.d + 1.0D);
@ -3171,11 +3196,11 @@ public abstract class World implements IBlockAccess {
return blockposition; return blockposition;
} }
public void B(BlockPosition blockposition) { public void B(BlockPosition blockposition) {
this.worldData.setSpawn(blockposition); this.worldData.setSpawn(new Location(getWorld(), blockposition.getX(), blockposition.getY(), blockposition.getZ()));
} }
public boolean a(EntityHuman entityhuman, BlockPosition blockposition) { public boolean a(EntityHuman entityhuman, BlockPosition blockposition) {
return true; return true;
} }

View File

@ -3,6 +3,7 @@ package net.minecraft.server;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
// CraftBukkit start // CraftBukkit start
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.event.weather.ThunderChangeEvent; import org.bukkit.event.weather.ThunderChangeEvent;
import org.bukkit.event.weather.WeatherChangeEvent; import org.bukkit.event.weather.WeatherChangeEvent;
// CraftBukkit end // CraftBukkit end
@ -13,9 +14,11 @@ public class WorldData {
private long b; private long b;
private WorldType c; private WorldType c;
private String d; private String d;
private int e; private double e;
private int f; private double f;
private int g; private double g;
private float yaw;
private float pitch;
private long h; private long h;
private long i; private long i;
private long j; private long j;
@ -108,6 +111,15 @@ public class WorldData {
this.e = nbttagcompound.getInt("SpawnX"); this.e = nbttagcompound.getInt("SpawnX");
this.f = nbttagcompound.getInt("SpawnY"); this.f = nbttagcompound.getInt("SpawnY");
this.g = nbttagcompound.getInt("SpawnZ"); this.g = nbttagcompound.getInt("SpawnZ");
// ImHacking Start - Add yaw and pitch to spawns
if (nbttagcompound.hasKey("SpawnYaw")) {
this.yaw = nbttagcompound.getFloat("SpawnYaw");
}
if (nbttagcompound.hasKey("SpawnPitch")) {
this.pitch = nbttagcompound.getFloat("SpawnPitch");
}
// ImHacking End
this.h = nbttagcompound.getLong("Time"); this.h = nbttagcompound.getLong("Time");
if (nbttagcompound.hasKeyOfType("DayTime", 99)) { if (nbttagcompound.hasKeyOfType("DayTime", 99)) {
this.i = nbttagcompound.getLong("DayTime"); this.i = nbttagcompound.getLong("DayTime");
@ -292,9 +304,13 @@ public class WorldData {
nbttagcompound.setString("generatorOptions", this.d); nbttagcompound.setString("generatorOptions", this.d);
nbttagcompound.setInt("GameType", this.u.getId()); nbttagcompound.setInt("GameType", this.u.getId());
nbttagcompound.setBoolean("MapFeatures", this.v); nbttagcompound.setBoolean("MapFeatures", this.v);
nbttagcompound.setInt("SpawnX", this.e); nbttagcompound.setDouble("SpawnX", this.e);
nbttagcompound.setInt("SpawnY", this.f); nbttagcompound.setDouble("SpawnY", this.f);
nbttagcompound.setInt("SpawnZ", this.g); nbttagcompound.setDouble("SpawnZ", this.g);
// ImHacking Start
nbttagcompound.setFloat("SpawnYaw", this.yaw);
nbttagcompound.setFloat("SpawnPitch", this.pitch);
// ImHacking End
nbttagcompound.setLong("Time", this.h); nbttagcompound.setLong("Time", this.h);
nbttagcompound.setLong("DayTime", this.i); nbttagcompound.setLong("DayTime", this.i);
nbttagcompound.setLong("SizeOnDisk", this.k); nbttagcompound.setLong("SizeOnDisk", this.k);
@ -334,15 +350,15 @@ public class WorldData {
return this.b; return this.b;
} }
public int c() { public double c() {
return this.e; return this.e;
} }
public int d() { public double d() {
return this.f; return this.f;
} }
public int e() { public double e() {
return this.g; return this.g;
} }
@ -366,11 +382,15 @@ public class WorldData {
this.i = i; this.i = i;
} }
public void setSpawn(BlockPosition blockposition) { // ImHacking Start - Add yaw and pitch to spawns
this.e = blockposition.getX(); public void setSpawn(Location location) {
this.f = blockposition.getY(); this.e = location.getX();
this.g = blockposition.getZ(); this.f = location.getY();
this.g = location.getZ();
this.yaw = location.getYaw();
this.pitch = location.getPitch();
} }
// ImHacking End
public String getName() { public String getName() {
return this.n; return this.n;

View File

@ -0,0 +1,139 @@
package net.minecraft.server;
public abstract class WorldProvider {
public static final float[] a = new float[]{1.0F, 0.75F, 0.5F, 0.25F, 0.0F, 0.25F, 0.5F, 0.75F};
protected World b;
private WorldType type;
private String i;
protected WorldChunkManager c;
protected boolean d;
public boolean e;
protected final float[] f = new float[16];
protected int dimension;
private final float[] j = new float[4];
public WorldProvider() {
}
public final void a(World var1) {
this.b = var1;
this.type = var1.getWorldData().getType();
this.i = var1.getWorldData().getGeneratorOptions();
this.b();
this.a();
}
protected void a() {
float var1 = 0.0F;
for(int var2 = 0; var2 <= 15; ++var2) {
float var3 = 1.0F - (float)var2 / 15.0F;
this.f[var2] = (1.0F - var3) / (var3 * 3.0F + 1.0F) * (1.0F - var1) + var1;
}
}
protected void b() {
WorldType var1 = this.b.getWorldData().getType();
if (var1 == WorldType.FLAT) {
WorldGenFlatInfo var2 = WorldGenFlatInfo.a(this.b.getWorldData().getGeneratorOptions());
this.c = new WorldChunkManagerHell(BiomeBase.getBiome(var2.a(), BiomeBase.ad), 0.5F);
} else if (var1 == WorldType.DEBUG_ALL_BLOCK_STATES) {
this.c = new WorldChunkManagerHell(BiomeBase.PLAINS, 0.0F);
} else {
this.c = new WorldChunkManager(this.b);
}
}
public IChunkProvider getChunkProvider() {
if (this.type == WorldType.FLAT) {
return new ChunkProviderFlat(this.b, this.b.getSeed(), this.b.getWorldData().shouldGenerateMapFeatures(), this.i);
} else if (this.type == WorldType.DEBUG_ALL_BLOCK_STATES) {
return new ChunkProviderDebug(this.b);
} else {
return this.type == WorldType.CUSTOMIZED ? new ChunkProviderGenerate(this.b, this.b.getSeed(), this.b.getWorldData().shouldGenerateMapFeatures(), this.i) : new ChunkProviderGenerate(this.b, this.b.getSeed(), this.b.getWorldData().shouldGenerateMapFeatures(), this.i);
}
}
public boolean canSpawn(int var1, int var2) {
return this.b.c(new BlockPosition(var1, 0, var2)) == Blocks.GRASS;
}
public float a(long var1, float var3) {
int var4 = (int)(var1 % 24000L);
float var5 = ((float)var4 + var3) / 24000.0F - 0.25F;
if (var5 < 0.0F) {
++var5;
}
if (var5 > 1.0F) {
--var5;
}
float var6 = var5;
var5 = 1.0F - (float)((Math.cos((double)var5 * 3.141592653589793D) + 1.0D) / 2.0D);
var5 = var6 + (var5 - var6) / 3.0F;
return var5;
}
public int a(long var1) {
return (int)(var1 / 24000L % 8L + 8L) % 8;
}
public boolean d() {
return true;
}
public boolean e() {
return true;
}
public static WorldProvider byDimension(int var0) {
if (var0 == -1) {
return new WorldProviderHell();
} else if (var0 == 0) {
return new WorldProviderNormal();
} else {
return var0 == 1 ? new WorldProviderTheEnd() : null;
}
}
public BlockPosition h() {
return null;
}
public int getSeaLevel() {
return this.type == WorldType.FLAT ? 4 : this.b.F() + 1;
}
public abstract String getName();
public abstract String getSuffix();
public WorldChunkManager m() {
return this.c;
}
public boolean n() {
return this.d;
}
public boolean o() {
return this.e;
}
public float[] p() {
return this.f;
}
public int getDimension() {
return this.dimension;
}
public WorldBorder getWorldBorder() {
return new WorldBorder();
}
}

View File

@ -17,6 +17,7 @@ import org.apache.logging.log4j.Logger;
import java.util.*; import java.util.*;
import java.util.logging.Level; import java.util.logging.Level;
import org.bukkit.Location;
import org.bukkit.WeatherType; import org.bukkit.WeatherType;
import org.bukkit.block.BlockState; import org.bukkit.block.BlockState;
import org.bukkit.craftbukkit.util.LongHash; import org.bukkit.craftbukkit.util.LongHash;
@ -33,8 +34,7 @@ public class WorldServer extends World implements IAsyncTaskHandler {
private final MinecraftServer server; private final MinecraftServer server;
public EntityTracker tracker; public EntityTracker tracker;
private final PlayerChunkMap manager; private final PlayerChunkMap manager;
// private final Set<NextTickListEntry> L = Sets.newHashSet(); // PAIL: Rename nextTickListHash private final HashTreeSet<NextTickListEntry> M = new HashTreeSet<>(); // CraftBukkit - HashTreeSet // PAIL: Rename nextTickList
private final HashTreeSet<NextTickListEntry> M = new HashTreeSet<NextTickListEntry>(); // CraftBukkit - HashTreeSet // PAIL: Rename nextTickList
private final Map<UUID, Entity> entitiesByUUID = Maps.newHashMap(); private final Map<UUID, Entity> entitiesByUUID = Maps.newHashMap();
public ChunkProviderServer chunkProviderServer; public ChunkProviderServer chunkProviderServer;
public boolean savingDisabled; public boolean savingDisabled;
@ -876,9 +876,11 @@ public class WorldServer extends World implements IAsyncTaskHandler {
private void b(WorldSettings worldsettings) { private void b(WorldSettings worldsettings) {
if (!this.worldProvider.e()) { if (!this.worldProvider.e()) {
this.worldData.setSpawn(BlockPosition.ZERO.up(this.worldProvider.getSeaLevel())); BlockPosition position = BlockPosition.ZERO.up(this.worldProvider.getSeaLevel());
this.worldData.setSpawn(new Location(getWorld(), position.getX(), position.getY(), position.getZ()));
} else if (this.worldData.getType() == WorldType.DEBUG_ALL_BLOCK_STATES) { } else if (this.worldData.getType() == WorldType.DEBUG_ALL_BLOCK_STATES) {
this.worldData.setSpawn(BlockPosition.ZERO.up()); BlockPosition position = BlockPosition.ZERO.up();
this.worldData.setSpawn(new Location(getWorld(), position.getX(), position.getY(), position.getZ()));
} else { } else {
this.isLoading = true; this.isLoading = true;
WorldChunkManager worldchunkmanager = this.worldProvider.m(); WorldChunkManager worldchunkmanager = this.worldProvider.m();
@ -898,7 +900,7 @@ public class WorldServer extends World implements IAsyncTaskHandler {
if (spawn.getWorld() != ((WorldServer) this).getWorld()) { if (spawn.getWorld() != ((WorldServer) this).getWorld()) {
throw new IllegalStateException("Cannot set spawn point for " + this.worldData.getName() + " to be in another world (" + spawn.getWorld().getName() + ")"); throw new IllegalStateException("Cannot set spawn point for " + this.worldData.getName() + " to be in another world (" + spawn.getWorld().getName() + ")");
} else { } else {
this.worldData.setSpawn(new BlockPosition(spawn.getBlockX(), spawn.getBlockY(), spawn.getBlockZ())); this.worldData.setSpawn(spawn);
this.isLoading = false; this.isLoading = false;
return; return;
} }
@ -924,7 +926,7 @@ public class WorldServer extends World implements IAsyncTaskHandler {
} }
} }
this.worldData.setSpawn(new BlockPosition(i, j, k)); this.worldData.setSpawn(new Location(getWorld(), i, j, k));
this.isLoading = false; this.isLoading = false;
if (worldsettings.c()) { if (worldsettings.c()) {
this.l(); this.l();
@ -937,8 +939,8 @@ public class WorldServer extends World implements IAsyncTaskHandler {
WorldGenBonusChest worldgenbonuschest = new WorldGenBonusChest(WorldServer.U, 10); WorldGenBonusChest worldgenbonuschest = new WorldGenBonusChest(WorldServer.U, 10);
for (int i = 0; i < 10; ++i) { for (int i = 0; i < 10; ++i) {
int j = this.worldData.c() + this.random.nextInt(6) - this.random.nextInt(6); int j = (int) this.worldData.c() + this.random.nextInt(6) - this.random.nextInt(6);
int k = this.worldData.e() + this.random.nextInt(6) - this.random.nextInt(6); int k = (int) this.worldData.e() + this.random.nextInt(6) - this.random.nextInt(6);
BlockPosition blockposition = this.r(new BlockPosition(j, 0, k)).up(); BlockPosition blockposition = this.r(new BlockPosition(j, 0, k)).up();
if (worldgenbonuschest.generate(this, this.random, blockposition)) { if (worldgenbonuschest.generate(this, this.random, blockposition)) {

View File

@ -1,7 +1,9 @@
package org.bukkit.craftbukkit; package org.bukkit.craftbukkit;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Map;
import net.minecraft.server.*; import net.minecraft.server.*;
@ -10,8 +12,10 @@ import org.bukkit.World;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.block.BlockState; import org.bukkit.block.BlockState;
import org.bukkit.craftbukkit.block.CraftBlock; import org.bukkit.craftbukkit.block.CraftBlock;
import org.bukkit.craftbukkit.entity.CraftHumanEntity;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
import org.bukkit.ChunkSnapshot; import org.bukkit.ChunkSnapshot;
import org.bukkit.entity.HumanEntity;
public class CraftChunk implements Chunk { public class CraftChunk implements Chunk {
private WeakReference<net.minecraft.server.Chunk> weakChunk; private WeakReference<net.minecraft.server.Chunk> weakChunk;
@ -24,7 +28,7 @@ public class CraftChunk implements Chunk {
public CraftChunk(net.minecraft.server.Chunk chunk) { public CraftChunk(net.minecraft.server.Chunk chunk) {
if (!(chunk instanceof EmptyChunk)) { if (!(chunk instanceof EmptyChunk)) {
this.weakChunk = new WeakReference<net.minecraft.server.Chunk>(chunk); this.weakChunk = new WeakReference<>(chunk);
} }
worldServer = (WorldServer) getHandle().world; worldServer = (WorldServer) getHandle().world;
@ -310,4 +314,78 @@ public class CraftChunk implements Chunk {
static { static {
Arrays.fill(emptySkyLight, (byte) 0xFF); Arrays.fill(emptySkyLight, (byte) 0xFF);
} }
@Override
public net.techcable.tacospigot.event.entity.ChunkSnapshot takeSnapshot() {
net.minecraft.server.Chunk handle = getHandle();
com.elevatemc.spigot.chunk.CraftChunkSnapshot snap = new com.elevatemc.spigot.chunk.CraftChunkSnapshot();
// save chunk sections to snapshot
for (int i = 0; i < 16; i++) {
if (handle.getSections()[i] != null) {
snap.getSections()[i] = handle.getSections()[i].createSnapshot();
}
}
// save tile entities to snapshot
for (Map.Entry<BlockPosition, TileEntity> entry : handle.tileEntities.entrySet()) {
NBTTagCompound nbt = new NBTTagCompound();
entry.getValue().b(nbt); // writeToNBT
snap.getTileEntities().add(nbt);
}
return snap;
}
@Override
public void restoreSnapshot(net.techcable.tacospigot.event.entity.ChunkSnapshot snapshot) {
com.elevatemc.spigot.chunk.CraftChunkSnapshot snap = (com.elevatemc.spigot.chunk.CraftChunkSnapshot) snapshot;
net.minecraft.server.Chunk handle = getHandle();
// add chunk sections from snapshot
for (int i = 0; i < 16; i++) {
if (snap.getSections()[i] == null) {
handle.getSections()[i] = null;
} else {
handle.getSections()[i] = new ChunkSection(i << 4, !worldServer.worldProvider.e);
handle.getSections()[i].restoreSnapshot(snap.getSections()[i]);
}
}
// clear tile entities currently in the chunk
for (TileEntity tileEntity : handle.tileEntities.values()) {
if (tileEntity instanceof IInventory) {
for (HumanEntity h : new ArrayList<> (((IInventory) tileEntity).getViewers())) {
if (h instanceof CraftHumanEntity) {
((CraftHumanEntity) h).getHandle().closeInventory();
}
}
}
worldServer.a(tileEntity);
}
handle.tileEntities.clear();
// add tile entities from snapshot
for (NBTTagCompound nbt : snap.getTileEntities()) {
// deserialize nbt to new tile entity instance
TileEntity tileEntity = TileEntity.c(nbt);
// TODO: might have to fix this
// move the tile entity into this chunk's space
tileEntity.position = new BlockPosition(
(tileEntity.position.getX() & 15) | handle.locX << 4,
tileEntity.position.getY(),
(tileEntity.position.getZ() & 15) | handle.locX << 4
);
// add it
handle.a(tileEntity);
}
handle.q = true; // needs saving flag
worldServer.getPlayerChunkMap().resend(x, z);
}
static {
Arrays.fill(emptySkyLight, (byte) 0xFF);
}
} }

View File

@ -106,11 +106,35 @@ public class CraftWorld implements World {
BlockPosition spawn = world.getSpawn(); BlockPosition spawn = world.getSpawn();
return new Location(this, spawn.getX(), spawn.getY(), spawn.getZ()); return new Location(this, spawn.getX(), spawn.getY(), spawn.getZ());
} }
@Override
public boolean setSpawnLocation(Location location) {
Location previousLocation = getSpawnLocation();
world.worldData.setSpawn(location);
// Notify anyone who's listening.
SpawnChangeEvent event = new SpawnChangeEvent(this, previousLocation);
server.getPluginManager().callEvent(event);
return true;
}
public boolean setSpawnLocation(int x, int y, int z) { public boolean setSpawnLocation(int x, int y, int z) {
try { try {
Location previousLocation = getSpawnLocation(); Location previousLocation = getSpawnLocation();
world.worldData.setSpawn(new BlockPosition(x, y, z)); world.worldData.setSpawn(new Location(this, x, y, z));
// Notify anyone who's listening.
SpawnChangeEvent event = new SpawnChangeEvent(this, previousLocation);
server.getPluginManager().callEvent(event);
return true;
} catch (Exception e) {
return false;
}
}
public boolean setSpawnLocation(double x, double y, double z, float yaw, float pitch) {
try {
Location previousLocation = getSpawnLocation();
world.worldData.setSpawn(new Location(this, x, y, z, yaw, pitch));
// Notify anyone who's listening. // Notify anyone who's listening.
SpawnChangeEvent event = new SpawnChangeEvent(this, previousLocation); SpawnChangeEvent event = new SpawnChangeEvent(this, previousLocation);

View File

@ -1,5 +1,6 @@
package org.bukkit.craftbukkit.entity; package org.bukkit.craftbukkit.entity;
import com.elevatemc.spigot.event.PlayerHealthChangeEvent;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.mojang.authlib.GameProfile; import com.mojang.authlib.GameProfile;
@ -1382,7 +1383,15 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
} }
public void setRealHealth(double health) { public void setRealHealth(double health) {
double previous = this.health; // ImHacking;
this.health = health; this.health = health;
// ImHacking Start - Player Health Change Event
if (previous != health) {
Bukkit.getPluginManager().callEvent(new PlayerHealthChangeEvent(this, previous, getHealth()));
}
// ImHacking End
} }
public void updateScaledHealth() { public void updateScaledHealth() {