parent
541b9cc461
commit
d8e54d4d69
27 changed files with 1621 additions and 1159 deletions
|
@ -6,11 +6,9 @@ import java.io.File;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.InetAddress;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -76,6 +74,7 @@ import common.util.WorldPos;
|
|||
import common.world.Region;
|
||||
import common.world.World;
|
||||
import common.world.WorldServer;
|
||||
import common.world.Region.FolderInfo;
|
||||
import io.netty.bootstrap.ServerBootstrap;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelException;
|
||||
|
@ -91,10 +90,8 @@ import io.netty.util.concurrent.Future;
|
|||
import io.netty.util.concurrent.GenericFutureListener;
|
||||
import server.command.CommandEnvironment;
|
||||
import server.command.FixedExecutor;
|
||||
import server.init.NodeRegistry;
|
||||
import server.network.HandshakeHandler;
|
||||
import server.network.Player;
|
||||
import server.world.Converter;
|
||||
|
||||
public final class Server implements IThreadListener, IServer {
|
||||
private static final LazyLoadBase<NioEventLoopGroup> SERVER_NIO_EVENTLOOP = new LazyLoadBase<NioEventLoopGroup>() {
|
||||
|
@ -144,7 +141,6 @@ public final class Server implements IThreadListener, IServer {
|
|||
public static void main(String[] args) {
|
||||
Util.checkOs();
|
||||
Registry.setup("Server thread");
|
||||
NodeRegistry.register();
|
||||
boolean debug = System.getProperty("server.debug", null) != null;
|
||||
boolean ipc = debug || System.getProperty("server.pipe", null) != null;
|
||||
int port = Integer.parseInt(System.getProperty("server.port", "" + Config.PORT));
|
||||
|
@ -159,63 +155,6 @@ public final class Server implements IThreadListener, IServer {
|
|||
Log.flushLog();
|
||||
}
|
||||
|
||||
public static void saveServerConfig(long time) {
|
||||
NBTTagCompound data = new NBTTagCompound();
|
||||
data.setLong("Time", time);
|
||||
data.setLong("LastAccess", System.currentTimeMillis());
|
||||
data.setString("Version", Config.VERSION);
|
||||
NBTTagCompound cfg = new NBTTagCompound();
|
||||
for(String cvar : Config.VARS.keySet()) {
|
||||
cfg.setString(cvar, Config.VARS.get(cvar).getValue());
|
||||
}
|
||||
data.setTag("Config", cfg);
|
||||
data.setTag("Universe", UniverseRegistry.saveNbt());
|
||||
File nfile = new File("server.nbt.tmp");
|
||||
File lfile = new File("server.nbt");
|
||||
try {
|
||||
NBTLoader.writeGZip(data, nfile);
|
||||
if(lfile.exists())
|
||||
lfile.delete();
|
||||
nfile.renameTo(lfile);
|
||||
}
|
||||
catch(Exception e) {
|
||||
Log.IO.error(e, "Fehler beim Schreiben von " + nfile);
|
||||
}
|
||||
}
|
||||
|
||||
public static long loadServerConfig() {
|
||||
Config.clear();
|
||||
UniverseRegistry.clear();
|
||||
File file = new File("server.nbt");
|
||||
if(!file.exists())
|
||||
file = new File("server.nbt.tmp");
|
||||
if(file.exists()) {
|
||||
try {
|
||||
NBTTagCompound tag = NBTLoader.readGZip(file);
|
||||
NBTTagCompound cfg = tag.getCompoundTag("Config");
|
||||
for(String key : cfg.getKeySet()) {
|
||||
Config.set(key, cfg.getString(key), null);
|
||||
}
|
||||
UniverseRegistry.loadNbt(tag.getCompoundTag("Universe"));
|
||||
long lastPlayed = tag.getLong("LastAccess");
|
||||
String version = tag.hasKey("Version", 8) ? tag.getString("Version") : null;
|
||||
version = version != null && version.isEmpty() ? "<unbekannt>" : version;
|
||||
long time = tag.hasKey("Time", 4) ? tag.getLong("Time") : World.START_TIME;
|
||||
Log.IO.info("Version: %s", version);
|
||||
Log.IO.info("Weltzeit: %d Ticks / %d Sekunden", time, time / 20L);
|
||||
Log.IO.info("Zuletzt geladen: %s", new SimpleDateFormat("dd.MM.yyyy HH:mm:ss").format(new Date(lastPlayed)));
|
||||
return time;
|
||||
}
|
||||
catch(Exception e) {
|
||||
Log.IO.error(e, "Fehler beim Lesen von " + file);
|
||||
Config.clear();
|
||||
UniverseRegistry.clear();
|
||||
}
|
||||
}
|
||||
Log.IO.info("Erstelle neue Welt und Konfiguration");
|
||||
return World.START_TIME;
|
||||
}
|
||||
|
||||
private Server(boolean debug, boolean ipc) {
|
||||
this.debug = debug;
|
||||
this.ipcpipe = ipc;
|
||||
|
@ -243,7 +182,7 @@ public final class Server implements IThreadListener, IServer {
|
|||
|
||||
public void saveWorldInfo() {
|
||||
if(!this.debug) {
|
||||
saveServerConfig(this.space.getDayTime());
|
||||
Region.saveWorldInfo(null, this.space.getDayTime());
|
||||
WorldServer.saveWarps(this.warps);
|
||||
}
|
||||
}
|
||||
|
@ -318,14 +257,13 @@ public final class Server implements IThreadListener, IServer {
|
|||
long time = System.currentTimeMillis();
|
||||
Log.JNI.info("Starte Server Version " + Config.VERSION);
|
||||
if(!this.debug) {
|
||||
Converter.convert();
|
||||
this.setMessage("Welt wird erstellt und geladen");
|
||||
long wtime = loadServerConfig();
|
||||
FolderInfo info = Region.loadWorldInfo(null);
|
||||
// if(dtime == -1L) // {
|
||||
// dtime = World.START_TIME;
|
||||
//// Config.set("spawnDim", "1", null);
|
||||
//// }
|
||||
this.worlds.add(this.space = new WorldServer(this, wtime,
|
||||
this.worlds.add(this.space = new WorldServer(this, info == null ? World.START_TIME : info.time,
|
||||
Space.INSTANCE, false));
|
||||
this.dimensions.put(this.space.dimension.getDimensionId(), this.space);
|
||||
new File("players").mkdirs();
|
||||
|
|
|
@ -1,537 +0,0 @@
|
|||
package server.ai;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import common.ai.EntityAIBase;
|
||||
import common.ai.EntityAIMoveTowardsRestriction;
|
||||
import common.ai.EntityAITasks;
|
||||
import common.ai.EntityJumpHelper;
|
||||
import common.ai.EntityLookHelper;
|
||||
import common.ai.EntityMoveHelper;
|
||||
import common.ai.EntitySenses;
|
||||
import common.ai.IEntityLivingNode;
|
||||
import common.block.Block;
|
||||
import common.collect.Lists;
|
||||
import common.color.TextColor;
|
||||
import common.entity.DamageSource;
|
||||
import common.entity.Entity;
|
||||
import common.entity.EntityDamageSource;
|
||||
import common.entity.item.EntityLeashKnot;
|
||||
import common.entity.item.EntityXp;
|
||||
import common.entity.npc.EntityNPC;
|
||||
import common.entity.types.CombatEntry;
|
||||
import common.entity.types.EntityBodyHelper;
|
||||
import common.entity.types.EntityLiving;
|
||||
import common.entity.types.EntityTameable;
|
||||
import common.init.Blocks;
|
||||
import common.init.Config;
|
||||
import common.item.ItemStack;
|
||||
import common.nbt.NBTTagCompound;
|
||||
import common.network.IPlayer;
|
||||
import common.pathfinding.PathNavigate;
|
||||
import common.pathfinding.PathNavigateGround;
|
||||
import common.rng.Random;
|
||||
import common.util.BlockPos;
|
||||
import common.world.WorldServer;
|
||||
|
||||
public abstract class EntityLivingNode<T extends EntityLiving> extends EntityNode<T> implements IEntityLivingNode {
|
||||
protected final Random rand;
|
||||
private final List<CombatEntry> combat = Lists.<CombatEntry>newArrayList();
|
||||
private EntityLookHelper lookHelper;
|
||||
protected EntityMoveHelper moveHelper;
|
||||
protected EntityJumpHelper jumpHelper;
|
||||
private EntityBodyHelper bodyHelper;
|
||||
protected PathNavigate navigator;
|
||||
protected final EntityAITasks tasks;
|
||||
protected final EntityAITasks targets;
|
||||
private EntityLiving target;
|
||||
private EntitySenses senses;
|
||||
private NBTTagCompound leashTag;
|
||||
private boolean isMovementAITaskSet;
|
||||
private EntityAIBase aiBase;
|
||||
private boolean attacked;
|
||||
private boolean damaged;
|
||||
private String blockType;
|
||||
private int lastDamaged;
|
||||
protected EntityNPC playerAttacker;
|
||||
private EntityLiving attackedBy;
|
||||
protected int lastDamage;
|
||||
protected int recentlyHit;
|
||||
private int lastAttacked;
|
||||
private EntityLiving attacker;
|
||||
private int lastAttackTime;
|
||||
|
||||
public EntityLivingNode(T entity) {
|
||||
super(entity);
|
||||
this.rand = entity.getRNG();
|
||||
this.tasks = new EntityAITasks();
|
||||
this.targets = new EntityAITasks();
|
||||
this.lookHelper = new EntityLookHelper(entity);
|
||||
this.moveHelper = new EntityMoveHelper(entity);
|
||||
this.jumpHelper = new EntityJumpHelper(entity);
|
||||
this.bodyHelper = new EntityBodyHelper(entity);
|
||||
this.navigator = this.getNewNavigator();
|
||||
this.senses = new EntitySenses(entity);
|
||||
this.aiBase = new EntityAIMoveTowardsRestriction(entity, 1.0D);
|
||||
this.registerTasks();
|
||||
}
|
||||
|
||||
public T getEntity() {
|
||||
return this.entity;
|
||||
}
|
||||
|
||||
public EntityLiving getAttackingEntity() {
|
||||
EntityLiving attacking = this.getAttacking();
|
||||
return attacking != null ? attacking : (this.playerAttacker != null ? this.playerAttacker : (this.attackedBy != null ? this.attackedBy : null));
|
||||
}
|
||||
|
||||
protected PathNavigate getNewNavigator() {
|
||||
return new PathNavigateGround(this.entity, this.entity.worldObj);
|
||||
}
|
||||
|
||||
// protected PathNavigate getNewNavigator() { EntityArachnoid
|
||||
// return new PathNavigateClimber(this.entity, this.entity.worldObj);
|
||||
// }
|
||||
|
||||
protected abstract void registerTasks();
|
||||
|
||||
public EntityLookHelper getLookHelper() {
|
||||
return this.lookHelper;
|
||||
}
|
||||
|
||||
public EntityMoveHelper getMoveHelper() {
|
||||
return this.moveHelper;
|
||||
}
|
||||
|
||||
public EntityJumpHelper getJumpHelper() {
|
||||
return this.jumpHelper;
|
||||
}
|
||||
|
||||
public PathNavigate getNavigator() {
|
||||
return this.navigator;
|
||||
}
|
||||
|
||||
public EntitySenses getEntitySenses() {
|
||||
return this.senses;
|
||||
}
|
||||
|
||||
public EntityLiving getAttackTarget() {
|
||||
return this.target;
|
||||
}
|
||||
|
||||
public void setAttackTarget(EntityLiving entitylivingbaseIn) {
|
||||
this.target = entitylivingbaseIn;
|
||||
}
|
||||
|
||||
public boolean hasPath()
|
||||
{
|
||||
return !this.navigator.noPath();
|
||||
}
|
||||
|
||||
public void updateRenderAngles() {
|
||||
this.bodyHelper.updateRenderAngles();
|
||||
}
|
||||
|
||||
protected void updateAITasks() {
|
||||
}
|
||||
|
||||
public void update() {
|
||||
this.senses.clearSensingCache();
|
||||
this.targets.onUpdateTasks();
|
||||
this.tasks.onUpdateTasks();
|
||||
this.navigator.onUpdateNavigation();
|
||||
this.updateAITasks();
|
||||
this.moveHelper.onUpdateMoveHelper();
|
||||
this.lookHelper.onUpdateLook();
|
||||
this.jumpHelper.doJump();
|
||||
}
|
||||
|
||||
public void setLeashTag(NBTTagCompound tag) {
|
||||
this.leashTag = tag;
|
||||
}
|
||||
|
||||
private void recreateLeash() {
|
||||
if(this.entity.getLeashed() && this.leashTag != null) {
|
||||
// if(this.leashTag.hasKey("PlayerName", 8)) {
|
||||
// String id = this.leashTag.getString("PlayerName");
|
||||
// if(!id.isEmpty()) {
|
||||
// for(EntityNPC entitylivingbase : this.worldObj.getEntitiesWithinAABB(EntityNPC.class,
|
||||
// this.getEntityBoundingBox().expand(10.0D, 10.0D, 10.0D))) {
|
||||
// if(entitylivingbase.getUser().equals(id)) {
|
||||
// this.leashedTo = entitylivingbase;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
if(this.leashTag.hasKey("X", 99) && this.leashTag.hasKey("Y", 99) && this.leashTag.hasKey("Z", 99)) {
|
||||
BlockPos blockpos = new BlockPos(this.leashTag.getInteger("X"), this.leashTag.getInteger("Y"),
|
||||
this.leashTag.getInteger("Z"));
|
||||
EntityLeashKnot entityleashknot = EntityLeashKnot.getKnotForPosition(this.entity.worldObj, blockpos);
|
||||
|
||||
if(entityleashknot == null) {
|
||||
entityleashknot = EntityLeashKnot.createKnot(this.entity.worldObj, blockpos);
|
||||
}
|
||||
|
||||
this.entity.setLeashedTo(entityleashknot, false);
|
||||
}
|
||||
else {
|
||||
this.entity.clearLeashed(false, true);
|
||||
}
|
||||
}
|
||||
|
||||
this.leashTag = null;
|
||||
}
|
||||
|
||||
protected void onUpdateLeashed(float distance)
|
||||
{
|
||||
}
|
||||
|
||||
// protected void onUpdateLeashed(float distance) EntityHorse
|
||||
// {
|
||||
// if (distance > 6.0F && this.entity.isEatingHaystack())
|
||||
// {
|
||||
// this.entity.setEatingHaystack(false);
|
||||
// }
|
||||
// }
|
||||
|
||||
public void updateLeashedState() {
|
||||
if(this.leashTag != null) {
|
||||
this.recreateLeash();
|
||||
}
|
||||
|
||||
if(this.entity.getLeashed()) {
|
||||
if(!this.entity.isEntityAlive()) {
|
||||
this.entity.clearLeashed(true, true);
|
||||
}
|
||||
|
||||
if(this.entity.getLeashedTo() == null || this.entity.getLeashedTo().dead) {
|
||||
this.entity.clearLeashed(true, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.entity.getLeashed() && this.entity.getLeashedTo() != null && this.entity.getLeashedTo().worldObj == this.entity.worldObj)
|
||||
{
|
||||
Entity entity = this.entity.getLeashedTo();
|
||||
this.entity.setHomePosAndDistance(new BlockPos((int)entity.posX, (int)entity.posY, (int)entity.posZ), 5);
|
||||
float f = this.entity.getDistanceToEntity(entity);
|
||||
|
||||
if (this.entity instanceof EntityTameable && ((EntityTameable)this.entity).isSitting())
|
||||
{
|
||||
if (f > 10.0F)
|
||||
{
|
||||
this.entity.clearLeashed(true, true);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.isMovementAITaskSet)
|
||||
{
|
||||
this.tasks.addTask(2, this.aiBase);
|
||||
|
||||
if (this.getNavigator() instanceof PathNavigateGround)
|
||||
{
|
||||
((PathNavigateGround)this.getNavigator()).setAvoidsWater(false);
|
||||
}
|
||||
|
||||
this.isMovementAITaskSet = true;
|
||||
}
|
||||
|
||||
this.onUpdateLeashed(f);
|
||||
|
||||
if (f > 4.0F)
|
||||
{
|
||||
this.getNavigator().tryMoveToEntityLiving(entity, 1.0D);
|
||||
}
|
||||
|
||||
if (f > 6.0F)
|
||||
{
|
||||
double d0 = (entity.posX - this.entity.posX) / (double)f;
|
||||
double d1 = (entity.posY - this.entity.posY) / (double)f;
|
||||
double d2 = (entity.posZ - this.entity.posZ) / (double)f;
|
||||
this.entity.motionX += d0 * Math.abs(d0) * 0.4D;
|
||||
this.entity.motionY += d1 * Math.abs(d1) * 0.4D;
|
||||
this.entity.motionZ += d2 * Math.abs(d2) * 0.4D;
|
||||
}
|
||||
|
||||
if (f > 10.0F)
|
||||
{
|
||||
this.entity.clearLeashed(true, true);
|
||||
}
|
||||
}
|
||||
else if (!this.entity.getLeashed() && this.isMovementAITaskSet)
|
||||
{
|
||||
this.isMovementAITaskSet = false;
|
||||
this.tasks.removeTask(this.aiBase);
|
||||
|
||||
if (this.getNavigator() instanceof PathNavigateGround)
|
||||
{
|
||||
((PathNavigateGround)this.getNavigator()).setAvoidsWater(true);
|
||||
}
|
||||
|
||||
this.entity.detachHome();
|
||||
}
|
||||
}
|
||||
|
||||
public void trackDamage(DamageSource source, int amount) {
|
||||
this.resetCombat();
|
||||
this.blockType = null;
|
||||
if(this.entity.isOnLadder()) {
|
||||
Block block = this.entity.worldObj
|
||||
.getState(new BlockPos(this.entity.posX, this.entity.getEntityBoundingBox().minY, this.entity.posZ)).getBlock();
|
||||
if(block == Blocks.ladder)
|
||||
this.blockType = "von einer Leiter";
|
||||
else if(block == Blocks.vine)
|
||||
this.blockType = "von Ranken";
|
||||
}
|
||||
else if(this.entity.isInLiquid()) {
|
||||
this.blockType = "aus dem Wasser";
|
||||
}
|
||||
CombatEntry entry = new CombatEntry(source, amount, this.blockType, this.entity.fallDistance);
|
||||
this.combat.add(entry);
|
||||
this.lastDamaged = this.entity.ticksExisted;
|
||||
this.damaged = true;
|
||||
if(entry.getSource().getEntity() instanceof EntityLiving && !this.attacked && this.entity.isEntityAlive())
|
||||
this.attacked = true;
|
||||
}
|
||||
|
||||
public void sendDeathMessage() {
|
||||
this.sendDeathMessage(false, false);
|
||||
}
|
||||
|
||||
protected void sendDeathMessage(boolean natural, boolean forAll) {
|
||||
// if(this.entity.worldObj.client)
|
||||
// return;
|
||||
String msg;
|
||||
String kill;
|
||||
IPlayer receiver = null;
|
||||
if(this.combat.size() == 0) {
|
||||
msg = kill = natural ? String.format("%s starb", this.entity.getColoredName(TextColor.LGRAY)) : null;
|
||||
}
|
||||
else {
|
||||
CombatEntry strong = null;
|
||||
CombatEntry block = null;
|
||||
int min = 0;
|
||||
float max = 0.0F;
|
||||
|
||||
for(int z = 0; z < this.combat.size(); ++z) {
|
||||
CombatEntry entry = (CombatEntry)this.combat.get(z);
|
||||
CombatEntry last = z > 0 ? (CombatEntry)this.combat.get(z - 1) : null;
|
||||
|
||||
if((entry.getSource() == DamageSource.fall || entry.getSource() == DamageSource.outOfWorld) &&
|
||||
entry.getFallDistance() > 0.0F && (strong == null || entry.getFallDistance() > max)) {
|
||||
if(z > 0) {
|
||||
strong = last;
|
||||
}
|
||||
else {
|
||||
strong = entry;
|
||||
}
|
||||
|
||||
max = entry.getFallDistance();
|
||||
}
|
||||
|
||||
if(entry.getBlockType() != null && (block == null || entry.getDamage() > min)) {
|
||||
block = entry;
|
||||
}
|
||||
}
|
||||
CombatEntry fall = max > 5.0F && strong != null ? strong : (min > 5 && block != null ? block : null);
|
||||
CombatEntry last = (CombatEntry)this.combat.get(this.combat.size() - 1);
|
||||
Entity lastEnt = last.getSource().getEntity();
|
||||
|
||||
if(fall != null && last.getSource() == DamageSource.fall) {
|
||||
if(fall.getSource() != DamageSource.fall && fall.getSource() != DamageSource.outOfWorld) {
|
||||
Entity fallEnt = fall.getSource().getEntity();
|
||||
if(fallEnt != null && (lastEnt == null || fallEnt != lastEnt)) {
|
||||
ItemStack fallItem = fallEnt instanceof EntityLiving ? ((EntityLiving)fallEnt).getHeldItem() : null;
|
||||
receiver = fallEnt.isPlayer() ? ((EntityNPC)fallEnt).connection : null;
|
||||
if(fallItem != null) { // && fallItem.hasDisplayName()) {
|
||||
msg = String.format("%s wurde von %s mit %s zum Fallen verdammt", this.entity.getColoredName(TextColor.CYAN),
|
||||
fallEnt.getColoredName(TextColor.CYAN), fallItem.getColoredName(TextColor.CYAN));
|
||||
kill = String.format(TextColor.CYAN + "* %s mit %s zum Fallen verdammt",
|
||||
this.entity.getColoredName(TextColor.CYAN), fallItem.getColoredName(TextColor.CYAN));
|
||||
}
|
||||
else {
|
||||
msg = String.format("%s wurde von %s zum Fallen verdammt", this.entity.getColoredName(TextColor.CYAN),
|
||||
fallEnt.getColoredName(TextColor.CYAN));
|
||||
kill = String.format(TextColor.CYAN + "* %s zum Fallen verdammt",
|
||||
this.entity.getColoredName(TextColor.CYAN));
|
||||
}
|
||||
}
|
||||
else if(lastEnt != null) {
|
||||
ItemStack lastItem = lastEnt instanceof EntityLiving ? ((EntityLiving)lastEnt).getHeldItem() : null;
|
||||
receiver = lastEnt.isPlayer() ? ((EntityNPC)lastEnt).connection : null;
|
||||
if(lastItem != null) { // && lastItem.hasDisplayName()) {
|
||||
msg = String.format("%s fiel zu tief und wurde von %s mit %s erledigt",
|
||||
this.entity.getColoredName(TextColor.BLUE),
|
||||
lastEnt.getColoredName(TextColor.BLUE), lastItem.getColoredName(TextColor.BLUE));
|
||||
kill = String.format(TextColor.BLUE + "* %s mit %s erledigt",
|
||||
this.entity.getColoredName(TextColor.BLUE), lastItem.getColoredName(TextColor.BLUE));
|
||||
}
|
||||
else {
|
||||
msg = String.format("%s fiel zu tief und wurde von %s erledigt", this.entity.getColoredName(TextColor.BLUE),
|
||||
lastEnt.getColoredName(TextColor.BLUE));
|
||||
kill = String.format(TextColor.BLUE + "%s erledigt", this.entity.getColoredName(TextColor.BLUE));
|
||||
}
|
||||
}
|
||||
else {
|
||||
msg = kill = natural ? String.format("%s wurde zum Fallen verdammt", this.entity.getColoredName(TextColor.CYAN)) : null;
|
||||
}
|
||||
}
|
||||
else {
|
||||
msg = kill = natural ? String.format("%s fiel " + (fall.getBlockType() == null ? "aus zu großer Höhe" : fall.getBlockType()),
|
||||
this.entity.getColoredName(TextColor.NEON)) : null;
|
||||
}
|
||||
}
|
||||
else {
|
||||
receiver = last.getSource().getEntity() != null && last.getSource().getEntity().isPlayer() ? ((EntityNPC)last.getSource().getEntity()).connection : null;
|
||||
msg = natural || (last.getSource() instanceof EntityDamageSource ? last.getSource().getEntity() != null : this.entity.getAttackingEntity() != null) ? last.getSource().getDeathMessage(this.entity) : null;
|
||||
kill = msg == null ? null : last.getSource().getKillMessage(this.entity);
|
||||
}
|
||||
}
|
||||
if(msg == null)
|
||||
return;
|
||||
if(receiver != null)
|
||||
receiver.addFeed(kill);
|
||||
if(forAll)
|
||||
for(IPlayer player : ((WorldServer)this.entity.worldObj).getServer().getIPlayers()) {
|
||||
if(player != receiver)
|
||||
player.addFeed(msg);
|
||||
}
|
||||
}
|
||||
|
||||
public EntityLiving getAttacking() {
|
||||
EntityLiving entity = null;
|
||||
EntityNPC player = null;
|
||||
int edmg = 0;
|
||||
int pdmg = 0;
|
||||
for(CombatEntry entry : this.combat) {
|
||||
if(entry.getSource().getEntity() != null && entry.getSource().getEntity().isPlayer() && (player == null || entry.getDamage() > pdmg)) {
|
||||
pdmg = entry.getDamage();
|
||||
player = (EntityNPC)entry.getSource().getEntity();
|
||||
}
|
||||
if(entry.getSource().getEntity() instanceof EntityLiving && (entity == null || entry.getDamage() > edmg)) {
|
||||
edmg = entry.getDamage();
|
||||
entity = (EntityLiving)entry.getSource().getEntity();
|
||||
}
|
||||
}
|
||||
return player != null && pdmg >= edmg / 3 ? player : entity;
|
||||
}
|
||||
|
||||
public void resetCombat() {
|
||||
int timeout = this.attacked ? 300 : 100;
|
||||
if(this.damaged && (!this.entity.isEntityAlive() || this.entity.ticksExisted - this.lastDamaged > timeout)) {
|
||||
this.damaged = false;
|
||||
this.attacked = false;
|
||||
this.combat.clear();
|
||||
}
|
||||
}
|
||||
|
||||
public int getMaxFallHeight() {
|
||||
if(this.target == null) {
|
||||
return 3;
|
||||
}
|
||||
else {
|
||||
int i = (int)((float)this.entity.getHealth() - (float)this.entity.getMaxHealth() * 0.33F);
|
||||
// i = i - (3 - this.worldObj.getDifficulty().getId()) * 4;
|
||||
|
||||
if(i < 0) {
|
||||
i = 0;
|
||||
}
|
||||
|
||||
return i + 3;
|
||||
}
|
||||
}
|
||||
|
||||
// public int getMaxFallHeight() EntityHaunter
|
||||
// {
|
||||
// return this.getAttackTarget() == null ? 3 : 3 + (this.getHealth() - 1);
|
||||
// }
|
||||
|
||||
public void updateAttacking() {
|
||||
if (this.recentlyHit > 0)
|
||||
{
|
||||
--this.recentlyHit;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.playerAttacker = null;
|
||||
}
|
||||
|
||||
if (this.attacker != null && !this.attacker.isEntityAlive())
|
||||
{
|
||||
this.attacker = null;
|
||||
}
|
||||
|
||||
// if(this.attackedBy.isPlayer() && ((EntityNPC)this.attackedBy).capabilities.isCreativeMode) {
|
||||
// this.attackedBy = null; // FIX Creative
|
||||
// }
|
||||
|
||||
if (this.attackedBy != null)
|
||||
{
|
||||
if (!this.attackedBy.isEntityAlive())
|
||||
{
|
||||
this.setAttackedBy(null);
|
||||
}
|
||||
else if (this.entity.ticksExisted - this.lastAttacked > 100)
|
||||
{
|
||||
this.setAttackedBy(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void dropExperience() {
|
||||
if ((this.recentlyHit > 0 || this.player) && this.entity.canDropLoot() && Config.mobXP)
|
||||
{
|
||||
int i = this.entity.getExperiencePoints(this.playerAttacker);
|
||||
|
||||
while (i > 0)
|
||||
{
|
||||
int j = EntityXp.getXPSplit(i);
|
||||
i -= j;
|
||||
this.world.spawnEntityInWorld(new EntityXp(this.world, this.entity.posX, this.entity.posY, this.entity.posZ, j));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public EntityLiving getAttackedBy()
|
||||
{
|
||||
return this.attackedBy;
|
||||
}
|
||||
|
||||
public int getAttackedTime()
|
||||
{
|
||||
return this.lastAttacked;
|
||||
}
|
||||
|
||||
public void setAttackedBy(EntityLiving livingBase)
|
||||
{
|
||||
this.attackedBy = livingBase;
|
||||
this.lastAttacked = this.entity.ticksExisted;
|
||||
}
|
||||
|
||||
public EntityLiving getLastAttack()
|
||||
{
|
||||
return this.attacker;
|
||||
}
|
||||
|
||||
public int getLastAttackTime()
|
||||
{
|
||||
return this.lastAttackTime;
|
||||
}
|
||||
|
||||
public void setLastAttack(Entity entity)
|
||||
{
|
||||
if (entity instanceof EntityLiving)
|
||||
{
|
||||
this.attacker = (EntityLiving)entity;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.attacker = null;
|
||||
}
|
||||
|
||||
this.lastAttackTime = this.entity.ticksExisted;
|
||||
}
|
||||
}
|
|
@ -1,84 +0,0 @@
|
|||
package server.ai;
|
||||
|
||||
import common.ai.IEntityMobNPCNode;
|
||||
import common.entity.Entity;
|
||||
import common.entity.attributes.AttributeInstance;
|
||||
import common.entity.attributes.Attributes;
|
||||
import common.entity.npc.AIHurtByAggressor;
|
||||
import common.entity.npc.EntityMobNPC;
|
||||
import common.entity.npc.EntityNPC;
|
||||
import common.entity.types.EntityLiving;
|
||||
import common.nbt.NBTTagCompound;
|
||||
|
||||
public class EntityMobNPCNode<T extends EntityMobNPC> extends EntityNPCNode<T> implements IEntityMobNPCNode {
|
||||
private int angerLevel;
|
||||
private int angerTarget;
|
||||
|
||||
public EntityMobNPCNode(T entity) {
|
||||
super(entity);
|
||||
}
|
||||
|
||||
protected void registerTasks() {
|
||||
super.registerTasks();
|
||||
this.targets.addTask(1, new AIHurtByAggressor(this.entity));
|
||||
}
|
||||
|
||||
protected void updateAITasks()
|
||||
{
|
||||
AttributeInstance iattributeinstance = this.entity.getEntityAttribute(Attributes.MOVEMENT_SPEED);
|
||||
|
||||
if (this.isAngry())
|
||||
{
|
||||
if (!iattributeinstance.hasModifier(Attributes.RUSHING_SPEED_MOD))
|
||||
{
|
||||
iattributeinstance.applyModifier(Attributes.RUSHING_SPEED_MOD);
|
||||
}
|
||||
|
||||
--this.angerLevel;
|
||||
}
|
||||
else if (iattributeinstance.hasModifier(Attributes.RUSHING_SPEED_MOD))
|
||||
{
|
||||
iattributeinstance.removeModifier(Attributes.RUSHING_SPEED_MOD);
|
||||
}
|
||||
|
||||
if (this.angerLevel > 0 && this.angerTarget != 0 && this.entity.getAttackedBy() == null)
|
||||
{
|
||||
Entity entity = this.world.getEntityByID(this.angerTarget);
|
||||
if(entity instanceof EntityLiving)
|
||||
this.entity.setAttackedBy((EntityLiving)entity);
|
||||
if(entity != null && entity.isPlayer())
|
||||
this.entity.playerAttacker = (EntityNPC)entity;
|
||||
this.entity.recentlyHit = this.entity.getAttackedTime();
|
||||
}
|
||||
|
||||
super.updateAITasks();
|
||||
}
|
||||
|
||||
public void writeNbt(NBTTagCompound tagCompound)
|
||||
{
|
||||
super.writeNbt(tagCompound);
|
||||
tagCompound.setShort("Anger", (short)this.angerLevel);
|
||||
}
|
||||
|
||||
public void readNbt(NBTTagCompound tagCompund)
|
||||
{
|
||||
super.readNbt(tagCompund);
|
||||
this.angerLevel = tagCompund.getShort("Anger");
|
||||
}
|
||||
|
||||
public void becomeAngryAt(Entity entity)
|
||||
{
|
||||
this.angerLevel = this.rand.excl(400, 800);
|
||||
if(entity instanceof EntityLiving)
|
||||
this.entity.setAttackedBy((EntityLiving)entity);
|
||||
}
|
||||
|
||||
public boolean isAngry()
|
||||
{
|
||||
return this.angerLevel > 0;
|
||||
}
|
||||
|
||||
public void setAngerTarget(EntityLiving entity) {
|
||||
this.angerTarget = entity.getId();
|
||||
}
|
||||
}
|
|
@ -17,21 +17,17 @@ import common.ai.EntityAISwimming;
|
|||
import common.ai.EntityAIWander;
|
||||
import common.ai.EntityAIWatchClosest;
|
||||
import common.ai.EntityAIWatchClosest2;
|
||||
import common.ai.IEntityNPCNode;
|
||||
import common.entity.npc.Alignment;
|
||||
import common.entity.npc.EntityNPC;
|
||||
import common.entity.types.EntityLiving;
|
||||
import common.init.Items;
|
||||
import common.item.ItemGunBase;
|
||||
import common.item.ItemStack;
|
||||
import common.pathfinding.PathNavigateGround;
|
||||
|
||||
public class EntityNPCNode<T extends EntityNPC> extends EntityLivingNode<T> implements IEntityNPCNode {
|
||||
public class EntityNPCNode extends EntityNode {
|
||||
protected final EntityAIAttackOnCollide aiMelee;
|
||||
protected final AIRangedAttack aiRanged;
|
||||
private boolean fleeing;
|
||||
|
||||
public EntityNPCNode(T entity) {
|
||||
public EntityNPCNode(EntityNPC entity) {
|
||||
super(entity);
|
||||
this.aiMelee = new EntityAIAttackOnCollide(entity, EntityLiving.class, 1.0D, true, true) {
|
||||
public boolean shouldExecute()
|
||||
|
@ -69,18 +65,22 @@ public class EntityNPCNode<T extends EntityNPC> extends EntityLivingNode<T> impl
|
|||
};
|
||||
}
|
||||
|
||||
public EntityNPC getEntity() {
|
||||
return (EntityNPC)this.entity;
|
||||
}
|
||||
|
||||
protected void registerTasks() {
|
||||
if(this.getNavigator() instanceof PathNavigateGround) {
|
||||
((PathNavigateGround)this.getNavigator()).setBreakDoors(true);
|
||||
((PathNavigateGround)this.getNavigator()).setAvoidsWater(true);
|
||||
}
|
||||
this.tasks.addTask(0, new EntityAISwimming(this.entity));
|
||||
this.tasks.addTask(0, new EntityAISwimming(this.getEntity()));
|
||||
// this.tasks.addTask(1, new EntityAIAttackOnCollide(this, EntityNPC.class, 0.6D, true, true));
|
||||
// this.tasks.addTask(1, new EntityAIAttackOnCollide(this, EntityLivingBase.class, 0.6D, true, true));
|
||||
this.tasks.addTask(1, new EntityAINpcMate(this.entity));
|
||||
this.tasks.addTask(2, new EntityAIAvoidEntity(this.entity, EntityLiving.class, new Predicate<EntityLiving>() {
|
||||
this.tasks.addTask(1, new EntityAINpcMate(this.getEntity()));
|
||||
this.tasks.addTask(2, new EntityAIAvoidEntity(this.getEntity(), EntityLiving.class, new Predicate<EntityLiving>() {
|
||||
public boolean test(EntityLiving entity) {
|
||||
return entity != EntityNPCNode.this.entity && EntityNPCNode.this.shouldFlee(entity);
|
||||
return entity != EntityNPCNode.this.entity && EntityNPC.this.shouldFlee(entity);
|
||||
}
|
||||
}, 8.0F, 1.1D, 1.1D) {
|
||||
{
|
||||
|
@ -105,27 +105,27 @@ public class EntityNPCNode<T extends EntityNPC> extends EntityLivingNode<T> impl
|
|||
// EntityNPC.this.isFleeing = false;
|
||||
// }
|
||||
});
|
||||
this.tasks.addTask(3, new EntityAIAvoidEntity(this.entity, EntityLiving.class, new Predicate<EntityLiving>() {
|
||||
this.tasks.addTask(3, new EntityAIAvoidEntity(this, EntityLiving.class, new Predicate<EntityLiving>() {
|
||||
public boolean test(EntityLiving entity) {
|
||||
return entity != EntityNPCNode.this.entity && EntityNPCNode.this.shouldFlee(entity);
|
||||
return entity != EntityNPC.this && EntityNPC.this.shouldFlee(entity);
|
||||
}
|
||||
}, 8.0F, 1.1D, 1.1D) {
|
||||
public void startExecuting() {
|
||||
super.startExecuting();
|
||||
EntityNPCNode.this.setAttackTarget(null);
|
||||
EntityNPCNode.this.fleeing = true;
|
||||
EntityNPC.this.setAttackTarget(null);
|
||||
EntityNPC.this.fleeing = true;
|
||||
}
|
||||
|
||||
public void resetTask() {
|
||||
super.resetTask();
|
||||
EntityNPCNode.this.fleeing = false;
|
||||
EntityNPC.this.fleeing = false;
|
||||
}
|
||||
});
|
||||
// this.tasks.addTask(2, new EntityAITempt(this, 1.0D, Items.golden_apple, false));
|
||||
this.tasks.addTask(4, new EntityAIOpenDoor(this.entity, true));
|
||||
this.tasks.addTask(5, new EntityAINagPlayer(this.entity));
|
||||
this.tasks.addTask(5, new EntityAILookAtTalkingPlayer(this.entity));
|
||||
this.tasks.addTask(6, new EntityAIWatchClosest2(this.entity, null, 3.0F, 1.0F) {
|
||||
this.tasks.addTask(4, new EntityAIOpenDoor(this, true));
|
||||
this.tasks.addTask(5, new EntityAINagPlayer(this));
|
||||
this.tasks.addTask(5, new EntityAILookAtTalkingPlayer(this));
|
||||
this.tasks.addTask(6, new EntityAIWatchClosest2(this, null, 3.0F, 1.0F) {
|
||||
private int sneakTime;
|
||||
|
||||
public void updateTask()
|
||||
|
@ -134,15 +134,15 @@ public class EntityNPCNode<T extends EntityNPC> extends EntityLivingNode<T> impl
|
|||
boolean flag = this.closestEntity.isPlayer() && this.closestEntity.isSneaking();
|
||||
if(this.sneakTime > 0) {
|
||||
if(--this.sneakTime == 0) {
|
||||
EntityNPCNode.this.entity.setSneaking(false);
|
||||
EntityNPC.this.setSneaking(false);
|
||||
}
|
||||
}
|
||||
else if(EntityNPCNode.this.getAttackTarget() == null && EntityNPCNode.this.rand.chance(flag ? 5 : 200)) {
|
||||
EntityNPCNode.this.entity.setSneaking(true);
|
||||
this.sneakTime = EntityNPCNode.this.rand.range(60, flag ? 160 : 120);
|
||||
else if(EntityNPC.this.getAttackTarget() == null && EntityNPC.this.rand.chance(flag ? 5 : 200)) {
|
||||
EntityNPC.this.setSneaking(true);
|
||||
this.sneakTime = EntityNPC.this.rand.range(60, flag ? 160 : 120);
|
||||
}
|
||||
else if(EntityNPCNode.this.getAttackTarget() != null) {
|
||||
EntityNPCNode.this.entity.setSneaking(false);
|
||||
else if(EntityNPC.this.getAttackTarget() != null) {
|
||||
EntityNPC.this.setSneaking(false);
|
||||
this.sneakTime = 0;
|
||||
}
|
||||
}
|
||||
|
@ -150,75 +150,41 @@ public class EntityNPCNode<T extends EntityNPC> extends EntityLivingNode<T> impl
|
|||
public void resetTask()
|
||||
{
|
||||
super.resetTask();
|
||||
EntityNPCNode.this.entity.setSneaking(false);
|
||||
EntityNPC.this.setSneaking(false);
|
||||
}
|
||||
});
|
||||
this.tasks.addTask(7, new EntityAINpcInteract(this.entity));
|
||||
this.tasks.addTask(8, new EntityAIWander(this.entity, 1.0D));
|
||||
this.tasks.addTask(8, new EntityAIPlay(this.entity, 1.1D));
|
||||
this.tasks.addTask(9, new EntityAIWatchClosest(this.entity, EntityLiving.class, 8.0F));
|
||||
this.targets.addTask(1, new EntityAIHurtByTarget(this.entity, false, /* EntityNPC.class, */ EntityLiving.class) {
|
||||
this.tasks.addTask(7, new EntityAINpcInteract(this));
|
||||
this.tasks.addTask(8, new EntityAIWander(this, 1.0D));
|
||||
this.tasks.addTask(8, new EntityAIPlay(this, 1.1D));
|
||||
this.tasks.addTask(9, new EntityAIWatchClosest(this, EntityLiving.class, 8.0F));
|
||||
this.targets.addTask(1, new EntityAIHurtByTarget(this, false, /* EntityNPC.class, */ EntityLiving.class) {
|
||||
protected boolean isSuitableTarget(EntityLiving entity) {
|
||||
if(entity != null && entity != EntityNPCNode.this.entity && EntityNPCNode.this.shouldFlee(entity)) {
|
||||
EntityNPCNode.this.setAttackTarget(null);
|
||||
EntityNPCNode.this.fleeing = true;
|
||||
if(entity != null && entity != EntityNPC.this && EntityNPC.this.shouldFlee(entity)) {
|
||||
EntityNPC.this.setAttackTarget(null);
|
||||
EntityNPC.this.fleeing = true;
|
||||
return false;
|
||||
}
|
||||
return entity != null && entity != EntityNPCNode.this.entity && (!(entity.isPlayer()) || EntityNPCNode.this.rand.chance(entity.getAttackedBy() == EntityNPCNode.this.entity ? 2 : 4))
|
||||
&& EntityNPCNode.this.canCounter(entity) && super.isSuitableTarget(entity);
|
||||
return entity != null && entity != EntityNPC.this && (!(entity.isPlayer()) || EntityNPC.this.rand.chance(entity.getAttackedBy() == EntityNPC.this ? 2 : 4))
|
||||
&& EntityNPC.this.canCounter(entity) && super.isSuitableTarget(entity);
|
||||
}
|
||||
});
|
||||
this.targets.addTask(2, new EntityAINearestAttackableTarget(this.entity, EntityLiving.class, 10, true, false, new Predicate<EntityLiving>() {
|
||||
this.targets.addTask(2, new EntityAINearestAttackableTarget(this, EntityLiving.class, 10, true, false, new Predicate<EntityLiving>() {
|
||||
public boolean test(EntityLiving entity) {
|
||||
if(entity != null && entity != EntityNPCNode.this.entity && EntityNPCNode.this.shouldFlee(entity)) {
|
||||
EntityNPCNode.this.setAttackTarget(null);
|
||||
EntityNPCNode.this.fleeing = true;
|
||||
if(entity != null && entity != EntityNPC.this && EntityNPC.this.shouldFlee(entity)) {
|
||||
EntityNPC.this.setAttackTarget(null);
|
||||
EntityNPC.this.fleeing = true;
|
||||
return false;
|
||||
}
|
||||
return entity != null && entity != EntityNPCNode.this.entity && !EntityNPCNode.this.fleeing && EntityNPCNode.this.entity.canAmbush(entity) && EntityNPCNode.this.canAttack(entity);
|
||||
return entity != null && entity != EntityNPC.this && !EntityNPC.this.fleeing && EntityNPC.this.canAmbush(entity) && EntityNPC.this.canAttack(entity);
|
||||
}
|
||||
}));
|
||||
// this.setCanPickUpLoot(true);
|
||||
|
||||
this.setCombatTask();
|
||||
if (worldIn != null && !worldIn.client)
|
||||
{
|
||||
this.setCombatTask();
|
||||
}
|
||||
}
|
||||
|
||||
public final boolean canInfight(Alignment align) {
|
||||
Alignment alignment = this.entity.getAlignmentCached();
|
||||
return alignment.chaotic || (!alignment.lawful &&
|
||||
((alignment.good && align.evil) || (alignment.evil && align.good)));
|
||||
}
|
||||
|
||||
public final boolean canMurder(Alignment align) {
|
||||
Alignment alignment = this.entity.getAlignmentCached();
|
||||
return alignment.chaotic && ((alignment.good && align.evil) || (alignment.evil && align.good));
|
||||
}
|
||||
|
||||
public boolean canCounter(EntityLiving entity) {
|
||||
return !(entity instanceof EntityNPC) ||
|
||||
(this.entity.getClass() == entity.getClass() ? this.canInfight(((EntityNPC)entity).getAlignmentCached()) :
|
||||
!this.entity.isPeaceful(((EntityNPC)entity).getClass()));
|
||||
}
|
||||
|
||||
public boolean canAttack(EntityLiving entity) {
|
||||
return entity instanceof EntityNPC && (this.entity.getClass() == entity.getClass() ? this.canMurder(((EntityNPC)entity).getAlignmentCached()) :
|
||||
this.entity.isAggressive(((EntityNPC)entity).getClass()));
|
||||
}
|
||||
|
||||
public boolean shouldFlee(EntityLiving entity) {
|
||||
return (this.entity.getHealth() <= (this.entity.getMaxHealth() / 4) || !this.canCounter(entity)) &&
|
||||
((entity instanceof EntityNPC && ((EntityNPC)entity).getNode().canAttack(this.entity) ||
|
||||
(entity == this.entity.getAttackedBy() && ((EntityNPC)entity).getNode().canCounter(this.entity))));
|
||||
}
|
||||
|
||||
public boolean isRangedWeapon(ItemStack stack) {
|
||||
return stack != null && (stack.getItem() == Items.bow || stack.getItem() instanceof ItemGunBase ||
|
||||
stack.getItem() == Items.snowball || stack.getItem() == Items.potion);
|
||||
}
|
||||
|
||||
// public boolean isRangedWeapon(ItemStack stack) { // EntityGargoyle
|
||||
// return false;
|
||||
// }
|
||||
|
||||
public void updateLeashedState() {
|
||||
if(!this.player)
|
||||
|
@ -239,9 +205,9 @@ public class EntityNPCNode<T extends EntityNPC> extends EntityLivingNode<T> impl
|
|||
if(!this.player) {
|
||||
this.tasks.removeTask(this.aiMelee);
|
||||
this.tasks.removeTask(this.aiRanged);
|
||||
ItemStack itemstack = this.entity.getHeldItem();
|
||||
ItemStack itemstack = this.getEntity().getHeldItem();
|
||||
|
||||
if (this.isRangedWeapon(itemstack))
|
||||
if (this.getEntity().isRangedWeapon(itemstack))
|
||||
{
|
||||
this.tasks.addTask(3, this.aiRanged);
|
||||
}
|
||||
|
|
|
@ -1,29 +1,436 @@
|
|||
package server.ai;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import common.ai.EntityAIBase;
|
||||
import common.ai.EntityAIMoveTowardsRestriction;
|
||||
import common.ai.EntityAITasks;
|
||||
import common.ai.EntityJumpHelper;
|
||||
import common.ai.EntityLookHelper;
|
||||
import common.ai.EntityMoveHelper;
|
||||
import common.ai.EntitySenses;
|
||||
import common.ai.IEntityNode;
|
||||
import common.block.Block;
|
||||
import common.collect.Lists;
|
||||
import common.color.TextColor;
|
||||
import common.entity.DamageSource;
|
||||
import common.entity.Entity;
|
||||
import common.entity.EntityDamageSource;
|
||||
import common.entity.item.EntityLeashKnot;
|
||||
import common.entity.npc.EntityNPC;
|
||||
import common.entity.types.CombatEntry;
|
||||
import common.entity.types.EntityBodyHelper;
|
||||
import common.entity.types.EntityLiving;
|
||||
import common.entity.types.EntityTameable;
|
||||
import common.init.Blocks;
|
||||
import common.item.ItemStack;
|
||||
import common.nbt.NBTTagCompound;
|
||||
import common.world.World;
|
||||
import common.network.IPlayer;
|
||||
import common.pathfinding.PathNavigate;
|
||||
import common.pathfinding.PathNavigateGround;
|
||||
import common.util.BlockPos;
|
||||
import common.world.WorldServer;
|
||||
|
||||
public class EntityNode<T extends Entity> implements IEntityNode {
|
||||
protected final T entity;
|
||||
public abstract class EntityNode implements IEntityNode {
|
||||
protected final EntityLiving entity;
|
||||
protected final boolean player;
|
||||
protected WorldServer world;
|
||||
private final List<CombatEntry> combat = Lists.<CombatEntry>newArrayList();
|
||||
private EntityLookHelper lookHelper;
|
||||
protected EntityMoveHelper moveHelper;
|
||||
protected EntityJumpHelper jumpHelper;
|
||||
private EntityBodyHelper bodyHelper;
|
||||
protected PathNavigate navigator;
|
||||
protected final EntityAITasks tasks;
|
||||
protected final EntityAITasks targets;
|
||||
private EntityLiving target;
|
||||
private EntitySenses senses;
|
||||
private Runnable tickFunc;
|
||||
private NBTTagCompound leashTag;
|
||||
private boolean isMovementAITaskSet;
|
||||
private EntityAIBase aiBase;
|
||||
private boolean attacked;
|
||||
private boolean damaged;
|
||||
private String blockType;
|
||||
private int lastDamaged;
|
||||
|
||||
public EntityNode(T entity) {
|
||||
public EntityNode(EntityLiving entity) {
|
||||
this.entity = entity;
|
||||
this.player = entity.isPlayer();
|
||||
this.world = (WorldServer)entity.worldObj;
|
||||
this.tasks = new EntityAITasks();
|
||||
this.targets = new EntityAITasks();
|
||||
this.lookHelper = new EntityLookHelper(entity);
|
||||
this.moveHelper = new EntityMoveHelper(entity);
|
||||
this.jumpHelper = new EntityJumpHelper(entity);
|
||||
this.bodyHelper = new EntityBodyHelper(entity);
|
||||
this.navigator = this.getNewNavigator();
|
||||
this.senses = new EntitySenses(entity);
|
||||
this.aiBase = new EntityAIMoveTowardsRestriction(entity, 1.0D);
|
||||
this.registerTasks();
|
||||
}
|
||||
|
||||
public void setWorld(World world) {
|
||||
this.world = (WorldServer)world;
|
||||
protected PathNavigate getNewNavigator() {
|
||||
return new PathNavigateGround(this.entity, this.entity.worldObj);
|
||||
}
|
||||
|
||||
// protected PathNavigate getNewNavigator() { EntityArachnoid
|
||||
// return new PathNavigateClimber(this.entity, this.entity.worldObj);
|
||||
// }
|
||||
|
||||
protected abstract void registerTasks();
|
||||
|
||||
public void setTickFunction(Runnable func) {
|
||||
this.tickFunc = func;
|
||||
}
|
||||
|
||||
public EntityLookHelper getLookHelper() {
|
||||
return this.lookHelper;
|
||||
}
|
||||
|
||||
public EntityMoveHelper getMoveHelper() {
|
||||
return this.moveHelper;
|
||||
}
|
||||
|
||||
public EntityJumpHelper getJumpHelper() {
|
||||
return this.jumpHelper;
|
||||
}
|
||||
|
||||
public PathNavigate getNavigator() {
|
||||
return this.navigator;
|
||||
}
|
||||
|
||||
public EntitySenses getEntitySenses() {
|
||||
return this.senses;
|
||||
}
|
||||
|
||||
public EntityLiving getAttackTarget() {
|
||||
return this.target;
|
||||
}
|
||||
|
||||
public void setAttackTarget(EntityLiving entitylivingbaseIn) {
|
||||
this.target = entitylivingbaseIn;
|
||||
}
|
||||
|
||||
public boolean hasPath()
|
||||
{
|
||||
return !this.navigator.noPath();
|
||||
}
|
||||
|
||||
public void updateRenderAngles() {
|
||||
this.bodyHelper.updateRenderAngles();
|
||||
}
|
||||
|
||||
public void readNbt(NBTTagCompound tag) {
|
||||
public void update() {
|
||||
this.senses.clearSensingCache();
|
||||
this.targets.onUpdateTasks();
|
||||
this.tasks.onUpdateTasks();
|
||||
this.navigator.onUpdateNavigation();
|
||||
if(this.tickFunc != null)
|
||||
this.tickFunc.run();
|
||||
this.moveHelper.onUpdateMoveHelper();
|
||||
this.lookHelper.onUpdateLook();
|
||||
this.jumpHelper.doJump();
|
||||
}
|
||||
|
||||
public void writeNbt(NBTTagCompound tag) {
|
||||
public void setLeashTag(NBTTagCompound tag) {
|
||||
this.leashTag = tag;
|
||||
}
|
||||
|
||||
private void recreateLeash() {
|
||||
if(this.entity.getLeashed() && this.leashTag != null) {
|
||||
// if(this.leashTag.hasKey("PlayerName", 8)) {
|
||||
// String id = this.leashTag.getString("PlayerName");
|
||||
// if(!id.isEmpty()) {
|
||||
// for(EntityNPC entitylivingbase : this.worldObj.getEntitiesWithinAABB(EntityNPC.class,
|
||||
// this.getEntityBoundingBox().expand(10.0D, 10.0D, 10.0D))) {
|
||||
// if(entitylivingbase.getUser().equals(id)) {
|
||||
// this.leashedTo = entitylivingbase;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
if(this.leashTag.hasKey("X", 99) && this.leashTag.hasKey("Y", 99) && this.leashTag.hasKey("Z", 99)) {
|
||||
BlockPos blockpos = new BlockPos(this.leashTag.getInteger("X"), this.leashTag.getInteger("Y"),
|
||||
this.leashTag.getInteger("Z"));
|
||||
EntityLeashKnot entityleashknot = EntityLeashKnot.getKnotForPosition(this.entity.worldObj, blockpos);
|
||||
|
||||
if(entityleashknot == null) {
|
||||
entityleashknot = EntityLeashKnot.createKnot(this.entity.worldObj, blockpos);
|
||||
}
|
||||
|
||||
this.entity.setLeashedTo(entityleashknot, false);
|
||||
}
|
||||
else {
|
||||
this.entity.clearLeashed(false, true);
|
||||
}
|
||||
}
|
||||
|
||||
this.leashTag = null;
|
||||
}
|
||||
|
||||
protected void onUpdateLeashed(float distance)
|
||||
{
|
||||
}
|
||||
|
||||
// protected void onUpdateLeashed(float distance) EntityHorse
|
||||
// {
|
||||
// if (distance > 6.0F && this.entity.isEatingHaystack())
|
||||
// {
|
||||
// this.entity.setEatingHaystack(false);
|
||||
// }
|
||||
// }
|
||||
|
||||
public void updateLeashedState() {
|
||||
if(this.leashTag != null) {
|
||||
this.recreateLeash();
|
||||
}
|
||||
|
||||
if(this.entity.getLeashed()) {
|
||||
if(!this.entity.isEntityAlive()) {
|
||||
this.entity.clearLeashed(true, true);
|
||||
}
|
||||
|
||||
if(this.entity.getLeashedTo() == null || this.entity.getLeashedTo().dead) {
|
||||
this.entity.clearLeashed(true, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.entity.getLeashed() && this.entity.getLeashedTo() != null && this.entity.getLeashedTo().worldObj == this.entity.worldObj)
|
||||
{
|
||||
Entity entity = this.entity.getLeashedTo();
|
||||
this.entity.setHomePosAndDistance(new BlockPos((int)entity.posX, (int)entity.posY, (int)entity.posZ), 5);
|
||||
float f = this.entity.getDistanceToEntity(entity);
|
||||
|
||||
if (this.entity instanceof EntityTameable && ((EntityTameable)this.entity).isSitting())
|
||||
{
|
||||
if (f > 10.0F)
|
||||
{
|
||||
this.entity.clearLeashed(true, true);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.isMovementAITaskSet)
|
||||
{
|
||||
this.tasks.addTask(2, this.aiBase);
|
||||
|
||||
if (this.getNavigator() instanceof PathNavigateGround)
|
||||
{
|
||||
((PathNavigateGround)this.getNavigator()).setAvoidsWater(false);
|
||||
}
|
||||
|
||||
this.isMovementAITaskSet = true;
|
||||
}
|
||||
|
||||
this.onUpdateLeashed(f);
|
||||
|
||||
if (f > 4.0F)
|
||||
{
|
||||
this.getNavigator().tryMoveToEntityLiving(entity, 1.0D);
|
||||
}
|
||||
|
||||
if (f > 6.0F)
|
||||
{
|
||||
double d0 = (entity.posX - this.entity.posX) / (double)f;
|
||||
double d1 = (entity.posY - this.entity.posY) / (double)f;
|
||||
double d2 = (entity.posZ - this.entity.posZ) / (double)f;
|
||||
this.entity.motionX += d0 * Math.abs(d0) * 0.4D;
|
||||
this.entity.motionY += d1 * Math.abs(d1) * 0.4D;
|
||||
this.entity.motionZ += d2 * Math.abs(d2) * 0.4D;
|
||||
}
|
||||
|
||||
if (f > 10.0F)
|
||||
{
|
||||
this.entity.clearLeashed(true, true);
|
||||
}
|
||||
}
|
||||
else if (!this.entity.getLeashed() && this.isMovementAITaskSet)
|
||||
{
|
||||
this.isMovementAITaskSet = false;
|
||||
this.tasks.removeTask(this.aiBase);
|
||||
|
||||
if (this.getNavigator() instanceof PathNavigateGround)
|
||||
{
|
||||
((PathNavigateGround)this.getNavigator()).setAvoidsWater(true);
|
||||
}
|
||||
|
||||
this.entity.detachHome();
|
||||
}
|
||||
}
|
||||
|
||||
public void trackDamage(DamageSource source, int amount) {
|
||||
this.resetCombat();
|
||||
this.blockType = null;
|
||||
if(this.entity.isOnLadder()) {
|
||||
Block block = this.entity.worldObj
|
||||
.getState(new BlockPos(this.entity.posX, this.entity.getEntityBoundingBox().minY, this.entity.posZ)).getBlock();
|
||||
if(block == Blocks.ladder)
|
||||
this.blockType = "von einer Leiter";
|
||||
else if(block == Blocks.vine)
|
||||
this.blockType = "von Ranken";
|
||||
}
|
||||
else if(this.entity.isInLiquid()) {
|
||||
this.blockType = "aus dem Wasser";
|
||||
}
|
||||
CombatEntry entry = new CombatEntry(source, amount, this.blockType, this.entity.fallDistance);
|
||||
this.combat.add(entry);
|
||||
this.lastDamaged = this.entity.ticksExisted;
|
||||
this.damaged = true;
|
||||
if(entry.getSource().getEntity() instanceof EntityLiving && !this.attacked && this.entity.isEntityAlive())
|
||||
this.attacked = true;
|
||||
}
|
||||
|
||||
public void sendDeathMessage() {
|
||||
this.sendDeathMessage(false, false);
|
||||
}
|
||||
|
||||
protected void sendDeathMessage(boolean natural, boolean forAll) {
|
||||
// if(this.entity.worldObj.client)
|
||||
// return;
|
||||
String msg;
|
||||
String kill;
|
||||
IPlayer receiver = null;
|
||||
if(this.combat.size() == 0) {
|
||||
msg = kill = natural ? String.format("%s starb", this.entity.getColoredName(TextColor.LGRAY)) : null;
|
||||
}
|
||||
else {
|
||||
CombatEntry strong = null;
|
||||
CombatEntry block = null;
|
||||
int min = 0;
|
||||
float max = 0.0F;
|
||||
|
||||
for(int z = 0; z < this.combat.size(); ++z) {
|
||||
CombatEntry entry = (CombatEntry)this.combat.get(z);
|
||||
CombatEntry last = z > 0 ? (CombatEntry)this.combat.get(z - 1) : null;
|
||||
|
||||
if((entry.getSource() == DamageSource.fall || entry.getSource() == DamageSource.outOfWorld) &&
|
||||
entry.getFallDistance() > 0.0F && (strong == null || entry.getFallDistance() > max)) {
|
||||
if(z > 0) {
|
||||
strong = last;
|
||||
}
|
||||
else {
|
||||
strong = entry;
|
||||
}
|
||||
|
||||
max = entry.getFallDistance();
|
||||
}
|
||||
|
||||
if(entry.getBlockType() != null && (block == null || entry.getDamage() > min)) {
|
||||
block = entry;
|
||||
}
|
||||
}
|
||||
CombatEntry fall = max > 5.0F && strong != null ? strong : (min > 5 && block != null ? block : null);
|
||||
CombatEntry last = (CombatEntry)this.combat.get(this.combat.size() - 1);
|
||||
Entity lastEnt = last.getSource().getEntity();
|
||||
|
||||
if(fall != null && last.getSource() == DamageSource.fall) {
|
||||
if(fall.getSource() != DamageSource.fall && fall.getSource() != DamageSource.outOfWorld) {
|
||||
Entity fallEnt = fall.getSource().getEntity();
|
||||
if(fallEnt != null && (lastEnt == null || fallEnt != lastEnt)) {
|
||||
ItemStack fallItem = fallEnt instanceof EntityLiving ? ((EntityLiving)fallEnt).getHeldItem() : null;
|
||||
receiver = fallEnt.isPlayer() ? ((EntityNPC)fallEnt).connection : null;
|
||||
if(fallItem != null) { // && fallItem.hasDisplayName()) {
|
||||
msg = String.format("%s wurde von %s mit %s zum Fallen verdammt", this.entity.getColoredName(TextColor.CYAN),
|
||||
fallEnt.getColoredName(TextColor.CYAN), fallItem.getColoredName(TextColor.CYAN));
|
||||
kill = String.format(TextColor.CYAN + "* %s mit %s zum Fallen verdammt",
|
||||
this.entity.getColoredName(TextColor.CYAN), fallItem.getColoredName(TextColor.CYAN));
|
||||
}
|
||||
else {
|
||||
msg = String.format("%s wurde von %s zum Fallen verdammt", this.entity.getColoredName(TextColor.CYAN),
|
||||
fallEnt.getColoredName(TextColor.CYAN));
|
||||
kill = String.format(TextColor.CYAN + "* %s zum Fallen verdammt",
|
||||
this.entity.getColoredName(TextColor.CYAN));
|
||||
}
|
||||
}
|
||||
else if(lastEnt != null) {
|
||||
ItemStack lastItem = lastEnt instanceof EntityLiving ? ((EntityLiving)lastEnt).getHeldItem() : null;
|
||||
receiver = lastEnt.isPlayer() ? ((EntityNPC)lastEnt).connection : null;
|
||||
if(lastItem != null) { // && lastItem.hasDisplayName()) {
|
||||
msg = String.format("%s fiel zu tief und wurde von %s mit %s erledigt",
|
||||
this.entity.getColoredName(TextColor.BLUE),
|
||||
lastEnt.getColoredName(TextColor.BLUE), lastItem.getColoredName(TextColor.BLUE));
|
||||
kill = String.format(TextColor.BLUE + "* %s mit %s erledigt",
|
||||
this.entity.getColoredName(TextColor.BLUE), lastItem.getColoredName(TextColor.BLUE));
|
||||
}
|
||||
else {
|
||||
msg = String.format("%s fiel zu tief und wurde von %s erledigt", this.entity.getColoredName(TextColor.BLUE),
|
||||
lastEnt.getColoredName(TextColor.BLUE));
|
||||
kill = String.format(TextColor.BLUE + "%s erledigt", this.entity.getColoredName(TextColor.BLUE));
|
||||
}
|
||||
}
|
||||
else {
|
||||
msg = kill = natural ? String.format("%s wurde zum Fallen verdammt", this.entity.getColoredName(TextColor.CYAN)) : null;
|
||||
}
|
||||
}
|
||||
else {
|
||||
msg = kill = natural ? String.format("%s fiel " + (fall.getBlockType() == null ? "aus zu großer Höhe" : fall.getBlockType()),
|
||||
this.entity.getColoredName(TextColor.NEON)) : null;
|
||||
}
|
||||
}
|
||||
else {
|
||||
receiver = last.getSource().getEntity() != null && last.getSource().getEntity().isPlayer() ? ((EntityNPC)last.getSource().getEntity()).connection : null;
|
||||
msg = natural || (last.getSource() instanceof EntityDamageSource ? last.getSource().getEntity() != null : this.entity.getAttackingEntity() != null) ? last.getSource().getDeathMessage(this.entity) : null;
|
||||
kill = msg == null ? null : last.getSource().getKillMessage(this.entity);
|
||||
}
|
||||
}
|
||||
if(msg == null)
|
||||
return;
|
||||
if(receiver != null)
|
||||
receiver.addFeed(kill);
|
||||
if(forAll)
|
||||
for(IPlayer player : ((WorldServer)this.entity.worldObj).getServer().getIPlayers()) {
|
||||
if(player != receiver)
|
||||
player.addFeed(msg);
|
||||
}
|
||||
}
|
||||
|
||||
public EntityLiving getAttacking() {
|
||||
EntityLiving entity = null;
|
||||
EntityNPC player = null;
|
||||
int edmg = 0;
|
||||
int pdmg = 0;
|
||||
for(CombatEntry entry : this.combat) {
|
||||
if(entry.getSource().getEntity() != null && entry.getSource().getEntity().isPlayer() && (player == null || entry.getDamage() > pdmg)) {
|
||||
pdmg = entry.getDamage();
|
||||
player = (EntityNPC)entry.getSource().getEntity();
|
||||
}
|
||||
if(entry.getSource().getEntity() instanceof EntityLiving && (entity == null || entry.getDamage() > edmg)) {
|
||||
edmg = entry.getDamage();
|
||||
entity = (EntityLiving)entry.getSource().getEntity();
|
||||
}
|
||||
}
|
||||
return player != null && pdmg >= edmg / 3 ? player : entity;
|
||||
}
|
||||
|
||||
public void resetCombat() {
|
||||
int timeout = this.attacked ? 300 : 100;
|
||||
if(this.damaged && (!this.entity.isEntityAlive() || this.entity.ticksExisted - this.lastDamaged > timeout)) {
|
||||
this.damaged = false;
|
||||
this.attacked = false;
|
||||
this.combat.clear();
|
||||
}
|
||||
}
|
||||
|
||||
public int getMaxFallHeight() {
|
||||
if(this.target == null) {
|
||||
return 3;
|
||||
}
|
||||
else {
|
||||
int i = (int)((float)this.entity.getHealth() - (float)this.entity.getMaxHealth() * 0.33F);
|
||||
// i = i - (3 - this.worldObj.getDifficulty().getId()) * 4;
|
||||
|
||||
if(i < 0) {
|
||||
i = 0;
|
||||
}
|
||||
|
||||
return i + 3;
|
||||
}
|
||||
}
|
||||
|
||||
// public int getMaxFallHeight() EntityHaunter
|
||||
// {
|
||||
// return this.getAttackTarget() == null ? 3 : 3 + (this.getHealth() - 1);
|
||||
// }
|
||||
}
|
||||
|
|
|
@ -1,136 +0,0 @@
|
|||
package server.init;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import common.ai.IEntityNode;
|
||||
import common.collect.Maps;
|
||||
import common.entity.Entity;
|
||||
import common.entity.animal.EntityBat;
|
||||
import common.entity.animal.EntityChicken;
|
||||
import common.entity.animal.EntityCow;
|
||||
import common.entity.animal.EntityDragon;
|
||||
import common.entity.animal.EntityHorse;
|
||||
import common.entity.animal.EntityMooshroom;
|
||||
import common.entity.animal.EntityMouse;
|
||||
import common.entity.animal.EntityOcelot;
|
||||
import common.entity.animal.EntityPig;
|
||||
import common.entity.animal.EntityRabbit;
|
||||
import common.entity.animal.EntitySheep;
|
||||
import common.entity.animal.EntitySquid;
|
||||
import common.entity.animal.EntityWolf;
|
||||
import common.entity.item.EntityBoat;
|
||||
import common.entity.item.EntityChestCart;
|
||||
import common.entity.item.EntityCrystal;
|
||||
import common.entity.item.EntityExplosion;
|
||||
import common.entity.item.EntityFalling;
|
||||
import common.entity.item.EntityFireworks;
|
||||
import common.entity.item.EntityHopperCart;
|
||||
import common.entity.item.EntityItem;
|
||||
import common.entity.item.EntityLeashKnot;
|
||||
import common.entity.item.EntityMinecart;
|
||||
import common.entity.item.EntityNuke;
|
||||
import common.entity.item.EntityOrb;
|
||||
import common.entity.item.EntityTnt;
|
||||
import common.entity.item.EntityTntCart;
|
||||
import common.entity.item.EntityXp;
|
||||
import common.entity.item.EntityXpBottle;
|
||||
import common.entity.npc.SpeciesInfo;
|
||||
import common.entity.projectile.EntityArrow;
|
||||
import common.entity.projectile.EntityBox;
|
||||
import common.entity.projectile.EntityBullet;
|
||||
import common.entity.projectile.EntityDie;
|
||||
import common.entity.projectile.EntityDynamite;
|
||||
import common.entity.projectile.EntityEgg;
|
||||
import common.entity.projectile.EntityFireCharge;
|
||||
import common.entity.projectile.EntityFireball;
|
||||
import common.entity.projectile.EntityHook;
|
||||
import common.entity.projectile.EntityPotion;
|
||||
import common.entity.projectile.EntitySnowball;
|
||||
import common.entity.types.EntityLiving;
|
||||
import common.entity.types.IObjectData;
|
||||
import common.log.Log;
|
||||
import common.nbt.NBTTagCompound;
|
||||
import common.world.World;
|
||||
|
||||
public abstract class NodeRegistry {
|
||||
private static final Map<Class<? extends Entity>, Class<? extends IEntityNode>> NODES = Maps.newHashMap();
|
||||
|
||||
private static void registerNode(Class<? extends Entity> clazz, Class<? extends IEntityNode> node) {
|
||||
if(clazz == null)
|
||||
throw new IllegalArgumentException("Kann keine null-Klasse registrieren");
|
||||
if(NODES.containsKey(clazz))
|
||||
throw new IllegalArgumentException("Klasse ist bereits registriert: " + clazz);
|
||||
NODES.put(clazz, node);
|
||||
}
|
||||
|
||||
public static void addNode(Entity entity) {
|
||||
IEntityNode node = null;
|
||||
Class<? extends IEntityNode> oclass = NODES.get(entity.getClass());
|
||||
Constructor[] consts = oclass.getConstructors();
|
||||
if(consts.length != 1)
|
||||
throw new IllegalArgumentException("Klasse " + oclass + " hat mehr als einen Konstruktor");
|
||||
try {
|
||||
node = (IEntityNode)consts[0].newInstance(entity);
|
||||
}
|
||||
catch(InstantiationException | IllegalAccessException | InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
entity.setNode(node);
|
||||
}
|
||||
|
||||
public static Class<? extends IEntityNode> getNodeClass(Class<? extends Entity> clazz) {
|
||||
return NODES.get(clazz);
|
||||
}
|
||||
|
||||
public static void register() {
|
||||
registerNode(EntityItem.class, );
|
||||
registerNode(EntityXp.class, );
|
||||
registerNode(EntityEgg.class, );
|
||||
registerNode(EntityLeashKnot.class, );
|
||||
registerNode(EntityArrow.class, );
|
||||
registerNode(EntitySnowball.class, );
|
||||
registerNode(EntityFireball.class, );
|
||||
registerNode(EntityFireCharge.class, );
|
||||
registerNode(EntityOrb.class, );
|
||||
registerNode(EntityPotion.class, );
|
||||
registerNode(EntityXpBottle.class, );
|
||||
registerNode(EntityBox.class, );
|
||||
registerNode(EntityTnt.class, );
|
||||
registerNode(EntityFalling.class, );
|
||||
registerNode(EntityFireworks.class, );
|
||||
registerNode(EntityBoat.class, );
|
||||
registerNode(EntityMinecart.class, );
|
||||
registerNode(EntityChestCart.class, );
|
||||
registerNode(EntityTntCart.class, );
|
||||
registerNode(EntityHopperCart.class, );
|
||||
registerNode(EntityHook.class, );
|
||||
registerNode(EntityDynamite.class, );
|
||||
registerNode(EntityNuke.class, );
|
||||
registerNode(EntityDie.class, );
|
||||
registerNode(EntityExplosion.class, );
|
||||
registerNode(EntityCrystal.class, );
|
||||
registerNode(EntityBullet.class, );
|
||||
|
||||
registerNode(EntityDragon.class, );
|
||||
registerNode(EntityBat.class, );
|
||||
registerNode(EntityPig.class, );
|
||||
registerNode(EntitySheep.class, );
|
||||
registerNode(EntityCow.class, );
|
||||
registerNode(EntityChicken.class, );
|
||||
registerNode(EntitySquid.class, );
|
||||
registerNode(EntityWolf.class, );
|
||||
registerNode(EntityMooshroom.class, );
|
||||
registerNode(EntityOcelot.class, );
|
||||
registerNode(EntityHorse.class, );
|
||||
registerNode(EntityRabbit.class, );
|
||||
registerNode(EntityMouse.class, );
|
||||
|
||||
for(int z = 0; z < SpeciesRegistry.SPECIMEN.size(); z++) {
|
||||
SpeciesInfo info = SpeciesRegistry.SPECIMEN.get(z);
|
||||
registerNode(info.clazz, );
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue