Skip to main content
edited tags
Link
Simon Forsberg
  • 59.7k
  • 9
  • 160
  • 312
Rollback to Revision 3
Source Link
holroy
  • 11.8k
  • 1
  • 27
  • 59

In my ExitSystem, the InputMultiplexer is just for testing purpose there.

How can I improve the code and mainly the system I've got?

public class EntityManager {

private ArrayList<Integer> entities = new ArrayList<>();
private ArrayList<ISystem> componentSystems = new ArrayList<>();

public void addEntity(int ID, ISystem... system) {
    this.entities.add(ID);
    this.componentSystems.addAll(Arrays.asList(system));
}

public void init() {
    for(ISystem system : this.componentSystems)
        system.init();
}

public void update() {
    for(ISystem system : this.componentSystems)
        system.update();
}

public void render(double currentTime) {
    for(ISystem system : this.componentSystems)
        system.render(currentTime);
}

public void dispose() {
    for(ISystem system : this.componentSystems)
        system.dispose();
}
}

The IEntityComponent:

public interface IEntityComponent {

public int getEntityID();
}

The ISystem:

public interface ISystem {

public void init();

public void update();

public void render(double currentTime);

public void dispose();

public IEntityComponent[] get();
}

The ComponentPosition:

public class ComponentPosition implements IEntityComponent{

public float posX;
public float posY;
public float posZ;

private int entityID;

// z axis exists for rendering system to determine if the object should be drawn on top
// of something else with a smaller posZ value

public ComponentPositiongetEntity(int entityID, float posX, float posY, float posZid) {
    this.entityID = entityID;
    this.posX = posX;
   return this.posY = posY;
    thisentities.posZ = posZ;
}

@Override
public int getEntityIDget(id) {
    return this.entityID;;
}
}

The ComponentVelocityIEntityComponent:

public class ComponentVelocity implementsinterface IEntityComponent {

public float velX;
public float velY;

private int entityID;

// movement on the z axis is not allowed!

public ComponentVelocity(int entityID, float velX, float velY) {
    this.entityID = entityID;
    this.velX = velX;
    this.velY = velY;
}

@Override
public int getEntityID() {
    return this.entityID;
}
}

The SystemMovementISystem:

public class SystemMovement implementsinterface ISystem {

private ComponentVelocity vecocity;
private ComponentPosition position;

public SystemMovement(ComponentPosition pos, ComponentVelocity vel) {
    this.position = pos;
    this.vecocity = vel;
}

@Override
public void init() {
    // can be called on initialisiation of the scene
}

@Override
public void update() {
    // each tick (currently 60t/s)
    
    this.position.posX += this.vecocity.velX;
    this.position.posY += this.vecocity.velY;
}

@Override
public void render(double currentTime) {
    // fps varies
}

@Override
public void dispose() {
    // on deletion to clear for example OpenGL stuff when used for rendering
}

@Override
public IEntityComponent[] get() {
    return new IEntityComponent[] {this.position, this.vecocity};
}
}

The SystemRenderer:

public class SystemRenderer implements ISystem {

private ComponentPosition position;

public SystemRenderer(ComponentPosition pos) {
    this.position = pos;
}

@Override
public void init() {
    // can be called on initialisiation of the scene
}

@Override
public void update() {
    // each tick (currently 60t/s)
}
;
@Override
public void render(double currentTime) {
    // fps varies
    if(this.position.getEntityID() == 0) // just for testing to see the change in player pos
        return;
    
    System.out.println("______________________________________");
    System.out.println("Entity: " + this.position.getEntityID());
    System.out.println(this.position.posX);
    System.out.println(this.position.posY);
}

@Override
public void dispose() {
    // on deletion to clear for example OpenGL stuff when used for rendering
}
;
@Override
public IEntityComponent[] get() {
    return new IEntityComponent[] {this.position};
}
}

The SystemPositionExitData:

public class SystemPositionExitData implements ISystemIEntityComponent {

private ComponentPosition position;

public SystemPosition(ComponentPosition pos) {
   int this.positionexit = pos;
}

@Override
public void init() {
    // can be called on initialisiation of the scene
}

@Override
public void update() {
    // each tick (currently 60t/s)
}

@Override
public void render(double currentTime) {
    // fps varies
}

@Override
public void dispose() {
    // on deletion to clear for example OpenGL stuff when used for rendering
}

@OverrideGLFW_KEY_ESCAPE;
public IEntityComponent[] get() {
    returnint newaction IEntityComponent[]= {this.position};
}GLFW_REPEAT;
}

The TestSceneExitSystem:

public class TestSceneExitSystem implements SceneISystem {

private EntityManager manager = new EntityManager();

@Override
public booleanvoid init() {
    InputMultiplexer.getInput().addComponent(new InputComponent.InputKeyComponent() {
        
        @Override
        public boolean onKeyPress(int key, int action) {
            if(key == GLFW_KEY_ESCAPE((ExitData)get()[0]).exit && action == GLFW_REPEAT((ExitData)get()[0]).action)
                Game.windowShouldClose();
            return true;
        }
    });
    
    ComponentPosition posPlayer = new ComponentPosition(1, 14, 15, 0);
    }
    this.manager.addEntity(new SystemPosition(new ComponentPosition(0, 12, 13, 1)), new SystemRenderer(new ComponentPosition(0, 12, 13, 1)));
    this.manager.addEntity(new SystemMovement(posPlayer, new ComponentVelocity(1, 1, 1)),@Override
           public newvoid SystemRendererupdate(posPlayer));
    
    this.manager.init();{
    return true;
}

@Override
public void updaterender() {
    this.manager.update();
}

@Override
public void renderdispose(double currentTime) {
    this.manager.render(currentTime);
}

@Override
public voidIEntityComponent[] disposeget() {
    this.manager.disposereturn new IEntityComponent[] {new ExitData()};
}
}

Note:

  • the Entity with the ID 0 could be for example a tree
  • the Entity with the ID 1 could be a player or a moving entity (thought AI is missing)

How can I improve the code and mainly the system I've got?

public class EntityManager {

private ArrayList<ISystem> componentSystems = new ArrayList<>();

public void addEntity(ISystem... system) {
    this.componentSystems.addAll(Arrays.asList(system));
}

public void init() {
    for(ISystem system : this.componentSystems)
        system.init();
}

public void update() {
    for(ISystem system : this.componentSystems)
        system.update();
}

public void render(double currentTime) {
    for(ISystem system : this.componentSystems)
        system.render(currentTime);
}

public void dispose() {
    for(ISystem system : this.componentSystems)
        system.dispose();
}
}

The IEntityComponent:

public interface IEntityComponent {

public int getEntityID();
}

The ISystem:

public interface ISystem {

public void init();

public void update();

public void render(double currentTime);

public void dispose();

public IEntityComponent[] get();
}

The ComponentPosition:

public class ComponentPosition implements IEntityComponent{

public float posX;
public float posY;
public float posZ;

private int entityID;

// z axis exists for rendering system to determine if the object should be drawn on top
// of something else with a smaller posZ value

public ComponentPosition(int entityID, float posX, float posY, float posZ) {
    this.entityID = entityID;
    this.posX = posX;
    this.posY = posY;
    this.posZ = posZ;
}

@Override
public int getEntityID() {
    return this.entityID;
}
}

The ComponentVelocity:

public class ComponentVelocity implements IEntityComponent {

public float velX;
public float velY;

private int entityID;

// movement on the z axis is not allowed!

public ComponentVelocity(int entityID, float velX, float velY) {
    this.entityID = entityID;
    this.velX = velX;
    this.velY = velY;
}

@Override
public int getEntityID() {
    return this.entityID;
}
}

The SystemMovement:

public class SystemMovement implements ISystem {

private ComponentVelocity vecocity;
private ComponentPosition position;

public SystemMovement(ComponentPosition pos, ComponentVelocity vel) {
    this.position = pos;
    this.vecocity = vel;
}

@Override
public void init() {
    // can be called on initialisiation of the scene
}

@Override
public void update() {
    // each tick (currently 60t/s)
    
    this.position.posX += this.vecocity.velX;
    this.position.posY += this.vecocity.velY;
}

@Override
public void render(double currentTime) {
    // fps varies
}

@Override
public void dispose() {
    // on deletion to clear for example OpenGL stuff when used for rendering
}

@Override
public IEntityComponent[] get() {
    return new IEntityComponent[] {this.position, this.vecocity};
}
}

The SystemRenderer:

public class SystemRenderer implements ISystem {

private ComponentPosition position;

public SystemRenderer(ComponentPosition pos) {
    this.position = pos;
}

@Override
public void init() {
    // can be called on initialisiation of the scene
}

@Override
public void update() {
    // each tick (currently 60t/s)
}

@Override
public void render(double currentTime) {
    // fps varies
    if(this.position.getEntityID() == 0) // just for testing to see the change in player pos
        return;
    
    System.out.println("______________________________________");
    System.out.println("Entity: " + this.position.getEntityID());
    System.out.println(this.position.posX);
    System.out.println(this.position.posY);
}

@Override
public void dispose() {
    // on deletion to clear for example OpenGL stuff when used for rendering
}

@Override
public IEntityComponent[] get() {
    return new IEntityComponent[] {this.position};
}
}

The SystemPosition:

public class SystemPosition implements ISystem {

private ComponentPosition position;

public SystemPosition(ComponentPosition pos) {
    this.position = pos;
}

@Override
public void init() {
    // can be called on initialisiation of the scene
}

@Override
public void update() {
    // each tick (currently 60t/s)
}

@Override
public void render(double currentTime) {
    // fps varies
}

@Override
public void dispose() {
    // on deletion to clear for example OpenGL stuff when used for rendering
}

@Override
public IEntityComponent[] get() {
    return new IEntityComponent[] {this.position};
}
}

The TestScene:

public class TestScene implements Scene {

private EntityManager manager = new EntityManager();

@Override
public boolean init() {
    InputMultiplexer.getInput().addComponent(new InputComponent.InputKeyComponent() {
        
        @Override
        public boolean onKeyPress(int key, int action) {
            if(key == GLFW_KEY_ESCAPE && action == GLFW_REPEAT)
                Game.windowShouldClose();
            return true;
        }
    });
    
    ComponentPosition posPlayer = new ComponentPosition(1, 14, 15, 0);
    
    this.manager.addEntity(new SystemPosition(new ComponentPosition(0, 12, 13, 1)), new SystemRenderer(new ComponentPosition(0, 12, 13, 1)));
    this.manager.addEntity(new SystemMovement(posPlayer, new ComponentVelocity(1, 1, 1)),
            new SystemRenderer(posPlayer));
    
    this.manager.init();
    return true;
}

@Override
public void update() {
    this.manager.update();
}

@Override
public void render(double currentTime) {
    this.manager.render(currentTime);
}

@Override
public void dispose() {
    this.manager.dispose();
}
}

Note:

  • the Entity with the ID 0 could be for example a tree
  • the Entity with the ID 1 could be a player or a moving entity (thought AI is missing)

In my ExitSystem, the InputMultiplexer is just for testing purpose there.

How can I improve the code and mainly the system I've got?

public class EntityManager {

private ArrayList<Integer> entities = new ArrayList<>();
private ArrayList<ISystem> componentSystems = new ArrayList<>();

public void addEntity(int ID, ISystem... system) {
    this.entities.add(ID);
    this.componentSystems.addAll(Arrays.asList(system));
}

public void init() {
    for(ISystem system : this.componentSystems)
        system.init();
}

public void update() {
    for(ISystem system : this.componentSystems)
        system.update();
}

public void render() {
    for(ISystem system : this.componentSystems)
        system.render();
}

public void dispose() {
    for(ISystem system : this.componentSystems)
        system.dispose();
}

public int getEntity(int id) {
    return this.entities.get(id);
}
}

The IEntityComponent:

public interface IEntityComponent {

}

The ISystem:

public interface ISystem {

public void init();

public void update();

public void render();

public void dispose();

public IEntityComponent[] get();
}

The ExitData:

public class ExitData implements IEntityComponent {

public int exit = GLFW_KEY_ESCAPE;
public int action = GLFW_REPEAT;
}

The ExitSystem:

public class ExitSystem implements ISystem {

@Override
public void init() {
    InputMultiplexer.getInput().addComponent(new InputComponent.InputKeyComponent() {
        
        @Override
        public boolean onKeyPress(int key, int action) {
            if(key == ((ExitData)get()[0]).exit && action == ((ExitData)get()[0]).action)
                Game.windowShouldClose();
            return true;
        }
    });
}

@Override
public void update() {
    
}

@Override
public void render() {
    
}

@Override
public void dispose() {
    
}

@Override
public IEntityComponent[] get() {
    return new IEntityComponent[] {new ExitData()};
}
}
improve code example as previous one shouldn't be used in ECS
Source Link

In my ExitSystem, the InputMultiplexer is just for testing purpose there.

How can I improve the code and mainly the system I've got?

public class EntityManager {

private ArrayList<Integer> entities = new ArrayList<>();
private ArrayList<ISystem> componentSystems = new ArrayList<>();

public void addEntity(int ID, ISystem... system) {
    this.entities.add(ID);
    this.componentSystems.addAll(Arrays.asList(system));
}

public void init() {
    for(ISystem system : this.componentSystems)
        system.init();
}

public void update() {
    for(ISystem system : this.componentSystems)
        system.update();
}

public void render(double currentTime) {
    for(ISystem system : this.componentSystems)
        system.render(currentTime);
}

public void dispose() {
    for(ISystem system : this.componentSystems)
        system.dispose();
}
}

The IEntityComponent:

public interface IEntityComponent {

public int getEntitygetEntityID();
}

The ISystem:

public interface ISystem {

public void init();

public void update();

public void render(double currentTime);

public void dispose();

public IEntityComponent[] get();
}

The ComponentPosition:

public class ComponentPosition implements IEntityComponent{

public float posX;
public float posY;
public float posZ;

private int identityID;

// z axis exists for rendering system to determine if the object should be drawn on top
// of something else with a smaller posZ value

public ComponentPosition(int entityID, float posX, float posY, float posZ) {
    returnthis.entityID = entityID;
    this.entitiesposX = posX;
    this.getposY = posY;
    this.posZ = posZ;
}

@Override
public int getEntityID(id); {
    return this.entityID;
}
}

The IEntityComponentComponentVelocity:

public interfaceclass ComponentVelocity implements IEntityComponent {

public float velX;
public float velY;

private int entityID;

// movement on the z axis is not allowed!

public ComponentVelocity(int entityID, float velX, float velY) {
    this.entityID = entityID;
    this.velX = velX;
    this.velY = velY;
}

@Override
public int getEntityID() {
    return this.entityID;
}
}

The ISystemSystemMovement:

public interfaceclass SystemMovement implements ISystem {

private ComponentVelocity vecocity;
private ComponentPosition position;

public SystemMovement(ComponentPosition pos, ComponentVelocity vel) {
    this.position = pos;
    this.vecocity = vel;
}

@Override
public void init(); {
    // can be called on initialisiation of the scene
}

@Override
public void update(); {
    // each tick (currently 60t/s)
    
    this.position.posX += this.vecocity.velX;
    this.position.posY += this.vecocity.velY;
}

@Override
public void render(double currentTime); {
    // fps varies
}

@Override
public void dispose(); {
    // on deletion to clear for example OpenGL stuff when used for rendering
}

@Override
public IEntityComponent[] get() {
    return new IEntityComponent[] {this.position, this.vecocity};
}
}

The ExitDataSystemRenderer:

public class ExitDataSystemRenderer implements IEntityComponentISystem {

private ComponentPosition position;

public intSystemRenderer(ComponentPosition exitpos) {
    this.position = GLFW_KEY_ESCAPE;pos;
}

@Override
public intvoid actioninit() ={
 GLFW_REPEAT;   // can be called on initialisiation of the scene
}

@Override
public void update() {
    // each tick (currently 60t/s)
}

@Override
public void render(double currentTime) {
    // fps varies
    if(this.position.getEntityID() == 0) // just for testing to see the change in player pos
        return;
    
    System.out.println("______________________________________");
    System.out.println("Entity: " + this.position.getEntityID());
    System.out.println(this.position.posX);
    System.out.println(this.position.posY);
}

@Override
public void dispose() {
    // on deletion to clear for example OpenGL stuff when used for rendering
}

@Override
public IEntityComponent[] get() {
    return new IEntityComponent[] {this.position};
}
}

The ExitSystemSystemPosition:

public class ExitSystemSystemPosition implements ISystem {

private ComponentPosition position;

public SystemPosition(ComponentPosition pos) {
    this.position = pos;
}

@Override
public void init() {
    // can be called on initialisiation of the scene
}

@Override
public void update() {
    // each tick (currently 60t/s)
}

@Override
public void render(double currentTime) {
    // fps varies
}

@Override
public void dispose() {
    // on deletion to clear for example OpenGL stuff when used for rendering
}

@Override
public IEntityComponent[] get() {
    return new IEntityComponent[] {this.position};
}
}

The TestScene:

public class TestScene implements Scene {

private EntityManager manager = new EntityManager();

@Override
public boolean init() {
    InputMultiplexer.getInput().addComponent(new InputComponent.InputKeyComponent() {
        
        @Override
        public boolean onKeyPress(int key, int action) {
            if(key == ((ExitData)get()[0]).exitGLFW_KEY_ESCAPE && action == ((ExitData)get()[0]).actionGLFW_REPEAT)
                Game.windowShouldClose();
            return true;
        }
    });
}    
    ComponentPosition posPlayer = new ComponentPosition(1, 14, 15, 0);
@Override    
public void update  this.manager.addEntity(new SystemPosition(new ComponentPosition(0, 12, 13, 1)), {new SystemRenderer(new ComponentPosition(0, 12, 13, 1)));
    this.manager.addEntity(new SystemMovement(posPlayer, new ComponentVelocity(1, 1, 1)),
            new SystemRenderer(posPlayer));
    
    this.manager.init();
    return true;
}

@Override
public void renderupdate() {
    this.manager.update();
}

@Override
public void disposerender(double currentTime) {
    this.manager.render(currentTime);
}

@Override
public IEntityComponent[]void getdispose() {
    return new IEntityComponent[] {new ExitDatathis.manager.dispose()};
}
}

Note:

  • the Entity with the ID 0 could be for example a tree
  • the Entity with the ID 1 could be a player or a moving entity (thought AI is missing)

In my ExitSystem, the InputMultiplexer is just for testing purpose there.

How can I improve the code and mainly the system I've got?

public class EntityManager {

private ArrayList<Integer> entities = new ArrayList<>();
private ArrayList<ISystem> componentSystems = new ArrayList<>();

public void addEntity(int ID, ISystem... system) {
    this.entities.add(ID);
    this.componentSystems.addAll(Arrays.asList(system));
}

public void init() {
    for(ISystem system : this.componentSystems)
        system.init();
}

public void update() {
    for(ISystem system : this.componentSystems)
        system.update();
}

public void render() {
    for(ISystem system : this.componentSystems)
        system.render();
}

public void dispose() {
    for(ISystem system : this.componentSystems)
        system.dispose();
}

public int getEntity(int id) {
    return this.entities.get(id);
}
}

The IEntityComponent:

public interface IEntityComponent {

}

The ISystem:

public interface ISystem {

public void init();

public void update();

public void render();

public void dispose();

public IEntityComponent[] get();
}

The ExitData:

public class ExitData implements IEntityComponent {

public int exit = GLFW_KEY_ESCAPE;
public int action = GLFW_REPEAT;
}

The ExitSystem:

public class ExitSystem implements ISystem {

@Override
public void init() {
    InputMultiplexer.getInput().addComponent(new InputComponent.InputKeyComponent() {
        
        @Override
        public boolean onKeyPress(int key, int action) {
            if(key == ((ExitData)get()[0]).exit && action == ((ExitData)get()[0]).action)
                Game.windowShouldClose();
            return true;
        }
    });
}

@Override
public void update() {
    
}

@Override
public void render() {
    
}

@Override
public void dispose() {
    
}

@Override
public IEntityComponent[] get() {
    return new IEntityComponent[] {new ExitData()};
}
}

How can I improve the code and mainly the system I've got?

public class EntityManager {

private ArrayList<ISystem> componentSystems = new ArrayList<>();

public void addEntity(ISystem... system) {
    this.componentSystems.addAll(Arrays.asList(system));
}

public void init() {
    for(ISystem system : this.componentSystems)
        system.init();
}

public void update() {
    for(ISystem system : this.componentSystems)
        system.update();
}

public void render(double currentTime) {
    for(ISystem system : this.componentSystems)
        system.render(currentTime);
}

public void dispose() {
    for(ISystem system : this.componentSystems)
        system.dispose();
}
}

The IEntityComponent:

public interface IEntityComponent {

public int getEntityID();
}

The ISystem:

public interface ISystem {

public void init();

public void update();

public void render(double currentTime);

public void dispose();

public IEntityComponent[] get();
}

The ComponentPosition:

public class ComponentPosition implements IEntityComponent{

public float posX;
public float posY;
public float posZ;

private int entityID;

// z axis exists for rendering system to determine if the object should be drawn on top
// of something else with a smaller posZ value

public ComponentPosition(int entityID, float posX, float posY, float posZ) {
    this.entityID = entityID;
    this.posX = posX;
    this.posY = posY;
    this.posZ = posZ;
}

@Override
public int getEntityID() {
    return this.entityID;
}
}

The ComponentVelocity:

public class ComponentVelocity implements IEntityComponent {

public float velX;
public float velY;

private int entityID;

// movement on the z axis is not allowed!

public ComponentVelocity(int entityID, float velX, float velY) {
    this.entityID = entityID;
    this.velX = velX;
    this.velY = velY;
}

@Override
public int getEntityID() {
    return this.entityID;
}
}

The SystemMovement:

public class SystemMovement implements ISystem {

private ComponentVelocity vecocity;
private ComponentPosition position;

public SystemMovement(ComponentPosition pos, ComponentVelocity vel) {
    this.position = pos;
    this.vecocity = vel;
}

@Override
public void init() {
    // can be called on initialisiation of the scene
}

@Override
public void update() {
    // each tick (currently 60t/s)
    
    this.position.posX += this.vecocity.velX;
    this.position.posY += this.vecocity.velY;
}

@Override
public void render(double currentTime) {
    // fps varies
}

@Override
public void dispose() {
    // on deletion to clear for example OpenGL stuff when used for rendering
}

@Override
public IEntityComponent[] get() {
    return new IEntityComponent[] {this.position, this.vecocity};
}
}

The SystemRenderer:

public class SystemRenderer implements ISystem {

private ComponentPosition position;

public SystemRenderer(ComponentPosition pos) {
    this.position = pos;
}

@Override
public void init() {
    // can be called on initialisiation of the scene
}

@Override
public void update() {
    // each tick (currently 60t/s)
}

@Override
public void render(double currentTime) {
    // fps varies
    if(this.position.getEntityID() == 0) // just for testing to see the change in player pos
        return;
    
    System.out.println("______________________________________");
    System.out.println("Entity: " + this.position.getEntityID());
    System.out.println(this.position.posX);
    System.out.println(this.position.posY);
}

@Override
public void dispose() {
    // on deletion to clear for example OpenGL stuff when used for rendering
}

@Override
public IEntityComponent[] get() {
    return new IEntityComponent[] {this.position};
}
}

The SystemPosition:

public class SystemPosition implements ISystem {

private ComponentPosition position;

public SystemPosition(ComponentPosition pos) {
    this.position = pos;
}

@Override
public void init() {
    // can be called on initialisiation of the scene
}

@Override
public void update() {
    // each tick (currently 60t/s)
}

@Override
public void render(double currentTime) {
    // fps varies
}

@Override
public void dispose() {
    // on deletion to clear for example OpenGL stuff when used for rendering
}

@Override
public IEntityComponent[] get() {
    return new IEntityComponent[] {this.position};
}
}

The TestScene:

public class TestScene implements Scene {

private EntityManager manager = new EntityManager();

@Override
public boolean init() {
    InputMultiplexer.getInput().addComponent(new InputComponent.InputKeyComponent() {
        
        @Override
        public boolean onKeyPress(int key, int action) {
            if(key == GLFW_KEY_ESCAPE && action == GLFW_REPEAT)
                Game.windowShouldClose();
            return true;
        }
    });
    
    ComponentPosition posPlayer = new ComponentPosition(1, 14, 15, 0);
    
    this.manager.addEntity(new SystemPosition(new ComponentPosition(0, 12, 13, 1)), new SystemRenderer(new ComponentPosition(0, 12, 13, 1)));
    this.manager.addEntity(new SystemMovement(posPlayer, new ComponentVelocity(1, 1, 1)),
            new SystemRenderer(posPlayer));
    
    this.manager.init();
    return true;
}

@Override
public void update() {
    this.manager.update();
}

@Override
public void render(double currentTime) {
    this.manager.render(currentTime);
}

@Override
public void dispose() {
    this.manager.dispose();
}
}

Note:

  • the Entity with the ID 0 could be for example a tree
  • the Entity with the ID 1 could be a player or a moving entity (thought AI is missing)
deleted 23 characters in body
Source Link
Jamal
  • 35.2k
  • 13
  • 134
  • 238
Loading
Source Link
Loading