Bugfixes
This commit is contained in:
@@ -41,21 +41,27 @@ public class EntityProcess extends BaseProcessor{
|
|||||||
|
|
||||||
//find all components used...
|
//find all components used...
|
||||||
for(Stype type : allDefs){
|
for(Stype type : allDefs){
|
||||||
imports.addAll(getImports(type.e));
|
|
||||||
allComponents.addAll(allComponents(type));
|
allComponents.addAll(allComponents(type));
|
||||||
}
|
}
|
||||||
|
|
||||||
//add all components w/ dependencies
|
//add all components w/ dependencies
|
||||||
allComponents.addAll(types(Depends.class));
|
allComponents.addAll(types(Depends.class).map(s -> Array.withArrays(getDependencies(s), s)).flatten());
|
||||||
|
|
||||||
|
//add component imports
|
||||||
|
for(Stype comp : allComponents){
|
||||||
|
imports.addAll(getImports(comp.e));
|
||||||
|
}
|
||||||
|
|
||||||
//create component interfaces
|
//create component interfaces
|
||||||
for(Stype component : allComponents){
|
for(Stype component : allComponents){
|
||||||
TypeSpec.Builder inter = TypeSpec.interfaceBuilder(interfaceName(component)).addModifiers(Modifier.PUBLIC).addAnnotation(EntityInterface.class);
|
TypeSpec.Builder inter = TypeSpec.interfaceBuilder(interfaceName(component)).addModifiers(Modifier.PUBLIC).addAnnotation(EntityInterface.class);
|
||||||
|
|
||||||
|
//implement extra interfaces these components may have, e.g. position
|
||||||
for(Stype extraInterface : component.interfaces()){
|
for(Stype extraInterface : component.interfaces()){
|
||||||
inter.addSuperinterface(extraInterface.mirror());
|
inter.addSuperinterface(extraInterface.mirror());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//implement super interfaces
|
||||||
Array<Stype> depends = getDependencies(component);
|
Array<Stype> depends = getDependencies(component);
|
||||||
for(Stype type : depends){
|
for(Stype type : depends){
|
||||||
inter.addSuperinterface(ClassName.get(packageName, interfaceName(type)));
|
inter.addSuperinterface(ClassName.get(packageName, interfaceName(type)));
|
||||||
@@ -100,7 +106,7 @@ public class EntityProcess extends BaseProcessor{
|
|||||||
Array<Svar> fields = comp.fields().select(f -> !f.is(Modifier.TRANSIENT));
|
Array<Svar> fields = comp.fields().select(f -> !f.is(Modifier.TRANSIENT));
|
||||||
for(Svar f : fields){
|
for(Svar f : fields){
|
||||||
VariableTree tree = f.tree();
|
VariableTree tree = f.tree();
|
||||||
FieldSpec.Builder fbuilder = FieldSpec.builder(f.tname(), f.name(), Modifier.PUBLIC);
|
FieldSpec.Builder fbuilder = FieldSpec.builder(f.tname(), f.name());
|
||||||
//add initializer if it exists
|
//add initializer if it exists
|
||||||
if(tree.getInitializer() != null){
|
if(tree.getInitializer() != null){
|
||||||
fbuilder.initializer(tree.getInitializer().toString());
|
fbuilder.initializer(tree.getInitializer().toString());
|
||||||
@@ -128,13 +134,15 @@ public class EntityProcess extends BaseProcessor{
|
|||||||
mbuilder.addParameter(var.tname(), var.name());
|
mbuilder.addParameter(var.tname(), var.name());
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean returns = !first.ret().toString().equals("void");
|
//only write the block if it's a void method with several entries
|
||||||
|
boolean writeBlock = first.ret().toString().equals("void") && entry.value.size > 1;
|
||||||
|
|
||||||
for(Smethod elem : entry.value){
|
for(Smethod elem : entry.value){
|
||||||
//get all statements in the method, copy them over
|
//get all statements in the method, copy them over
|
||||||
MethodTree methodTree = elem.tree();
|
MethodTree methodTree = elem.tree();
|
||||||
BlockTree blockTree = methodTree.getBody();
|
BlockTree blockTree = methodTree.getBody();
|
||||||
String str = blockTree.toString();
|
String str = blockTree.toString();
|
||||||
|
//name for code blocks in the methods
|
||||||
String blockName = elem.up().getSimpleName().toString().toLowerCase().replace("comp", "");
|
String blockName = elem.up().getSimpleName().toString().toLowerCase().replace("comp", "");
|
||||||
|
|
||||||
//skip empty blocks
|
//skip empty blocks
|
||||||
@@ -143,13 +151,20 @@ public class EntityProcess extends BaseProcessor{
|
|||||||
}
|
}
|
||||||
|
|
||||||
//wrap scope to prevent variable leakage
|
//wrap scope to prevent variable leakage
|
||||||
if(!returns) mbuilder.addCode(blockName + ": {\n");
|
if(writeBlock){
|
||||||
|
//replace return; with block break
|
||||||
|
str = str.replace("return;", "break " + blockName + ";");
|
||||||
|
mbuilder.addCode(blockName + ": {\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
//trim block
|
||||||
|
str = str.substring(2, str.length() - 1);
|
||||||
|
|
||||||
//make sure to remove braces here
|
//make sure to remove braces here
|
||||||
mbuilder.addCode(str.substring(2, str.length() - 1).replace("return;", "break " + blockName + ";"));
|
mbuilder.addCode(str);
|
||||||
|
|
||||||
//end scope
|
//end scope
|
||||||
if(!returns) mbuilder.addCode("}\n");
|
if(writeBlock) mbuilder.addCode("}\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.addMethod(mbuilder.build());
|
builder.addMethod(mbuilder.build());
|
||||||
@@ -194,7 +209,7 @@ public class EntityProcess extends BaseProcessor{
|
|||||||
}
|
}
|
||||||
|
|
||||||
Array<String> getImports(Element elem){
|
Array<String> getImports(Element elem){
|
||||||
return Array.with(trees.getPath(elem).getCompilationUnit().getImports()).map(t -> t.toString());
|
return Array.with(trees.getPath(elem).getCompilationUnit().getImports()).map(Object::toString);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return interface for a component type */
|
/** @return interface for a component type */
|
||||||
|
|||||||
230
core/src/mindustry/entities/def/EntityComps.java
Normal file
230
core/src/mindustry/entities/def/EntityComps.java
Normal file
@@ -0,0 +1,230 @@
|
|||||||
|
package mindustry.entities.def;
|
||||||
|
|
||||||
|
import arc.graphics.*;
|
||||||
|
import arc.math.*;
|
||||||
|
import arc.math.geom.*;
|
||||||
|
import arc.struct.Bits;
|
||||||
|
import arc.struct.*;
|
||||||
|
import arc.util.*;
|
||||||
|
import arc.util.pooling.*;
|
||||||
|
import mindustry.annotations.Annotations.*;
|
||||||
|
import mindustry.content.*;
|
||||||
|
import mindustry.ctype.*;
|
||||||
|
import mindustry.entities.bullet.*;
|
||||||
|
import mindustry.entities.units.*;
|
||||||
|
import mindustry.gen.*;
|
||||||
|
import mindustry.type.*;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
import static mindustry.Vars.content;
|
||||||
|
|
||||||
|
public class EntityComps{
|
||||||
|
|
||||||
|
@Depends({HealthComp.class, VelComp.class, StatusComp.class})
|
||||||
|
class UnitComp{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class OwnerComp{
|
||||||
|
Entityc owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
class TimedComp extends EntityComp implements Scaled{
|
||||||
|
float time, lifetime = 1f;
|
||||||
|
|
||||||
|
void update(){
|
||||||
|
time = Math.min(time + Time.delta(), lifetime);
|
||||||
|
|
||||||
|
if(time >= lifetime){
|
||||||
|
remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float fin(){
|
||||||
|
return time / lifetime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class HealthComp{
|
||||||
|
float health, maxHealth;
|
||||||
|
boolean dead;
|
||||||
|
|
||||||
|
float healthf(){
|
||||||
|
return health / maxHealth;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class PosComp implements Position{
|
||||||
|
float x, y;
|
||||||
|
|
||||||
|
void set(float x, float y){
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Depends(PosComp.class)
|
||||||
|
class VelComp{
|
||||||
|
//transient fields act as imports from any other component clases; these are ignored by the generator
|
||||||
|
transient float x, y;
|
||||||
|
|
||||||
|
final Vec2 vel = new Vec2();
|
||||||
|
|
||||||
|
void update(){
|
||||||
|
x += vel.x;
|
||||||
|
y += vel.y;
|
||||||
|
vel.scl(0.9f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Depends(PosComp.class)
|
||||||
|
class HitboxComp{
|
||||||
|
transient float x, y;
|
||||||
|
|
||||||
|
float hitSize;
|
||||||
|
|
||||||
|
boolean collides(Hitboxc other){
|
||||||
|
return Intersector.overlapsRect(x - hitSize/2f, y - hitSize/2f, hitSize, hitSize,
|
||||||
|
other.getX() - other.getHitSize()/2f, other.getY() - other.getHitSize()/2f, other.getHitSize(), other.getHitSize());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Depends(PosComp.class)
|
||||||
|
class StatusComp{
|
||||||
|
private Array<StatusEntry> statuses = new Array<>();
|
||||||
|
private Bits applied = new Bits(content.getBy(ContentType.status).size);
|
||||||
|
|
||||||
|
private float speedMultiplier;
|
||||||
|
private float damageMultiplier;
|
||||||
|
private float armorMultiplier;
|
||||||
|
|
||||||
|
void apply(StatusEffect effect, float duration){
|
||||||
|
if(effect == StatusEffects.none || effect == null || isImmune(effect)) return; //don't apply empty or immune effects
|
||||||
|
|
||||||
|
if(statuses.size > 0){
|
||||||
|
//check for opposite effects
|
||||||
|
for(StatusEntry entry : statuses){
|
||||||
|
//extend effect
|
||||||
|
if(entry.effect == effect){
|
||||||
|
entry.time = Math.max(entry.time, duration);
|
||||||
|
return;
|
||||||
|
}else if(entry.effect.reactsWith(effect)){ //find opposite
|
||||||
|
StatusEntry.tmp.effect = entry.effect;
|
||||||
|
//TODO unit cannot be null here
|
||||||
|
entry.effect.getTransition(null, effect, entry.time, duration, StatusEntry.tmp);
|
||||||
|
entry.time = StatusEntry.tmp.time;
|
||||||
|
|
||||||
|
if(StatusEntry.tmp.effect != entry.effect){
|
||||||
|
entry.effect = StatusEntry.tmp.effect;
|
||||||
|
}
|
||||||
|
|
||||||
|
//stop looking when one is found
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//otherwise, no opposites found, add direct effect
|
||||||
|
StatusEntry entry = Pools.obtain(StatusEntry.class, StatusEntry::new);
|
||||||
|
entry.set(effect, duration);
|
||||||
|
statuses.add(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isImmune(StatusEffect effect){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Color getStatusColor(){
|
||||||
|
if(statuses.size == 0){
|
||||||
|
return Tmp.c1.set(Color.white);
|
||||||
|
}
|
||||||
|
|
||||||
|
float r = 0f, g = 0f, b = 0f;
|
||||||
|
for(StatusEntry entry : statuses){
|
||||||
|
r += entry.effect.color.r;
|
||||||
|
g += entry.effect.color.g;
|
||||||
|
b += entry.effect.color.b;
|
||||||
|
}
|
||||||
|
return Tmp.c1.set(r / statuses.size, g / statuses.size, b / statuses.size, 1f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void update(){
|
||||||
|
applied.clear();
|
||||||
|
speedMultiplier = damageMultiplier = armorMultiplier = 1f;
|
||||||
|
|
||||||
|
if(statuses.isEmpty()) return;
|
||||||
|
|
||||||
|
statuses.eachFilter(entry -> {
|
||||||
|
entry.time = Math.max(entry.time - Time.delta(), 0);
|
||||||
|
applied.set(entry.effect.id);
|
||||||
|
|
||||||
|
if(entry.time <= 0){
|
||||||
|
Pools.free(entry);
|
||||||
|
return true;
|
||||||
|
}else{
|
||||||
|
speedMultiplier *= entry.effect.speedMultiplier;
|
||||||
|
armorMultiplier *= entry.effect.armorMultiplier;
|
||||||
|
damageMultiplier *= entry.effect.damageMultiplier;
|
||||||
|
//TODO unit can't be null
|
||||||
|
entry.effect.update(null, entry.time);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean hasEffect(StatusEffect effect){
|
||||||
|
return applied.get(effect.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeSave(DataOutput stream) throws IOException{
|
||||||
|
stream.writeByte(statuses.size);
|
||||||
|
for(StatusEntry entry : statuses){
|
||||||
|
stream.writeByte(entry.effect.id);
|
||||||
|
stream.writeFloat(entry.time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void readSave(DataInput stream, byte version) throws IOException{
|
||||||
|
for(StatusEntry effect : statuses){
|
||||||
|
Pools.free(effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
statuses.clear();
|
||||||
|
|
||||||
|
byte amount = stream.readByte();
|
||||||
|
for(int i = 0; i < amount; i++){
|
||||||
|
byte id = stream.readByte();
|
||||||
|
float time = stream.readFloat();
|
||||||
|
StatusEntry entry = Pools.obtain(StatusEntry.class, StatusEntry::new);
|
||||||
|
entry.set(content.getByID(ContentType.status, id), time);
|
||||||
|
statuses.add(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class BulletComp{
|
||||||
|
BulletType bullet;
|
||||||
|
|
||||||
|
void init(){
|
||||||
|
bullet.init();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@BaseComponent
|
||||||
|
class EntityComp{
|
||||||
|
int id;
|
||||||
|
|
||||||
|
void init(){}
|
||||||
|
|
||||||
|
void update(){}
|
||||||
|
|
||||||
|
void remove(){}
|
||||||
|
|
||||||
|
<T> T as(Class<T> type){
|
||||||
|
return (T)this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,220 +1,10 @@
|
|||||||
package mindustry.entities.def;
|
package mindustry.entities.def;
|
||||||
|
|
||||||
import arc.graphics.*;
|
|
||||||
import arc.math.geom.*;
|
|
||||||
import arc.struct.Bits;
|
|
||||||
import arc.struct.*;
|
|
||||||
import arc.util.*;
|
|
||||||
import arc.util.pooling.*;
|
|
||||||
import mindustry.annotations.Annotations.*;
|
import mindustry.annotations.Annotations.*;
|
||||||
import mindustry.content.*;
|
import mindustry.entities.def.EntityComps.*;
|
||||||
import mindustry.ctype.*;
|
|
||||||
import mindustry.entities.bullet.*;
|
|
||||||
import mindustry.entities.units.*;
|
|
||||||
import mindustry.gen.*;
|
|
||||||
import mindustry.net.*;
|
|
||||||
import mindustry.type.*;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
|
|
||||||
import static mindustry.Vars.content;
|
|
||||||
|
|
||||||
class EntityDefs{
|
class EntityDefs{
|
||||||
|
|
||||||
@EntityDef({UnitComp.class, ConnectionComp.class})
|
@EntityDef({BulletComp.class, VelComp.class, TimedComp.class})
|
||||||
class PlayerDef{}
|
|
||||||
|
|
||||||
@EntityDef({BulletComp.class, VelComp.class})
|
|
||||||
class BulletDef{}
|
class BulletDef{}
|
||||||
|
|
||||||
@Depends({HealthComp.class, VelComp.class, StatusComp.class})
|
|
||||||
class UnitComp{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class HealthComp{
|
|
||||||
float health, maxHealth;
|
|
||||||
boolean dead;
|
|
||||||
|
|
||||||
float healthf(){
|
|
||||||
return health / maxHealth;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class PosComp implements Position{
|
|
||||||
float x, y;
|
|
||||||
|
|
||||||
void set(float x, float y){
|
|
||||||
this.x = x;
|
|
||||||
this.y = y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Depends(PosComp.class)
|
|
||||||
class VelComp{
|
|
||||||
//transient fields act as imports from any other component clases; these are ignored by the generator
|
|
||||||
transient float x, y;
|
|
||||||
|
|
||||||
final Vec2 vel = new Vec2();
|
|
||||||
|
|
||||||
void update(){
|
|
||||||
x += vel.x;
|
|
||||||
y += vel.y;
|
|
||||||
vel.scl(0.9f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Depends(PosComp.class)
|
|
||||||
class HitboxComp{
|
|
||||||
transient float x, y;
|
|
||||||
|
|
||||||
float hitSize;
|
|
||||||
|
|
||||||
boolean collides(Hitboxc other){
|
|
||||||
return Intersector.overlapsRect(x - hitSize/2f, y - hitSize/2f, hitSize, hitSize,
|
|
||||||
other.getX() - other.getHitSize()/2f, other.getY() - other.getHitSize()/2f, other.getHitSize(), other.getHitSize());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Depends(PosComp.class)
|
|
||||||
class StatusComp{
|
|
||||||
private Array<StatusEntry> statuses = new Array<>();
|
|
||||||
private Bits applied = new Bits(content.getBy(ContentType.status).size);
|
|
||||||
|
|
||||||
private float speedMultiplier;
|
|
||||||
private float damageMultiplier;
|
|
||||||
private float armorMultiplier;
|
|
||||||
|
|
||||||
void apply(StatusEffect effect, float duration){
|
|
||||||
if(effect == StatusEffects.none || effect == null || isImmune(effect)) return; //don't apply empty or immune effects
|
|
||||||
|
|
||||||
if(statuses.size > 0){
|
|
||||||
//check for opposite effects
|
|
||||||
for(StatusEntry entry : statuses){
|
|
||||||
//extend effect
|
|
||||||
if(entry.effect == effect){
|
|
||||||
entry.time = Math.max(entry.time, duration);
|
|
||||||
return;
|
|
||||||
}else if(entry.effect.reactsWith(effect)){ //find opposite
|
|
||||||
StatusEntry.tmp.effect = entry.effect;
|
|
||||||
//TODO unit cannot be null here
|
|
||||||
entry.effect.getTransition(null, effect, entry.time, duration, StatusEntry.tmp);
|
|
||||||
entry.time = StatusEntry.tmp.time;
|
|
||||||
|
|
||||||
if(StatusEntry.tmp.effect != entry.effect){
|
|
||||||
entry.effect = StatusEntry.tmp.effect;
|
|
||||||
}
|
|
||||||
|
|
||||||
//stop looking when one is found
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//otherwise, no opposites found, add direct effect
|
|
||||||
StatusEntry entry = Pools.obtain(StatusEntry.class, StatusEntry::new);
|
|
||||||
entry.set(effect, duration);
|
|
||||||
statuses.add(entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean isImmune(StatusEffect effect){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Color getStatusColor(){
|
|
||||||
if(statuses.size == 0){
|
|
||||||
return Tmp.c1.set(Color.white);
|
|
||||||
}
|
|
||||||
|
|
||||||
float r = 0f, g = 0f, b = 0f;
|
|
||||||
for(StatusEntry entry : statuses){
|
|
||||||
r += entry.effect.color.r;
|
|
||||||
g += entry.effect.color.g;
|
|
||||||
b += entry.effect.color.b;
|
|
||||||
}
|
|
||||||
return Tmp.c1.set(r / statuses.size, g / statuses.size, b / statuses.size, 1f);
|
|
||||||
}
|
|
||||||
|
|
||||||
void update(){
|
|
||||||
applied.clear();
|
|
||||||
speedMultiplier = damageMultiplier = armorMultiplier = 1f;
|
|
||||||
|
|
||||||
if(statuses.isEmpty()) return;
|
|
||||||
|
|
||||||
statuses.eachFilter(entry -> {
|
|
||||||
entry.time = Math.max(entry.time - Time.delta(), 0);
|
|
||||||
applied.set(entry.effect.id);
|
|
||||||
|
|
||||||
if(entry.time <= 0){
|
|
||||||
Pools.free(entry);
|
|
||||||
return true;
|
|
||||||
}else{
|
|
||||||
speedMultiplier *= entry.effect.speedMultiplier;
|
|
||||||
armorMultiplier *= entry.effect.armorMultiplier;
|
|
||||||
damageMultiplier *= entry.effect.damageMultiplier;
|
|
||||||
//TODO unit can't be null
|
|
||||||
entry.effect.update(null, entry.time);
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean hasEffect(StatusEffect effect){
|
|
||||||
return applied.get(effect.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
void writeSave(DataOutput stream) throws IOException{
|
|
||||||
stream.writeByte(statuses.size);
|
|
||||||
for(StatusEntry entry : statuses){
|
|
||||||
stream.writeByte(entry.effect.id);
|
|
||||||
stream.writeFloat(entry.time);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void readSave(DataInput stream, byte version) throws IOException{
|
|
||||||
for(StatusEntry effect : statuses){
|
|
||||||
Pools.free(effect);
|
|
||||||
}
|
|
||||||
|
|
||||||
statuses.clear();
|
|
||||||
|
|
||||||
byte amount = stream.readByte();
|
|
||||||
for(int i = 0; i < amount; i++){
|
|
||||||
byte id = stream.readByte();
|
|
||||||
float time = stream.readFloat();
|
|
||||||
StatusEntry entry = Pools.obtain(StatusEntry.class, StatusEntry::new);
|
|
||||||
entry.set(content.getByID(ContentType.status, id), time);
|
|
||||||
statuses.add(entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class ConnectionComp{
|
|
||||||
NetConnection connection;
|
|
||||||
}
|
|
||||||
|
|
||||||
class BulletComp{
|
|
||||||
BulletType bullet;
|
|
||||||
|
|
||||||
void init(){
|
|
||||||
bullet.init();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@BaseComponent
|
|
||||||
class EntityComp{
|
|
||||||
int id;
|
|
||||||
|
|
||||||
void init(){}
|
|
||||||
|
|
||||||
<T> T as(Class<T> type){
|
|
||||||
return (T)this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void testing(){
|
|
||||||
Entityc abullet = new BulletGen();
|
|
||||||
Entityc aplayer = new PlayerGen();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user