From d8e54d4d69281e6de7fbf016fed53552dba3f229 Mon Sep 17 00:00:00 2001 From: Sen Date: Mon, 12 May 2025 18:48:05 +0200 Subject: [PATCH] Revert "split entity ai to server #2+" This reverts commit ad828ec6b449201b7845b05bcf334423f43fea29. --- client/src/client/Client.java | 8 +- client/src/client/gui/GuiConvert.java | 214 +++++++ client/src/client/gui/GuiMenu.java | 5 +- .../src/client}/world/Converter.java | 434 ++++++++++---- common/src/common/ai/AIFireballAttack.java | 6 +- .../common/ai/EntityAIControlledByPlayer.java | 2 +- common/src/common/ai/IEntityLivingNode.java | 21 - common/src/common/ai/IEntityMobNPCNode.java | 14 - common/src/common/ai/IEntityNPCNode.java | 9 - common/src/common/ai/IEntityNode.java | 15 +- common/src/common/entity/Entity.java | 19 +- .../common/entity/npc/AIHurtByAggressor.java | 22 - .../common/entity/npc/EntityChaosMarine.java | 2 +- .../src/common/entity/npc/EntityGargoyle.java | 4 + .../src/common/entity/npc/EntityMobNPC.java | 294 +++++++++- common/src/common/entity/npc/EntityNPC.java | 65 ++- .../common/entity/npc/EntitySpaceMarine.java | 2 +- .../src/common/entity/types/EntityLiving.java | 104 +++- common/src/common/util/Util.java | 8 - common/src/common/world/Region.java | 149 ++++- common/src/common/world/WorldServer.java | 1 - server/src/server/Server.java | 70 +-- server/src/server/ai/EntityLivingNode.java | 537 ------------------ server/src/server/ai/EntityMobNPCNode.java | 84 --- server/src/server/ai/EntityNPCNode.java | 128 ++--- server/src/server/ai/EntityNode.java | 427 +++++++++++++- server/src/server/init/NodeRegistry.java | 136 ----- 27 files changed, 1621 insertions(+), 1159 deletions(-) create mode 100755 client/src/client/gui/GuiConvert.java rename {server/src/server => client/src/client}/world/Converter.java (79%) delete mode 100644 common/src/common/ai/IEntityLivingNode.java delete mode 100644 common/src/common/ai/IEntityMobNPCNode.java delete mode 100644 common/src/common/ai/IEntityNPCNode.java delete mode 100644 common/src/common/entity/npc/AIHurtByAggressor.java delete mode 100644 server/src/server/ai/EntityLivingNode.java delete mode 100644 server/src/server/ai/EntityMobNPCNode.java delete mode 100644 server/src/server/init/NodeRegistry.java diff --git a/client/src/client/Client.java b/client/src/client/Client.java index e0ab9f0..ddeec71 100755 --- a/client/src/client/Client.java +++ b/client/src/client/Client.java @@ -162,6 +162,7 @@ import common.util.Util; import common.util.HitPosition.ObjectType; import common.world.Chunk; import common.world.LightType; +import common.world.Region; import common.world.State; import common.world.World; import common.world.WorldClient; @@ -279,7 +280,7 @@ public class Client implements IThreadListener, IClient { private final List chat = Lists.newArrayList(); private final List feed = Lists.newArrayList(); private final List hotbar = Lists.newArrayList(); - private final File config = new File(System.getProperty("config.file", "client.cfg")); + private final File config = new File(System.getProperty("config.file", "game.cfg")); private boolean primary; private boolean secondary; @@ -1774,8 +1775,8 @@ public class Client implements IThreadListener, IClient { String.format("XYZ: %.3f / %.3f / %.3f", this.viewEntity.posX, this.viewEntity.getEntityBoundingBox().minY, this.viewEntity.posZ) + "\n" + String.format("Block: %d %d %d, R: '%s/%s'", blockpos.getX(), blockpos.getY(), blockpos.getZ(), - Util.getRegionFolder(blockpos.getX() >> 4, blockpos.getZ() >> 4), - Util.getRegionName(blockpos.getX() >> 4, blockpos.getZ() >> 4)) + "\n" + + Region.getRegionFolder(blockpos.getX() >> 4, blockpos.getZ() >> 4), + Region.getRegionName(blockpos.getX() >> 4, blockpos.getZ() >> 4)) + "\n" + String.format("Chunk: %d %d %d + %d %d %d, FOV: %.1f °%s", blockpos.getX() >> 4, blockpos.getY() >> 4, blockpos.getZ() >> 4, blockpos.getX() & 15, blockpos.getY() & 15, blockpos.getZ() & 15, this.zooming ? (this.fov / this.zoomLevel) : this.fov, this.zooming ? @@ -2216,6 +2217,7 @@ public class Client implements IThreadListener, IClient { Log.SYSTEM.info("Beende ..."); unload(false); this.getSoundManager().unload(); + Region.killIO(); this.renderGlobal.stopChunkBuilders(); if(audio.end()) Log.SOUND.info("Audiogerät geschlossen"); diff --git a/client/src/client/gui/GuiConvert.java b/client/src/client/gui/GuiConvert.java new file mode 100755 index 0000000..e3e0a31 --- /dev/null +++ b/client/src/client/gui/GuiConvert.java @@ -0,0 +1,214 @@ +package client.gui; + +import java.io.File; +import java.io.FileFilter; +import java.text.SimpleDateFormat; +import java.util.Collections; +import java.util.Date; + +import client.Client.FileMode; +import client.gui.element.ActButton; +import client.gui.element.ActButton.Mode; +import client.gui.element.GuiList; +import client.gui.element.ListEntry; +import client.gui.element.NavButton; +import client.renderer.Drawing; +import client.world.Converter; +import common.color.TextColor; +import common.dimension.Space; +import common.log.Log; +import common.world.Region; +import common.world.World; +import common.world.Region.FolderInfo; +import common.world.Region.SaveVersion; + +public class GuiConvert extends GuiList implements ActButton.Callback +{ + protected class SaveInfo implements Comparable, ListEntry { + private final String file; + private final int dimensions; + private final int players; + private final long seed; + private final FolderInfo info; + + public SaveInfo(String file, int dimensions, int players, long seed, FolderInfo info) { + this.file = file; + this.dimensions = dimensions; + this.players = players; + this.seed = seed; + this.info = info; + } + + public String getFile() { + return this.file; + } + + public int getDimensions() { + return this.dimensions; + } + + public int getPlayers() { + return this.players; + } + + public boolean mustConvert() { + return this.info.legacy != null; + } + + public String getVersion() { + return this.info.legacy == null ? (this.info.version == null ? "" : this.info.version) : this.info.legacy.toString(); + } + + public boolean isIncompatible() { + return this.info.legacy == SaveVersion.RELEASE_1_13; + } + + public long getLastPlayed() { + return this.info.lastPlayed; + } + + public long getSeed() { + return this.seed; + } + + public int compareTo(SaveInfo comp) { + return this.info.lastPlayed < comp.info.lastPlayed ? 1 : (this.info.lastPlayed > comp.info.lastPlayed ? -1 : this.file.compareTo(comp.file)); + } + + public void select(boolean isDoubleClick, int mouseX, int mouseY) + { + boolean use = !this.isIncompatible() && this.mustConvert(); + GuiConvert.this.selectButton.enabled = use; + + if (isDoubleClick && use) + { + GuiConvert.this.use(GuiConvert.this.selectButton, Mode.PRIMARY); + } + } + + public void draw(int x, int y, int mouseXIn, int mouseYIn, boolean hover) + { + Drawing.drawText((this.isIncompatible() ? TextColor.DRED : "") + this.getFile() + (this.mustConvert() ? "" : + (TextColor.GRAY + " - " + TextColor.RESET + (this.getPlayers() > 0 ? this.getPlayers() + " Spieler" : "Keine Spieler"))), + x + 2, y, 0xffffffff); + Drawing.drawText((this.mustConvert() ? (this.isIncompatible() ? TextColor.CRIMSON : "") + this.getVersion() : (this.getDimensions() <= 0 ? "Keine Dimensionen" : this.getDimensions() + " Dimension" + (this.getDimensions() != 1 ? "en" : "") + " erschaffen")) + , x + 2, y + 18, 0xff808080); + Drawing.drawText(this.mustConvert() ? (this.isIncompatible() ? TextColor.CRIMSON + "Kann nicht konvertiert werden!" : + "Muss konvertiert werden!") : ( // "Kreativmodus: " + (info.isNoCreative() ? "Aus" : "An") + + "Zuletzt gespielt: " + DATE_FORMAT.format(new Date(this.getLastPlayed()))) + " " + TextColor.LGRAY + this.getVersion(), x + 2, y + 18 + 16, 0xff808080); + } + } + + public static final GuiConvert INSTANCE = new GuiConvert(); + private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss"); + + private ActButton selectButton; + private File dir = null; + + private GuiConvert() + { + } + + private void load() { + this.elements.clear(); + if(this.dir == null || !this.dir.exists() || !this.dir.isDirectory()) + return; + try + { + File[] files = dir.listFiles(); + if(files == null) + throw new RuntimeException("Kann den Speicherordner für Welten nicht lesen oder öffnen!"); + for(File file : files) { + if(!file.isDirectory()) + continue; + FolderInfo info = Region.loadWorldInfo(file); + if(info == null) + info = Converter.convertMapFormat(file, false); + if(info == null) { + this.elements.add(new SaveInfo(file.getName(), -1, -1, + 0L, new FolderInfo(World.START_TIME, file.lastModified(), null, null))); + continue; + } + int dims = -1; + int players = -1; + if(info.legacy == null) { + dims = 0; + File[] folders = new File(new File(dir, file.getName()), "chunk").listFiles(new FileFilter() { + public boolean accept(File pathname) { + return pathname.isDirectory() && !pathname.getName().equals(Space.INSTANCE.getDimensionName()); + } + }); + if(folders != null) { + for(File sub : folders) { + File[] dim = sub.listFiles(); + if(dim != null && dim.length > 0) + dims++; + } + } + File[] plrs = new File(new File(dir, file.getName()), "players").listFiles(new FileFilter() { + public boolean accept(File pathname) { + return pathname.getName().endsWith(".nbt"); + } + }); + players = plrs == null ? 0 : plrs.length; + } + this.elements.add(new SaveInfo(file.getName(), dims, players, + 0L, info)); + } + Collections.sort(this.elements); + } + catch (Exception e) + { + Log.IO.error("Konnte Weltliste nicht laden", e); + this.elements.clear(); + } + } + + public void init(int width, int height) + { + super.init(width, height); + this.setDimensions(width, height, 32, height - 32); + + this.load(); + + this.add(this.selectButton = new ActButton(width / 2 - 383, height - 28, 150, 24, this, "Konvertieren")); + this.add(new NavButton(width / 2 + 233, height - 28, 150, 24, GuiMenu.INSTANCE, "Abbrechen")); + + this.add(new ActButton(4, 4, 200, 24, new ActButton.Callback() { + public void use(ActButton elem, ActButton.Mode action) { + if(GuiConvert.this.gm.world != null) + return; + GuiConvert.this.gm.showFileDialog(FileMode.DIRECTORY_LOAD, "Ordner wählen", GuiConvert.this.dir, new FileCallback() { + public void selected(File file) { + GuiConvert.this.dir = file; + GuiConvert.this.gm.displayGuiScreen(GuiConvert.this); + } + }); + } + }, "Ordner wählen ...")); + + this.selectButton.enabled = false; + } + + public String getTitle() { + return "Welt auswählen"; + } + + public int getListWidth() + { + return 660; + } + + public int getSlotHeight() + { + return 56; + } + + public void use(ActButton button, Mode mode) + { + String dir = this.getSelected().getFile(); + File folder = new File(this.dir, dir); + if(folder.isDirectory()) + Converter.convertMapFormat(folder, true); + } +} diff --git a/client/src/client/gui/GuiMenu.java b/client/src/client/gui/GuiMenu.java index 54cbb34..17a9f4e 100644 --- a/client/src/client/gui/GuiMenu.java +++ b/client/src/client/gui/GuiMenu.java @@ -94,11 +94,12 @@ public class GuiMenu extends Gui { } } }); - this.add(new ActButton(0, 102, 400, 24, new ActButton.Callback() { + this.add(new NavButton(0, 102, 196, 24, GuiConvert.INSTANCE, "Welt konvertieren")); + this.add(new ActButton(204, 102, 196, 24, new ActButton.Callback() { public void use(ActButton elem, ActButton.Mode action) { GuiMenu.this.gm.interrupted = true; } - }, "Client schließen")); + }, "Spiel beenden")); this.shift(); this.add(new Label(4, /* this.gm.fb_y - 2 */ 0, 200, 20, TextColor.VIOLET + Config.VERSION, true)); this.splashLabel = this.add(new Label(0, 160, width, 24, "")); diff --git a/server/src/server/world/Converter.java b/client/src/client/world/Converter.java similarity index 79% rename from server/src/server/world/Converter.java rename to client/src/client/world/Converter.java index 5bc9269..33bf568 100644 --- a/server/src/server/world/Converter.java +++ b/client/src/client/world/Converter.java @@ -1,4 +1,4 @@ -package server.world; +package client.world; import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; @@ -7,14 +7,16 @@ import java.io.File; import java.io.FilenameFilter; import java.io.IOException; import java.io.RandomAccessFile; -import java.text.SimpleDateFormat; import java.util.Arrays; -import java.util.Date; import java.util.Map; import java.util.Map.Entry; import java.util.zip.GZIPInputStream; import java.util.zip.InflaterInputStream; +import client.Client; +import client.gui.GuiConvert; +import client.gui.GuiLoading; +import client.gui.GuiLoading.Callback; import common.biome.Biome; import common.block.Block; import common.block.BlockCactus; @@ -90,26 +92,15 @@ import common.world.Region; import common.world.State; import common.world.Weather; import common.world.World; -import server.Server; - -public abstract class Converter { - private static enum SaveVersion { - ALPHA_1_0("Alpha 1.0 - Beta 1.2"), - BETA_1_3("Beta 1.3 - Release 1.8.9"), - RELEASE_1_9("Release 1.9 - Release 1.12.2"), - RELEASE_1_13("Release 1.13 +"); - - private final String name; - - private SaveVersion(String name) { - this.name = name; - } - - public String toString() { - return this.name; - } - } +import common.world.Region.FolderInfo; +import common.world.Region.SaveVersion; +public final class Converter { +// public static interface Callback { +// void postMessage(String msg); +// void postProgress(int progress); +// } + private static class AnvilRegion { private final int[] offsets = new int[1024]; @@ -191,7 +182,11 @@ public abstract class Converter { State getState(int id, int data); } - private static long postProgress(long start, int progress) { + private Converter() { + } + + private long postProgress(long start, int progress) { +// SKC.info("... " + progress + "%"); if(System.currentTimeMillis() - start >= 500L) { start = System.currentTimeMillis(); Log.JNI.info("... " + progress + "%"); @@ -203,7 +198,16 @@ public abstract class Converter { private static final Map ENTITY_MAP = Maps.newHashMap(); private static final Map TILE_MAP = Maps.newHashMap(); private static final char[] BLOCK_MAP = new char[65536]; +// private static final Map BLOCK_FUNCS = Maps.newHashMap(); private static final Map OLD_GAMERULES = Maps.newHashMap(); + + private String action; + private String task; + private String file; + private int totalRegions; + private int doneRegions; + private int totalChunks; + private int doneChunks; private static void mapEntity(Class clazz, String ... names) { String name = EntityRegistry.getEntityString(clazz); @@ -249,6 +253,17 @@ public abstract class Converter { } } +// private static void mapBlockDynamic(BlockFunction func, int id, int data) { +// BLOCK_MAP[(id << 4) | data] = (char)0x000f; +// BLOCK_FUNCS.put((char)((id << 4) | data), func); +// } +// +// private static void mapBlockDynamic(BlockFunction func, int id) { +// for(int z = 0; z < 16; z++) { +// mapBlockDynamic(func, id, z); +// } +// } + static { OLD_GAMERULES.put("doFireTick", "fireTick"); OLD_GAMERULES.put("mobGriefing", "mobGriefing"); @@ -258,6 +273,7 @@ public abstract class Converter { OLD_GAMERULES.put("doEntityDrops", "dropObjects"); OLD_GAMERULES.put("naturalRegeneration", "naturalRegeneration"); OLD_GAMERULES.put("doDaylightCycle", "daylightCycle"); +// OLD_GAMERULES.put("showDeathMessages", "deathMessages"); OLD_GAMERULES.put("keepInventory", "keepInventory"); OLD_GAMERULES.put("doWeatherCycle", "weatherChanges"); OLD_GAMERULES.put("randomTickSpeed", "randomTickSpeed"); @@ -290,6 +306,7 @@ public abstract class Converter { mapTile(TileEntityDaylightDetector.class, "DLDetector", "daylight_detector"); mapTile(TileEntityHopper.class, "Hopper", "hopper"); mapTile(TileEntityComparator.class, "Comparator", "comparator"); +// mapTile(TileEntityFlowerPot.class, "FlowerPot", "flower_pot"); mapTile(TileEntityBanner.class, "Banner", "banner"); mapBlock(Blocks.stone.getState(), 1); @@ -592,6 +609,11 @@ public abstract class Converter { mapBlockData(Blocks.stonebrick_stairs, 109); mapBlock(Blocks.mycelium, 110); mapBlockData(Blocks.waterlily, 111); +// mapBlockDynamic(new BlockFunction() { +// public IBlockState getState(int id, int data) { +// return Blocks.waterlily.getDefaultState().withProperty(BlockDirectional.FACING, Facing.randHorizontal(RANDOM)); +// } +// }, 111); mapBlock(Blocks.blood_brick, 112); mapBlockData(Blocks.blood_brick_fence, 113); mapBlockData(Blocks.blood_brick_stairs, 114); @@ -800,7 +822,97 @@ public abstract class Converter { return Blocks.stained_hardened_clay.getState().withProperty(BlockColored.COLOR, DyeColor.byMetadata(data)); } }, 252); + // 253, 254 mapBlock(Blocks.obsidian, 255); + +// addBlock(137, 49); // Command Block +// addBlock(166, 0); // Barrier +// addBlock(168, 98); // Prismarine +// // addBlock(169, 169); // Sea Lantern --> Lamp +// addBlock(179, 24); // Red Sandstone +// addBlock(180, 128); // Red Sandstone Stairs +// addBlock(181, 43, 1); // Red Sandstone Double Slab +// +// addBlock(198, 101); // End Rod +// addBlock(199, 102); // Chorus Plant +// addBlock(200, 102); // Chorus Flower +// addBlock(201, 155); // Purpur Block +// addBlock(203, 156); // Purpur Stairs +// addBlock(206, 98); // End Stone Bricks +// addBlock(207, 142); // Beetroot Block +// addBlock(208, 60); // Grass Path +// addBlock(209, 20); // End Gateway +// addBlock(210, 137); // Repeating Command Block +// addBlock(211, 137); // Chain Command Block +// addBlock(212, 79); // Frosted Ice +// addBlock(213, 87); // Magma Block +// addBlock(214, 100); // Nether Wart Block +// addBlock(215, 112); // Red Nether Brick +// addBlock(216, 155); // Bone Block +// addBlock(217, 20); // Structure Void +// addBlock(218, 158); // Observer +// addBlock(255, 49); // Structure Block +// addBlock(202, 155, 2); // Purpur Pillar +// addBlock(204, 43, 7); // Purpur Double Slab + +// if(block > 197 && adddata != null) +// adddata.set(cx, cy, cz, 0); +// if(block == 1 || block == 19) { // Stone, Sponge +// data.set(cx, cy, cz, 0); +// } +// else if(block == 29 || block == 33 || block == 34) { // Piston, Sticky Piston, Piston Head +// int dt = data.get(cx, cy, cz); +// if((dt & 7) == 6) +// data.set(cx, cy, cz, (dt & 8) | 1); +// } +// else if(block == 97) { // Monster Egg +// int dt = data.get(cx, cy, cz); +// switch(dt) { +// case 0: +// default: +// blocks[c] = (byte)1; +// data.set(cx, cy, cz, 0); +// break; +// case 1: +// blocks[c] = (byte)4; +// data.set(cx, cy, cz, 0); +// break; +// case 2: +// case 3: +// case 4: +// case 5: +// blocks[c] = (byte)98; +// data.set(cx, cy, cz, dt - 2); +// break; +// } +// } +// mapBlock(new BlockFunction() { +// public IBlockState getState(int id, int data) { +// return Blocks.waterlily.getDefaultState().withProperty(BlockDirectional.FACING, Facing.randHorizontal(RANDOM)); +// } +// }, 111); +// else if(block == 111) { // Water Lily +// data.set(cx, cy, cz, RANDOM.zrange(4)); +// } +// else if(block == 251 || block == 252) { // Concrete, Concrete Powder +// blocks[c] = (byte)159; +// } +// else if(block >= 235 && block <= 250) { // Glazed Terracotta +// blocks[c] = (byte)159; +// data.set(cx, cy, cz, block - 235); +// } +// else if(block >= 219 && block <= 234) { // Shulker Box +// blocks[c] = (byte)35; +// data.set(cx, cy, cz, block - 219); +// } +// else if(block == 205) { // Purpur Slab +// blocks[c] = (byte)44; +// data.set(cx, cy, cz, (data.get(cx, cy, cz) & 8) == 8 ? 15 : 7); +// } +// else if(block == 182) { // Red Sandstone Slab +// blocks[c] = (byte)44; +// data.set(cx, cy, cz, (data.get(cx, cy, cz) & 8) == 8 ? 9 : 1); +// } } private static void convertTile(NBTTagCompound ent) { @@ -1001,13 +1113,17 @@ public abstract class Converter { return tag; } - private static long convertChunks(File dir, File file, long start, int progress, int total) { + private long convertChunks(File dir, File file, long start, int progress, int total) { String name = file.getName(); + this.file = name; + this.totalChunks = 1024; boolean legacy = name.endsWith(".mcr"); int rx, rz; String[] reg = name.split("\\."); if(reg.length != 4) { Log.JNI.warn("Unbekannte Region " + file); + this.doneChunks = 0; + this.file = null; return start; } try { @@ -1016,6 +1132,8 @@ public abstract class Converter { } catch(NumberFormatException e) { Log.JNI.warn("Unbekannte Region " + file); + this.doneChunks = 0; + this.file = null; return start; } try { @@ -1028,6 +1146,7 @@ public abstract class Converter { for(int bx = 0; bx < 4; bx++) { for(int bz = 0; bz < 4; bz++) { if(!oldreg.hasRegion(bx, bz)) { + this.doneChunks += 64; continue; } areas++; @@ -1042,6 +1161,7 @@ public abstract class Converter { DataInputStream in = oldreg.getInputStream(x, z); if(in == null) { Log.JNI.warn("Konnte " + file.getPath() + "@" + x + "," + z + " nicht lesen"); + this.doneChunks += 1; continue; } NBTTagCompound tag = NBTLoader.read(in); @@ -1052,6 +1172,7 @@ public abstract class Converter { // out.close(); newreg.writeTag(nx, nz, tag); } + this.doneChunks += 1; } } newreg.close(false); @@ -1069,26 +1190,36 @@ public abstract class Converter { catch(IOException e) { e.printStackTrace(); } + this.doneChunks = 0; + this.file = null; return start; } - public static boolean convert() { + public static FolderInfo convertMapFormat(File dir, boolean load) { long cur = System.currentTimeMillis(); - if(new File("server.nbt").exists()) - return false; - File ldat = new File("level.dat"); + if(load) + Log.JNI.info("Welt '" + dir + "' wird konvertiert"); + if(new File(dir, "level.nbt").exists()) { + if(load) + Log.JNI.error("Datei level.nbt existiert bereits"); + return null; + } + File ldat = new File(dir, "level.dat"); if(!ldat.exists()) - ldat = new File("level.dat_old"); - if(!ldat.exists()) - return false; - Log.JNI.info("Welt wird konvertiert"); + ldat = new File(dir, "level.dat_old"); + if(!ldat.exists()) { + if(load) + Log.JNI.error("Datei level.dat und level.dat_old nicht gefunden"); + return null; + } NBTTagCompound nbt; try { nbt = NBTLoader.readGZip(ldat); } catch(Exception e) { - Log.JNI.error(e, "Fehler beim Lesen von level.dat"); - return false; + if(load) + Log.JNI.error(e, "Fehler beim Lesen von level.dat"); + return null; } nbt = nbt.getCompoundTag("Data"); int version = nbt.getInteger("version"); @@ -1096,77 +1227,182 @@ public abstract class Converter { // nbt.setBoolean("incompatible", data >= 1400); SaveVersion ver = data >= 1400 ? SaveVersion.RELEASE_1_13 : (data >= 100 ? SaveVersion.RELEASE_1_9 : (version == 19132 || version == 19133 ? SaveVersion.BETA_1_3 : (version == 0 ? SaveVersion.ALPHA_1_0 : null))); if(ver == null) { - Log.IO.error("Version %d ist unbekannt", version); - return false; + if(load) + Log.IO.error("Version %d ist unbekannt", version); + return null; } long wtime = nbt.getLong(nbt.hasKey("DayTime", 99) ? "DayTime" : "Time") + World.START_TIME; - Log.IO.info("Version: %s", ver); - Log.IO.info("Weltzeit: %d Ticks / %d Sekunden", wtime, wtime / 20L); - Log.IO.info("Zuletzt geladen: %s", new SimpleDateFormat("dd.MM.yyyy HH:mm:ss").format(new Date(nbt.getLong("LastPlayed")))); - if(ver != SaveVersion.RELEASE_1_13) { - Log.JNI.info("Konvertiere Chunk-Daten von region/*.mca,*.mcr"); - File regionDir = new File("region"); - if(regionDir.exists()) { - File chunkDir = new File(new File("chunk"), "terra"); - Log.JNI.info("Konvertiere Welt nach '" + chunkDir + "' ..."); - Log.JNI.info("Durchsuche Ordner unter '" + regionDir + "' nach .mca- und .mcr-Dateien ..."); - File[] files = regionDir.listFiles(new FilenameFilter() { - public boolean accept(File file, String name) { - return name.endsWith(".mca") || name.endsWith(".mcr"); - } - }); - if(files.length == 0) { - Log.JNI.info("Keine .mca- oder .mcr-Dateien gefunden."); + if(!load) + return new FolderInfo(wtime, nbt.getLong("LastPlayed"), ver, null); +// nbt.setString("verdesc", ver); +// NBTTagCompound nbt = getLegacyWorldInfo(dir); +// if(nbt == null) +// return false; + final Converter conv = new Converter(); + Client.CLIENT.displayGuiScreen(new GuiLoading("Konvertiere Welt ...", new Callback() { + public void poll(Client gm, GuiLoading gui) { + if(conv.totalRegions > 0) { + gui.setBar(conv.task, "Regionen", conv.totalRegions); + gui.setProgress(conv.doneRegions); } else { - Log.JNI.info("Ingesamt wurden " + files.length + " .mca-Dateien und .mcr-Dateien gefunden, konvertiere ..."); - if(ver == SaveVersion.RELEASE_1_9) - Log.JNI.info("Konvertiere von neuerer Version, dies wird Blöcke entfernen ..."); - chunkDir.mkdirs(); - int progress = 0; - long time = System.currentTimeMillis(); - long start = postProgress(time, 0); - for(File file : files) { - int percent = (int)Math.round(100.0D * (double)progress / (double)files.length); - Log.JNI.info("Konvertiere Chunk-Daten: " + file.getName() + " (" + progress + "/" + files.length + ")"); - start = convertChunks(chunkDir, file, start, progress, files.length); - ++progress; - start = postProgress(start, percent); - } - time = System.currentTimeMillis() - time; - Log.JNI.info("Fertig. Konversion dauerte " + ((time / 60000L) > 0 ? ((time / 60000L) + " Minuten und ") : "") + ((time / 1000L) % 60L) + " Sekunden."); + gui.resetBar(); } + if(conv.totalChunks > 0) { + gui.setSub(conv.file, "Chunks", conv.totalChunks); + gui.setSubProgress(conv.doneChunks); + } + else { + gui.resetSub(); + } + gui.setTask(conv.action); } - } - else { - Log.JNI.warn("Konvertiere keine Chunk-Daten, da Version zu neu"); - } - Log.JNI.info("Konvertiere Daten von level.dat"); - Config.clear(); - UniverseRegistry.clear(); - if(nbt.hasKey("GameRules", 10)) { - NBTTagCompound rules = nbt.getCompoundTag("GameRules"); - for(Entry rule : OLD_GAMERULES.entrySet()) { - if(rules.hasKey(rule.getKey(), 8)) - Config.set(rule.getValue(), rules.getString(rule.getKey()), null); + })); + final NBTTagCompound tag = nbt; + new Thread(new Runnable() { + public void run() { + Log.IO.info("Version: %s", ver); + if(ver != SaveVersion.RELEASE_1_13) { + conv.action = "Suche nach Chunk-Daten"; + Log.JNI.info("Konvertiere Chunk-Daten von region/*.mca,*.mcr"); + File regionDir = new File(dir, "region"); + if(regionDir.exists()) { + File chunkDir = new File(new File(dir, "chunk"), "terra"); + Log.JNI.info("Konvertiere Welt nach '" + chunkDir + "' ..."); + Log.JNI.info("Durchsuche Ordner unter '" + regionDir + "' nach .mca- und .mcr-Dateien ..."); + File[] files = regionDir.listFiles(new FilenameFilter() { + public boolean accept(File file, String name) { + return name.endsWith(".mca") || name.endsWith(".mcr"); + } + }); + if(files.length == 0) { + Log.JNI.info("Keine .mca- oder .mcr-Dateien gefunden."); + } + else { + conv.task = "Konvertiere Chunkdaten"; + conv.totalRegions = files.length; + Log.JNI.info("Ingesamt wurden " + files.length + " .mca-Dateien und .mcr-Dateien gefunden, konvertiere ..."); + if(ver == SaveVersion.RELEASE_1_9) + Log.JNI.info("Konvertiere von neuerer Version, dies wird Blöcke entfernen ..."); + chunkDir.mkdirs(); + int progress = 0; + long time = System.currentTimeMillis(); + long start = conv.postProgress(time, 0); + for(File file : files) { + int percent = (int)Math.round(100.0D * (double)progress / (double)files.length); + Log.JNI.info("Konvertiere Chunk-Daten: " + file.getName() + " (" + progress + "/" + files.length + ")"); + start = conv.convertChunks(chunkDir, file, start, progress, files.length); + ++progress; + start = conv.postProgress(start, percent); + conv.doneRegions += 1; + } + time = System.currentTimeMillis() - time; + Log.JNI.info("Fertig. Konversion dauerte " + ((time / 60000L) > 0 ? ((time / 60000L) + " Minuten und ") : "") + ((time / 1000L) % 60L) + " Sekunden."); + } + } + } + else { + Log.JNI.warn("Konvertiere keine Chunk-Daten, da Version zu neu"); + } + conv.doneRegions = 0; + conv.task = null; + conv.action = "Konvertiere level.dat"; + Log.JNI.info("Konvertiere Daten von level.dat"); + Config.clear(); + UniverseRegistry.clear(); + if(tag.hasKey("GameRules", 10)) { + NBTTagCompound rules = tag.getCompoundTag("GameRules"); + for(Entry rule : OLD_GAMERULES.entrySet()) { + if(rules.hasKey(rule.getKey(), 8)) + Config.set(rule.getValue(), rules.getString(rule.getKey()), null); + } + } + // Config.setVar("noRespawn", "" + nbt.getBoolean("hardcore"), false); + // int id = nbt.getInteger("GameType"); + // Config.set("defaultNoCreative", "" + (id == 2 || id == 0), false); + Log.JNI.info("Speichere neue level.nbt ..."); + Region.saveWorldInfo(dir, wtime); +// if(tag.hasKey("Player", 10)) { +// conv.action = "Konvertiere Spielerdaten"; +// NBTTagCompound player = tag.getCompoundTag("Player"); +// NBTTagList pos = player.getTagList("Pos", 6); +// NBTTagList motion = player.getTagList("Motion", 6); +// NBTTagList rotation = player.getTagList("Rotation", 5); +// boolean ground = player.getBoolean("OnGround"); +// BlockPos spawn = null; +// // boolean force = player.getBoolean("OnGround"); +// // int mode = -1; +// // if(player.hasKey("playerGameType", 99)) { +// // mode = player.getInteger("playerGameType"); +// // mode = mode == 0 || mode == 2 ? 0 : (mode == 1 || mode == 3 ? 1 : -1); +// // } +// if(player.hasKey("SpawnX", 99) && player.hasKey("SpawnY", 99) && player.hasKey("SpawnZ", 99)) { +// spawn = new BlockPos(player.getInteger("SpawnX"), player.getInteger("SpawnY"), +// player.getInteger("SpawnZ")); +// // force = player.getBoolean("SpawnForced"); +// } +// player.getKeySet().clear(); +// player.setTag("Pos", pos); +// player.setTag("Motion", motion); +// player.setTag("Rotation", rotation); +// player.setBoolean("OnGround", ground); +// player.setInteger("Dimension", 1); +// player.setString("id", EntityRegistry.getEntityString(EntityHuman.class)); +// if(spawn != null) { +// player.setInteger("SpawnX", spawn.getX()); +// player.setInteger("SpawnY", spawn.getY()); +// player.setInteger("SpawnZ", spawn.getZ()); +// player.setInteger("SpawnDim", 1); +// // player.setBoolean("SpawnForced", force); +// } +// player.setInteger("OriginX", tag.getInteger("SpawnX")); +// player.setInteger("OriginY", tag.getInteger("SpawnY")); +// player.setInteger("OriginZ", tag.getInteger("SpawnZ")); +// player.setInteger("OriginDim", 1); +// player.setString("CustomName", user.substring(0, 1).toUpperCase() + user.substring(1)); +// NBTTagCompound plr = new NBTTagCompound(); +// plr.setInteger("selected", 0); +// NBTTagList list = new NBTTagList(); +// list.appendTag(player); +// plr.setTag("characters", list); +// // if(mode >= 0) +// // player.setBoolean("creative", mode == 1); +// Log.JNI.info("Speichere neue Spielerdaten " + user.toLowerCase() + ".nbt ..."); +// File pdat = new File(new File(dir, "players"), user.toLowerCase() + ".nbt"); +// try { +// pdat.getParentFile().mkdirs(); +// NBTLoader.writeGZip(plr, pdat); +// } +// catch(Exception e) { +// Log.JNI.error(e, "Fehler beim Schreiben von " + pdat); +// } +// } + Weather weather = tag.getBoolean("thundering") ? Weather.THUNDER : (tag.getBoolean("raining") ? Weather.RAIN : Weather.CLEAR); + if(weather != Weather.CLEAR) { + conv.action = "Konvertiere Dimensionsdaten"; + NBTTagCompound dataTag = new NBTTagCompound(); + dataTag.setString("Weather", weather.getName()); + Log.JNI.info("Speichere neue data.nbt ..."); + File dataFile = new File(new File(new File(dir, "chunk"), "terra"), "data.nbt"); + try { + NBTLoader.writeGZip(dataTag, dataFile); + } + catch(Exception e) { + Log.JNI.error(e, "Konnte Weltdaten nicht speichern"); + } + } + Log.IO.info("Welt '" + dir + "' wurde in %d Sekunden konvertiert", (System.currentTimeMillis() - cur) / 1000L); + Client.CLIENT.schedule(new Runnable() { + public void run() { + Client.CLIENT.displayGuiScreen(GuiConvert.INSTANCE); + } + }); } - } - Log.JNI.info("Speichere neue server.nbt ..."); - Server.saveServerConfig(wtime); - Weather weather = nbt.getBoolean("thundering") ? Weather.THUNDER : (nbt.getBoolean("raining") ? Weather.RAIN : Weather.CLEAR); - if(weather != Weather.CLEAR) { - NBTTagCompound dataTag = new NBTTagCompound(); - dataTag.setString("Weather", weather.getName()); - Log.JNI.info("Speichere neue data.nbt ..."); - File dataFile = new File(new File(new File("chunk"), "terra"), "data.nbt"); - try { - NBTLoader.writeGZip(dataTag, dataFile); - } - catch(Exception e) { - Log.JNI.error(e, "Konnte Weltdaten nicht speichern"); - } - } - Log.IO.info("Welt wurde in %d Sekunden konvertiert", (System.currentTimeMillis() - cur) / 1000L); - return true; + }, "Converter Thread").start(); + return new FolderInfo(wtime, System.currentTimeMillis(), null, Config.VERSION); } + +// public static NBTTagCompound getLegacyWorldInfo(File worldDir) { +// return nbt; +// } } diff --git a/common/src/common/ai/AIFireballAttack.java b/common/src/common/ai/AIFireballAttack.java index 23b492c..87a3b8d 100755 --- a/common/src/common/ai/AIFireballAttack.java +++ b/common/src/common/ai/AIFireballAttack.java @@ -30,7 +30,7 @@ public class AIFireballAttack extends EntityAIBase public boolean shouldExecute() { - return this.parentEntity.getNode().getAttackTarget() != null; + return this.parentEntity.getAttackTarget() != null; } public void startExecuting() @@ -45,7 +45,7 @@ public class AIFireballAttack extends EntityAIBase public void updateTask() { - EntityLiving target = this.parentEntity.getNode().getAttackTarget(); + EntityLiving target = this.parentEntity.getAttackTarget(); // double d0 = 64.0D; if (target.getDistanceSqToEntity(this.parentEntity) < this.distance * this.distance && this.parentEntity.canEntityBeSeen(target)) @@ -84,7 +84,7 @@ public class AIFireballAttack extends EntityAIBase world.spawnEntityInWorld(fireball); this.attackTimer = -this.delay * this.parentEntity.getRNG().range(1, 4); } - this.parentEntity.getNode().getLookHelper().setLookPositionWithEntity(target, 30.0f, 30.0f); + this.parentEntity.getLookHelper().setLookPositionWithEntity(target, 30.0f, 30.0f); } else if (this.attackTimer > 0) { diff --git a/common/src/common/ai/EntityAIControlledByPlayer.java b/common/src/common/ai/EntityAIControlledByPlayer.java index 1bee8cc..320f4d1 100755 --- a/common/src/common/ai/EntityAIControlledByPlayer.java +++ b/common/src/common/ai/EntityAIControlledByPlayer.java @@ -166,7 +166,7 @@ public class EntityAIControlledByPlayer extends EntityAIBase if (flag && 0 == WalkNodeProcessor.getColliding(this.thisEntity.worldObj, this.thisEntity, l, j, i1, j1, k1, l1, false, false, true) && 1 == WalkNodeProcessor.getColliding(this.thisEntity.worldObj, this.thisEntity, i, j + 1, k, j1, k1, l1, false, false, true) && 1 == WalkNodeProcessor.getColliding(this.thisEntity.worldObj, this.thisEntity, l, j + 1, i1, j1, k1, l1, false, false, true)) { - entitycreature.getNode().getJumpHelper().setJumping(); + entitycreature.getJumpHelper().setJumping(); } } diff --git a/common/src/common/ai/IEntityLivingNode.java b/common/src/common/ai/IEntityLivingNode.java deleted file mode 100644 index 6c10816..0000000 --- a/common/src/common/ai/IEntityLivingNode.java +++ /dev/null @@ -1,21 +0,0 @@ -package common.ai; - -import common.entity.DamageSource; -import common.entity.types.EntityLiving; -import common.nbt.NBTTagCompound; - -public interface IEntityLivingNode extends IEntityNode { - void update(); - void updateRenderAngles(); - void updateLeashedState(); - void setLeashTag(NBTTagCompound tag); - EntityLiving getAttacking(); - EntityLiving getAttackTarget(); - void resetCombat(); - void trackDamage(DamageSource source, int amount); - void sendDeathMessage(); - EntityJumpHelper getJumpHelper(); - EntityLookHelper getLookHelper(); - void updateAttacking(); - void dropExperience(); -} diff --git a/common/src/common/ai/IEntityMobNPCNode.java b/common/src/common/ai/IEntityMobNPCNode.java deleted file mode 100644 index b913f8c..0000000 --- a/common/src/common/ai/IEntityMobNPCNode.java +++ /dev/null @@ -1,14 +0,0 @@ -package common.ai; - -import common.entity.Entity; -import common.entity.types.EntityLiving; - -public interface IEntityMobNPCNode extends IEntityNPCNode { - - void becomeAngryAt(Entity entity); - - boolean isAngry(); - - void setAngerTarget(EntityLiving entity); - -} \ No newline at end of file diff --git a/common/src/common/ai/IEntityNPCNode.java b/common/src/common/ai/IEntityNPCNode.java deleted file mode 100644 index f513d38..0000000 --- a/common/src/common/ai/IEntityNPCNode.java +++ /dev/null @@ -1,9 +0,0 @@ -package common.ai; - -import common.entity.types.EntityLiving; - -public interface IEntityNPCNode extends IEntityLivingNode { - void setCombatTask(); - boolean canCounter(EntityLiving entity); - boolean canAttack(EntityLiving entity); -} diff --git a/common/src/common/ai/IEntityNode.java b/common/src/common/ai/IEntityNode.java index d38f988..d4d89ee 100644 --- a/common/src/common/ai/IEntityNode.java +++ b/common/src/common/ai/IEntityNode.java @@ -1,10 +1,17 @@ package common.ai; +import common.entity.DamageSource; +import common.entity.types.EntityLiving; import common.nbt.NBTTagCompound; -import common.world.World; public interface IEntityNode { - void readNbt(NBTTagCompound tag); - void writeNbt(NBTTagCompound tag); - void setWorld(World world); + void update(); + void updateRenderAngles(); + void updateLeashedState(); + void setLeashTag(NBTTagCompound tag); + EntityLiving getAttacking(); + EntityLiving getAttackTarget(); + void resetCombat(); + void trackDamage(DamageSource source, int amount); + void sendDeathMessage(); } diff --git a/common/src/common/entity/Entity.java b/common/src/common/entity/Entity.java index 8921c9a..61d7871 100755 --- a/common/src/common/entity/Entity.java +++ b/common/src/common/entity/Entity.java @@ -2,8 +2,6 @@ package common.entity; import java.util.List; -import common.ai.IEntityLivingNode; -import common.ai.IEntityNode; import common.block.Block; import common.block.BlockFence; import common.block.BlockFenceGate; @@ -47,14 +45,13 @@ import common.world.State; import common.world.World; import common.world.WorldServer; -public abstract class Entity +public abstract class Entity { private static final BoundingBox ZERO_AABB = new BoundingBox(0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D); private static int nextID; protected final DataWatcher dataWatcher; protected final Random rand; - protected T node; private int eid; public World worldObj; @@ -120,14 +117,6 @@ public abstract class Entity public boolean isAirBorne; protected PortalType inPortal; // private boolean invulnerable; - - public T getNode() { - return this.node; - } - - public void setNode(T node) { - this.node = node; - } public int getId() { @@ -1141,8 +1130,6 @@ public abstract class Entity public void setWorld(World worldIn) { this.worldObj = worldIn; - if(this.node != null) - this.node.setWorld(worldIn); } /** @@ -1536,8 +1523,6 @@ public abstract class Entity tagCompund.setBoolean("IgnoreFall", this.ignoreFall); this.writeEntityToNBT(tagCompund); - if(this.node != null) - this.node.writeNbt(tagCompund); if (this.vehicle != null && !(this.isPlayer())) { @@ -1607,8 +1592,6 @@ public abstract class Entity // this.setSilent(tagCompund.getBoolean("Silent")); this.ignoreFall = tagCompund.getBoolean("IgnoreFall"); this.readEntityFromNBT(tagCompund); - if(this.node != null) - this.node.readNbt(tagCompund); if (this.shouldSetPosAfterLoading()) { diff --git a/common/src/common/entity/npc/AIHurtByAggressor.java b/common/src/common/entity/npc/AIHurtByAggressor.java deleted file mode 100644 index fe7838e..0000000 --- a/common/src/common/entity/npc/AIHurtByAggressor.java +++ /dev/null @@ -1,22 +0,0 @@ -package common.entity.npc; - -import common.ai.EntityAIHurtByTarget; -import common.entity.types.EntityLiving; - -public class AIHurtByAggressor extends EntityAIHurtByTarget -{ - public AIHurtByAggressor(EntityMobNPC p_i45828_1_) - { - super(p_i45828_1_, true); - } - - protected void setEntityAttackTarget(EntityLiving creatureIn, EntityLiving entityLivingBaseIn) - { - super.setEntityAttackTarget(creatureIn, entityLivingBaseIn); - - if (creatureIn.getClass() == this.taskOwner.getClass()) - { - ((EntityMobNPC)creatureIn).getNode().becomeAngryAt(entityLivingBaseIn); - } - } -} \ No newline at end of file diff --git a/common/src/common/entity/npc/EntityChaosMarine.java b/common/src/common/entity/npc/EntityChaosMarine.java index 1e18b2a..cccb1b3 100755 --- a/common/src/common/entity/npc/EntityChaosMarine.java +++ b/common/src/common/entity/npc/EntityChaosMarine.java @@ -108,7 +108,7 @@ public class EntityChaosMarine extends EntityNPC { return 20; } - public int getAttackSpeed() { + protected int getAttackSpeed() { return 5; } diff --git a/common/src/common/entity/npc/EntityGargoyle.java b/common/src/common/entity/npc/EntityGargoyle.java index 69914e3..0f6b358 100755 --- a/common/src/common/entity/npc/EntityGargoyle.java +++ b/common/src/common/entity/npc/EntityGargoyle.java @@ -141,6 +141,10 @@ public class EntityGargoyle extends EntityFlyingNPC // this.launchBoxToEntity(target); // } + public boolean isRangedWeapon(ItemStack stack) { + return false; + } + public boolean attackEntityFrom(DamageSource source, int amount) { // if (this.isEntityInvulnerable(source)) diff --git a/common/src/common/entity/npc/EntityMobNPC.java b/common/src/common/entity/npc/EntityMobNPC.java index c504d19..e36c35f 100755 --- a/common/src/common/entity/npc/EntityMobNPC.java +++ b/common/src/common/entity/npc/EntityMobNPC.java @@ -1,45 +1,317 @@ package common.entity.npc; -import common.ai.IEntityMobNPCNode; +import common.ai.EntityAIHurtByTarget; import common.entity.DamageSource; import common.entity.Entity; +import common.entity.attributes.AttributeInstance; +import common.entity.attributes.Attributes; import common.entity.types.EntityLiving; +import common.nbt.NBTTagCompound; import common.world.World; -public abstract class EntityMobNPC extends EntityNPC +public abstract class EntityMobNPC extends EntityNPC { - public T getNode() { - return this.node; - } - + private int angerLevel; +// private int randomSoundDelay; + private int angerTarget; +// private Class angerClass; + public EntityMobNPC(World worldIn) { super(worldIn); + this.targets.addTask(1, new AIHurtByAggressor(this)); +// this.targets.addTask(2, new AITargetAggressor(this)); } +// public boolean isImmuneToFire() +// { +// return true; +// } + public void setAttackedBy(EntityLiving livingBase) { super.setAttackedBy(livingBase); if (livingBase != null) { - this.node.setAngerTarget(livingBase); + this.angerTarget = livingBase.getId(); } } - + +// protected void applyEntityAI() +// { +// this.targets.addTask(1, new EntityMobNPC.AIHurtByAggressor(this)); +// this.targets.addTask(2, new EntityMobNPC.AITargetAggressor(this)); +// } + +// protected void applyEntityAttributes() +// { +// super.applyEntityAttributes(); +// this.getEntityAttribute(Attributes.REINFORCEMENT_CHANCE).setBaseValue(0.0D); +// this.getEntityAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(0.23000000417232513D); +// this.getEntityAttribute(Attributes.ATTACK_DAMAGE).setBaseValue(5.0D); +// } + +// /** +// * Called to update the entity's position/logic. +// */ +// public void onUpdate() +// { +// super.onUpdate(); +// } + + protected void updateAITasks() + { + AttributeInstance iattributeinstance = this.getEntityAttribute(Attributes.MOVEMENT_SPEED); + + if (this.isAngry()) + { + if (/* !this.isChild() && */ !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.randomSoundDelay > 0 && --this.randomSoundDelay == 0) +// { +// this.playSound("mob.zombiepig.zpigangry", this.getSoundVolume() * 2.0F, ((this.rand.floatv() - this.rand.floatv()) * 0.2F + 1.0F) * 1.8F); +// } + + if (this.angerLevel > 0 && this.angerTarget != 0 && this.getAttackedBy() == null) + { + Entity entity = this.worldObj.getEntityByID(this.angerTarget); + if(entity instanceof EntityLiving) + this.setAttackedBy((EntityLiving)entity); + if(entity != null && entity.isPlayer()) + this.playerAttacker = (EntityNPC)entity; + this.recentlyHit = this.getAttackedTime(); + } + + super.updateAITasks(); + } + +// /** +// * Checks if the entity's current position is a valid location to spawn this entity. +// */ +// public boolean getCanSpawnHere() +// { +// return this.worldObj.getDifficulty() != Difficulty.PEACEFUL; +// } + + /** + * (abstract) Protected helper method to write subclass entity data to NBT. + */ + public void writeEntityToNBT(NBTTagCompound tagCompound) + { + super.writeEntityToNBT(tagCompound); + tagCompound.setShort("Anger", (short)this.angerLevel); + +// if (this.angerTarget != null) +// { +// tagCompound.setString("HurtBy", this.angerTarget); +// } +// else +// { +// tagCompound.setString("HurtBy", ""); +// } + } + + /** + * (abstract) Protected helper method to read subclass entity data from NBT. + */ + public void readEntityFromNBT(NBTTagCompound tagCompund) + { + super.readEntityFromNBT(tagCompund); + this.angerLevel = tagCompund.getShort("Anger"); +// String s = tagCompund.getString("HurtBy"); +// +// if (s.length() > 0) +// { +// this.angerTarget = s; +// EntityNPC entityplayer = this.worldObj.getPlayer(this.angerTarget); +// this.setAttackedBy(entityplayer); +// +// if (entityplayer != null) +// { +// this.playerAttacker = entityplayer; +// this.recentlyHit = this.getAttackedTime(); +// } +// } + } + + /** + * Called when the entity is attacked. + */ public boolean attackEntityFrom(DamageSource source, int amount) { +// if (this.isEntityInvulnerable(source)) +// { +// return false; +// } +// else +// { Entity entity = source.getEntity(); if (entity != null && entity instanceof EntityNPC) { - this.node.becomeAngryAt(entity); + this.becomeAngryAt(entity); } return super.attackEntityFrom(source, amount); +// } } - public boolean isAggressive(Class clazz) { - return this.node.isAngry() && clazz != this.getClass() && !this.isPeaceful(clazz); + /** + * Causes this PigZombie to become angry at the supplied Entity (which will be a player). + */ + private void becomeAngryAt(Entity p_70835_1_) + { + this.angerLevel = this.rand.excl(400, 800); +// this.randomSoundDelay = this.rand.zrange(40); + + if (p_70835_1_ instanceof EntityLiving) + { + this.setAttackedBy((EntityLiving)p_70835_1_); + } } + + public boolean isAngry() + { + return this.angerLevel > 0; + } + +// /** +// * Returns the sound this mob makes while it's alive. +// */ +// protected String getLivingSound() +// { +// return "mob.zombiepig.zpig"; +// } +// +// /** +// * Returns the sound this mob makes when it is hurt. +// */ +// protected String getHurtSound() +// { +// return "mob.zombiepig.zpighurt"; +// } +// +// /** +// * Returns the sound this mob makes on death. +// */ +// protected String getDeathSound() +// { +// return "mob.zombiepig.zpigdeath"; +// } + +// /** +// * Drop 0-2 items of this living's type +// * +// * @param wasRecentlyHit true if this this entity was recently hit by appropriate entity (generally only if player +// * or tameable) +// * @param lootingModifier level of enchanment to be applied to this drop +// */ +// protected void dropFewItems(boolean wasRecentlyHit, int lootingModifier) +// { +// int i = this.rand.zrange(2 + lootingModifier); +// +// for (int j = 0; j < i; ++j) +// { +// this.dropItem(Items.rotten_flesh, 1); +// } +// +// i = this.rand.zrange(2 + lootingModifier); +// +// for (int k = 0; k < i; ++k) +// { +// this.dropItem(Items.gold_nugget, 1); +// } +// } +// +// /** +// * Called when a player interacts with a mob. e.g. gets milk from a cow, gets into the saddle on a pig. +// */ +// public boolean interact(EntityNPC player) +// { +// return false; +// } +// +// /** +// * Causes this Entity to drop a random item. +// */ +// protected void addRandomDrop() +// { +// this.dropItem(Items.gold_ingot, 1); +// } +// +// /** +// * Gives armor or weapon for entity based on given DifficultyInstance +// */ +// protected void setEquipmentBasedOnDifficulty(DifficultyInstance difficulty) +// { +// this.setItem(0, new ItemStack(Items.golden_sword)); +// } +// +// /** +// * Called only once on an entity when first time spawned, via egg, mob spawner, natural spawning etc, but not called +// * when entity is reloaded from nbt. Mainly used for initializing attributes and inventory +// */ +// public IEntityLivingData onInitialSpawn(DifficultyInstance difficulty, IEntityLivingData livingdata) +// { +// super.onInitialSpawn(difficulty, livingdata); +//// this.setVillager(false); +// return livingdata; +// } + +// public int getColor() { +// return 0xff9494; +// } + +// public void onStruckByLightning(EntityLightning lightningBolt) { +// } + + public boolean isAggressive(Class clazz) { + return this.isAngry() && clazz != this.getClass() && !this.isPeaceful(clazz); + } + + static class AIHurtByAggressor extends EntityAIHurtByTarget + { + public AIHurtByAggressor(EntityMobNPC p_i45828_1_) + { + super(p_i45828_1_, true); + } + + protected void setEntityAttackTarget(EntityLiving creatureIn, EntityLiving entityLivingBaseIn) + { + super.setEntityAttackTarget(creatureIn, entityLivingBaseIn); + + if (creatureIn.getClass() == this.taskOwner.getClass()) + { + ((EntityMobNPC)creatureIn).becomeAngryAt(entityLivingBaseIn); + } + } + } + +// static class AITargetAggressor extends EntityAINearestAttackableTarget +// { +// public AITargetAggressor(EntityMobNPC p_i45829_1_) +// { +// super(p_i45829_1_, EntityLiving.class, 10, true, false, new Predicate() { +// public boolean test(EntityLiving entity) { +// return entity.isPlayer(); // || entity instanceof EntityNPC; +// } +// }); +// } +// +// public boolean shouldExecute() +// { +// return ((EntityMobNPC)this.taskOwner).isAngry() && super.shouldExecute(); +// } +// } } diff --git a/common/src/common/entity/npc/EntityNPC.java b/common/src/common/entity/npc/EntityNPC.java index 9eb5926..ffd5e7b 100755 --- a/common/src/common/entity/npc/EntityNPC.java +++ b/common/src/common/entity/npc/EntityNPC.java @@ -2,8 +2,24 @@ package common.entity.npc; import java.lang.reflect.InvocationTargetException; import java.util.List; +import java.util.function.Predicate; + import common.IClient; -import common.ai.IEntityNPCNode; +import common.ai.AIRangedAttack; +import common.ai.EntityAIAttackOnCollide; +import common.ai.EntityAIAvoidEntity; +import common.ai.EntityAIHurtByTarget; +import common.ai.EntityAILookAtTalkingPlayer; +import common.ai.EntityAINagPlayer; +import common.ai.EntityAINearestAttackableTarget; +import common.ai.EntityAINpcInteract; +import common.ai.EntityAINpcMate; +import common.ai.EntityAIOpenDoor; +import common.ai.EntityAIPlay; +import common.ai.EntityAISwimming; +import common.ai.EntityAIWander; +import common.ai.EntityAIWatchClosest; +import common.ai.EntityAIWatchClosest2; import common.block.Block; import common.block.BlockBed; import common.dimension.Space; @@ -62,6 +78,7 @@ import common.packet.CPacketInput; import common.packet.CPacketPlayer; import common.packet.SPacketEntityEquipment; import common.packet.SPacketEntityVelocity; +import common.pathfinding.PathNavigateGround; import common.potion.Potion; import common.potion.PotionEffect; import common.rng.Random; @@ -81,7 +98,7 @@ import common.world.World; import common.world.WorldClient; import common.world.WorldServer; -public abstract class EntityNPC extends EntityLiving +public abstract class EntityNPC extends EntityLiving { public static class CharacterTypeData { @@ -193,10 +210,6 @@ public abstract class EntityNPC extends EntityLiving extends EntityLiving extends EntityLiving extends Entity +public abstract class EntityLiving extends Entity { private static final ItemStack[] EMPTY_INV = new ItemStack[5]; + protected IEntityNode node; private AttributeMap attributes; private final Map effects = Maps.newEnumMap(Potion.class); public int soundTimer; @@ -104,6 +105,13 @@ public abstract class EntityLiving extends Entity extends Entity extends Entity 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.ticksExisted - this.lastAttacked > 100) + { + this.setAttackedBy(null); + } + } + if(!this.worldObj.client) { - this.node.updateAttacking(); - if(!this.firstEffectUpdate && Config.radiation) { // && // (!(this.isPlayer()) || !((EntityNPCMP)this).creative)) { float radiation = this.radiation + (float)this.attributes.getAttributeInstance(Attributes.RADIATION).getAttributeValue(); @@ -357,9 +389,16 @@ public abstract class EntityLiving extends Entity 0 || this.isPlayer()) && this.canDropLoot() && Config.mobXP) { - this.node.dropExperience(); + int i = this.getExperiencePoints(this.playerAttacker); + + while (i > 0) + { + int j = EntityXp.getXPSplit(i); + i -= j; + this.worldObj.spawnEntityInWorld(new EntityXp(this.worldObj, this.posX, this.posY, this.posZ, j)); + } } this.setDead(); @@ -413,6 +452,46 @@ public abstract class EntityLiving extends Entity extends Entity> 9, z < 0 ? 'n' : 'p', ((z < 0) ? -z : z) >> 9); - } - - public static String getRegionName(int x, int z) { - return String.format("r.%c%X%c%X.rgn", x < 0 ? 'n' : 'p', ((x < 0) ? -x : x) >> 3, z < 0 ? 'n' : 'p', ((z < 0) ? -z : z) >> 3); - } } diff --git a/common/src/common/world/Region.java b/common/src/common/world/Region.java index ea0a6ae..06bbb84 100755 --- a/common/src/common/world/Region.java +++ b/common/src/common/world/Region.java @@ -22,7 +22,9 @@ import common.collect.Lists; import common.collect.Maps; import common.entity.Entity; import common.init.BlockRegistry; +import common.init.Config; import common.init.EntityRegistry; +import common.init.UniverseRegistry; import common.log.Log; import common.nbt.NBTLoader; import common.nbt.NBTTagCompound; @@ -31,9 +33,39 @@ import common.tileentity.TileEntity; import common.util.BlockPos; import common.util.NextTickListEntry; import common.util.NibbleArray; -import common.util.Util; public class Region { + public static enum SaveVersion { + ALPHA_1_0("Alpha 1.0 - Beta 1.2"), + BETA_1_3("Beta 1.3 - Release 1.8.9"), + RELEASE_1_9("Release 1.9 - Release 1.12.2"), + RELEASE_1_13("Release 1.13 +"); + + private final String name; + + private SaveVersion(String name) { + this.name = name; + } + + public String toString() { + return this.name; + } + } + + public static class FolderInfo { + public final long time; + public final long lastPlayed; + public final SaveVersion legacy; + public final String version; + + public FolderInfo(long time, long lastPlayed, SaveVersion legacy, String version) { + this.time = time; + this.lastPlayed = lastPlayed; + this.legacy = legacy; + this.version = version; + } + } + private static class ChunkBuffer extends ByteArrayOutputStream { public ChunkBuffer() { super(8096); @@ -58,7 +90,10 @@ public class Region { private static final Map CACHE = Maps.newHashMap(); private static final List QUEUE = Collections.synchronizedList(Lists.newArrayList()); - + +// public static long lastPlayed; +// public static int version; +// public static String owner; private static volatile long queued; private static volatile long saved; private static volatile boolean waiting; @@ -78,10 +113,10 @@ public class Region { private boolean modified; public Region(File dir, int x, int z) { - File sdir = new File(dir, Util.getRegionFolder(x << 3, z << 3)); + File sdir = new File(dir, getRegionFolder(x << 3, z << 3)); if(!sdir.exists()) sdir.mkdirs(); - this.regFile = new File(sdir, Util.getRegionName(x << 3, z << 3)); + this.regFile = new File(sdir, getRegionName(x << 3, z << 3)); this.folder = dir; this.xPos = x; this.zPos = z; @@ -278,6 +313,13 @@ public class Region { this.write(x, z, buf.getData(), buf.size()); } +// public NBTTagCompound readTag(int x, int z) throws IOException { +// byte[] data = this.read(x, z); +// if(data == null) +// return null; +// return CompressedStreamTools.read(new DataInputStream(new BufferedInputStream(new InflaterInputStream(new ByteArrayInputStream(data))))); +// } + public File getFile() { return this.regFile; } @@ -294,7 +336,7 @@ public class Region { } private static File getExpansionFile(File dir, int x, int z) { - File sdir = new File(dir, Util.getRegionFolder(x, z)); + File sdir = new File(dir, getRegionFolder(x, z)); if(!sdir.exists()) sdir.mkdirs(); return new File(sdir, String.format("c.%c%X%c%X.chk", x < 0 ? 'n' : 'p', (x < 0) ? -x : x, z < 0 ? 'n' : 'p', (z < 0) ? -z : z)); @@ -357,6 +399,14 @@ public class Region { // getRegionFile(dir, x >> 3, z >> 3).writeTag(x & 7, z & 7, tag); } + public static String getRegionFolder(int x, int z) { + return String.format("%c%03X%c%03X", x < 0 ? 'n' : 'p', ((x < 0) ? -x : x) >> 9, z < 0 ? 'n' : 'p', ((z < 0) ? -z : z) >> 9); + } + + public static String getRegionName(int x, int z) { + return String.format("r.%c%X%c%X.rgn", x < 0 ? 'n' : 'p', ((x < 0) ? -x : x) >> 3, z < 0 ? 'n' : 'p', ((z < 0) ? -z : z) >> 3); + } + public static Chunk readNbt(WorldServer world, int x, int z, NBTTagCompound tag) { // if(!tag.hasKey("Level", 10)) { // Log.error("Chunk-Datei bei " + x + "," + z + " hat keine Level-Daten, überspringe"); @@ -630,4 +680,93 @@ public class Region { public static void killIO() { killed = true; } + + public static void saveWorldInfo(File worldDir, 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()); +// Config.Value value = Config.VARS.get(cvar); +// switch(value.getType()) { +// case BOOLEAN: +// cfg.setString(cvar, "" + value.getBoolean()); +// break; +// case INTEGER: +// cfg.setString(cvar, "" + value.getInt()); +// break; +// case FLOAT: +// cfg.setString(cvar, "" + value.getFloat()); +// break; +// case STRING: +// cfg.setString(cvar, value.getString()); +// break; +// } + } + data.setTag("Config", cfg); + data.setTag("Universe", UniverseRegistry.saveNbt()); + if(worldDir != null) + worldDir.mkdirs(); + File nfile = new File(worldDir, "level.nbt.tmp"); + File lfile = new File(worldDir, "level.nbt"); + try { +// File ofile = new File(worldDir, "level.nbt_old"); + NBTLoader.writeGZip(data, nfile); +// if(ofile.exists()) +// ofile.delete(); +// lfile.renameTo(ofile); + if(lfile.exists()) + lfile.delete(); + nfile.renameTo(lfile); +// if(nfile.exists()) +// nfile.delete(); + } + catch(Exception e) { + Log.JNI.error(e, "Fehler beim Schreiben von " + nfile); + } + } + + public static FolderInfo loadWorldInfo(File worldDir) { + Config.clear(); + UniverseRegistry.clear(); + File file = new File(worldDir, "level.nbt"); + if(!file.exists()) + file = new File(worldDir, "level.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")); + // tag.getInteger("Version"); + long lastPlayed = tag.getLong("LastAccess"); + String version = tag.hasKey("Version", 8) ? tag.getString("Version") : null; + version = version != null && version.isEmpty() ? null : version; + long time = tag.hasKey("Time", 4) ? tag.getLong("Time") : World.START_TIME; + return new FolderInfo(time, lastPlayed, null, version); + } + catch(Exception e) { + Log.JNI.error(e, "Fehler beim Lesen von " + file); + } + } + return null; + } + +// public static void reloadWorldInfo(File worldDir) { +// File file = new File(worldDir, "level.nbt"); +// if(file.exists()) { +// Config.clear(); +// try { +// Config.readFromNbt(NBTLoader.readGZip(file).getCompoundTag("Config"), true); +// } +// catch(Exception e) { +// Log.error("Fehler beim Lesen von " + file, e); +// return; +// } +// } +// } } diff --git a/common/src/common/world/WorldServer.java b/common/src/common/world/WorldServer.java index e6edce1..934b9ee 100755 --- a/common/src/common/world/WorldServer.java +++ b/common/src/common/world/WorldServer.java @@ -962,7 +962,6 @@ public final class WorldServer extends World { } protected void onEntityAdded(Entity entityIn) { - // TODO: add node this.trackEntity(entityIn); this.entityIds.addKey(entityIn.getId(), entityIn); Entity[] aentity = entityIn.getParts(); diff --git a/server/src/server/Server.java b/server/src/server/Server.java index c69725b..728a53d 100755 --- a/server/src/server/Server.java +++ b/server/src/server/Server.java @@ -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 SERVER_NIO_EVENTLOOP = new LazyLoadBase() { @@ -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() ? "" : 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(); diff --git a/server/src/server/ai/EntityLivingNode.java b/server/src/server/ai/EntityLivingNode.java deleted file mode 100644 index 584f859..0000000 --- a/server/src/server/ai/EntityLivingNode.java +++ /dev/null @@ -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 extends EntityNode implements IEntityLivingNode { - protected final Random rand; - private final List combat = Lists.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; - } -} diff --git a/server/src/server/ai/EntityMobNPCNode.java b/server/src/server/ai/EntityMobNPCNode.java deleted file mode 100644 index 0779e52..0000000 --- a/server/src/server/ai/EntityMobNPCNode.java +++ /dev/null @@ -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 extends EntityNPCNode 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(); - } -} diff --git a/server/src/server/ai/EntityNPCNode.java b/server/src/server/ai/EntityNPCNode.java index 1c0f807..b314cdc 100644 --- a/server/src/server/ai/EntityNPCNode.java +++ b/server/src/server/ai/EntityNPCNode.java @@ -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 extends EntityLivingNode 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 extends EntityLivingNode 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() { + this.tasks.addTask(1, new EntityAINpcMate(this.getEntity())); + this.tasks.addTask(2, new EntityAIAvoidEntity(this.getEntity(), EntityLiving.class, new Predicate() { 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 extends EntityLivingNode impl // EntityNPC.this.isFleeing = false; // } }); - this.tasks.addTask(3, new EntityAIAvoidEntity(this.entity, EntityLiving.class, new Predicate() { + this.tasks.addTask(3, new EntityAIAvoidEntity(this, EntityLiving.class, new Predicate() { 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 extends EntityLivingNode 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 extends EntityLivingNode 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() { + this.targets.addTask(2, new EntityAINearestAttackableTarget(this, EntityLiving.class, 10, true, false, new Predicate() { 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 extends EntityLivingNode 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); } diff --git a/server/src/server/ai/EntityNode.java b/server/src/server/ai/EntityNode.java index 914b118..2f4c0a7 100644 --- a/server/src/server/ai/EntityNode.java +++ b/server/src/server/ai/EntityNode.java @@ -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 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 combat = Lists.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); +// } } diff --git a/server/src/server/init/NodeRegistry.java b/server/src/server/init/NodeRegistry.java deleted file mode 100644 index e38b428..0000000 --- a/server/src/server/init/NodeRegistry.java +++ /dev/null @@ -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> NODES = Maps.newHashMap(); - - private static void registerNode(Class clazz, Class 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 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 getNodeClass(Class 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, ); - } - } -}