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>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>com.loohp</groupId>
|
<groupId>com.loohp</groupId>
|
||||||
<artifactId>Limbo</artifactId>
|
<artifactId>Limbo</artifactId>
|
||||||
<version>0.3.8-ALPHA</version>
|
<version>0.4.0-ALPHA-SNAPSHOT</version>
|
||||||
<build>
|
<build>
|
||||||
<sourceDirectory>src/main/java</sourceDirectory>
|
<sourceDirectory>src/main/java</sourceDirectory>
|
||||||
<resources>
|
<resources>
|
||||||
|
|
|
||||||
|
|
@ -152,7 +152,7 @@ public class Console implements CommandSender {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
while (true) {
|
while (true) {
|
||||||
String command = tabReader.readLine(PROMPT);
|
String command = tabReader.readLine(PROMPT).trim();
|
||||||
if (command.length() > 0) {
|
if (command.length() > 0) {
|
||||||
String[] input = CustomStringUtils.splitStringToArgs(command);
|
String[] input = CustomStringUtils.splitStringToArgs(command);
|
||||||
new Thread(() -> Limbo.getInstance().dispatchCommand(this, input)).start();
|
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.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.Reader;
|
||||||
|
import java.io.StringWriter;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
@ -18,32 +21,36 @@ import com.loohp.limbo.Utils.YamlOrder;
|
||||||
|
|
||||||
public class FileConfiguration {
|
public class FileConfiguration {
|
||||||
|
|
||||||
File file;
|
private Map<String, Object> mapping;
|
||||||
|
private String header;
|
||||||
Map<String, Object> mapping;
|
|
||||||
String header;
|
|
||||||
|
|
||||||
public FileConfiguration(File file) throws FileNotFoundException {
|
public FileConfiguration(File file) throws FileNotFoundException {
|
||||||
this.file = file;
|
|
||||||
if (file.exists()) {
|
if (file.exists()) {
|
||||||
reloadConfig();
|
reloadConfig(new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8));
|
||||||
} else {
|
} else {
|
||||||
mapping = new LinkedHashMap<>();
|
mapping = new LinkedHashMap<>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
public FileConfiguration(InputStream input){
|
public FileConfiguration(InputStream input){
|
||||||
reloadConfig(input);
|
reloadConfig(new InputStreamReader(input, StandardCharsets.UTF_8));
|
||||||
}
|
}
|
||||||
|
|
||||||
public FileConfiguration reloadConfig() throws FileNotFoundException {
|
public FileConfiguration(Reader reader){
|
||||||
return reloadConfig(new FileInputStream(file));
|
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();
|
Yaml yml = new Yaml();
|
||||||
mapping = yml.load(input);
|
mapping = yml.load(reader);
|
||||||
return this;
|
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();
|
DumperOptions options = new DumperOptions();
|
||||||
options.setIndent(2);
|
options.setIndent(2);
|
||||||
options.setPrettyFlow(true);
|
options.setPrettyFlow(true);
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,10 @@ import java.awt.image.BufferedImage;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
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.Optional;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
|
|
@ -17,28 +21,43 @@ import com.loohp.limbo.World.World;
|
||||||
|
|
||||||
public class ServerProperties {
|
public class ServerProperties {
|
||||||
|
|
||||||
File file;
|
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";
|
||||||
int maxPlayers;
|
|
||||||
int serverPort;
|
private File file;
|
||||||
String serverIp;
|
private int maxPlayers;
|
||||||
NamespacedKey levelName;
|
private int serverPort;
|
||||||
String schemFileName;
|
private String serverIp;
|
||||||
NamespacedKey levelDimension;
|
private NamespacedKey levelName;
|
||||||
GameMode defaultGamemode;
|
private String schemFileName;
|
||||||
Location worldSpawn;
|
private NamespacedKey levelDimension;
|
||||||
boolean reducedDebugInfo;
|
private GameMode defaultGamemode;
|
||||||
boolean allowFlight;
|
private Location worldSpawn;
|
||||||
String motdJson;
|
private boolean reducedDebugInfo;
|
||||||
String versionString;
|
private boolean allowFlight;
|
||||||
int protocol;
|
private String motdJson;
|
||||||
boolean bungeecord;
|
private String versionString;
|
||||||
|
private int protocol;
|
||||||
|
private boolean bungeecord;
|
||||||
|
private int viewDistance;
|
||||||
|
private double ticksPerSecond;
|
||||||
|
|
||||||
Optional<BufferedImage> favicon;
|
Optional<BufferedImage> favicon;
|
||||||
|
|
||||||
public ServerProperties(File file) throws IOException {
|
public ServerProperties(File file) throws IOException {
|
||||||
this.file = file;
|
this.file = file;
|
||||||
|
|
||||||
|
Properties def = new Properties();
|
||||||
|
def.load(new InputStreamReader(getClass().getClassLoader().getResourceAsStream("server.properties"), StandardCharsets.UTF_8));
|
||||||
|
|
||||||
Properties prop = new Properties();
|
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;
|
protocol = Limbo.getInstance().serverImplmentationProtocol;
|
||||||
|
|
||||||
|
|
@ -63,6 +82,8 @@ public class ServerProperties {
|
||||||
motdJson = prop.getProperty("motd");
|
motdJson = prop.getProperty("motd");
|
||||||
versionString = prop.getProperty("version");
|
versionString = prop.getProperty("version");
|
||||||
bungeecord = Boolean.parseBoolean(prop.getProperty("bungeecord"));
|
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");
|
File png = new File("server-icon.png");
|
||||||
if (png.exists()) {
|
if (png.exists()) {
|
||||||
|
|
@ -156,4 +177,12 @@ public class ServerProperties {
|
||||||
return protocol;
|
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.TreeMap;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
|
@ -108,6 +109,8 @@ public class Limbo {
|
||||||
public final int serverImplmentationProtocol = 754;
|
public final int serverImplmentationProtocol = 754;
|
||||||
public final String limboImplementationVersion;
|
public final String limboImplementationVersion;
|
||||||
|
|
||||||
|
private AtomicBoolean isRunning;
|
||||||
|
|
||||||
private ServerConnection server;
|
private ServerConnection server;
|
||||||
private Console console;
|
private Console console;
|
||||||
|
|
||||||
|
|
@ -126,6 +129,9 @@ public class Limbo {
|
||||||
|
|
||||||
private DimensionRegistry dimensionRegistry;
|
private DimensionRegistry dimensionRegistry;
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private Tick tick;
|
||||||
|
|
||||||
private Metrics metrics;
|
private Metrics metrics;
|
||||||
|
|
||||||
public AtomicInteger entityIdCount = new AtomicInteger();
|
public AtomicInteger entityIdCount = new AtomicInteger();
|
||||||
|
|
@ -136,6 +142,7 @@ public class Limbo {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public Limbo() throws IOException, ParseException, NumberFormatException, ClassNotFoundException, InterruptedException {
|
public Limbo() throws IOException, ParseException, NumberFormatException, ClassNotFoundException, InterruptedException {
|
||||||
instance = this;
|
instance = this;
|
||||||
|
isRunning = new AtomicBoolean(true);
|
||||||
|
|
||||||
if (!noGui) {
|
if (!noGui) {
|
||||||
while (!GUI.loadFinish) {
|
while (!GUI.loadFinish) {
|
||||||
|
|
@ -304,6 +311,8 @@ public class Limbo {
|
||||||
|
|
||||||
server = new ServerConnection(properties.getServerIp(), properties.getServerPort());
|
server = new ServerConnection(properties.getServerIp(), properties.getServerPort());
|
||||||
|
|
||||||
|
tick = new Tick(this);
|
||||||
|
|
||||||
metrics = new Metrics();
|
metrics = new Metrics();
|
||||||
|
|
||||||
console.run();
|
console.run();
|
||||||
|
|
@ -357,6 +366,27 @@ public class Limbo {
|
||||||
return world;
|
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() {
|
public ServerProperties getServerProperties() {
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
@ -387,12 +417,12 @@ public class Limbo {
|
||||||
|
|
||||||
public void addPlayer(Player player) {
|
public void addPlayer(Player player) {
|
||||||
playersByName.put(player.getName(), player);
|
playersByName.put(player.getName(), player);
|
||||||
playersByUUID.put(player.getUUID(), player);
|
playersByUUID.put(player.getUniqueId(), player);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removePlayer(Player player) {
|
public void removePlayer(Player player) {
|
||||||
playersByName.remove(player.getName());
|
playersByName.remove(player.getName());
|
||||||
playersByUUID.remove(player.getUUID());
|
playersByUUID.remove(player.getUniqueId());
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<World> getWorlds() {
|
public List<World> getWorlds() {
|
||||||
|
|
@ -453,6 +483,7 @@ public class Limbo {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void stopServer() {
|
public void stopServer() {
|
||||||
|
isRunning.set(false);
|
||||||
console.sendMessage("Stopping Server...");
|
console.sendMessage("Stopping Server...");
|
||||||
|
|
||||||
for (LimboPlugin plugin : Limbo.getInstance().getPluginManager().getPlugins()) {
|
for (LimboPlugin plugin : Limbo.getInstance().getPluginManager().getPlugins()) {
|
||||||
|
|
@ -476,6 +507,10 @@ public class Limbo {
|
||||||
System.exit(0);
|
System.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isRunning() {
|
||||||
|
return isRunning.get();
|
||||||
|
}
|
||||||
|
|
||||||
public int getNextEntityId() {
|
public int getNextEntityId() {
|
||||||
if (entityIdCount.get() == Integer.MAX_VALUE) {
|
if (entityIdCount.get() == Integer.MAX_VALUE) {
|
||||||
return entityIdCount.getAndSet(0);
|
return entityIdCount.getAndSet(0);
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,11 @@ import java.util.UUID;
|
||||||
|
|
||||||
import com.loohp.limbo.Limbo;
|
import com.loohp.limbo.Limbo;
|
||||||
import com.loohp.limbo.Commands.CommandSender;
|
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.PlayerChatEvent;
|
||||||
import com.loohp.limbo.Events.PlayerTeleportEvent;
|
import com.loohp.limbo.Events.PlayerTeleportEvent;
|
||||||
import com.loohp.limbo.Location.Location;
|
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.PacketPlayOutPositionAndLook;
|
||||||
import com.loohp.limbo.Server.Packets.PacketPlayOutRespawn;
|
import com.loohp.limbo.Server.Packets.PacketPlayOutRespawn;
|
||||||
import com.loohp.limbo.Utils.GameMode;
|
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.BaseComponent;
|
||||||
import net.md_5.bungee.api.chat.TextComponent;
|
import net.md_5.bungee.api.chat.TextComponent;
|
||||||
import net.md_5.bungee.chat.ComponentSerializer;
|
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 ClientConnection clientConnection;
|
||||||
|
public final PlayerInteractManager playerInteractManager;
|
||||||
|
|
||||||
private final String username;
|
protected final String username;
|
||||||
private final UUID uuid;
|
|
||||||
protected GameMode gamemode;
|
protected GameMode gamemode;
|
||||||
|
protected DataWatcher watcher;
|
||||||
|
|
||||||
protected int entityId;
|
@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;
|
||||||
|
|
||||||
private 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());
|
||||||
public Player(ClientConnection clientConnection, String username, UUID uuid, int entityId, Location location) {
|
|
||||||
this.clientConnection = clientConnection;
|
this.clientConnection = clientConnection;
|
||||||
this.username = username;
|
this.username = username;
|
||||||
this.uuid = uuid;
|
|
||||||
this.entityId = entityId;
|
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() {
|
public GameMode getGamemode() {
|
||||||
|
|
@ -56,40 +73,94 @@ public class Player implements CommandSender {
|
||||||
this.gamemode = gamemode;
|
this.gamemode = gamemode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public World getWorld() {
|
@Deprecated
|
||||||
return location.clone().getWorld();
|
protected void setEntityId(int entityId) {
|
||||||
|
this.entityId = entityId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getEntityId() {
|
public float getAdditionalHearts() {
|
||||||
return entityId;
|
return additionalHearts;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Location getLocation() {
|
public void setAdditionalHearts(float additionalHearts) {
|
||||||
return location.clone();
|
this.additionalHearts = additionalHearts;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLocation(Location location) {
|
public int getScore() {
|
||||||
this.location = location;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
@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 void setLeftShoulder(Entity leftShoulder) {
|
||||||
|
this.leftShoulder = leftShoulder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Entity getRightShoulder() {
|
||||||
|
return rightShoulder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRightShoulder(Entity rightShoulder) {
|
||||||
|
this.rightShoulder = rightShoulder;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return username;
|
return username;
|
||||||
}
|
}
|
||||||
|
|
||||||
public UUID getUUID() {
|
@Override
|
||||||
return uuid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasPermission(String permission) {
|
public boolean hasPermission(String permission) {
|
||||||
return Limbo.getInstance().getPermissionsManager().hasPermission(this, permission);
|
return Limbo.getInstance().getPermissionsManager().hasPermission(this, permission);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void teleport(Location location) {
|
public void teleport(Location location) {
|
||||||
PlayerTeleportEvent event = Limbo.getInstance().getEventsManager().callEvent(new PlayerTeleportEvent(this, getLocation(), location));
|
PlayerTeleportEvent event = Limbo.getInstance().getEventsManager().callEvent(new PlayerTeleportEvent(this, getLocation(), location));
|
||||||
if (!event.isCancelled()) {
|
if (!event.isCancelled()) {
|
||||||
location = event.getTo();
|
location = event.getTo();
|
||||||
|
super.teleport(location);
|
||||||
try {
|
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);
|
PacketPlayOutRespawn respawn = new PacketPlayOutRespawn(location.getWorld(), Limbo.getInstance().getDimensionRegistry().getCodec(), 0, gamemode, false, false, true);
|
||||||
clientConnection.sendPacket(respawn);
|
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) {
|
public void sendMessage(String message, UUID uuid) {
|
||||||
sendMessage(TextComponent.fromLegacyText(message), 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;
|
package com.loohp.limbo.Player;
|
||||||
|
|
||||||
|
import com.loohp.limbo.Location.Location;
|
||||||
import com.loohp.limbo.Utils.GameMode;
|
import com.loohp.limbo.Utils.GameMode;
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
|
|
@ -14,7 +15,12 @@ public class Unsafe {
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public void a(Player a, int b) {
|
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")) {
|
if (name.endsWith("plugin.yml") || name.endsWith("limbo.yml")) {
|
||||||
found = true;
|
found = true;
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
FileConfiguration pluginYaml = new FileConfiguration(zip);
|
FileConfiguration pluginYaml = new FileConfiguration(zip);
|
||||||
String main = pluginYaml.get("main", String.class);
|
String main = pluginYaml.get("main", String.class);
|
||||||
String pluginName = pluginYaml.get("name", 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.File.ServerProperties;
|
||||||
import com.loohp.limbo.Location.Location;
|
import com.loohp.limbo.Location.Location;
|
||||||
import com.loohp.limbo.Player.Player;
|
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.Packet;
|
||||||
import com.loohp.limbo.Server.Packets.PacketHandshakingIn;
|
import com.loohp.limbo.Server.Packets.PacketHandshakingIn;
|
||||||
import com.loohp.limbo.Server.Packets.PacketLoginInLoginStart;
|
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.PacketPlayInTabComplete;
|
||||||
import com.loohp.limbo.Server.Packets.PacketPlayOutDeclareCommands;
|
import com.loohp.limbo.Server.Packets.PacketPlayOutDeclareCommands;
|
||||||
import com.loohp.limbo.Server.Packets.PacketPlayOutDisconnect;
|
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.PacketPlayOutLogin;
|
||||||
import com.loohp.limbo.Server.Packets.PacketPlayOutMapChunk;
|
|
||||||
import com.loohp.limbo.Server.Packets.PacketPlayOutPlayerAbilities;
|
import com.loohp.limbo.Server.Packets.PacketPlayOutPlayerAbilities;
|
||||||
import com.loohp.limbo.Server.Packets.PacketPlayOutPlayerAbilities.PlayerAbilityFlags;
|
import com.loohp.limbo.Server.Packets.PacketPlayOutPlayerAbilities.PlayerAbilityFlags;
|
||||||
import com.loohp.limbo.Server.Packets.PacketPlayOutPlayerInfo;
|
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;
|
||||||
import com.loohp.limbo.Server.Packets.PacketPlayOutPlayerInfo.PlayerInfoData.PlayerInfoDataAddPlayer.PlayerSkinProperty;
|
import com.loohp.limbo.Server.Packets.PacketPlayOutPlayerInfo.PlayerInfoData.PlayerInfoDataAddPlayer.PlayerSkinProperty;
|
||||||
import com.loohp.limbo.Server.Packets.PacketPlayOutPositionAndLook;
|
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.PacketPlayOutSpawnPosition;
|
||||||
import com.loohp.limbo.Server.Packets.PacketPlayOutTabComplete;
|
import com.loohp.limbo.Server.Packets.PacketPlayOutTabComplete;
|
||||||
import com.loohp.limbo.Server.Packets.PacketPlayOutTabComplete.TabCompleteMatches;
|
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.BaseComponent;
|
||||||
import net.md_5.bungee.api.chat.TextComponent;
|
import net.md_5.bungee.api.chat.TextComponent;
|
||||||
import net.md_5.bungee.chat.ComponentSerializer;
|
import net.md_5.bungee.chat.ComponentSerializer;
|
||||||
import net.querz.mca.Chunk;
|
|
||||||
|
|
||||||
public class ClientConnection extends Thread {
|
public class ClientConnection extends Thread {
|
||||||
|
|
||||||
public enum ClientState {
|
public static enum ClientState {
|
||||||
LEGACY,
|
LEGACY,
|
||||||
HANDSHAKE,
|
HANDSHAKE,
|
||||||
STATUS,
|
STATUS,
|
||||||
|
|
@ -97,10 +95,14 @@ public class ClientConnection extends Thread {
|
||||||
|
|
||||||
private InetAddress inetAddress;
|
private InetAddress inetAddress;
|
||||||
|
|
||||||
|
private boolean ready;
|
||||||
|
|
||||||
public ClientConnection(Socket client_socket) {
|
public ClientConnection(Socket client_socket) {
|
||||||
this.client_socket = client_socket;
|
this.client_socket = client_socket;
|
||||||
this.inetAddress = client_socket.getInetAddress();
|
this.inetAddress = client_socket.getInetAddress();
|
||||||
this.lastKeepAlivePayLoad = new AtomicLong();
|
this.lastKeepAlivePayLoad = new AtomicLong();
|
||||||
|
this.running = false;
|
||||||
|
this.ready = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public InetAddress getInetAddress() {
|
public InetAddress getInetAddress() {
|
||||||
|
|
@ -131,6 +133,10 @@ public class ClientConnection extends Thread {
|
||||||
return running;
|
return running;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isReady() {
|
||||||
|
return ready;
|
||||||
|
}
|
||||||
|
|
||||||
public synchronized void sendPacket(PacketOut packet) throws IOException {
|
public synchronized void sendPacket(PacketOut packet) throws IOException {
|
||||||
byte[] packetByte = packet.serializePacket();
|
byte[] packetByte = packet.serializePacket();
|
||||||
DataTypeIO.writeVarInt(output, packetByte.length);
|
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"));
|
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);
|
inetAddress = InetAddress.getByName(ip);
|
||||||
|
|
||||||
String skinJson = data[3];
|
if (data.length > 3) {
|
||||||
|
String skinJson = data[3];
|
||||||
|
|
||||||
String skin = skinJson.split("\"value\":\"")[1].split("\"")[0];
|
String skin = skinJson.split("\"value\":\"")[1].split("\"")[0];
|
||||||
String signature = skinJson.split("\"signature\":\"")[1].split("\"")[0];
|
String signature = skinJson.split("\"signature\":\"")[1].split("\"")[0];
|
||||||
bungeeSkin = new SkinResponse(skin, signature);
|
bungeeSkin = new SkinResponse(skin, signature);
|
||||||
|
}
|
||||||
} catch (Exception e) {
|
} 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!");
|
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!")});
|
disconnectDuringLogin(new BaseComponent[] {new TextComponent(ChatColor.RED + "Please connect from the proxy!")});
|
||||||
|
|
@ -260,7 +268,8 @@ public class ClientConnection extends Thread {
|
||||||
|
|
||||||
state = ClientState.PLAY;
|
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);
|
Limbo.getInstance().addPlayer(player);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
@ -292,37 +301,11 @@ public class ClientConnection extends Thread {
|
||||||
|
|
||||||
World world = s.getWorld();
|
World world = s.getWorld();
|
||||||
|
|
||||||
for (int x = 0; x < world.getChunks().length; x++) {
|
player.playerInteractManager.update();
|
||||||
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++) {
|
SkinResponse skinresponce = isBungeecord && bungeeSkin != null ? bungeeSkin : MojangAPIUtils.getSkinFromMojangServer(player.getName());
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SkinResponse skinresponce = isBungeecord ? bungeeSkin : MojangAPIUtils.getSkinFromMojangServer(player.getName());
|
|
||||||
PlayerSkinProperty skin = skinresponce != null ? new PlayerSkinProperty(skinresponce.getSkin(), skinresponce.getSignature()) : null;
|
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);
|
sendPacket(info);
|
||||||
/*
|
/*
|
||||||
for (ClientConnection client : Limbo.getInstance().getServerConnection().getClients()) {
|
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<>();
|
Set<PlayerAbilityFlags> flags = new HashSet<>();
|
||||||
if (p.isAllowFlight()) {
|
if (p.isAllowFlight()) {
|
||||||
flags.add(PlayerAbilityFlags.FLY);
|
flags.add(PlayerAbilityFlags.FLY);
|
||||||
|
|
@ -359,9 +339,15 @@ public class ClientConnection extends Thread {
|
||||||
sendPacket(spawnPos);
|
sendPacket(spawnPos);
|
||||||
|
|
||||||
PacketPlayOutPositionAndLook positionLook = new PacketPlayOutPositionAndLook(s.getX(), s.getY(), s.getZ(), s.getYaw(), s.getPitch(), 1);
|
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);
|
sendPacket(positionLook);
|
||||||
|
|
||||||
|
player.getDataWatcher().update();
|
||||||
|
PacketPlayOutEntityMetadata show = new PacketPlayOutEntityMetadata(player, false, Player.class.getDeclaredField("skinLayers"));
|
||||||
|
sendPacket(show);
|
||||||
|
|
||||||
|
ready = true;
|
||||||
|
|
||||||
while (client_socket.isConnected()) {
|
while (client_socket.isConnected()) {
|
||||||
try {
|
try {
|
||||||
int size = DataTypeIO.readVarInt(input);
|
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);
|
PacketPlayOutPositionAndLook cancel = new PacketPlayOutPositionAndLook(returnTo.getX(), returnTo.getY(), returnTo.getZ(), returnTo.getYaw(), returnTo.getPitch(), 1);
|
||||||
sendPacket(cancel);
|
sendPacket(cancel);
|
||||||
} else {
|
} 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);
|
PacketPlayOutUpdateViewPosition response = new PacketPlayOutUpdateViewPosition((int) player.getLocation().getX() >> 4, (int) player.getLocation().getZ() >> 4);
|
||||||
sendPacket(response);
|
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);
|
PacketPlayOutPositionAndLook cancel = new PacketPlayOutPositionAndLook(returnTo.getX(), returnTo.getY(), returnTo.getZ(), returnTo.getYaw(), returnTo.getPitch(), 1);
|
||||||
sendPacket(cancel);
|
sendPacket(cancel);
|
||||||
} else {
|
} 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);
|
PacketPlayOutUpdateViewPosition response = new PacketPlayOutUpdateViewPosition((int) player.getLocation().getX() >> 4, (int) player.getLocation().getZ() >> 4);
|
||||||
sendPacket(response);
|
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);
|
PacketPlayOutPositionAndLook cancel = new PacketPlayOutPositionAndLook(returnTo.getX(), returnTo.getY(), returnTo.getZ(), returnTo.getYaw(), returnTo.getPitch(), 1);
|
||||||
sendPacket(cancel);
|
sendPacket(cancel);
|
||||||
} else {
|
} 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);
|
PacketPlayOutUpdateViewPosition response = new PacketPlayOutUpdateViewPosition((int) player.getLocation().getX() >> 4, (int) player.getLocation().getZ() >> 4);
|
||||||
sendPacket(response);
|
sendPacket(response);
|
||||||
}
|
}
|
||||||
|
|
@ -457,7 +443,7 @@ public class ClientConnection extends Thread {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (Exception e) {}
|
} catch (Exception e) {e.printStackTrace();}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
client_socket.close();
|
client_socket.close();
|
||||||
|
|
|
||||||
|
|
@ -6,16 +6,16 @@ import java.io.IOException;
|
||||||
|
|
||||||
import com.loohp.limbo.Utils.DataTypeIO;
|
import com.loohp.limbo.Utils.DataTypeIO;
|
||||||
|
|
||||||
public class PacketPlayOutShowPlayerSkins extends PacketOut {
|
public class PacketPlayOutEntityDestroy extends PacketOut {
|
||||||
|
|
||||||
private int entityId;
|
private int[] entityIds;
|
||||||
|
|
||||||
public PacketPlayOutShowPlayerSkins(int entityId) {
|
public PacketPlayOutEntityDestroy(int... entityIds) {
|
||||||
this.entityId = entityId;
|
this.entityIds = entityIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getEntityId() {
|
public int[] getEntityIds() {
|
||||||
return entityId;
|
return entityIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -24,13 +24,10 @@ public class PacketPlayOutShowPlayerSkins extends PacketOut {
|
||||||
|
|
||||||
DataOutputStream output = new DataOutputStream(buffer);
|
DataOutputStream output = new DataOutputStream(buffer);
|
||||||
output.writeByte(Packet.getPlayOut().get(getClass()));
|
output.writeByte(Packet.getPlayOut().get(getClass()));
|
||||||
|
DataTypeIO.writeVarInt(output, entityIds.length);
|
||||||
DataTypeIO.writeVarInt(output, entityId);
|
for (int id : entityIds) {
|
||||||
output.writeByte(16);
|
DataTypeIO.writeVarInt(output, id);
|
||||||
DataTypeIO.writeVarInt(output, 0);
|
}
|
||||||
int bitmask = 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40;
|
|
||||||
output.writeByte(bitmask);
|
|
||||||
output.writeByte(0xff);
|
|
||||||
|
|
||||||
return buffer.toByteArray();
|
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 isFlat;
|
||||||
private boolean copyMetaData;
|
private boolean copyMetaData;
|
||||||
|
|
||||||
public PacketPlayOutRespawn(World world, CompoundTag dimensionCodec, long hashedSeed, GameMode gamemode, boolean isDebug,
|
public PacketPlayOutRespawn(World world, CompoundTag dimensionCodec, long hashedSeed, GameMode gamemode, boolean isDebug, boolean isFlat, boolean copyMetaData) {
|
||||||
boolean isFlat, boolean copyMetaData) {
|
|
||||||
this.dimension = world.getEnvironment();
|
this.dimension = world.getEnvironment();
|
||||||
this.dimensionCodec = dimensionCodec;
|
this.dimensionCodec = dimensionCodec;
|
||||||
this.worldName = new NamespacedKey(world.getName()).toString();
|
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 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.Player.Player;
|
||||||
import com.loohp.limbo.Utils.GameMode;
|
import com.loohp.limbo.Utils.GameMode;
|
||||||
|
import com.loohp.limbo.World.World;
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public class Unsafe {
|
public class Unsafe {
|
||||||
|
|
||||||
private com.loohp.limbo.Player.Unsafe playerUnsafe;
|
private com.loohp.limbo.Player.Unsafe playerUnsafe;
|
||||||
|
private com.loohp.limbo.World.Unsafe worldUnsafe;
|
||||||
|
|
||||||
protected Unsafe() {
|
protected Unsafe() {
|
||||||
try {
|
try {
|
||||||
|
|
@ -16,6 +21,11 @@ public class Unsafe {
|
||||||
playerConstructor.setAccessible(true);
|
playerConstructor.setAccessible(true);
|
||||||
playerUnsafe = playerConstructor.newInstance();
|
playerUnsafe = playerConstructor.newInstance();
|
||||||
playerConstructor.setAccessible(false);
|
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();}
|
} catch (Exception e) {e.printStackTrace();}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -29,4 +39,19 @@ public class Unsafe {
|
||||||
playerUnsafe.a(player, 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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@ package com.loohp.limbo.Utils;
|
||||||
|
|
||||||
public class NamespacedKey {
|
public class NamespacedKey {
|
||||||
|
|
||||||
|
public static final String MINECRAFT_KEY = "minecraft";
|
||||||
|
|
||||||
private String namespace;
|
private String namespace;
|
||||||
private String key;
|
private String key;
|
||||||
|
|
||||||
|
|
@ -21,6 +23,10 @@ public class NamespacedKey {
|
||||||
this.key = key;
|
this.key = key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static NamespacedKey minecraft(String key) {
|
||||||
|
return new NamespacedKey(MINECRAFT_KEY, key);
|
||||||
|
}
|
||||||
|
|
||||||
public String getNamespace() {
|
public String getNamespace() {
|
||||||
return namespace;
|
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");
|
//short height = nbt.getShort("Height");
|
||||||
byte[] blockdata = nbt.getByteArray("BlockData");
|
byte[] blockdata = nbt.getByteArray("BlockData");
|
||||||
CompoundTag palette = nbt.getCompoundTag("Palette");
|
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<>();
|
Map<Integer, String> mapping = new HashMap<>();
|
||||||
for (String key : palette.keySet()) {
|
for (String key : palette.keySet()) {
|
||||||
mapping.put(palette.getInt(key), key);
|
mapping.put(palette.getInt(key), key);
|
||||||
|
|
@ -54,19 +54,21 @@ public class Schematic {
|
||||||
|
|
||||||
Chunk chunk = world.getChunkAtWorldPos(x, z);
|
Chunk chunk = world.getChunkAtWorldPos(x, z);
|
||||||
|
|
||||||
Iterator<CompoundTag> itr = blockEntities.iterator();
|
if (blockEntities != null) {
|
||||||
while (itr.hasNext()) {
|
Iterator<CompoundTag> itr = blockEntities.iterator();
|
||||||
CompoundTag tag = itr.next();
|
while (itr.hasNext()) {
|
||||||
int[] pos = tag.getIntArray("Pos");
|
CompoundTag tag = itr.next();
|
||||||
|
int[] pos = tag.getIntArray("Pos");
|
||||||
|
|
||||||
if (pos[0] == x && pos[1] == y && pos[2] == z) {
|
if (pos[0] == x && pos[1] == y && pos[2] == z) {
|
||||||
ListTag<CompoundTag> newTag = chunk.getTileEntities();
|
ListTag<CompoundTag> newTag = chunk.getTileEntities();
|
||||||
newTag.add(SchematicConvertionUtils.toTileEntityTag(tag));
|
newTag.add(SchematicConvertionUtils.toTileEntityTag(tag));
|
||||||
chunk.setTileEntities(newTag);
|
chunk.setTileEntities(newTag);
|
||||||
itr.remove();
|
itr.remove();
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
index++;
|
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;
|
package com.loohp.limbo.World;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
import java.util.Arrays;
|
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 com.loohp.limbo.Utils.SchematicConvertionUtils;
|
||||||
|
|
||||||
import net.querz.mca.Chunk;
|
import net.querz.mca.Chunk;
|
||||||
|
|
@ -17,6 +35,7 @@ public class World {
|
||||||
private int length;
|
private int length;
|
||||||
private LightEngineBlock lightEngineBlock;
|
private LightEngineBlock lightEngineBlock;
|
||||||
private LightEngineSky lightEngineSky;
|
private LightEngineSky lightEngineSky;
|
||||||
|
private Map<Entity, DataWatcher> entities;
|
||||||
|
|
||||||
public World(String name, int width, int length, Environment environment) {
|
public World(String name, int width, int length, Environment environment) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
|
@ -52,6 +71,8 @@ public class World {
|
||||||
if (environment.hasSkyLight()) {
|
if (environment.hasSkyLight()) {
|
||||||
this.lightEngineSky = new LightEngineSky(this);
|
this.lightEngineSky = new LightEngineSky(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.entities = new LinkedHashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public LightEngineBlock getLightEngineBlock() {
|
public LightEngineBlock getLightEngineBlock() {
|
||||||
|
|
@ -108,6 +129,49 @@ public class World {
|
||||||
return this.chunks[(x >> 4)][(z >> 4)];
|
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() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
@ -132,6 +196,81 @@ public class World {
|
||||||
return (length >> 4) + 1;
|
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
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
final int prime = 31;
|
final int prime = 31;
|
||||||
|
|
|
||||||
|
|
@ -27,17 +27,21 @@
|
||||||
"PacketPlayOutChat": "0x0E",
|
"PacketPlayOutChat": "0x0E",
|
||||||
"PacketPlayOutPlayerAbilities": "0x30",
|
"PacketPlayOutPlayerAbilities": "0x30",
|
||||||
"PacketPlayOutMapChunk": "0x20",
|
"PacketPlayOutMapChunk": "0x20",
|
||||||
|
"PacketPlayOutUnloadChunk": "0x1C",
|
||||||
"PacketPlayOutLightUpdate": "0x23",
|
"PacketPlayOutLightUpdate": "0x23",
|
||||||
"PacketPlayOutKeepAlive": "0x1F",
|
"PacketPlayOutKeepAlive": "0x1F",
|
||||||
"PacketPlayOutPlayerInfo": "0x32",
|
"PacketPlayOutPlayerInfo": "0x32",
|
||||||
"PacketPlayOutUpdateViewPosition": "0x40",
|
"PacketPlayOutUpdateViewPosition": "0x40",
|
||||||
"PacketPlayOutShowPlayerSkins": "0x44",
|
|
||||||
"PacketPlayOutDisconnect": "0x19",
|
"PacketPlayOutDisconnect": "0x19",
|
||||||
"PacketPlayOutPluginMessaging": "0x17",
|
"PacketPlayOutPluginMessaging": "0x17",
|
||||||
"PacketPlayOutTabComplete": "0x0F",
|
"PacketPlayOutTabComplete": "0x0F",
|
||||||
"PacketPlayOutDeclareCommands": "0x10",
|
"PacketPlayOutDeclareCommands": "0x10",
|
||||||
"PacketPlayOutRespawn": "0x39",
|
"PacketPlayOutRespawn": "0x39",
|
||||||
"PacketPlayOutGameState": "0x1D"
|
"PacketPlayOutGameState": "0x1D",
|
||||||
|
"PacketPlayOutEntityDestroy": "0x36",
|
||||||
|
"PacketPlayOutEntityMetadata": "0x44",
|
||||||
|
"PacketPlayOutSpawnEntity": "0x00",
|
||||||
|
"PacketPlayOutSpawnEntityLiving": "0x02"
|
||||||
},
|
},
|
||||||
"StatusIn": {
|
"StatusIn": {
|
||||||
"0x01": "PacketStatusInPing",
|
"0x01": "PacketStatusInPing",
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,12 @@ world-spawn=world;20.5;17;22.5;-90;0
|
||||||
#Reduce debug info
|
#Reduce debug info
|
||||||
reduced-debug-info=false
|
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
|
#Server list message in Json
|
||||||
motd={"text":"","extra":[{"text":"Limbo Server!","color":"yellow"}]}
|
motd={"text":"","extra":[{"text":"Limbo Server!","color":"yellow"}]}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue