Paper/src/main/java/net/minecraft/server/WorldServer.java
Andrew Ardill 12e377501e Implements interface for changing the view distance.
Uses default view distance if player's view distance is not set

Throws an illegal argument exception if view distance is set too high
or too low.

Pushes notifications of server and world view distance changes to the player.
Move view distance functions from PlayerManger to WorldServer.
Set player minimum view distance to 1 for now.
Reset player's 'last known' position when recalculating visible chunks.

Use per-player view distance in chunk distance checks
2011-08-15 14:57:25 +10:00

238 lines
8.5 KiB
Java

package net.minecraft.server;
import java.util.ArrayList;
import java.util.List;
// CraftBukkit start
import org.bukkit.BlockChangeDelegate;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.craftbukkit.generator.CustomChunkGenerator;
import org.bukkit.craftbukkit.generator.InternalChunkGenerator;
import org.bukkit.craftbukkit.generator.NetherChunkGenerator;
import org.bukkit.craftbukkit.generator.NormalChunkGenerator;
import org.bukkit.craftbukkit.generator.SkyLandsChunkGenerator;
import org.bukkit.event.weather.LightningStrikeEvent;
public class WorldServer extends World implements BlockChangeDelegate {
// CraftBukkit end
public ChunkProviderServer chunkProviderServer;
public boolean weirdIsOpCache = false;
public boolean canSave;
public final MinecraftServer server; // CraftBukkit - private -> public final
private EntityList G = new EntityList();
// CraftBukkit start - extra variables
private int viewDistance; // keep track of changes to view distance
private boolean viewDistanceSet; // ...and if any changes have been made
// CraftBukkit end
// CraftBukkit start - change signature
public WorldServer(MinecraftServer minecraftserver, IDataManager idatamanager, String s, int i, long j, org.bukkit.World.Environment env, ChunkGenerator gen) {
super(idatamanager, s, j, WorldProvider.byDimension(env.getId()), gen, env);
this.server = minecraftserver;
this.dimension = i;
this.pvpMode = minecraftserver.pvpMode;
// use view distance from configuration manager, instead of property manager
// TODO allow saving view distance per world
this.manager = new PlayerManager(minecraftserver, this.dimension, minecraftserver.serverConfigurationManager.getViewDistance());
}
public final int dimension;
public EntityTracker tracker;
public PlayerManager manager;
// CraftBukkit end
public void entityJoinedWorld(Entity entity, boolean flag) {
/* CraftBukkit start - We prevent spawning in general, so this butchering is not needed
if (!this.server.spawnAnimals && (entity instanceof EntityAnimal || entity instanceof EntityWaterAnimal)) {
entity.die();
}
// CraftBukkit end */
if (entity.passenger == null || !(entity.passenger instanceof EntityHuman)) {
super.entityJoinedWorld(entity, flag);
}
}
public void vehicleEnteredWorld(Entity entity, boolean flag) {
super.entityJoinedWorld(entity, flag);
}
protected IChunkProvider b() {
IChunkLoader ichunkloader = this.w.a(this.worldProvider);
// CraftBukkit start
InternalChunkGenerator gen;
if (this.generator != null) {
gen = new CustomChunkGenerator(this, this.getSeed(), this.generator);
} else if (this.worldProvider instanceof WorldProviderHell) {
gen = new NetherChunkGenerator(this, this.getSeed());
} else if (this.worldProvider instanceof WorldProviderSky) {
gen = new SkyLandsChunkGenerator(this, this.getSeed());
} else {
gen = new NormalChunkGenerator(this, this.getSeed());
}
this.chunkProviderServer = new ChunkProviderServer(this, ichunkloader, gen);
// CraftBukkit end
return this.chunkProviderServer;
}
public List getTileEntities(int i, int j, int k, int l, int i1, int j1) {
ArrayList arraylist = new ArrayList();
for (int k1 = 0; k1 < this.c.size(); ++k1) {
TileEntity tileentity = (TileEntity) this.c.get(k1);
if (tileentity.x >= i && tileentity.y >= j && tileentity.z >= k && tileentity.x < l && tileentity.y < i1 && tileentity.z < j1) {
arraylist.add(tileentity);
}
}
return arraylist;
}
public boolean a(EntityHuman entityhuman, int i, int j, int k) {
int l = (int) MathHelper.abs((float) (i - this.worldData.c()));
int i1 = (int) MathHelper.abs((float) (k - this.worldData.e()));
if (l > i1) {
i1 = l;
}
// CraftBukkit - Configurable spawn protection
return i1 > this.getServer().getSpawnRadius() || this.server.serverConfigurationManager.isOp(entityhuman.name);
}
protected void c(Entity entity) {
super.c(entity);
this.G.a(entity.id, entity);
}
protected void d(Entity entity) {
super.d(entity);
this.G.d(entity.id);
}
public Entity getEntity(int i) {
return (Entity) this.G.a(i);
}
public boolean strikeLightning(Entity entity) {
// CraftBukkit start
LightningStrikeEvent lightning = new LightningStrikeEvent(this.getWorld(), (org.bukkit.entity.LightningStrike) entity.getBukkitEntity());
this.getServer().getPluginManager().callEvent(lightning);
if (lightning.isCancelled()) {
return false;
}
if (super.strikeLightning(entity)) {
this.server.serverConfigurationManager.sendPacketNearby(entity.locX, entity.locY, entity.locZ, 512.0D, this.dimension, new Packet71Weather(entity));
// CraftBukkit end
return true;
} else {
return false;
}
}
public void a(Entity entity, byte b0) {
Packet38EntityStatus packet38entitystatus = new Packet38EntityStatus(entity.id, b0);
// CraftBukkit
this.server.getTracker(this.dimension).sendPacketToEntity(entity, packet38entitystatus);
}
public Explosion createExplosion(Entity entity, double d0, double d1, double d2, float f, boolean flag) {
// CraftBukkit start
Explosion explosion = super.createExplosion(entity, d0, d1, d2, f, flag);
if (explosion.wasCanceled) {
return explosion;
}
/* Remove
explosion.a = flag;
explosion.a();
explosion.a(false);
*/
this.server.serverConfigurationManager.sendPacketNearby(d0, d1, d2, 64.0D, this.dimension, new Packet60Explosion(d0, d1, d2, f, explosion.blocks));
// CraftBukkit end
return explosion;
}
public void playNote(int i, int j, int k, int l, int i1) {
super.playNote(i, j, k, l, i1);
// CraftBukkit
this.server.serverConfigurationManager.sendPacketNearby((double) i, (double) j, (double) k, 64.0D, this.dimension, new Packet54PlayNoteBlock(i, j, k, l, i1));
}
public void saveLevel() {
this.w.e();
}
protected void i() {
boolean flag = this.v();
super.i();
if (flag != this.v()) {
// CraftBukkit start - only sending weather packets to those affected
for (int i = 0; i < this.players.size(); ++i) {
if (((EntityPlayer) this.players.get(i)).world == this) {
((EntityPlayer) this.players.get(i)).netServerHandler.sendPacket(new Packet70Bed(flag ? 2 : 1));
}
}
// CraftBukkit end
}
}
// CraftBukkit start - add getter and setter for view distance
public int getViewDistance() {
if (viewDistanceSet) {
return viewDistance;
} else {
return getServer().getViewDistance();
}
}
/**
* This method enforces notchian view distances. Do not set it below 3 or above 15.
* It is possible to set view distance per-player to any positive value.
* @param viewDistance the number of chunks players herein managed can see by default.
* @throws IllegalArgumentException If view distance is less than 3 or greater than 15
*/
public void setViewDistance(int viewDistance) throws IllegalArgumentException{
if (viewDistance > 15) {
throw new IllegalArgumentException("Too big view radius!");
} else if (viewDistance < 3) {
throw new IllegalArgumentException("Too small view radius!");
} else {
this.viewDistance = viewDistance;
this.viewDistanceSet = true;
updateViewDistance();
}
}
public void resetViewDistance() {
viewDistanceSet = false;
updateViewDistance();
}
public boolean isViewDistanceSet() {
return viewDistanceSet;
}
public void updateViewDistance() {
// notify players that they may have to update their view distance
for (Object entityPlayerObject : this.manager.managedPlayers) {
if (entityPlayerObject instanceof EntityPlayer) {
((EntityPlayer) entityPlayerObject).updateViewDistance();
}
}
}
// CraftBukkit end
}