forked from BLOCKFANTASY/LOOHP-Limbo
0.4.0 SNAPSHOT
This commit is contained in:
parent
a0f45a5b17
commit
8d2b7ea0cb
2
pom.xml
2
pom.xml
|
|
@ -4,7 +4,7 @@
|
|||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.loohp</groupId>
|
||||
<artifactId>Limbo</artifactId>
|
||||
<version>0.3.8-ALPHA</version>
|
||||
<version>0.4.0-ALPHA-SNAPSHOT</version>
|
||||
<build>
|
||||
<sourceDirectory>src/main/java</sourceDirectory>
|
||||
<resources>
|
||||
|
|
|
|||
|
|
@ -152,7 +152,7 @@ public class Console implements CommandSender {
|
|||
return;
|
||||
}
|
||||
while (true) {
|
||||
String command = tabReader.readLine(PROMPT);
|
||||
String command = tabReader.readLine(PROMPT).trim();
|
||||
if (command.length() > 0) {
|
||||
String[] input = CustomStringUtils.splitStringToArgs(command);
|
||||
new Thread(() -> Limbo.getInstance().dispatchCommand(this, input)).start();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,135 @@
|
|||
package com.loohp.limbo.Entity;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import com.loohp.limbo.Limbo;
|
||||
import com.loohp.limbo.Entity.DataWatcher.WatchableField;
|
||||
import com.loohp.limbo.Entity.DataWatcher.WatchableObjectType;
|
||||
import com.loohp.limbo.Location.Location;
|
||||
import com.loohp.limbo.Utils.Rotation3f;
|
||||
import com.loohp.limbo.World.World;
|
||||
|
||||
public class ArmorStand extends LivingEntity {
|
||||
|
||||
@WatchableField(MetadataIndex = 14, WatchableObjectType = WatchableObjectType.BYTE, IsBitmask = true, Bitmask = 0x01)
|
||||
protected boolean small = false;
|
||||
@WatchableField(MetadataIndex = 14, WatchableObjectType = WatchableObjectType.BYTE, IsBitmask = true, Bitmask = 0x04)
|
||||
protected boolean arms = false;
|
||||
@WatchableField(MetadataIndex = 14, WatchableObjectType = WatchableObjectType.BYTE, IsBitmask = true, Bitmask = 0x08)
|
||||
protected boolean noBasePlate = false;
|
||||
@WatchableField(MetadataIndex = 14, WatchableObjectType = WatchableObjectType.BYTE, IsBitmask = true, Bitmask = 0x10)
|
||||
protected boolean marker = false;
|
||||
@WatchableField(MetadataIndex = 15, WatchableObjectType = WatchableObjectType.ROTATION)
|
||||
protected Rotation3f headRotation = new Rotation3f(0.0, 0.0, 0.0);
|
||||
@WatchableField(MetadataIndex = 16, WatchableObjectType = WatchableObjectType.ROTATION)
|
||||
protected Rotation3f bodyRotation = new Rotation3f(0.0, 0.0, 0.0);
|
||||
@WatchableField(MetadataIndex = 17, WatchableObjectType = WatchableObjectType.ROTATION)
|
||||
protected Rotation3f leftArmRotation = new Rotation3f(-10.0, 0.0, -10.0);
|
||||
@WatchableField(MetadataIndex = 18, WatchableObjectType = WatchableObjectType.ROTATION)
|
||||
protected Rotation3f rightArmRotation = new Rotation3f(-15.0, 0.0, 10.0);
|
||||
@WatchableField(MetadataIndex = 19, WatchableObjectType = WatchableObjectType.ROTATION)
|
||||
protected Rotation3f leftLegRotation = new Rotation3f(-1.0, 0.0, -1.0);
|
||||
@WatchableField(MetadataIndex = 20, WatchableObjectType = WatchableObjectType.ROTATION)
|
||||
protected Rotation3f rightLegRotation = new Rotation3f(1.0, 0.0, 1.0);
|
||||
|
||||
public ArmorStand(int entityId, UUID uuid, World world, double x, double y, double z, float yaw, float pitch) {
|
||||
super(EntityType.ARMOR_STAND, entityId, uuid, world, x, y, z, yaw, pitch);
|
||||
}
|
||||
|
||||
public ArmorStand(UUID uuid, World world, double x, double y, double z, float yaw, float pitch) {
|
||||
this(Limbo.getInstance().getNextEntityId(), uuid, world, x, y, z, yaw, pitch);
|
||||
}
|
||||
|
||||
public ArmorStand(World world, double x, double y, double z, float yaw, float pitch) {
|
||||
this(Limbo.getInstance().getNextEntityId(), UUID.randomUUID(), world, x, y, z, yaw, pitch);
|
||||
}
|
||||
|
||||
public ArmorStand(UUID uuid, Location location) {
|
||||
this(Limbo.getInstance().getNextEntityId(), uuid, location.getWorld(), location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
|
||||
}
|
||||
|
||||
public ArmorStand(Location location) {
|
||||
this(Limbo.getInstance().getNextEntityId(), UUID.randomUUID(), location.getWorld(), location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
|
||||
}
|
||||
|
||||
public boolean isSmall() {
|
||||
return small;
|
||||
}
|
||||
|
||||
public void setSmall(boolean small) {
|
||||
this.small = small;
|
||||
}
|
||||
|
||||
public boolean showArms() {
|
||||
return arms;
|
||||
}
|
||||
|
||||
public void setArms(boolean arms) {
|
||||
this.arms = arms;
|
||||
}
|
||||
|
||||
public boolean hasNoBasePlate() {
|
||||
return noBasePlate;
|
||||
}
|
||||
|
||||
public void setNoBasePlate(boolean noBasePlate) {
|
||||
this.noBasePlate = noBasePlate;
|
||||
}
|
||||
|
||||
public boolean isMarker() {
|
||||
return marker;
|
||||
}
|
||||
|
||||
public void setMarker(boolean marker) {
|
||||
this.marker = marker;
|
||||
}
|
||||
|
||||
public Rotation3f getHeadRotation() {
|
||||
return headRotation;
|
||||
}
|
||||
|
||||
public void setHeadRotation(Rotation3f headRotation) {
|
||||
this.headRotation = headRotation;
|
||||
}
|
||||
|
||||
public Rotation3f getBodyRotation() {
|
||||
return bodyRotation;
|
||||
}
|
||||
|
||||
public void setBodyRotation(Rotation3f bodyRotation) {
|
||||
this.bodyRotation = bodyRotation;
|
||||
}
|
||||
|
||||
public Rotation3f getLeftArmRotation() {
|
||||
return leftArmRotation;
|
||||
}
|
||||
|
||||
public void setLeftArmRotation(Rotation3f leftArmRotation) {
|
||||
this.leftArmRotation = leftArmRotation;
|
||||
}
|
||||
|
||||
public Rotation3f getRightArmRotation() {
|
||||
return rightArmRotation;
|
||||
}
|
||||
|
||||
public void setRightArmRotation(Rotation3f rightArmRotation) {
|
||||
this.rightArmRotation = rightArmRotation;
|
||||
}
|
||||
|
||||
public Rotation3f getLeftLegRotation() {
|
||||
return leftLegRotation;
|
||||
}
|
||||
|
||||
public void setLeftLegRotation(Rotation3f leftLegRotation) {
|
||||
this.leftLegRotation = leftLegRotation;
|
||||
}
|
||||
|
||||
public Rotation3f getRightLegRotation() {
|
||||
return rightLegRotation;
|
||||
}
|
||||
|
||||
public void setRightLegRotation(Rotation3f rightLegRotation) {
|
||||
this.rightLegRotation = rightLegRotation;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,178 @@
|
|||
package com.loohp.limbo.Entity;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
public class DataWatcher {
|
||||
|
||||
private Entity entity;
|
||||
private Map<Field, WatchableObject> values;
|
||||
|
||||
public DataWatcher(Entity entity) {
|
||||
this.entity = entity;
|
||||
this.values = new HashMap<>();
|
||||
|
||||
Class<?> clazz = entity.getClass();
|
||||
while (clazz != null) {
|
||||
for (Field field : clazz.getDeclaredFields()) {
|
||||
WatchableField a = field.getAnnotation(WatchableField.class);
|
||||
if (a != null) {
|
||||
field.setAccessible(true);
|
||||
try {
|
||||
values.put(field, new WatchableObject(field.get(entity), a.MetadataIndex(), a.WatchableObjectType(), a.IsOptional(), a.IsBitmask(), a.Bitmask()));
|
||||
} catch (IllegalArgumentException | IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
clazz = clazz.getSuperclass();
|
||||
}
|
||||
}
|
||||
|
||||
public Entity getEntity() {
|
||||
return entity;
|
||||
}
|
||||
|
||||
public boolean isValid() {
|
||||
return entity.isValid();
|
||||
}
|
||||
|
||||
public synchronized Map<Field, WatchableObject> update() throws IllegalArgumentException, IllegalAccessException {
|
||||
if (!isValid()) {
|
||||
return null;
|
||||
}
|
||||
Map<Field, WatchableObject> updated = new HashMap<>();
|
||||
for (Entry<Field, WatchableObject> entry : values.entrySet()) {
|
||||
Field field = entry.getKey();
|
||||
WatchableObject watchableObj = entry.getValue();
|
||||
field.setAccessible(true);
|
||||
Object newValue = field.get(entity);
|
||||
if ((newValue == null && watchableObj.getValue() != null) || (newValue != null && watchableObj.getValue() == null) || (newValue != null && watchableObj.getValue() != null && !newValue.equals(watchableObj.getValue()))) {
|
||||
watchableObj.setValue(newValue);
|
||||
updated.put(field, watchableObj);
|
||||
}
|
||||
}
|
||||
return updated;
|
||||
}
|
||||
|
||||
public Map<Field, WatchableObject> getWatchableObjects() {
|
||||
return Collections.unmodifiableMap(values);
|
||||
}
|
||||
|
||||
public static class WatchableObject {
|
||||
|
||||
private int index;
|
||||
private WatchableObjectType type;
|
||||
private boolean optional;
|
||||
private boolean isBitmask;
|
||||
private int bitmask;
|
||||
|
||||
private Object value;
|
||||
|
||||
public WatchableObject(Object value, int index, WatchableObjectType type, boolean optional, boolean isBitmask, int bitmask) {
|
||||
this.index = index;
|
||||
this.type = type;
|
||||
this.optional = optional;
|
||||
this.isBitmask = isBitmask;
|
||||
this.bitmask = bitmask;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public WatchableObject(Object value, int index, WatchableObjectType type, boolean isBitmask, int bitmask) {
|
||||
this(value, index, type, false, isBitmask, bitmask);
|
||||
}
|
||||
|
||||
public WatchableObject(Object value, int index, WatchableObjectType type, boolean optional) {
|
||||
this(value, index, type, optional, false, 0x00);
|
||||
}
|
||||
|
||||
public WatchableObject(Object value, int index, WatchableObjectType type) {
|
||||
this(value, index, type, false, false, 0x00);
|
||||
}
|
||||
|
||||
public Object getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(Object newValue) {
|
||||
this.value = newValue;
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
public WatchableObjectType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public boolean isOptional() {
|
||||
return optional;
|
||||
}
|
||||
|
||||
public boolean isBitmask() {
|
||||
return isBitmask;
|
||||
}
|
||||
|
||||
public int getBitmask() {
|
||||
return bitmask;
|
||||
}
|
||||
}
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
public static @interface WatchableField {
|
||||
int MetadataIndex();
|
||||
WatchableObjectType WatchableObjectType();
|
||||
boolean IsOptional() default false;
|
||||
boolean IsBitmask() default false;
|
||||
int Bitmask() default 0x00;
|
||||
}
|
||||
|
||||
public static enum WatchableObjectType {
|
||||
BYTE(0),
|
||||
VARINT(1, 17),
|
||||
FLOAT(2),
|
||||
STRING(3),
|
||||
CHAT(4, 5),
|
||||
SLOT(6),
|
||||
BOOLEAN(7),
|
||||
ROTATION(8),
|
||||
POSITION(9, 10),
|
||||
DIRECTION(11),
|
||||
UUID(-1, 12),
|
||||
BLOCKID(-1, 13),
|
||||
NBT(14),
|
||||
PARTICLE(15),
|
||||
VILLAGER_DATA(16),
|
||||
POSE(18);
|
||||
|
||||
int typeId;
|
||||
int optionalTypeId;
|
||||
|
||||
WatchableObjectType(int typeId, int optionalTypeId) {
|
||||
this.typeId = typeId;
|
||||
this.optionalTypeId = optionalTypeId;
|
||||
}
|
||||
|
||||
WatchableObjectType(int typeId) {
|
||||
this(typeId, -1);
|
||||
}
|
||||
|
||||
public int getTypeId() {
|
||||
return typeId;
|
||||
}
|
||||
|
||||
public int getOptionalTypeId() {
|
||||
return optionalTypeId;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,283 @@
|
|||
package com.loohp.limbo.Entity;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import com.loohp.limbo.Limbo;
|
||||
import com.loohp.limbo.Entity.DataWatcher.WatchableField;
|
||||
import com.loohp.limbo.Entity.DataWatcher.WatchableObjectType;
|
||||
import com.loohp.limbo.Location.Location;
|
||||
import com.loohp.limbo.World.World;
|
||||
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
|
||||
public abstract class Entity {
|
||||
|
||||
@WatchableField(MetadataIndex = 0, WatchableObjectType = WatchableObjectType.BYTE, IsBitmask = true, Bitmask = 0x01)
|
||||
protected boolean onFire = false;
|
||||
@WatchableField(MetadataIndex = 0, WatchableObjectType = WatchableObjectType.BYTE, IsBitmask = true, Bitmask = 0x02)
|
||||
protected boolean crouching = false;
|
||||
@WatchableField(MetadataIndex = 0, WatchableObjectType = WatchableObjectType.BYTE, IsBitmask = true, Bitmask = 0x04)
|
||||
protected boolean unused = false;
|
||||
@WatchableField(MetadataIndex = 0, WatchableObjectType = WatchableObjectType.BYTE, IsBitmask = true, Bitmask = 0x08)
|
||||
protected boolean sprinting = false;
|
||||
@WatchableField(MetadataIndex = 0, WatchableObjectType = WatchableObjectType.BYTE, IsBitmask = true, Bitmask = 0x10)
|
||||
protected boolean swimming = false;
|
||||
@WatchableField(MetadataIndex = 0, WatchableObjectType = WatchableObjectType.BYTE, IsBitmask = true, Bitmask = 0x20)
|
||||
protected boolean invisible = false;
|
||||
@WatchableField(MetadataIndex = 0, WatchableObjectType = WatchableObjectType.BYTE, IsBitmask = true, Bitmask = 0x40)
|
||||
protected boolean glowing = false;
|
||||
@WatchableField(MetadataIndex = 0, WatchableObjectType = WatchableObjectType.BYTE, IsBitmask = true, Bitmask = 0x80)
|
||||
protected boolean elytraFlying = false;
|
||||
@WatchableField(MetadataIndex = 1, WatchableObjectType = WatchableObjectType.VARINT)
|
||||
protected int air = 300;
|
||||
@WatchableField(MetadataIndex = 2, WatchableObjectType = WatchableObjectType.CHAT, IsOptional = true)
|
||||
protected BaseComponent[] customName = null;
|
||||
@WatchableField(MetadataIndex = 3, WatchableObjectType = WatchableObjectType.BOOLEAN)
|
||||
protected boolean customNameVisible = false;
|
||||
@WatchableField(MetadataIndex = 4, WatchableObjectType = WatchableObjectType.BOOLEAN)
|
||||
protected boolean silent = false;
|
||||
@WatchableField(MetadataIndex = 5, WatchableObjectType = WatchableObjectType.BOOLEAN)
|
||||
protected boolean noGravity = false;
|
||||
@WatchableField(MetadataIndex = 6, WatchableObjectType = WatchableObjectType.POSE)
|
||||
protected Pose pose = Pose.STANDING;
|
||||
|
||||
protected final EntityType type;
|
||||
|
||||
protected int entityId;
|
||||
protected UUID uuid;
|
||||
protected World world;
|
||||
protected double x;
|
||||
protected double y;
|
||||
protected double z;
|
||||
protected float yaw;
|
||||
protected float pitch;
|
||||
|
||||
public Entity(EntityType type, int entityId, UUID uuid, World world, double x, double y, double z, float yaw, float pitch) {
|
||||
this.type = type;
|
||||
this.entityId = entityId;
|
||||
this.uuid = uuid;
|
||||
this.world = world;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.yaw = yaw;
|
||||
this.pitch = pitch;
|
||||
}
|
||||
|
||||
public Entity(EntityType type, UUID uuid, World world, double x, double y, double z, float yaw, float pitch) {
|
||||
this(type, Limbo.getInstance().getNextEntityId(), uuid, world, x, y, z, yaw, pitch);
|
||||
}
|
||||
|
||||
public Entity(EntityType type, World world, double x, double y, double z, float yaw, float pitch) {
|
||||
this(type, Limbo.getInstance().getNextEntityId(), UUID.randomUUID(), world, x, y, z, yaw, pitch);
|
||||
}
|
||||
|
||||
public Entity(EntityType type, UUID uuid, Location location) {
|
||||
this(type, Limbo.getInstance().getNextEntityId(), uuid, location.getWorld(), location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
|
||||
}
|
||||
|
||||
public Entity(EntityType type, Location location) {
|
||||
this(type, Limbo.getInstance().getNextEntityId(), UUID.randomUUID(), location.getWorld(), location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
|
||||
}
|
||||
|
||||
public EntityType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public Location getLocation() {
|
||||
return new Location(world, x, y, z, yaw, pitch);
|
||||
}
|
||||
|
||||
public void teleport(Location location) {
|
||||
this.world = location.getWorld();
|
||||
this.x = location.getX();
|
||||
this.y = location.getY();
|
||||
this.z = location.getZ();
|
||||
this.yaw = location.getYaw();
|
||||
this.pitch = location.getPitch();
|
||||
}
|
||||
|
||||
public BaseComponent[] getCustomName() {
|
||||
return customName;
|
||||
}
|
||||
|
||||
public void setCustomName(String name) {
|
||||
this.customName = name == null ? null : new BaseComponent[] {new TextComponent(name)};
|
||||
}
|
||||
|
||||
public void setCustomName(BaseComponent component) {
|
||||
this.customName = component == null ? null : new BaseComponent[] {component};
|
||||
}
|
||||
|
||||
public void setCustomName(BaseComponent[] components) {
|
||||
this.customName = components;
|
||||
}
|
||||
|
||||
public boolean isOnFire() {
|
||||
return onFire;
|
||||
}
|
||||
|
||||
public void setOnFire(boolean onFire) {
|
||||
this.onFire = onFire;
|
||||
}
|
||||
|
||||
public boolean isCrouching() {
|
||||
return crouching;
|
||||
}
|
||||
|
||||
public void setCrouching(boolean crouching) {
|
||||
this.crouching = crouching;
|
||||
}
|
||||
|
||||
public boolean isSprinting() {
|
||||
return sprinting;
|
||||
}
|
||||
|
||||
public void setSprinting(boolean sprinting) {
|
||||
this.sprinting = sprinting;
|
||||
}
|
||||
|
||||
public boolean isSwimming() {
|
||||
return swimming;
|
||||
}
|
||||
|
||||
public void setSwimming(boolean swimming) {
|
||||
this.swimming = swimming;
|
||||
}
|
||||
|
||||
public boolean isInvisible() {
|
||||
return invisible;
|
||||
}
|
||||
|
||||
public void setInvisible(boolean invisible) {
|
||||
this.invisible = invisible;
|
||||
}
|
||||
|
||||
public boolean isGlowing() {
|
||||
return glowing;
|
||||
}
|
||||
|
||||
public void setGlowing(boolean glowing) {
|
||||
this.glowing = glowing;
|
||||
}
|
||||
|
||||
public boolean isElytraFlying() {
|
||||
return elytraFlying;
|
||||
}
|
||||
|
||||
public void setElytraFlying(boolean elytraFlying) {
|
||||
this.elytraFlying = elytraFlying;
|
||||
}
|
||||
|
||||
public int getAir() {
|
||||
return air;
|
||||
}
|
||||
|
||||
public void setAir(int air) {
|
||||
this.air = air;
|
||||
}
|
||||
|
||||
public boolean isCustomNameVisible() {
|
||||
return customNameVisible;
|
||||
}
|
||||
|
||||
public void setCustomNameVisible(boolean customNameVisible) {
|
||||
this.customNameVisible = customNameVisible;
|
||||
}
|
||||
|
||||
public boolean isSilent() {
|
||||
return silent;
|
||||
}
|
||||
|
||||
public void setSilent(boolean silent) {
|
||||
this.silent = silent;
|
||||
}
|
||||
|
||||
public boolean hasGravity() {
|
||||
return !noGravity;
|
||||
}
|
||||
|
||||
public void setGravity(boolean gravity) {
|
||||
this.noGravity = !gravity;
|
||||
}
|
||||
|
||||
public Pose getPose() {
|
||||
return pose;
|
||||
}
|
||||
|
||||
public void setPose(Pose pose) {
|
||||
this.pose = pose;
|
||||
}
|
||||
|
||||
public World getWorld() {
|
||||
return world;
|
||||
}
|
||||
|
||||
public void setWorld(World world) {
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
public double getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public void setX(double x) {
|
||||
this.x = x;
|
||||
}
|
||||
|
||||
public double getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
public void setY(double y) {
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
public double getZ() {
|
||||
return z;
|
||||
}
|
||||
|
||||
public void setZ(double z) {
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
public float getYaw() {
|
||||
return yaw;
|
||||
}
|
||||
|
||||
public void setYaw(float yaw) {
|
||||
this.yaw = yaw;
|
||||
}
|
||||
|
||||
public float getPitch() {
|
||||
return pitch;
|
||||
}
|
||||
|
||||
public void setPitch(float pitch) {
|
||||
this.pitch = pitch;
|
||||
}
|
||||
|
||||
public int getEntityId() {
|
||||
return entityId;
|
||||
}
|
||||
|
||||
public UUID getUniqueId() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public boolean isValid() {
|
||||
return world.getEntities().contains(this);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public void remove() {
|
||||
Limbo.getInstance().getUnsafe().removeEntity(world, this);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public DataWatcher getDataWatcher() {
|
||||
return Limbo.getInstance().getUnsafe().getDataWatcher(world, this);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,395 @@
|
|||
package com.loohp.limbo.Entity;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.loohp.limbo.Utils.NamespacedKey;
|
||||
import com.loohp.limbo.Player.Player;
|
||||
|
||||
public enum EntityType {
|
||||
|
||||
// These strings MUST match the strings in nms.EntityTypes and are case sensitive.
|
||||
/**
|
||||
* An item resting on the ground.
|
||||
* <p>
|
||||
* Spawn with {@link World#dropItem(Location, ItemStack)} or {@link
|
||||
* World#dropItemNaturally(Location, ItemStack)}
|
||||
*/
|
||||
//DROPPED_ITEM("item", Item.class, 1, false),
|
||||
/**
|
||||
* An experience orb.
|
||||
*/
|
||||
//EXPERIENCE_ORB("experience_orb", ExperienceOrb.class, 2),
|
||||
/**
|
||||
* @see AreaEffectCloud
|
||||
*/
|
||||
//AREA_EFFECT_CLOUD("area_effect_cloud", AreaEffectCloud.class, 3),
|
||||
/**
|
||||
* @see ElderGuardian
|
||||
*/
|
||||
//ELDER_GUARDIAN("elder_guardian", ElderGuardian.class, 4),
|
||||
/**
|
||||
* @see WitherSkeleton
|
||||
*/
|
||||
//WITHER_SKELETON("wither_skeleton", WitherSkeleton.class, 5),
|
||||
/**
|
||||
* @see Stray
|
||||
*/
|
||||
//STRAY("stray", Stray.class, 6),
|
||||
/**
|
||||
* A flying chicken egg.
|
||||
*/
|
||||
//EGG("egg", Egg.class, 7),
|
||||
/**
|
||||
* A leash attached to a fencepost.
|
||||
*/
|
||||
//LEASH_HITCH("leash_knot", LeashHitch.class, 8),
|
||||
/**
|
||||
* A painting on a wall.
|
||||
*/
|
||||
//PAINTING("painting", Painting.class, 9),
|
||||
/**
|
||||
* An arrow projectile; may get stuck in the ground.
|
||||
*/
|
||||
//ARROW("arrow", Arrow.class, 10),
|
||||
/**
|
||||
* A flying snowball.
|
||||
*/
|
||||
//SNOWBALL("snowball", Snowball.class, 11),
|
||||
/**
|
||||
* A flying large fireball, as thrown by a Ghast for example.
|
||||
*/
|
||||
//FIREBALL("fireball", LargeFireball.class, 12),
|
||||
/**
|
||||
* A flying small fireball, such as thrown by a Blaze or player.
|
||||
*/
|
||||
//SMALL_FIREBALL("small_fireball", SmallFireball.class, 13),
|
||||
/**
|
||||
* A flying ender pearl.
|
||||
*/
|
||||
//ENDER_PEARL("ender_pearl", EnderPearl.class, 14),
|
||||
/**
|
||||
* An ender eye signal.
|
||||
*/
|
||||
//ENDER_SIGNAL("eye_of_ender", EnderSignal.class, 15),
|
||||
/**
|
||||
* A flying splash potion.
|
||||
*/
|
||||
//SPLASH_POTION("potion", ThrownPotion.class, 16, false),
|
||||
/**
|
||||
* A flying experience bottle.
|
||||
*/
|
||||
//THROWN_EXP_BOTTLE("experience_bottle", ThrownExpBottle.class, 17),
|
||||
/**
|
||||
* An item frame on a wall.
|
||||
*/
|
||||
//ITEM_FRAME("item_frame", ItemFrame.class, 18),
|
||||
/**
|
||||
* A flying wither skull projectile.
|
||||
*/
|
||||
//WITHER_SKULL("wither_skull", WitherSkull.class, 19),
|
||||
/**
|
||||
* Primed TNT that is about to explode.
|
||||
*/
|
||||
//PRIMED_TNT("tnt", TNTPrimed.class, 20),
|
||||
/**
|
||||
* A block that is going to or is about to fall.
|
||||
*/
|
||||
//FALLING_BLOCK("falling_block", FallingBlock.class, 21, false),
|
||||
/**
|
||||
* Internal representation of a Firework once it has been launched.
|
||||
*/
|
||||
//FIREWORK("firework_rocket", Firework.class, 22, false),
|
||||
/**
|
||||
* @see Husk
|
||||
*/
|
||||
//HUSK("husk", Husk.class, 23),
|
||||
/**
|
||||
* Like {@link #ARROW} but causes the {@link PotionEffectType#GLOWING} effect on all team members.
|
||||
*/
|
||||
//SPECTRAL_ARROW("spectral_arrow", SpectralArrow.class, 24),
|
||||
/**
|
||||
* Bullet fired by {@link #SHULKER}.
|
||||
*/
|
||||
//SHULKER_BULLET("shulker_bullet", ShulkerBullet.class, 25),
|
||||
/**
|
||||
* Like {@link #FIREBALL} but with added effects.
|
||||
*/
|
||||
//DRAGON_FIREBALL("dragon_fireball", DragonFireball.class, 26),
|
||||
/**
|
||||
* @see ZombieVillager
|
||||
*/
|
||||
//ZOMBIE_VILLAGER("zombie_villager", ZombieVillager.class, 27),
|
||||
/**
|
||||
* @see SkeletonHorse
|
||||
*/
|
||||
//SKELETON_HORSE("skeleton_horse", SkeletonHorse.class, 28),
|
||||
/**
|
||||
* @see ZombieHorse
|
||||
*/
|
||||
//ZOMBIE_HORSE("zombie_horse", ZombieHorse.class, 29),
|
||||
/**
|
||||
* Mechanical entity with an inventory for placing weapons / armor into.
|
||||
*/
|
||||
ARMOR_STAND("armor_stand", ArmorStand.class, 1),
|
||||
/**
|
||||
* @see Donkey
|
||||
*/
|
||||
//DONKEY("donkey", Donkey.class, 31),
|
||||
/**
|
||||
* @see Mule
|
||||
*/
|
||||
//MULE("mule", Mule.class, 32),
|
||||
/**
|
||||
* @see EvokerFangs
|
||||
*/
|
||||
//EVOKER_FANGS("evoker_fangs", EvokerFangs.class, 33),
|
||||
/**
|
||||
* @see Evoker
|
||||
*/
|
||||
//EVOKER("evoker", Evoker.class, 34),
|
||||
/**
|
||||
* @see Vex
|
||||
*/
|
||||
//VEX("vex", Vex.class, 35),
|
||||
/**
|
||||
* @see Vindicator
|
||||
*/
|
||||
//VINDICATOR("vindicator", Vindicator.class, 36),
|
||||
/**
|
||||
* @see Illusioner
|
||||
*/
|
||||
//ILLUSIONER("illusioner", Illusioner.class, 37),
|
||||
/**
|
||||
* @see CommandMinecart
|
||||
*/
|
||||
//MINECART_COMMAND("command_block_minecart", CommandMinecart.class, 40),
|
||||
/**
|
||||
* A placed boat.
|
||||
*/
|
||||
//BOAT("boat", Boat.class, 41),
|
||||
/**
|
||||
* @see RideableMinecart
|
||||
*/
|
||||
//MINECART("minecart", RideableMinecart.class, 42),
|
||||
/**
|
||||
* @see StorageMinecart
|
||||
*/
|
||||
//MINECART_CHEST("chest_minecart", StorageMinecart.class, 43),
|
||||
/**
|
||||
* @see PoweredMinecart
|
||||
*/
|
||||
//MINECART_FURNACE("furnace_minecart", PoweredMinecart.class, 44),
|
||||
/**
|
||||
* @see ExplosiveMinecart
|
||||
*/
|
||||
//MINECART_TNT("tnt_minecart", ExplosiveMinecart.class, 45),
|
||||
/**
|
||||
* @see HopperMinecart
|
||||
*/
|
||||
//MINECART_HOPPER("hopper_minecart", HopperMinecart.class, 46),
|
||||
/**
|
||||
* @see SpawnerMinecart
|
||||
*/
|
||||
//MINECART_MOB_SPAWNER("spawner_minecart", SpawnerMinecart.class, 47),
|
||||
//CREEPER("creeper", Creeper.class, 50),
|
||||
//SKELETON("skeleton", Skeleton.class, 51),
|
||||
//SPIDER("spider", Spider.class, 52),
|
||||
//GIANT("giant", Giant.class, 53),
|
||||
//ZOMBIE("zombie", Zombie.class, 54),
|
||||
//SLIME("slime", Slime.class, 55),
|
||||
//GHAST("ghast", Ghast.class, 56),
|
||||
//ZOMBIFIED_PIGLIN("zombified_piglin", PigZombie.class, 57),
|
||||
//ENDERMAN("enderman", Enderman.class, 58),
|
||||
//CAVE_SPIDER("cave_spider", CaveSpider.class, 59),
|
||||
//SILVERFISH("silverfish", Silverfish.class, 60),
|
||||
//BLAZE("blaze", Blaze.class, 61),
|
||||
//MAGMA_CUBE("magma_cube", MagmaCube.class, 62),
|
||||
//ENDER_DRAGON("ender_dragon", EnderDragon.class, 63),
|
||||
//WITHER("wither", Wither.class, 64),
|
||||
//BAT("bat", Bat.class, 65),
|
||||
//WITCH("witch", Witch.class, 66),
|
||||
//ENDERMITE("endermite", Endermite.class, 67),
|
||||
//GUARDIAN("guardian", Guardian.class, 68),
|
||||
//SHULKER("shulker", Shulker.class, 69),
|
||||
//PIG("pig", Pig.class, 90),
|
||||
//SHEEP("sheep", Sheep.class, 91),
|
||||
//COW("cow", Cow.class, 92),
|
||||
//CHICKEN("chicken", Chicken.class, 93),
|
||||
//SQUID("squid", Squid.class, 94),
|
||||
//WOLF("wolf", Wolf.class, 95),
|
||||
//MUSHROOM_COW("mooshroom", MushroomCow.class, 96),
|
||||
//SNOWMAN("snow_golem", Snowman.class, 97),
|
||||
//OCELOT("ocelot", Ocelot.class, 98),
|
||||
//IRON_GOLEM("iron_golem", IronGolem.class, 99),
|
||||
//HORSE("horse", Horse.class, 100),
|
||||
//RABBIT("rabbit", Rabbit.class, 101),
|
||||
//POLAR_BEAR("polar_bear", PolarBear.class, 102),
|
||||
//LLAMA("llama", Llama.class, 103),
|
||||
//LLAMA_SPIT("llama_spit", LlamaSpit.class, 104),
|
||||
//PARROT("parrot", Parrot.class, 105),
|
||||
//VILLAGER("villager", Villager.class, 120),
|
||||
//ENDER_CRYSTAL("end_crystal", EnderCrystal.class, 200),
|
||||
//TURTLE("turtle", Turtle.class, -1),
|
||||
//PHANTOM("phantom", Phantom.class, -1),
|
||||
//TRIDENT("trident", Trident.class, -1),
|
||||
//COD("cod", Cod.class, -1),
|
||||
//SALMON("salmon", Salmon.class, -1),
|
||||
//PUFFERFISH("pufferfish", PufferFish.class, -1),
|
||||
//TROPICAL_FISH("tropical_fish", TropicalFish.class, -1),
|
||||
//DROWNED("drowned", Drowned.class, -1),
|
||||
//DOLPHIN("dolphin", Dolphin.class, -1),
|
||||
//CAT("cat", Cat.class, -1),
|
||||
//PANDA("panda", Panda.class, -1),
|
||||
//PILLAGER("pillager", Pillager.class, -1),
|
||||
//RAVAGER("ravager", Ravager.class, -1),
|
||||
//TRADER_LLAMA("trader_llama", TraderLlama.class, -1),
|
||||
//WANDERING_TRADER("wandering_trader", WanderingTrader.class, -1),
|
||||
//FOX("fox", Fox.class, -1),
|
||||
//BEE("bee", Bee.class, -1),
|
||||
//HOGLIN("hoglin", Hoglin.class, -1),
|
||||
//PIGLIN("piglin", Piglin.class, -1),
|
||||
//STRIDER("strider", Strider.class, -1),
|
||||
//ZOGLIN("zoglin", Zoglin.class, -1),
|
||||
//PIGLIN_BRUTE("piglin_brute", PiglinBrute.class, -1),
|
||||
/**
|
||||
* A fishing line and bobber.
|
||||
*/
|
||||
//FISHING_HOOK("fishing_bobber", FishHook.class, -1, false),
|
||||
/**
|
||||
* A bolt of lightning.
|
||||
* <p>
|
||||
* Spawn with {@link World#strikeLightning(Location)}.
|
||||
*/
|
||||
//LIGHTNING("lightning_bolt", LightningStrike.class, -1, false),
|
||||
PLAYER("player", Player.class, 106, false),
|
||||
/**
|
||||
* An unknown entity without an Entity Class
|
||||
*/
|
||||
UNKNOWN(null, null, -1, false);
|
||||
|
||||
private final String name;
|
||||
private final Class<? extends Entity> clazz;
|
||||
private final short typeId;
|
||||
private final boolean independent;
|
||||
private final boolean living;
|
||||
private final NamespacedKey key;
|
||||
|
||||
private static final Map<String, EntityType> NAME_MAP = new HashMap<>();
|
||||
private static final Map<Short, EntityType> ID_MAP = new HashMap<>();
|
||||
|
||||
static {
|
||||
for (EntityType type : values()) {
|
||||
if (type.name != null) {
|
||||
NAME_MAP.put(type.name.toLowerCase(java.util.Locale.ENGLISH), type);
|
||||
}
|
||||
if (type.typeId > 0) {
|
||||
ID_MAP.put(type.typeId, type);
|
||||
}
|
||||
}
|
||||
|
||||
// Add legacy names
|
||||
/*
|
||||
NAME_MAP.put("xp_orb", EXPERIENCE_ORB);
|
||||
NAME_MAP.put("eye_of_ender_signal", ENDER_SIGNAL);
|
||||
NAME_MAP.put("xp_bottle", THROWN_EXP_BOTTLE);
|
||||
NAME_MAP.put("fireworks_rocket", FIREWORK);
|
||||
NAME_MAP.put("evocation_fangs", EVOKER_FANGS);
|
||||
NAME_MAP.put("evocation_illager", EVOKER);
|
||||
NAME_MAP.put("vindication_illager", VINDICATOR);
|
||||
NAME_MAP.put("illusion_illager", ILLUSIONER);
|
||||
NAME_MAP.put("commandblock_minecart", MINECART_COMMAND);
|
||||
NAME_MAP.put("snowman", SNOWMAN);
|
||||
NAME_MAP.put("villager_golem", IRON_GOLEM);
|
||||
NAME_MAP.put("ender_crystal", ENDER_CRYSTAL);
|
||||
NAME_MAP.put("zombie_pigman", ZOMBIFIED_PIGLIN);
|
||||
*/
|
||||
}
|
||||
|
||||
private EntityType(String name, Class<? extends Entity> clazz, int typeId) {
|
||||
this(name, clazz, typeId, true);
|
||||
}
|
||||
|
||||
private EntityType(String name, Class<? extends Entity> clazz, int typeId, boolean independent) {
|
||||
this.name = name;
|
||||
this.clazz = clazz;
|
||||
this.typeId = (short) typeId;
|
||||
this.independent = independent;
|
||||
this.living = clazz != null && LivingEntity.class.isAssignableFrom(clazz);
|
||||
this.key = (name == null) ? null : NamespacedKey.minecraft(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the entity type name.
|
||||
*
|
||||
* @return the entity type's name
|
||||
* @deprecated Magic value
|
||||
*/
|
||||
@Deprecated
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public NamespacedKey getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public Class<? extends Entity> getEntityClass() {
|
||||
return clazz;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the entity network type id.
|
||||
*
|
||||
* @return the network type id
|
||||
*/
|
||||
public short getTypeId() {
|
||||
return typeId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an entity type from its name.
|
||||
*
|
||||
* @param name the entity type's name
|
||||
* @return the matching entity type or null
|
||||
* @deprecated Magic value
|
||||
*/
|
||||
@Deprecated
|
||||
public static EntityType fromName(String name) {
|
||||
if (name == null) {
|
||||
return null;
|
||||
}
|
||||
return NAME_MAP.get(name.toLowerCase(java.util.Locale.ENGLISH));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an entity from its id.
|
||||
*
|
||||
* @param id the raw type id
|
||||
* @return the matching entity type or null
|
||||
* @deprecated Magic value
|
||||
*/
|
||||
@Deprecated
|
||||
public static EntityType fromId(int id) {
|
||||
if (id > Short.MAX_VALUE) {
|
||||
return null;
|
||||
}
|
||||
return ID_MAP.get((short) id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Some entities cannot be spawned using {@link
|
||||
* World#spawnEntity(Location, EntityType)} or {@link
|
||||
* World#spawn(Location, Class)}, usually because they require additional
|
||||
* information in order to spawn.
|
||||
*
|
||||
* @return False if the entity type cannot be spawned
|
||||
*/
|
||||
public boolean isSpawnable() {
|
||||
return independent;
|
||||
}
|
||||
|
||||
public boolean isAlive() {
|
||||
return living;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,132 @@
|
|||
package com.loohp.limbo.Entity;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import com.loohp.limbo.Limbo;
|
||||
import com.loohp.limbo.Entity.DataWatcher.WatchableField;
|
||||
import com.loohp.limbo.Entity.DataWatcher.WatchableObjectType;
|
||||
import com.loohp.limbo.Inventory.EquipmentSlot;
|
||||
import com.loohp.limbo.Location.Location;
|
||||
import com.loohp.limbo.World.BlockPosition;
|
||||
import com.loohp.limbo.World.World;
|
||||
|
||||
public abstract class LivingEntity extends Entity {
|
||||
|
||||
@WatchableField(MetadataIndex = 7, WatchableObjectType = WatchableObjectType.BYTE, IsBitmask = true, Bitmask = 0x01)
|
||||
protected boolean handActive = false;
|
||||
@WatchableField(MetadataIndex = 7, WatchableObjectType = WatchableObjectType.BYTE, IsBitmask = true, Bitmask = 0x02)
|
||||
protected boolean activeHand = false; //false = main hand, true = off hand
|
||||
@WatchableField(MetadataIndex = 7, WatchableObjectType = WatchableObjectType.BYTE, IsBitmask = true, Bitmask = 0x04)
|
||||
protected boolean inRiptideSpinAttack = false;
|
||||
@WatchableField(MetadataIndex = 8, WatchableObjectType = WatchableObjectType.FLOAT)
|
||||
protected float health = 1.0F;
|
||||
@WatchableField(MetadataIndex = 9, WatchableObjectType = WatchableObjectType.VARINT)
|
||||
protected int potionEffectColor = 0;
|
||||
@WatchableField(MetadataIndex = 10, WatchableObjectType = WatchableObjectType.BOOLEAN)
|
||||
protected boolean potionEffectAmbient = false;
|
||||
@WatchableField(MetadataIndex = 11, WatchableObjectType = WatchableObjectType.VARINT)
|
||||
protected int arrowsInEntity = 0;
|
||||
@WatchableField(MetadataIndex = 12, WatchableObjectType = WatchableObjectType.VARINT)
|
||||
protected int absorption = 0;
|
||||
@WatchableField(MetadataIndex = 13, WatchableObjectType = WatchableObjectType.POSITION, IsOptional = true)
|
||||
protected BlockPosition sleepingLocation = null;
|
||||
|
||||
public LivingEntity(EntityType type, int entityId, UUID uuid, World world, double x, double y, double z, float yaw, float pitch) {
|
||||
super(type, entityId, uuid, world, x, y, z, yaw, pitch);
|
||||
}
|
||||
|
||||
public LivingEntity(EntityType type, UUID uuid, World world, double x, double y, double z, float yaw, float pitch) {
|
||||
this(type, Limbo.getInstance().getNextEntityId(), uuid, world, x, y, z, yaw, pitch);
|
||||
}
|
||||
|
||||
public LivingEntity(EntityType type, World world, double x, double y, double z, float yaw, float pitch) {
|
||||
this(type, Limbo.getInstance().getNextEntityId(), UUID.randomUUID(), world, x, y, z, yaw, pitch);
|
||||
}
|
||||
|
||||
public LivingEntity(EntityType type, UUID uuid, Location location) {
|
||||
this(type, Limbo.getInstance().getNextEntityId(), uuid, location.getWorld(), location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
|
||||
}
|
||||
|
||||
public LivingEntity(EntityType type, Location location) {
|
||||
this(type, Limbo.getInstance().getNextEntityId(), UUID.randomUUID(), location.getWorld(), location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
|
||||
}
|
||||
|
||||
public boolean isHandActive() {
|
||||
return handActive;
|
||||
}
|
||||
|
||||
public void setHandActive(boolean handActive) {
|
||||
this.handActive = handActive;
|
||||
}
|
||||
|
||||
public EquipmentSlot getActiveHand() {
|
||||
return activeHand ? EquipmentSlot.OFFHAND : EquipmentSlot.MAINHAND;
|
||||
}
|
||||
|
||||
public void setActiveHand(EquipmentSlot activeHand) {
|
||||
if (activeHand.equals(EquipmentSlot.MAINHAND)) {
|
||||
this.activeHand = false;
|
||||
} else if (activeHand.equals(EquipmentSlot.OFFHAND)) {
|
||||
this.activeHand = true;
|
||||
} else {
|
||||
throw new IllegalArgumentException("Invalid EquipmentSlot " + activeHand.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isInRiptideSpinAttack() {
|
||||
return inRiptideSpinAttack;
|
||||
}
|
||||
|
||||
public void setInRiptideSpinAttack(boolean inRiptideSpinAttack) {
|
||||
this.inRiptideSpinAttack = inRiptideSpinAttack;
|
||||
}
|
||||
|
||||
public float getHealth() {
|
||||
return health;
|
||||
}
|
||||
|
||||
public void setHealth(float health) {
|
||||
this.health = health;
|
||||
}
|
||||
|
||||
public int getPotionEffectColor() {
|
||||
return potionEffectColor;
|
||||
}
|
||||
|
||||
public void setPotionEffectColor(int potionEffectColor) {
|
||||
this.potionEffectColor = potionEffectColor;
|
||||
}
|
||||
|
||||
public boolean isPotionEffectAmbient() {
|
||||
return potionEffectAmbient;
|
||||
}
|
||||
|
||||
public void setPotionEffectAmbient(boolean potionEffectAmbient) {
|
||||
this.potionEffectAmbient = potionEffectAmbient;
|
||||
}
|
||||
|
||||
public int getArrowsInEntity() {
|
||||
return arrowsInEntity;
|
||||
}
|
||||
|
||||
public void setArrowsInEntity(int arrowsInEntity) {
|
||||
this.arrowsInEntity = arrowsInEntity;
|
||||
}
|
||||
|
||||
public int getAbsorption() {
|
||||
return absorption;
|
||||
}
|
||||
|
||||
public void setAbsorption(int absorption) {
|
||||
this.absorption = absorption;
|
||||
}
|
||||
|
||||
public BlockPosition getSleepingLocation() {
|
||||
return sleepingLocation;
|
||||
}
|
||||
|
||||
public void setSleepingLocation(BlockPosition sleepingLocation) {
|
||||
this.sleepingLocation = sleepingLocation;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
package com.loohp.limbo.Entity;
|
||||
|
||||
public enum Pose {
|
||||
|
||||
STANDING(0),
|
||||
FALL_FLYING(1),
|
||||
SLEEPING(2),
|
||||
SWIMMING(3),
|
||||
SPIN_ATTACK(4),
|
||||
SNEAKING(5),
|
||||
DYING(6);
|
||||
|
||||
private static final Pose[] VALUES = values();
|
||||
|
||||
private int id;
|
||||
|
||||
Pose(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public static Pose fromId(int id) {
|
||||
for (Pose pose : VALUES) {
|
||||
if (id == pose.id) {
|
||||
return pose;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -3,9 +3,12 @@ package com.loohp.limbo.File;
|
|||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.io.Reader;
|
||||
import java.io.StringWriter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
|
@ -18,32 +21,36 @@ import com.loohp.limbo.Utils.YamlOrder;
|
|||
|
||||
public class FileConfiguration {
|
||||
|
||||
File file;
|
||||
|
||||
Map<String, Object> mapping;
|
||||
String header;
|
||||
private Map<String, Object> mapping;
|
||||
private String header;
|
||||
|
||||
public FileConfiguration(File file) throws FileNotFoundException {
|
||||
this.file = file;
|
||||
if (file.exists()) {
|
||||
reloadConfig();
|
||||
reloadConfig(new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8));
|
||||
} else {
|
||||
mapping = new LinkedHashMap<>();
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public FileConfiguration(InputStream input){
|
||||
reloadConfig(input);
|
||||
reloadConfig(new InputStreamReader(input, StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
public FileConfiguration reloadConfig() throws FileNotFoundException {
|
||||
return reloadConfig(new FileInputStream(file));
|
||||
public FileConfiguration(Reader reader){
|
||||
reloadConfig(reader);
|
||||
}
|
||||
|
||||
private FileConfiguration reloadConfig(InputStream input) {
|
||||
public FileConfiguration reloadConfig(File file) throws FileNotFoundException {
|
||||
return reloadConfig(new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
public FileConfiguration reloadConfig(InputStream input) {
|
||||
return reloadConfig(new InputStreamReader(input, StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
public FileConfiguration reloadConfig(Reader reader) {
|
||||
Yaml yml = new Yaml();
|
||||
mapping = yml.load(input);
|
||||
mapping = yml.load(reader);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
@ -87,7 +94,29 @@ public class FileConfiguration {
|
|||
}
|
||||
}
|
||||
|
||||
public void saveConfig(File file) throws FileNotFoundException, UnsupportedEncodingException {
|
||||
public String saveToString() throws IOException {
|
||||
DumperOptions options = new DumperOptions();
|
||||
options.setIndent(2);
|
||||
options.setPrettyFlow(true);
|
||||
options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
|
||||
Representer customRepresenter = new Representer();
|
||||
YamlOrder customProperty = new YamlOrder();
|
||||
customRepresenter.setPropertyUtils(customProperty);
|
||||
Yaml yaml = new Yaml(customRepresenter, options);
|
||||
|
||||
StringWriter writer = new StringWriter();
|
||||
PrintWriter pw = new PrintWriter(writer);
|
||||
if (header != null) {
|
||||
pw.println("#" + header.replace("\n", "\n#"));
|
||||
}
|
||||
yaml.dump(mapping, pw);
|
||||
pw.flush();
|
||||
pw.close();
|
||||
|
||||
return writer.toString();
|
||||
}
|
||||
|
||||
public void saveConfig(File file) throws IOException {
|
||||
DumperOptions options = new DumperOptions();
|
||||
options.setIndent(2);
|
||||
options.setPrettyFlow(true);
|
||||
|
|
|
|||
|
|
@ -4,6 +4,10 @@ import java.awt.image.BufferedImage;
|
|||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.PrintWriter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Optional;
|
||||
import java.util.Properties;
|
||||
|
||||
|
|
@ -16,29 +20,44 @@ import com.loohp.limbo.Utils.NamespacedKey;
|
|||
import com.loohp.limbo.World.World;
|
||||
|
||||
public class ServerProperties {
|
||||
|
||||
public static final String COMMENT = "For explaination of what each of the options does, please visit:\nhttps://github.com/LOOHP/Limbo/blob/master/src/main/resources/server.properties";
|
||||
|
||||
File file;
|
||||
int maxPlayers;
|
||||
int serverPort;
|
||||
String serverIp;
|
||||
NamespacedKey levelName;
|
||||
String schemFileName;
|
||||
NamespacedKey levelDimension;
|
||||
GameMode defaultGamemode;
|
||||
Location worldSpawn;
|
||||
boolean reducedDebugInfo;
|
||||
boolean allowFlight;
|
||||
String motdJson;
|
||||
String versionString;
|
||||
int protocol;
|
||||
boolean bungeecord;
|
||||
private File file;
|
||||
private int maxPlayers;
|
||||
private int serverPort;
|
||||
private String serverIp;
|
||||
private NamespacedKey levelName;
|
||||
private String schemFileName;
|
||||
private NamespacedKey levelDimension;
|
||||
private GameMode defaultGamemode;
|
||||
private Location worldSpawn;
|
||||
private boolean reducedDebugInfo;
|
||||
private boolean allowFlight;
|
||||
private String motdJson;
|
||||
private String versionString;
|
||||
private int protocol;
|
||||
private boolean bungeecord;
|
||||
private int viewDistance;
|
||||
private double ticksPerSecond;
|
||||
|
||||
Optional<BufferedImage> favicon;
|
||||
|
||||
public ServerProperties(File file) throws IOException {
|
||||
this.file = file;
|
||||
|
||||
Properties def = new Properties();
|
||||
def.load(new InputStreamReader(getClass().getClassLoader().getResourceAsStream("server.properties"), StandardCharsets.UTF_8));
|
||||
|
||||
Properties prop = new Properties();
|
||||
prop.load(new FileInputStream(file));
|
||||
prop.load(new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8));
|
||||
|
||||
for (Entry<Object, Object> entry : def.entrySet()) {
|
||||
String key = entry.getKey().toString();
|
||||
String value = entry.getValue().toString();
|
||||
prop.putIfAbsent(key, value);
|
||||
}
|
||||
prop.store(new PrintWriter(file, StandardCharsets.UTF_8), COMMENT);
|
||||
|
||||
protocol = Limbo.getInstance().serverImplmentationProtocol;
|
||||
|
||||
|
|
@ -63,6 +82,8 @@ public class ServerProperties {
|
|||
motdJson = prop.getProperty("motd");
|
||||
versionString = prop.getProperty("version");
|
||||
bungeecord = Boolean.parseBoolean(prop.getProperty("bungeecord"));
|
||||
viewDistance = Integer.parseInt(prop.getProperty("view-distance"));
|
||||
ticksPerSecond = Double.parseDouble(prop.getProperty("ticks-per-second"));
|
||||
|
||||
File png = new File("server-icon.png");
|
||||
if (png.exists()) {
|
||||
|
|
@ -155,5 +176,13 @@ public class ServerProperties {
|
|||
public int getProtocol() {
|
||||
return protocol;
|
||||
}
|
||||
|
||||
public int getViewDistance() {
|
||||
return viewDistance;
|
||||
}
|
||||
|
||||
public double getDefinedTicksPerSecond() {
|
||||
return ticksPerSecond;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
package com.loohp.limbo.Inventory;
|
||||
|
||||
public enum EquipmentSlot {
|
||||
|
||||
MAINHAND,
|
||||
OFFHAND,
|
||||
HELMENT,
|
||||
CHESTPLATE,
|
||||
LEGGINGS,
|
||||
BOOTS;
|
||||
|
||||
}
|
||||
|
|
@ -27,6 +27,7 @@ import java.util.Set;
|
|||
import java.util.TreeMap;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
|
@ -108,6 +109,8 @@ public class Limbo {
|
|||
public final int serverImplmentationProtocol = 754;
|
||||
public final String limboImplementationVersion;
|
||||
|
||||
private AtomicBoolean isRunning;
|
||||
|
||||
private ServerConnection server;
|
||||
private Console console;
|
||||
|
||||
|
|
@ -126,6 +129,9 @@ public class Limbo {
|
|||
|
||||
private DimensionRegistry dimensionRegistry;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private Tick tick;
|
||||
|
||||
private Metrics metrics;
|
||||
|
||||
public AtomicInteger entityIdCount = new AtomicInteger();
|
||||
|
|
@ -136,6 +142,7 @@ public class Limbo {
|
|||
@SuppressWarnings("unchecked")
|
||||
public Limbo() throws IOException, ParseException, NumberFormatException, ClassNotFoundException, InterruptedException {
|
||||
instance = this;
|
||||
isRunning = new AtomicBoolean(true);
|
||||
|
||||
if (!noGui) {
|
||||
while (!GUI.loadFinish) {
|
||||
|
|
@ -304,6 +311,8 @@ public class Limbo {
|
|||
|
||||
server = new ServerConnection(properties.getServerIp(), properties.getServerPort());
|
||||
|
||||
tick = new Tick(this);
|
||||
|
||||
metrics = new Metrics();
|
||||
|
||||
console.run();
|
||||
|
|
@ -357,6 +366,27 @@ public class Limbo {
|
|||
return world;
|
||||
}
|
||||
|
||||
public void registerWorld(World world) {
|
||||
if (!worlds.contains(world)) {
|
||||
worlds.add(world);
|
||||
} else {
|
||||
throw new RuntimeException("World already registered");
|
||||
}
|
||||
}
|
||||
|
||||
public void unregisterWorld(World world) {
|
||||
if (worlds.indexOf(world) == 0) {
|
||||
throw new RuntimeException("World already registered");
|
||||
} else if (!worlds.contains(world)) {
|
||||
throw new RuntimeException("World not registered");
|
||||
} else {
|
||||
for (Player player : world.getPlayers()) {
|
||||
player.teleport(properties.getWorldSpawn());
|
||||
}
|
||||
worlds.remove(world);
|
||||
}
|
||||
}
|
||||
|
||||
public ServerProperties getServerProperties() {
|
||||
return properties;
|
||||
}
|
||||
|
|
@ -387,12 +417,12 @@ public class Limbo {
|
|||
|
||||
public void addPlayer(Player player) {
|
||||
playersByName.put(player.getName(), player);
|
||||
playersByUUID.put(player.getUUID(), player);
|
||||
playersByUUID.put(player.getUniqueId(), player);
|
||||
}
|
||||
|
||||
public void removePlayer(Player player) {
|
||||
playersByName.remove(player.getName());
|
||||
playersByUUID.remove(player.getUUID());
|
||||
playersByUUID.remove(player.getUniqueId());
|
||||
}
|
||||
|
||||
public List<World> getWorlds() {
|
||||
|
|
@ -453,6 +483,7 @@ public class Limbo {
|
|||
}
|
||||
|
||||
public void stopServer() {
|
||||
isRunning.set(false);
|
||||
console.sendMessage("Stopping Server...");
|
||||
|
||||
for (LimboPlugin plugin : Limbo.getInstance().getPluginManager().getPlugins()) {
|
||||
|
|
@ -476,6 +507,10 @@ public class Limbo {
|
|||
System.exit(0);
|
||||
}
|
||||
|
||||
public boolean isRunning() {
|
||||
return isRunning.get();
|
||||
}
|
||||
|
||||
public int getNextEntityId() {
|
||||
if (entityIdCount.get() == Integer.MAX_VALUE) {
|
||||
return entityIdCount.getAndSet(0);
|
||||
|
|
|
|||
|
|
@ -5,6 +5,11 @@ import java.util.UUID;
|
|||
|
||||
import com.loohp.limbo.Limbo;
|
||||
import com.loohp.limbo.Commands.CommandSender;
|
||||
import com.loohp.limbo.Entity.DataWatcher;
|
||||
import com.loohp.limbo.Entity.DataWatcher.WatchableField;
|
||||
import com.loohp.limbo.Entity.DataWatcher.WatchableObjectType;
|
||||
import com.loohp.limbo.Entity.EntityType;
|
||||
import com.loohp.limbo.Entity.LivingEntity;
|
||||
import com.loohp.limbo.Events.PlayerChatEvent;
|
||||
import com.loohp.limbo.Events.PlayerTeleportEvent;
|
||||
import com.loohp.limbo.Location.Location;
|
||||
|
|
@ -14,30 +19,42 @@ import com.loohp.limbo.Server.Packets.PacketPlayOutGameState;
|
|||
import com.loohp.limbo.Server.Packets.PacketPlayOutPositionAndLook;
|
||||
import com.loohp.limbo.Server.Packets.PacketPlayOutRespawn;
|
||||
import com.loohp.limbo.Utils.GameMode;
|
||||
import com.loohp.limbo.World.World;
|
||||
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import net.md_5.bungee.chat.ComponentSerializer;
|
||||
|
||||
public class Player implements CommandSender {
|
||||
public class Player extends LivingEntity implements CommandSender {
|
||||
|
||||
public final ClientConnection clientConnection;
|
||||
public final PlayerInteractManager playerInteractManager;
|
||||
|
||||
private final String username;
|
||||
private final UUID uuid;
|
||||
protected final String username;
|
||||
protected GameMode gamemode;
|
||||
protected DataWatcher watcher;
|
||||
|
||||
protected int entityId;
|
||||
|
||||
private Location location;
|
||||
@WatchableField(MetadataIndex = 14, WatchableObjectType = WatchableObjectType.FLOAT)
|
||||
protected float additionalHearts = 0.0F;
|
||||
@WatchableField(MetadataIndex = 15, WatchableObjectType = WatchableObjectType.VARINT)
|
||||
protected int score = 0;
|
||||
@WatchableField(MetadataIndex = 16, WatchableObjectType = WatchableObjectType.BYTE)
|
||||
protected byte skinLayers = 0;
|
||||
@WatchableField(MetadataIndex = 17, WatchableObjectType = WatchableObjectType.BYTE)
|
||||
protected byte mainHand = 1;
|
||||
//@WatchableField(MetadataIndex = 18, WatchableObjectType = WatchableObjectType.NBT)
|
||||
//protected Entity leftShoulder = null;
|
||||
//@WatchableField(MetadataIndex = 19, WatchableObjectType = WatchableObjectType.NBT)
|
||||
//protected Entity rightShoulder = null;
|
||||
|
||||
public Player(ClientConnection clientConnection, String username, UUID uuid, int entityId, Location location) {
|
||||
public Player(ClientConnection clientConnection, String username, UUID uuid, int entityId, Location location, PlayerInteractManager playerInteractManager) throws IllegalArgumentException, IllegalAccessException {
|
||||
super(EntityType.PLAYER, entityId, uuid, location.getWorld(), location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
|
||||
this.clientConnection = clientConnection;
|
||||
this.username = username;
|
||||
this.uuid = uuid;
|
||||
this.entityId = entityId;
|
||||
this.location = location.clone();
|
||||
this.playerInteractManager = playerInteractManager;
|
||||
this.playerInteractManager.setPlayer(this);
|
||||
this.watcher = new DataWatcher(this);
|
||||
this.watcher.update();
|
||||
}
|
||||
|
||||
public GameMode getGamemode() {
|
||||
|
|
@ -55,41 +72,95 @@ public class Player implements CommandSender {
|
|||
}
|
||||
this.gamemode = gamemode;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
protected void setEntityId(int entityId) {
|
||||
this.entityId = entityId;
|
||||
}
|
||||
|
||||
public World getWorld() {
|
||||
return location.clone().getWorld();
|
||||
public float getAdditionalHearts() {
|
||||
return additionalHearts;
|
||||
}
|
||||
|
||||
public void setAdditionalHearts(float additionalHearts) {
|
||||
this.additionalHearts = additionalHearts;
|
||||
}
|
||||
|
||||
public int getScore() {
|
||||
return score;
|
||||
}
|
||||
|
||||
public void setScore(int score) {
|
||||
this.score = score;
|
||||
}
|
||||
|
||||
public byte getSkinLayers() {
|
||||
return skinLayers;
|
||||
}
|
||||
|
||||
public void setSkinLayers(byte skinLayers) {
|
||||
this.skinLayers = skinLayers;
|
||||
}
|
||||
|
||||
public byte getMainHand() {
|
||||
return mainHand;
|
||||
}
|
||||
|
||||
public void setMainHand(byte mainHand) {
|
||||
this.mainHand = mainHand;
|
||||
}
|
||||
|
||||
public int getEntityId() {
|
||||
return entityId;
|
||||
@Override
|
||||
public DataWatcher getDataWatcher() {
|
||||
return watcher;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
return Limbo.getInstance().getPlayers().contains(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
public Entity getLeftShoulder() {
|
||||
return leftShoulder;
|
||||
}
|
||||
|
||||
public Location getLocation() {
|
||||
return location.clone();
|
||||
public void setLeftShoulder(Entity leftShoulder) {
|
||||
this.leftShoulder = leftShoulder;
|
||||
}
|
||||
|
||||
public void setLocation(Location location) {
|
||||
this.location = location;
|
||||
public Entity getRightShoulder() {
|
||||
return rightShoulder;
|
||||
}
|
||||
|
||||
public void setRightShoulder(Entity rightShoulder) {
|
||||
this.rightShoulder = rightShoulder;
|
||||
}
|
||||
*/
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public UUID getUUID() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(String permission) {
|
||||
return Limbo.getInstance().getPermissionsManager().hasPermission(this, permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void teleport(Location location) {
|
||||
PlayerTeleportEvent event = Limbo.getInstance().getEventsManager().callEvent(new PlayerTeleportEvent(this, getLocation(), location));
|
||||
if (!event.isCancelled()) {
|
||||
location = event.getTo();
|
||||
super.teleport(location);
|
||||
try {
|
||||
if (!this.location.getWorld().equals(location.getWorld())) {
|
||||
if (!world.equals(location.getWorld())) {
|
||||
PacketPlayOutRespawn respawn = new PacketPlayOutRespawn(location.getWorld(), Limbo.getInstance().getDimensionRegistry().getCodec(), 0, gamemode, false, false, true);
|
||||
clientConnection.sendPacket(respawn);
|
||||
}
|
||||
|
|
@ -101,6 +172,10 @@ public class Player implements CommandSender {
|
|||
}
|
||||
}
|
||||
|
||||
protected void setLocation(Location location) {
|
||||
super.teleport(location);
|
||||
}
|
||||
|
||||
public void sendMessage(String message, UUID uuid) {
|
||||
sendMessage(TextComponent.fromLegacyText(message), uuid);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,135 @@
|
|||
package com.loohp.limbo.Player;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.loohp.limbo.Limbo;
|
||||
import com.loohp.limbo.Entity.Entity;
|
||||
import com.loohp.limbo.Location.Location;
|
||||
import com.loohp.limbo.Server.Packets.PacketPlayOutEntityDestroy;
|
||||
import com.loohp.limbo.Server.Packets.PacketPlayOutEntityMetadata;
|
||||
import com.loohp.limbo.Server.Packets.PacketPlayOutLightUpdate;
|
||||
import com.loohp.limbo.Server.Packets.PacketPlayOutMapChunk;
|
||||
import com.loohp.limbo.Server.Packets.PacketPlayOutSpawnEntity;
|
||||
import com.loohp.limbo.Server.Packets.PacketPlayOutSpawnEntityLiving;
|
||||
import com.loohp.limbo.Server.Packets.PacketPlayOutUnloadChunk;
|
||||
import com.loohp.limbo.World.World;
|
||||
|
||||
import net.querz.mca.Chunk;
|
||||
|
||||
public class PlayerInteractManager {
|
||||
|
||||
private Player player;
|
||||
|
||||
private Set<Entity> entities;
|
||||
private Map<Chunk, World> chunks;
|
||||
|
||||
public PlayerInteractManager() {
|
||||
this.player = null;
|
||||
this.entities = new HashSet<>();
|
||||
this.chunks = new HashMap<>();
|
||||
}
|
||||
|
||||
protected void setPlayer(Player player) {
|
||||
if (this.player == null) {
|
||||
this.player = player;
|
||||
} else {
|
||||
throw new RuntimeException("Player in PlayerInteractManager cannot be changed once created");
|
||||
}
|
||||
}
|
||||
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
public void update() throws IOException {
|
||||
int viewDistanceChunks = Limbo.getInstance().getServerProperties().getViewDistance();
|
||||
int viewDistanceBlocks = viewDistanceChunks << 4;
|
||||
Location location = player.getLocation();
|
||||
Set<Entity> entitiesInRange = player.getWorld().getEntities().stream().filter(each -> each.getLocation().distanceSquared(location) < viewDistanceBlocks * viewDistanceBlocks).collect(Collectors.toSet());
|
||||
for (Entity entity : entitiesInRange) {
|
||||
if (!entities.contains(entity)) {
|
||||
if (entity.getType().isAlive()) {
|
||||
PacketPlayOutSpawnEntityLiving packet = new PacketPlayOutSpawnEntityLiving(entity.getEntityId(), entity.getUniqueId(), entity.getType(), entity.getX(), entity.getY(), entity.getZ(), entity.getYaw(), entity.getPitch(), entity.getPitch(), (short) 0, (short) 0, (short) 0);
|
||||
player.clientConnection.sendPacket(packet);
|
||||
|
||||
PacketPlayOutEntityMetadata meta = new PacketPlayOutEntityMetadata(entity);
|
||||
player.clientConnection.sendPacket(meta);
|
||||
} else {
|
||||
PacketPlayOutSpawnEntity packet = new PacketPlayOutSpawnEntity(entity.getEntityId(), entity.getUniqueId(), entity.getType(), entity.getX(), entity.getY(), entity.getZ(), entity.getPitch(), entity.getYaw(), (short) 0, (short) 0, (short) 0);
|
||||
player.clientConnection.sendPacket(packet);
|
||||
|
||||
PacketPlayOutEntityMetadata meta = new PacketPlayOutEntityMetadata(entity);
|
||||
player.clientConnection.sendPacket(meta);
|
||||
}
|
||||
}
|
||||
}
|
||||
List<Integer> ids = new ArrayList<>();
|
||||
for (Entity entity : entities) {
|
||||
if (!entitiesInRange.contains(entity)) {
|
||||
ids.add(entity.getEntityId());
|
||||
}
|
||||
}
|
||||
PacketPlayOutEntityDestroy packet = new PacketPlayOutEntityDestroy(ids.stream().mapToInt(each -> each).toArray());
|
||||
player.clientConnection.sendPacket(packet);
|
||||
|
||||
entities = entitiesInRange;
|
||||
|
||||
int playerChunkX = (int) location.getX() >> 4;
|
||||
int playerChunkZ = (int) location.getZ() >> 4;
|
||||
World world = location.getWorld();
|
||||
|
||||
Set<Chunk> chunksInRange = new HashSet<>();
|
||||
|
||||
for (int x = playerChunkX - viewDistanceChunks; x < playerChunkX + viewDistanceChunks; x++) {
|
||||
for (int z = playerChunkZ - viewDistanceChunks; z < playerChunkZ + viewDistanceChunks; z++) {
|
||||
Chunk chunk = world.getChunkAt(x, z);
|
||||
if (chunk != null) {
|
||||
chunksInRange.add(chunk);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (Entry<Chunk, World> entry : chunks.entrySet()) {
|
||||
Chunk chunk = entry.getKey();
|
||||
if (location.getWorld().getChunkXZ(chunk) == null) {
|
||||
World world0 = entry.getValue();
|
||||
int[] chunkPos = world0.getChunkXZ(chunk);
|
||||
PacketPlayOutUnloadChunk packet0 = new PacketPlayOutUnloadChunk(chunkPos[0], chunkPos[1]);
|
||||
player.clientConnection.sendPacket(packet0);
|
||||
}
|
||||
}
|
||||
|
||||
for (Chunk chunk : chunksInRange) {
|
||||
if (!chunks.containsKey(chunk)) {
|
||||
int[] chunkPos = world.getChunkXZ(chunk);
|
||||
PacketPlayOutMapChunk packet0 = new PacketPlayOutMapChunk(chunkPos[0], chunkPos[1], chunk, world.getEnvironment());
|
||||
player.clientConnection.sendPacket(packet0);
|
||||
|
||||
List<Byte[]> blockChunk = world.getLightEngineBlock().getBlockLightBitMask(chunkPos[0], chunkPos[1]);
|
||||
if (blockChunk == null) {
|
||||
blockChunk = new ArrayList<>();
|
||||
}
|
||||
List<Byte[]> skyChunk = null;
|
||||
if (world.hasSkyLight()) {
|
||||
skyChunk = world.getLightEngineSky().getSkyLightBitMask(chunkPos[0], chunkPos[1]);
|
||||
}
|
||||
if (skyChunk == null) {
|
||||
skyChunk = new ArrayList<>();
|
||||
}
|
||||
PacketPlayOutLightUpdate chunkdata = new PacketPlayOutLightUpdate(chunkPos[0], chunkPos[1], true, skyChunk, blockChunk);
|
||||
player.clientConnection.sendPacket(chunkdata);
|
||||
}
|
||||
}
|
||||
|
||||
chunks = chunksInRange.stream().collect(Collectors.toMap(each -> each, each -> world));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
package com.loohp.limbo.Player;
|
||||
|
||||
import com.loohp.limbo.Location.Location;
|
||||
import com.loohp.limbo.Utils.GameMode;
|
||||
|
||||
@Deprecated
|
||||
|
|
@ -14,7 +15,12 @@ public class Unsafe {
|
|||
|
||||
@Deprecated
|
||||
public void a(Player a, int b) {
|
||||
a.entityId = b;
|
||||
a.setEntityId(b);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void a(Player a, Location b) {
|
||||
a.setLocation(b);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,6 @@ public class PluginManager {
|
|||
if (name.endsWith("plugin.yml") || name.endsWith("limbo.yml")) {
|
||||
found = true;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
FileConfiguration pluginYaml = new FileConfiguration(zip);
|
||||
String main = pluginYaml.get("main", String.class);
|
||||
String pluginName = pluginYaml.get("name", String.class);
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import com.loohp.limbo.Events.StatusPingEvent;
|
|||
import com.loohp.limbo.File.ServerProperties;
|
||||
import com.loohp.limbo.Location.Location;
|
||||
import com.loohp.limbo.Player.Player;
|
||||
import com.loohp.limbo.Player.PlayerInteractManager;
|
||||
import com.loohp.limbo.Server.Packets.Packet;
|
||||
import com.loohp.limbo.Server.Packets.PacketHandshakingIn;
|
||||
import com.loohp.limbo.Server.Packets.PacketLoginInLoginStart;
|
||||
|
|
@ -40,9 +41,8 @@ import com.loohp.limbo.Server.Packets.PacketPlayInRotation;
|
|||
import com.loohp.limbo.Server.Packets.PacketPlayInTabComplete;
|
||||
import com.loohp.limbo.Server.Packets.PacketPlayOutDeclareCommands;
|
||||
import com.loohp.limbo.Server.Packets.PacketPlayOutDisconnect;
|
||||
import com.loohp.limbo.Server.Packets.PacketPlayOutLightUpdate;
|
||||
import com.loohp.limbo.Server.Packets.PacketPlayOutEntityMetadata;
|
||||
import com.loohp.limbo.Server.Packets.PacketPlayOutLogin;
|
||||
import com.loohp.limbo.Server.Packets.PacketPlayOutMapChunk;
|
||||
import com.loohp.limbo.Server.Packets.PacketPlayOutPlayerAbilities;
|
||||
import com.loohp.limbo.Server.Packets.PacketPlayOutPlayerAbilities.PlayerAbilityFlags;
|
||||
import com.loohp.limbo.Server.Packets.PacketPlayOutPlayerInfo;
|
||||
|
|
@ -50,7 +50,6 @@ import com.loohp.limbo.Server.Packets.PacketPlayOutPlayerInfo.PlayerInfoAction;
|
|||
import com.loohp.limbo.Server.Packets.PacketPlayOutPlayerInfo.PlayerInfoData;
|
||||
import com.loohp.limbo.Server.Packets.PacketPlayOutPlayerInfo.PlayerInfoData.PlayerInfoDataAddPlayer.PlayerSkinProperty;
|
||||
import com.loohp.limbo.Server.Packets.PacketPlayOutPositionAndLook;
|
||||
import com.loohp.limbo.Server.Packets.PacketPlayOutShowPlayerSkins;
|
||||
import com.loohp.limbo.Server.Packets.PacketPlayOutSpawnPosition;
|
||||
import com.loohp.limbo.Server.Packets.PacketPlayOutTabComplete;
|
||||
import com.loohp.limbo.Server.Packets.PacketPlayOutTabComplete.TabCompleteMatches;
|
||||
|
|
@ -72,11 +71,10 @@ import net.md_5.bungee.api.ChatColor;
|
|||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import net.md_5.bungee.chat.ComponentSerializer;
|
||||
import net.querz.mca.Chunk;
|
||||
|
||||
public class ClientConnection extends Thread {
|
||||
|
||||
public enum ClientState {
|
||||
public static enum ClientState {
|
||||
LEGACY,
|
||||
HANDSHAKE,
|
||||
STATUS,
|
||||
|
|
@ -97,10 +95,14 @@ public class ClientConnection extends Thread {
|
|||
|
||||
private InetAddress inetAddress;
|
||||
|
||||
private boolean ready;
|
||||
|
||||
public ClientConnection(Socket client_socket) {
|
||||
this.client_socket = client_socket;
|
||||
this.inetAddress = client_socket.getInetAddress();
|
||||
this.lastKeepAlivePayLoad = new AtomicLong();
|
||||
this.running = false;
|
||||
this.ready = false;
|
||||
}
|
||||
|
||||
public InetAddress getInetAddress() {
|
||||
|
|
@ -131,6 +133,10 @@ public class ClientConnection extends Thread {
|
|||
return running;
|
||||
}
|
||||
|
||||
public boolean isReady() {
|
||||
return ready;
|
||||
}
|
||||
|
||||
public synchronized void sendPacket(PacketOut packet) throws IOException {
|
||||
byte[] packetByte = packet.serializePacket();
|
||||
DataTypeIO.writeVarInt(output, packetByte.length);
|
||||
|
|
@ -232,11 +238,13 @@ public class ClientConnection extends Thread {
|
|||
bungeeUUID = UUID.fromString(data[2].replaceFirst("([0-9a-fA-F]{8})([0-9a-fA-F]{4})([0-9a-fA-F]{4})([0-9a-fA-F]{4})([0-9a-fA-F]+)", "$1-$2-$3-$4-$5"));
|
||||
inetAddress = InetAddress.getByName(ip);
|
||||
|
||||
String skinJson = data[3];
|
||||
|
||||
String skin = skinJson.split("\"value\":\"")[1].split("\"")[0];
|
||||
String signature = skinJson.split("\"signature\":\"")[1].split("\"")[0];
|
||||
bungeeSkin = new SkinResponse(skin, signature);
|
||||
if (data.length > 3) {
|
||||
String skinJson = data[3];
|
||||
|
||||
String skin = skinJson.split("\"value\":\"")[1].split("\"")[0];
|
||||
String signature = skinJson.split("\"signature\":\"")[1].split("\"")[0];
|
||||
bungeeSkin = new SkinResponse(skin, signature);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Limbo.getInstance().getConsole().sendMessage("If you wish to use bungeecord's IP forwarding, please enable that in your bungeecord config.yml as well!");
|
||||
disconnectDuringLogin(new BaseComponent[] {new TextComponent(ChatColor.RED + "Please connect from the proxy!")});
|
||||
|
|
@ -260,7 +268,8 @@ public class ClientConnection extends Thread {
|
|||
|
||||
state = ClientState.PLAY;
|
||||
|
||||
player = new Player(this, username, uuid, Limbo.getInstance().getNextEntityId(), Limbo.getInstance().getServerProperties().getWorldSpawn());
|
||||
player = new Player(this, username, uuid, Limbo.getInstance().getNextEntityId(), Limbo.getInstance().getServerProperties().getWorldSpawn(), new PlayerInteractManager());
|
||||
player.setSkinLayers((byte) (0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40));
|
||||
Limbo.getInstance().addPlayer(player);
|
||||
|
||||
break;
|
||||
|
|
@ -292,37 +301,11 @@ public class ClientConnection extends Thread {
|
|||
|
||||
World world = s.getWorld();
|
||||
|
||||
for (int x = 0; x < world.getChunks().length; x++) {
|
||||
for (int z = 0; z < world.getChunks()[x].length; z++) {
|
||||
Chunk chunk = world.getChunks()[x][z];
|
||||
if (chunk != null) {
|
||||
PacketPlayOutMapChunk chunkdata = new PacketPlayOutMapChunk(x, z, chunk, world.getEnvironment());
|
||||
sendPacket(chunkdata);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int x = 0; x < world.getChunks().length; x++) {
|
||||
for (int z = 0; z < world.getChunks()[x].length; z++) {
|
||||
List<Byte[]> blockChunk = world.getLightEngineBlock().getBlockLightBitMask(x, z);
|
||||
if (blockChunk == null) {
|
||||
blockChunk = new ArrayList<>();
|
||||
}
|
||||
List<Byte[]> skyChunk = null;
|
||||
if (world.hasSkyLight()) {
|
||||
skyChunk = world.getLightEngineSky().getSkyLightBitMask(x, z);
|
||||
}
|
||||
if (skyChunk == null) {
|
||||
skyChunk = new ArrayList<>();
|
||||
}
|
||||
PacketPlayOutLightUpdate chunkdata = new PacketPlayOutLightUpdate(x, z, true, skyChunk, blockChunk);
|
||||
sendPacket(chunkdata);
|
||||
}
|
||||
}
|
||||
player.playerInteractManager.update();
|
||||
|
||||
SkinResponse skinresponce = isBungeecord ? bungeeSkin : MojangAPIUtils.getSkinFromMojangServer(player.getName());
|
||||
SkinResponse skinresponce = isBungeecord && bungeeSkin != null ? bungeeSkin : MojangAPIUtils.getSkinFromMojangServer(player.getName());
|
||||
PlayerSkinProperty skin = skinresponce != null ? new PlayerSkinProperty(skinresponce.getSkin(), skinresponce.getSignature()) : null;
|
||||
PacketPlayOutPlayerInfo info = new PacketPlayOutPlayerInfo(PlayerInfoAction.ADD_PLAYER, player.getUUID(), new PlayerInfoData.PlayerInfoDataAddPlayer(player.getName(), Optional.ofNullable(skin), p.getDefaultGamemode(), 0, false, Optional.empty()));
|
||||
PacketPlayOutPlayerInfo info = new PacketPlayOutPlayerInfo(PlayerInfoAction.ADD_PLAYER, player.getUniqueId(), new PlayerInfoData.PlayerInfoDataAddPlayer(player.getName(), Optional.ofNullable(skin), p.getDefaultGamemode(), 0, false, Optional.empty()));
|
||||
sendPacket(info);
|
||||
/*
|
||||
for (ClientConnection client : Limbo.getInstance().getServerConnection().getClients()) {
|
||||
|
|
@ -332,9 +315,6 @@ public class ClientConnection extends Thread {
|
|||
}
|
||||
*/
|
||||
|
||||
PacketPlayOutShowPlayerSkins show = new PacketPlayOutShowPlayerSkins(player.getEntityId());
|
||||
sendPacket(show);
|
||||
|
||||
Set<PlayerAbilityFlags> flags = new HashSet<>();
|
||||
if (p.isAllowFlight()) {
|
||||
flags.add(PlayerAbilityFlags.FLY);
|
||||
|
|
@ -359,9 +339,15 @@ public class ClientConnection extends Thread {
|
|||
sendPacket(spawnPos);
|
||||
|
||||
PacketPlayOutPositionAndLook positionLook = new PacketPlayOutPositionAndLook(s.getX(), s.getY(), s.getZ(), s.getYaw(), s.getPitch(), 1);
|
||||
player.setLocation(new Location(world, s.getX(), s.getY(), s.getZ(), s.getYaw(), s.getPitch()));
|
||||
Limbo.getInstance().getUnsafe().setPlayerLocationSilently(player, new Location(world, s.getX(), s.getY(), s.getZ(), s.getYaw(), s.getPitch()));
|
||||
sendPacket(positionLook);
|
||||
|
||||
player.getDataWatcher().update();
|
||||
PacketPlayOutEntityMetadata show = new PacketPlayOutEntityMetadata(player, false, Player.class.getDeclaredField("skinLayers"));
|
||||
sendPacket(show);
|
||||
|
||||
ready = true;
|
||||
|
||||
while (client_socket.isConnected()) {
|
||||
try {
|
||||
int size = DataTypeIO.readVarInt(input);
|
||||
|
|
@ -381,7 +367,7 @@ public class ClientConnection extends Thread {
|
|||
PacketPlayOutPositionAndLook cancel = new PacketPlayOutPositionAndLook(returnTo.getX(), returnTo.getY(), returnTo.getZ(), returnTo.getYaw(), returnTo.getPitch(), 1);
|
||||
sendPacket(cancel);
|
||||
} else {
|
||||
player.setLocation(event.getTo());
|
||||
Limbo.getInstance().getUnsafe().setPlayerLocationSilently(player, event.getTo());
|
||||
PacketPlayOutUpdateViewPosition response = new PacketPlayOutUpdateViewPosition((int) player.getLocation().getX() >> 4, (int) player.getLocation().getZ() >> 4);
|
||||
sendPacket(response);
|
||||
}
|
||||
|
|
@ -396,7 +382,7 @@ public class ClientConnection extends Thread {
|
|||
PacketPlayOutPositionAndLook cancel = new PacketPlayOutPositionAndLook(returnTo.getX(), returnTo.getY(), returnTo.getZ(), returnTo.getYaw(), returnTo.getPitch(), 1);
|
||||
sendPacket(cancel);
|
||||
} else {
|
||||
player.setLocation(event.getTo());
|
||||
Limbo.getInstance().getUnsafe().setPlayerLocationSilently(player, event.getTo());
|
||||
PacketPlayOutUpdateViewPosition response = new PacketPlayOutUpdateViewPosition((int) player.getLocation().getX() >> 4, (int) player.getLocation().getZ() >> 4);
|
||||
sendPacket(response);
|
||||
}
|
||||
|
|
@ -411,7 +397,7 @@ public class ClientConnection extends Thread {
|
|||
PacketPlayOutPositionAndLook cancel = new PacketPlayOutPositionAndLook(returnTo.getX(), returnTo.getY(), returnTo.getZ(), returnTo.getYaw(), returnTo.getPitch(), 1);
|
||||
sendPacket(cancel);
|
||||
} else {
|
||||
player.setLocation(event.getTo());
|
||||
Limbo.getInstance().getUnsafe().setPlayerLocationSilently(player, event.getTo());
|
||||
PacketPlayOutUpdateViewPosition response = new PacketPlayOutUpdateViewPosition((int) player.getLocation().getX() >> 4, (int) player.getLocation().getZ() >> 4);
|
||||
sendPacket(response);
|
||||
}
|
||||
|
|
@ -457,7 +443,7 @@ public class ClientConnection extends Thread {
|
|||
|
||||
}
|
||||
|
||||
} catch (Exception e) {}
|
||||
} catch (Exception e) {e.printStackTrace();}
|
||||
|
||||
try {
|
||||
client_socket.close();
|
||||
|
|
|
|||
|
|
@ -6,16 +6,16 @@ import java.io.IOException;
|
|||
|
||||
import com.loohp.limbo.Utils.DataTypeIO;
|
||||
|
||||
public class PacketPlayOutShowPlayerSkins extends PacketOut {
|
||||
|
||||
private int entityId;
|
||||
|
||||
public PacketPlayOutShowPlayerSkins(int entityId) {
|
||||
this.entityId = entityId;
|
||||
}
|
||||
public class PacketPlayOutEntityDestroy extends PacketOut {
|
||||
|
||||
public int getEntityId() {
|
||||
return entityId;
|
||||
private int[] entityIds;
|
||||
|
||||
public PacketPlayOutEntityDestroy(int... entityIds) {
|
||||
this.entityIds = entityIds;
|
||||
}
|
||||
|
||||
public int[] getEntityIds() {
|
||||
return entityIds;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -24,13 +24,10 @@ public class PacketPlayOutShowPlayerSkins extends PacketOut {
|
|||
|
||||
DataOutputStream output = new DataOutputStream(buffer);
|
||||
output.writeByte(Packet.getPlayOut().get(getClass()));
|
||||
|
||||
DataTypeIO.writeVarInt(output, entityId);
|
||||
output.writeByte(16);
|
||||
DataTypeIO.writeVarInt(output, 0);
|
||||
int bitmask = 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40;
|
||||
output.writeByte(bitmask);
|
||||
output.writeByte(0xff);
|
||||
DataTypeIO.writeVarInt(output, entityIds.length);
|
||||
for (int id : entityIds) {
|
||||
DataTypeIO.writeVarInt(output, id);
|
||||
}
|
||||
|
||||
return buffer.toByteArray();
|
||||
}
|
||||
|
|
@ -0,0 +1,156 @@
|
|||
package com.loohp.limbo.Server.Packets;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.loohp.limbo.Entity.DataWatcher.WatchableObject;
|
||||
import com.loohp.limbo.Entity.DataWatcher.WatchableObjectType;
|
||||
import com.loohp.limbo.Entity.Entity;
|
||||
import com.loohp.limbo.Entity.Pose;
|
||||
import com.loohp.limbo.Utils.DataTypeIO;
|
||||
import com.loohp.limbo.Utils.Rotation3f;
|
||||
import com.loohp.limbo.World.BlockPosition;
|
||||
|
||||
import net.md_5.bungee.chat.ComponentSerializer;
|
||||
|
||||
public class PacketPlayOutEntityMetadata extends PacketOut {
|
||||
|
||||
public static final int END_OFF_METADATA = 0xff;
|
||||
|
||||
private Entity entity;
|
||||
public boolean allFields;
|
||||
public Field[] fields;
|
||||
|
||||
public PacketPlayOutEntityMetadata(Entity entity, boolean allFields, Field... fields) {
|
||||
this.entity = entity;
|
||||
this.allFields = allFields;
|
||||
this.fields = fields;
|
||||
}
|
||||
|
||||
public PacketPlayOutEntityMetadata(Entity entity) {
|
||||
this(entity, true);
|
||||
}
|
||||
|
||||
public Entity getEntity() {
|
||||
return entity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] serializePacket() throws IOException {
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
|
||||
DataOutputStream output = new DataOutputStream(buffer);
|
||||
output.writeByte(Packet.getPlayOut().get(getClass()));
|
||||
DataTypeIO.writeVarInt(output, entity.getEntityId());
|
||||
Collection<WatchableObject> watches;
|
||||
if (allFields) {
|
||||
watches = new HashSet<>(entity.getDataWatcher().getWatchableObjects().values());
|
||||
} else {
|
||||
watches = new HashSet<>();
|
||||
Map<Field, WatchableObject> entries = entity.getDataWatcher().getWatchableObjects();
|
||||
for (Field field : fields) {
|
||||
WatchableObject watch = entries.get(field);
|
||||
if (watch != null) {
|
||||
watches.add(watch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Map<Integer, Integer> bitmasks = new HashMap<>();
|
||||
Iterator<WatchableObject> itr = watches.iterator();
|
||||
while (itr.hasNext()) {
|
||||
WatchableObject watch = itr.next();
|
||||
if (watch.isBitmask()) {
|
||||
itr.remove();
|
||||
Integer bitmask = bitmasks.get(watch.getIndex());
|
||||
if (bitmask == null) {
|
||||
bitmask = 0;
|
||||
}
|
||||
if ((boolean) watch.getValue()) {
|
||||
bitmask |= watch.getBitmask();
|
||||
} else {
|
||||
bitmask &= ~watch.getBitmask();
|
||||
}
|
||||
bitmasks.put(watch.getIndex(), bitmask);
|
||||
}
|
||||
}
|
||||
for (Entry<Integer, Integer> entry : bitmasks.entrySet()) {
|
||||
watches.add(new WatchableObject(entry.getValue().byteValue(), entry.getKey(), WatchableObjectType.BYTE));
|
||||
}
|
||||
|
||||
for (WatchableObject watch : watches) {
|
||||
output.writeByte(watch.getIndex());
|
||||
if (watch.isOptional()) {
|
||||
DataTypeIO.writeVarInt(output, watch.getType().getOptionalTypeId());
|
||||
output.writeBoolean(watch.getValue() != null);
|
||||
} else {
|
||||
DataTypeIO.writeVarInt(output, watch.getType().getTypeId());
|
||||
}
|
||||
if (!watch.isOptional() || watch.getValue() != null) {
|
||||
switch (watch.getType()) {
|
||||
//case BLOCKID:
|
||||
// break;
|
||||
case POSITION:
|
||||
DataTypeIO.writeBlockPosition(output, (BlockPosition) watch.getValue());
|
||||
break;
|
||||
case BOOLEAN:
|
||||
output.writeBoolean((boolean) watch.getValue());
|
||||
break;
|
||||
case BYTE:
|
||||
output.writeByte((byte) watch.getValue());
|
||||
break;
|
||||
case CHAT:
|
||||
DataTypeIO.writeString(output, ComponentSerializer.toString(watch.getValue()), StandardCharsets.UTF_8);
|
||||
break;
|
||||
//case DIRECTION:
|
||||
// break;
|
||||
case FLOAT:
|
||||
output.writeFloat((float) watch.getValue());
|
||||
break;
|
||||
//case NBT:
|
||||
// break;
|
||||
//case PARTICLE:
|
||||
// break;
|
||||
case POSE:
|
||||
DataTypeIO.writeVarInt(output, ((Pose) watch.getValue()).getId());
|
||||
break;
|
||||
case ROTATION:
|
||||
Rotation3f rotation = (Rotation3f) watch.getValue();
|
||||
output.writeFloat((float) rotation.getX());
|
||||
output.writeFloat((float) rotation.getY());
|
||||
output.writeFloat((float) rotation.getZ());
|
||||
break;
|
||||
//case SLOT:
|
||||
// break;
|
||||
case STRING:
|
||||
DataTypeIO.writeString(output, watch.getValue().toString(), StandardCharsets.UTF_8);
|
||||
break;
|
||||
case UUID:
|
||||
DataTypeIO.writeUUID(output, (UUID) watch.getValue());
|
||||
break;
|
||||
case VARINT:
|
||||
DataTypeIO.writeVarInt(output, (int) watch.getValue());
|
||||
break;
|
||||
//case VILLAGER_DATA:
|
||||
// break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
output.writeByte(END_OFF_METADATA);
|
||||
|
||||
return buffer.toByteArray();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -25,8 +25,7 @@ public class PacketPlayOutRespawn extends PacketOut {
|
|||
private boolean isFlat;
|
||||
private boolean copyMetaData;
|
||||
|
||||
public PacketPlayOutRespawn(World world, CompoundTag dimensionCodec, long hashedSeed, GameMode gamemode, boolean isDebug,
|
||||
boolean isFlat, boolean copyMetaData) {
|
||||
public PacketPlayOutRespawn(World world, CompoundTag dimensionCodec, long hashedSeed, GameMode gamemode, boolean isDebug, boolean isFlat, boolean copyMetaData) {
|
||||
this.dimension = world.getEnvironment();
|
||||
this.dimensionCodec = dimensionCodec;
|
||||
this.worldName = new NamespacedKey(world.getName()).toString();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,111 @@
|
|||
package com.loohp.limbo.Server.Packets;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.loohp.limbo.Entity.EntityType;
|
||||
import com.loohp.limbo.Utils.DataTypeIO;
|
||||
|
||||
public class PacketPlayOutSpawnEntity extends PacketOut {
|
||||
|
||||
private int entityId;
|
||||
private UUID uuid;
|
||||
private EntityType type;
|
||||
private double x;
|
||||
private double y;
|
||||
private double z;
|
||||
private float pitch;
|
||||
private float yaw;
|
||||
private int data;
|
||||
private short velocityX;
|
||||
private short velocityY;
|
||||
private short velocityZ;
|
||||
|
||||
public PacketPlayOutSpawnEntity(int entityId, UUID uuid, EntityType type, double x, double y, double z, float pitch, float yaw, short velocityX, short velocityY, short velocityZ) {
|
||||
this.entityId = entityId;
|
||||
this.uuid = uuid;
|
||||
this.type = type;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.pitch = pitch;
|
||||
this.yaw = yaw;
|
||||
this.data = 0; //TO-DO
|
||||
this.velocityX = velocityX;
|
||||
this.velocityY = velocityY;
|
||||
this.velocityZ = velocityZ;
|
||||
}
|
||||
|
||||
public int getEntityId() {
|
||||
return entityId;
|
||||
}
|
||||
|
||||
public UUID getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public EntityType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public double getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public double getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
public double getZ() {
|
||||
return z;
|
||||
}
|
||||
|
||||
public float getPitch() {
|
||||
return pitch;
|
||||
}
|
||||
|
||||
public float getYaw() {
|
||||
return yaw;
|
||||
}
|
||||
|
||||
public int getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public short getVelocityX() {
|
||||
return velocityX;
|
||||
}
|
||||
|
||||
public short getVelocityY() {
|
||||
return velocityY;
|
||||
}
|
||||
|
||||
public short getVelocityZ() {
|
||||
return velocityZ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] serializePacket() throws IOException {
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
|
||||
DataOutputStream output = new DataOutputStream(buffer);
|
||||
output.writeByte(Packet.getPlayOut().get(getClass()));
|
||||
DataTypeIO.writeVarInt(output, entityId);
|
||||
DataTypeIO.writeUUID(output, uuid);
|
||||
DataTypeIO.writeVarInt(output, type.getTypeId());
|
||||
output.writeDouble(x);
|
||||
output.writeDouble(y);
|
||||
output.writeDouble(z);
|
||||
output.writeByte((byte) (int) (pitch * 256.0F / 360.0F));
|
||||
output.writeByte((byte) (int) (yaw * 256.0F / 360.0F));
|
||||
output.writeInt(data);
|
||||
output.writeShort((int) (velocityX * 8000));
|
||||
output.writeShort((int) (velocityY * 8000));
|
||||
output.writeShort((int) (velocityZ * 8000));
|
||||
|
||||
return buffer.toByteArray();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
package com.loohp.limbo.Server.Packets;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.loohp.limbo.Entity.EntityType;
|
||||
import com.loohp.limbo.Utils.DataTypeIO;
|
||||
|
||||
public class PacketPlayOutSpawnEntityLiving extends PacketOut {
|
||||
|
||||
private int entityId;
|
||||
private UUID uuid;
|
||||
private EntityType type;
|
||||
private double x;
|
||||
private double y;
|
||||
private double z;
|
||||
private float yaw;
|
||||
private float pitch;
|
||||
private float headPitch;
|
||||
private short velocityX;
|
||||
private short velocityY;
|
||||
private short velocityZ;
|
||||
|
||||
public PacketPlayOutSpawnEntityLiving(int entityId, UUID uuid, EntityType type, double x, double y, double z, float yaw, float pitch, float headPitch, short velocityX, short velocityY, short velocityZ) {
|
||||
this.entityId = entityId;
|
||||
this.uuid = uuid;
|
||||
this.type = type;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.yaw = yaw;
|
||||
this.pitch = pitch;
|
||||
this.headPitch = headPitch;
|
||||
this.velocityX = velocityX;
|
||||
this.velocityY = velocityY;
|
||||
this.velocityZ = velocityZ;
|
||||
}
|
||||
|
||||
public int getEntityId() {
|
||||
return entityId;
|
||||
}
|
||||
|
||||
public UUID getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public EntityType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public double getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public double getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
public double getZ() {
|
||||
return z;
|
||||
}
|
||||
|
||||
public float getYaw() {
|
||||
return yaw;
|
||||
}
|
||||
|
||||
public float getPitch() {
|
||||
return pitch;
|
||||
}
|
||||
|
||||
public float getHeadPitch() {
|
||||
return headPitch;
|
||||
}
|
||||
|
||||
public short getVelocityX() {
|
||||
return velocityX;
|
||||
}
|
||||
|
||||
public short getVelocityY() {
|
||||
return velocityY;
|
||||
}
|
||||
|
||||
public short getVelocityZ() {
|
||||
return velocityZ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] serializePacket() throws IOException {
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
|
||||
DataOutputStream output = new DataOutputStream(buffer);
|
||||
output.writeByte(Packet.getPlayOut().get(getClass()));
|
||||
DataTypeIO.writeVarInt(output, entityId);
|
||||
DataTypeIO.writeUUID(output, uuid);
|
||||
DataTypeIO.writeVarInt(output, type.getTypeId());
|
||||
output.writeDouble(x);
|
||||
output.writeDouble(y);
|
||||
output.writeDouble(z);
|
||||
output.writeByte((byte) (int) (yaw * 256.0F / 360.0F));
|
||||
output.writeByte((byte) (int) (pitch * 256.0F / 360.0F));
|
||||
output.writeByte((byte) (int) (headPitch * 256.0F / 360.0F));
|
||||
output.writeShort((int) (velocityX * 8000));
|
||||
output.writeShort((int) (velocityY * 8000));
|
||||
output.writeShort((int) (velocityZ * 8000));
|
||||
|
||||
return buffer.toByteArray();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
package com.loohp.limbo.Server.Packets;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class PacketPlayOutUnloadChunk extends PacketOut {
|
||||
|
||||
private int chunkX;
|
||||
private int chunkZ;
|
||||
|
||||
public PacketPlayOutUnloadChunk(int chunkX, int chunkZ) {
|
||||
this.chunkX = chunkX;
|
||||
this.chunkZ = chunkZ;
|
||||
}
|
||||
|
||||
public int getChunkX() {
|
||||
return chunkX;
|
||||
}
|
||||
|
||||
public int getChunkZ() {
|
||||
return chunkZ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] serializePacket() throws IOException {
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
|
||||
DataOutputStream output = new DataOutputStream(buffer);
|
||||
output.writeByte(Packet.getPlayOut().get(getClass()));
|
||||
output.writeInt(chunkX);
|
||||
output.writeInt(chunkZ);
|
||||
|
||||
return buffer.toByteArray();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
package com.loohp.limbo;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
public class Tick {
|
||||
|
||||
private TimerTask timerTask;
|
||||
|
||||
public Tick(Limbo instance) {
|
||||
this.timerTask = new TimerTask () {
|
||||
@Override
|
||||
public void run () {
|
||||
if (instance.isRunning()) {
|
||||
instance.getPlayers().forEach(each -> {
|
||||
if (each.clientConnection.isReady()) {
|
||||
try {
|
||||
each.playerInteractManager.update();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
/*
|
||||
try {
|
||||
each.getDataWatcher().update();
|
||||
} catch (IllegalArgumentException | IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
*/
|
||||
}
|
||||
});
|
||||
instance.getWorlds().forEach(each -> {
|
||||
try {
|
||||
each.update();
|
||||
} catch (IllegalArgumentException | IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.cancel();
|
||||
}
|
||||
}
|
||||
};
|
||||
new Timer().schedule(timerTask, 0, Math.round(1000 / instance.getServerProperties().getDefinedTicksPerSecond()));
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
timerTask.cancel();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -2,13 +2,18 @@ package com.loohp.limbo;
|
|||
|
||||
import java.lang.reflect.Constructor;
|
||||
|
||||
import com.loohp.limbo.Entity.DataWatcher;
|
||||
import com.loohp.limbo.Entity.Entity;
|
||||
import com.loohp.limbo.Location.Location;
|
||||
import com.loohp.limbo.Player.Player;
|
||||
import com.loohp.limbo.Utils.GameMode;
|
||||
import com.loohp.limbo.World.World;
|
||||
|
||||
@Deprecated
|
||||
public class Unsafe {
|
||||
|
||||
private com.loohp.limbo.Player.Unsafe playerUnsafe;
|
||||
private com.loohp.limbo.World.Unsafe worldUnsafe;
|
||||
|
||||
protected Unsafe() {
|
||||
try {
|
||||
|
|
@ -16,6 +21,11 @@ public class Unsafe {
|
|||
playerConstructor.setAccessible(true);
|
||||
playerUnsafe = playerConstructor.newInstance();
|
||||
playerConstructor.setAccessible(false);
|
||||
|
||||
Constructor<com.loohp.limbo.World.Unsafe> worldConstructor = com.loohp.limbo.World.Unsafe.class.getDeclaredConstructor();
|
||||
worldConstructor.setAccessible(true);
|
||||
worldUnsafe = worldConstructor.newInstance();
|
||||
worldConstructor.setAccessible(false);
|
||||
} catch (Exception e) {e.printStackTrace();}
|
||||
}
|
||||
|
||||
|
|
@ -28,5 +38,20 @@ public class Unsafe {
|
|||
public void setPlayerEntityId(Player player, int entityId) {
|
||||
playerUnsafe.a(player, entityId);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void removeEntity(World world, Entity entity) {
|
||||
worldUnsafe.a(world, entity);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public DataWatcher getDataWatcher(World world, Entity entity) {
|
||||
return worldUnsafe.b(world, entity);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void setPlayerLocationSilently(Player player, Location location) {
|
||||
playerUnsafe.a(player, location);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
package com.loohp.limbo.Utils;
|
||||
|
||||
public class NamespacedKey {
|
||||
|
||||
public static final String MINECRAFT_KEY = "minecraft";
|
||||
|
||||
private String namespace;
|
||||
private String key;
|
||||
|
|
@ -20,6 +22,10 @@ public class NamespacedKey {
|
|||
this.namespace = namespace;
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public static NamespacedKey minecraft(String key) {
|
||||
return new NamespacedKey(MINECRAFT_KEY, key);
|
||||
}
|
||||
|
||||
public String getNamespace() {
|
||||
return namespace;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,77 @@
|
|||
package com.loohp.limbo.Utils;
|
||||
|
||||
public class Rotation3f {
|
||||
|
||||
private double x;
|
||||
private double y;
|
||||
private double z;
|
||||
|
||||
public Rotation3f(double x, double y, double z) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
public double getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public void setX(double x) {
|
||||
this.x = x;
|
||||
}
|
||||
|
||||
public double getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
public void setY(double y) {
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
public double getZ() {
|
||||
return z;
|
||||
}
|
||||
|
||||
public void setZ(double z) {
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
long temp;
|
||||
temp = Double.doubleToLongBits(x);
|
||||
result = prime * result + (int) (temp ^ (temp >>> 32));
|
||||
temp = Double.doubleToLongBits(y);
|
||||
result = prime * result + (int) (temp ^ (temp >>> 32));
|
||||
temp = Double.doubleToLongBits(z);
|
||||
result = prime * result + (int) (temp ^ (temp >>> 32));
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
Rotation3f other = (Rotation3f) obj;
|
||||
if (Double.doubleToLongBits(x) != Double.doubleToLongBits(other.x)) {
|
||||
return false;
|
||||
}
|
||||
if (Double.doubleToLongBits(y) != Double.doubleToLongBits(other.y)) {
|
||||
return false;
|
||||
}
|
||||
if (Double.doubleToLongBits(z) != Double.doubleToLongBits(other.z)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -19,7 +19,7 @@ public class Schematic {
|
|||
//short height = nbt.getShort("Height");
|
||||
byte[] blockdata = nbt.getByteArray("BlockData");
|
||||
CompoundTag palette = nbt.getCompoundTag("Palette");
|
||||
ListTag<CompoundTag> blockEntities = nbt.getListTag("BlockEntities").asTypedList(CompoundTag.class);
|
||||
ListTag<CompoundTag> blockEntities = nbt.containsKey("BlockEntities") ? nbt.getListTag("BlockEntities").asTypedList(CompoundTag.class) : null;
|
||||
Map<Integer, String> mapping = new HashMap<>();
|
||||
for (String key : palette.keySet()) {
|
||||
mapping.put(palette.getInt(key), key);
|
||||
|
|
@ -54,19 +54,21 @@ public class Schematic {
|
|||
|
||||
Chunk chunk = world.getChunkAtWorldPos(x, z);
|
||||
|
||||
Iterator<CompoundTag> itr = blockEntities.iterator();
|
||||
while (itr.hasNext()) {
|
||||
CompoundTag tag = itr.next();
|
||||
int[] pos = tag.getIntArray("Pos");
|
||||
|
||||
if (pos[0] == x && pos[1] == y && pos[2] == z) {
|
||||
ListTag<CompoundTag> newTag = chunk.getTileEntities();
|
||||
newTag.add(SchematicConvertionUtils.toTileEntityTag(tag));
|
||||
chunk.setTileEntities(newTag);
|
||||
itr.remove();
|
||||
break;
|
||||
if (blockEntities != null) {
|
||||
Iterator<CompoundTag> itr = blockEntities.iterator();
|
||||
while (itr.hasNext()) {
|
||||
CompoundTag tag = itr.next();
|
||||
int[] pos = tag.getIntArray("Pos");
|
||||
|
||||
if (pos[0] == x && pos[1] == y && pos[2] == z) {
|
||||
ListTag<CompoundTag> newTag = chunk.getTileEntities();
|
||||
newTag.add(SchematicConvertionUtils.toTileEntityTag(tag));
|
||||
chunk.setTileEntities(newTag);
|
||||
itr.remove();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
package com.loohp.limbo.World;
|
||||
|
||||
import com.loohp.limbo.Entity.DataWatcher;
|
||||
import com.loohp.limbo.Entity.Entity;
|
||||
|
||||
@Deprecated
|
||||
public class Unsafe {
|
||||
|
||||
private Unsafe() {}
|
||||
|
||||
@Deprecated
|
||||
public void a(World a, Entity b) {
|
||||
a.removeEntity(b);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public DataWatcher b(World a, Entity b) {
|
||||
return a.getDataWatcher(b);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,7 +1,25 @@
|
|||
package com.loohp.limbo.World;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.loohp.limbo.Limbo;
|
||||
import com.loohp.limbo.Entity.ArmorStand;
|
||||
import com.loohp.limbo.Entity.DataWatcher;
|
||||
import com.loohp.limbo.Entity.DataWatcher.WatchableObject;
|
||||
import com.loohp.limbo.Entity.Entity;
|
||||
import com.loohp.limbo.Entity.EntityType;
|
||||
import com.loohp.limbo.Location.Location;
|
||||
import com.loohp.limbo.Player.Player;
|
||||
import com.loohp.limbo.Server.Packets.PacketPlayOutEntityDestroy;
|
||||
import com.loohp.limbo.Server.Packets.PacketPlayOutEntityMetadata;
|
||||
import com.loohp.limbo.Utils.SchematicConvertionUtils;
|
||||
|
||||
import net.querz.mca.Chunk;
|
||||
|
|
@ -17,6 +35,7 @@ public class World {
|
|||
private int length;
|
||||
private LightEngineBlock lightEngineBlock;
|
||||
private LightEngineSky lightEngineSky;
|
||||
private Map<Entity, DataWatcher> entities;
|
||||
|
||||
public World(String name, int width, int length, Environment environment) {
|
||||
this.name = name;
|
||||
|
|
@ -52,6 +71,8 @@ public class World {
|
|||
if (environment.hasSkyLight()) {
|
||||
this.lightEngineSky = new LightEngineSky(this);
|
||||
}
|
||||
|
||||
this.entities = new LinkedHashMap<>();
|
||||
}
|
||||
|
||||
public LightEngineBlock getLightEngineBlock() {
|
||||
|
|
@ -107,6 +128,49 @@ public class World {
|
|||
public Chunk getChunkAtWorldPos(int x, int z) {
|
||||
return this.chunks[(x >> 4)][(z >> 4)];
|
||||
}
|
||||
|
||||
public Chunk getChunkAt(int x, int z) {
|
||||
if (x < 0 || z < 0 || x >= chunks.length || z >= chunks[x].length) {
|
||||
return null;
|
||||
}
|
||||
return this.chunks[x][z];
|
||||
}
|
||||
|
||||
public int getChunkX(Chunk chunk) {
|
||||
for (int x = 0; x < chunks.length; x++) {
|
||||
for (int z = 0; z < chunks[x].length; z++) {
|
||||
Chunk c = getChunkAt(x, z);
|
||||
if (c.equals(chunk)) {
|
||||
return x;
|
||||
}
|
||||
}
|
||||
}
|
||||
return Integer.MIN_VALUE;
|
||||
}
|
||||
|
||||
public int getChunkZ(Chunk chunk) {
|
||||
for (int x = 0; x < chunks.length; x++) {
|
||||
for (int z = 0; z < chunks[x].length; z++) {
|
||||
Chunk c = getChunkAt(x, z);
|
||||
if (c.equals(chunk)) {
|
||||
return z;
|
||||
}
|
||||
}
|
||||
}
|
||||
return Integer.MIN_VALUE;
|
||||
}
|
||||
|
||||
public int[] getChunkXZ(Chunk chunk) {
|
||||
for (int x = 0; x < chunks.length; x++) {
|
||||
for (int z = 0; z < chunks[x].length; z++) {
|
||||
Chunk c = getChunkAt(x, z);
|
||||
if (c.equals(chunk)) {
|
||||
return new int[] {x, z};
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
|
|
@ -131,6 +195,81 @@ public class World {
|
|||
public int getChunkLength() {
|
||||
return (length >> 4) + 1;
|
||||
}
|
||||
|
||||
public Set<Entity> getEntities() {
|
||||
return Collections.unmodifiableSet(entities.keySet());
|
||||
}
|
||||
|
||||
public Entity spawnEntity(EntityType type, Location location) {
|
||||
if (!location.getWorld().equals(this)) {
|
||||
throw new IllegalArgumentException("Location not in world.");
|
||||
}
|
||||
Entity entity;
|
||||
switch (type) {
|
||||
case ARMOR_STAND:
|
||||
entity = new ArmorStand(location);
|
||||
break;
|
||||
default:
|
||||
throw new UnsupportedOperationException("This EntityType cannot be summoned.");
|
||||
}
|
||||
entities.put(entity, new DataWatcher(entity));
|
||||
return entity;
|
||||
}
|
||||
|
||||
public Entity addEntity(Entity entity) {
|
||||
if (entity.getWorld().equals(this)) {
|
||||
entities.put(entity, new DataWatcher(entity));
|
||||
} else {
|
||||
throw new IllegalArgumentException("Location not in world.");
|
||||
}
|
||||
return entity;
|
||||
}
|
||||
|
||||
public List<Player> getPlayers() {
|
||||
return Limbo.getInstance().getPlayers().stream().filter(each -> each.getWorld().equals(this)).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
protected void removeEntity(Entity entity) {
|
||||
entities.remove(entity);
|
||||
PacketPlayOutEntityDestroy packet = new PacketPlayOutEntityDestroy(entity.getEntityId());
|
||||
for (Player player : getPlayers()) {
|
||||
try {
|
||||
player.clientConnection.sendPacket(packet);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected DataWatcher getDataWatcher(Entity entity) {
|
||||
return entities.get(entity);
|
||||
}
|
||||
|
||||
public void update() throws IllegalArgumentException, IllegalAccessException {
|
||||
for (DataWatcher watcher : entities.values()) {
|
||||
if (watcher.getEntity().getWorld().equals(this)) {
|
||||
Map<Field, WatchableObject> updated = watcher.update();
|
||||
PacketPlayOutEntityMetadata packet = new PacketPlayOutEntityMetadata(watcher.getEntity(), false, updated.keySet().toArray(new Field[0]));
|
||||
for (Player player : getPlayers()) {
|
||||
try {
|
||||
player.clientConnection.sendPacket(packet);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
PacketPlayOutEntityDestroy packet = new PacketPlayOutEntityDestroy(watcher.getEntity().getEntityId());
|
||||
for (Player player : getPlayers()) {
|
||||
try {
|
||||
player.clientConnection.sendPacket(packet);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
entities.remove(watcher.getEntity());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
|
|
|
|||
|
|
@ -27,17 +27,21 @@
|
|||
"PacketPlayOutChat": "0x0E",
|
||||
"PacketPlayOutPlayerAbilities": "0x30",
|
||||
"PacketPlayOutMapChunk": "0x20",
|
||||
"PacketPlayOutUnloadChunk": "0x1C",
|
||||
"PacketPlayOutLightUpdate": "0x23",
|
||||
"PacketPlayOutKeepAlive": "0x1F",
|
||||
"PacketPlayOutPlayerInfo": "0x32",
|
||||
"PacketPlayOutUpdateViewPosition": "0x40",
|
||||
"PacketPlayOutShowPlayerSkins": "0x44",
|
||||
"PacketPlayOutDisconnect": "0x19",
|
||||
"PacketPlayOutPluginMessaging": "0x17",
|
||||
"PacketPlayOutTabComplete": "0x0F",
|
||||
"PacketPlayOutDeclareCommands": "0x10",
|
||||
"PacketPlayOutRespawn": "0x39",
|
||||
"PacketPlayOutGameState": "0x1D"
|
||||
"PacketPlayOutGameState": "0x1D",
|
||||
"PacketPlayOutEntityDestroy": "0x36",
|
||||
"PacketPlayOutEntityMetadata": "0x44",
|
||||
"PacketPlayOutSpawnEntity": "0x00",
|
||||
"PacketPlayOutSpawnEntityLiving": "0x02"
|
||||
},
|
||||
"StatusIn": {
|
||||
"0x01": "PacketStatusInPing",
|
||||
|
|
|
|||
|
|
@ -28,6 +28,12 @@ world-spawn=world;20.5;17;22.5;-90;0
|
|||
#Reduce debug info
|
||||
reduced-debug-info=false
|
||||
|
||||
#The view distance of the server
|
||||
view-distance=6
|
||||
|
||||
#Ticks per second of the server
|
||||
ticks-per-second=5
|
||||
|
||||
#Server list message in Json
|
||||
motd={"text":"","extra":[{"text":"Limbo Server!","color":"yellow"}]}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue