dominion-dev / dominion-ecs-java Goto Github PK
View Code? Open in Web Editor NEWInsanely fast ECS (Entity Component System) for Java
Home Page: https://dominion-dev.github.io
License: MIT License
Insanely fast ECS (Entity Component System) for Java
Home Page: https://dominion-dev.github.io
License: MIT License
In my actual project, I create monster entities in a System. In order to take advantage of multi-core, I use parallelStream and create monster entities in it, and cache the Entity to Component, but I found that in the next System, the Entity in the Component obtained by the context.findEntitiesWith()
method is different from the hashCode of ResultSet.entity()
example code like this.
public enum State {
S1, S2, S3;
}
public static class C {
private final Entity entity;
public C(Entity entity) {
this.entity = entity;
}
}
public static class B {
}
public static class A {
private C c;
public A(Dominion dominion) {
c = new C(dominion.createEntity(this));
c.entity.setState(S1);
}
}
public static void main(String[] args) {
final Dominion dominion = Dominion.create();
final var list = List.<Runnable>of(() -> {
for (int i = 0; i < 200; i++) {
final var a = new A(dominion);
a.c.entity.add(new B());
}
}, () -> {
for (int i = 0; i < 200; i++) {
final var a = new A(dominion);
a.c.entity.add(new B());
}
}, () -> {
for (int i = 0; i < 200; i++) {
final var a = new A(dominion);
a.c.entity.add(new B());
}
});
final var scheduler = dominion.createScheduler();
scheduler.schedule(() -> list.parallelStream().forEach(Runnable::run));
scheduler.schedule(() -> {
dominion.findEntitiesWith(A.class).stream().forEach(rs->{
if(rs.entity().hashCode() != rs.comp().c.entity.hashCode()) {
System.out.println("1111111111111111111");
System.exit(-1);
}
});
System.exit(0);
});
scheduler.tickAtFixedRate(10);
}
If I remove a.c.entity.add(new B());
, the program is fine.
If I change paralleStream()
to stream()
, this program is fine.
Is IntStack designed to be thread-safe? @enricostara
this code is fine.
public static void main(String[] args) {
final Dominion dominion = Dominion.create();
final var list = List.<Runnable>of(() -> {
for (int i = 0; i < 100; i++) {
dominion.createEntity(new A()).add(new B());
}
}, () -> {
for (int i = 0; i < 100; i++) {
dominion.createEntity(new A()).add(new B());
}
}, () -> {
for (int i = 0; i < 100; i++) {
dominion.createEntity(new A()).add(new B());
}
});
final var scheduler = dominion.createScheduler();
scheduler.schedule(() -> list.parallelStream().forEach(Runnable::run));
scheduler.tickAtFixedRate(10);
}
this code is also fine.
public static void main(String[] args) {
final Dominion dominion = Dominion.create();
final var list = List.<Runnable>of(() -> {
for (int i = 0; i < 100; i++) {
dominion.createEntity(new A()).add(new B());
}
}, () -> {
for (int i = 0; i < 100; i++) {
dominion.createEntity(new A()).add(new B());
}
}, () -> {
for (int i = 0; i < 100; i++) {
dominion.createEntity(new A()).add(new B()).add(new C());
}
});
final var scheduler = dominion.createScheduler();
scheduler.schedule(() -> list.stream().forEach(Runnable::run));
scheduler.tickAtFixedRate(10);
}
but I get some error with this code
public static void main(String[] args) {
final Dominion dominion = Dominion.create();
final var list = List.<Runnable>of(() -> {
for (int i = 0; i < 100; i++) {
dominion.createEntity(new A()).add(new B());
}
}, () -> {
for (int i = 0; i < 100; i++) {
dominion.createEntity(new A()).add(new B());
}
}, () -> {
for (int i = 0; i < 100; i++) {
dominion.createEntity(new A()).add(new B()).add(new C());
}
});
final var scheduler = dominion.createScheduler();
scheduler.schedule(() -> list.parallelStream().forEach(Runnable::run));
scheduler.tickAtFixedRate(10);
}
严重 dominion.SystemScheduler invoke
java.lang.IllegalArgumentException: java.lang.IllegalArgumentException: java.lang.IllegalArgumentException: Invalid chunkById [LinkedChunk={id=1, dataLength=1, capacity=4096, size=0, previous=null, next=null, of Tenant={id=1, dataLength=1, nextId=|0:1:0|, subject=root}}] retrieved by [4097]
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:480)
at java.base/java.util.concurrent.ForkJoinTask.getThrowableException(ForkJoinTask.java:562)
at java.base/java.util.concurrent.ForkJoinTask.reportException(ForkJoinTask.java:591)
at java.base/java.util.concurrent.ForkJoinTask.joinForPoolInvoke(ForkJoinTask.java:1042)
at java.base/java.util.concurrent.ForkJoinPool.invoke(ForkJoinPool.java:2639)
at dev.dominion.ecs.engine/dev.dominion.ecs.engine.SystemScheduler.forkAndJoin(SystemScheduler.java:113)
at dev.dominion.ecs.engine/dev.dominion.ecs.engine.SystemScheduler$Single.call(SystemScheduler.java:262)
at dev.dominion.ecs.engine/dev.dominion.ecs.engine.SystemScheduler$Single.call(SystemScheduler.java:239)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: java.lang.IllegalArgumentException: java.lang.IllegalArgumentException: Invalid chunkById [LinkedChunk={id=1, dataLength=1, capacity=4096, size=0, previous=null, next=null, of Tenant={id=1, dataLength=1, nextId=|0:1:0|, subject=root}}] retrieved by [4097]
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:480)
at java.base/java.util.concurrent.ForkJoinTask.getThrowableException(ForkJoinTask.java:562)
at java.base/java.util.concurrent.ForkJoinTask.reportException(ForkJoinTask.java:591)
at java.base/java.util.concurrent.ForkJoinTask.invoke(ForkJoinTask.java:689)
at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateParallel(ForEachOps.java:159)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateParallel(ForEachOps.java:173)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:233)
at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596)
at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:765)
at dev.dominion.ecs.engine/dev.dominion.ecs.engine.Test.lambda$main$3(Test.java:38)
at dev.dominion.ecs.engine/dev.dominion.ecs.engine.SystemScheduler$2.compute(SystemScheduler.java:116)
at java.base/java.util.concurrent.RecursiveAction.exec(RecursiveAction.java:194)
at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:373)
at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1182)
at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1655)
at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1622)
at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:165)
Caused by: java.lang.IllegalArgumentException: Invalid chunkById [LinkedChunk={id=1, dataLength=1, capacity=4096, size=0, previous=null, next=null, of Tenant={id=1, dataLength=1, nextId=|0:1:0|, subject=root}}] retrieved by [4097]
at dev.dominion.ecs.engine/dev.dominion.ecs.engine.collections.ChunkedPool$Tenant.freeId(ChunkedPool.java:273)
at dev.dominion.ecs.engine/dev.dominion.ecs.engine.collections.ChunkedPool$Tenant.freeId(ChunkedPool.java:263)
at dev.dominion.ecs.engine/dev.dominion.ecs.engine.CompositionRepository.modifyComponents(CompositionRepository.java:167)
at dev.dominion.ecs.engine/dev.dominion.ecs.engine.CompositionRepository.addComponent(CompositionRepository.java:185)
at dev.dominion.ecs.engine/dev.dominion.ecs.engine.IntEntity.add(IntEntity.java:91)
at dev.dominion.ecs.engine/dev.dominion.ecs.engine.Test.lambda$main$2(Test.java:34)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
at java.base/java.util.AbstractList$RandomAccessSpliterator.forEachRemaining(AbstractList.java:720)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
at java.base/java.util.stream.ForEachOps$ForEachTask.compute(ForEachOps.java:290)
at java.base/java.util.concurrent.CountedCompleter.exec(CountedCompleter.java:754)
... 5 more
and this code
public static void main(String[] args) {
final Dominion dominion = Dominion.create();
final var list = List.<Runnable>of(() -> {
for (int i = 0; i < 100; i++) {
final var entity = dominion.createEntity(new A()).setState(S1);
entity.add(new B());
entity.setState(S2);
}
}, () -> {
for (int i = 0; i < 100; i++) {
final var entity = dominion.createEntity(new A()).setState(S1);
entity.add(new B());
entity.setState(S2);
}
}, () -> {
for (int i = 0; i < 100; i++) {
final var entity = dominion.createEntity(new A()).setState(S1);
entity.add(new B());
entity.setState(S3);
}
});
final var scheduler = dominion.createScheduler();
scheduler.schedule(() -> list.parallelStream().forEach(Runnable::run));
scheduler.tickAtFixedRate(10);
}
严重 dominion.SystemScheduler invoke
java.lang.IllegalArgumentException: java.lang.IllegalArgumentException: java.lang.IllegalArgumentException: Invalid chunkById [LinkedChunk={id=2, dataLength=0, capacity=4096, size=1, previous=null, next=null, of Tenant={id=2, dataLength=0, nextId=|0:2:0|, subject=|1085:[4, 0]|}}] retrieved by [8194]
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:480)
at java.base/java.util.concurrent.ForkJoinTask.getThrowableException(ForkJoinTask.java:562)
at java.base/java.util.concurrent.ForkJoinTask.reportException(ForkJoinTask.java:591)
at java.base/java.util.concurrent.ForkJoinTask.joinForPoolInvoke(ForkJoinTask.java:1042)
at java.base/java.util.concurrent.ForkJoinPool.invoke(ForkJoinPool.java:2639)
at dev.dominion.ecs.engine/dev.dominion.ecs.engine.SystemScheduler.forkAndJoin(SystemScheduler.java:113)
at dev.dominion.ecs.engine/dev.dominion.ecs.engine.SystemScheduler$Single.call(SystemScheduler.java:262)
at dev.dominion.ecs.engine/dev.dominion.ecs.engine.SystemScheduler$Single.call(SystemScheduler.java:239)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: java.lang.IllegalArgumentException: java.lang.IllegalArgumentException: Invalid chunkById [LinkedChunk={id=2, dataLength=0, capacity=4096, size=1, previous=null, next=null, of Tenant={id=2, dataLength=0, nextId=|0:2:0|, subject=|1085:[4, 0]|}}] retrieved by [8194]
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:480)
at java.base/java.util.concurrent.ForkJoinTask.getThrowableException(ForkJoinTask.java:562)
at java.base/java.util.concurrent.ForkJoinTask.reportException(ForkJoinTask.java:591)
at java.base/java.util.concurrent.ForkJoinTask.invoke(ForkJoinTask.java:689)
at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateParallel(ForEachOps.java:159)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateParallel(ForEachOps.java:173)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:233)
at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596)
at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:765)
at dev.dominion.ecs.engine/dev.dominion.ecs.engine.FixBug.lambda$main$3(FixBug.java:51)
at dev.dominion.ecs.engine/dev.dominion.ecs.engine.SystemScheduler$2.compute(SystemScheduler.java:116)
at java.base/java.util.concurrent.RecursiveAction.exec(RecursiveAction.java:194)
at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:373)
at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1182)
at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1655)
at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1622)
at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:165)
Caused by: java.lang.IllegalArgumentException: Invalid chunkById [LinkedChunk={id=2, dataLength=0, capacity=4096, size=1, previous=null, next=null, of Tenant={id=2, dataLength=0, nextId=|0:2:0|, subject=|1085:[4, 0]|}}] retrieved by [8194]
at dev.dominion.ecs.engine/dev.dominion.ecs.engine.collections.ChunkedPool$Tenant.freeId(ChunkedPool.java:273)
at dev.dominion.ecs.engine/dev.dominion.ecs.engine.collections.ChunkedPool$Tenant.freeStateId(ChunkedPool.java:267)
at dev.dominion.ecs.engine/dev.dominion.ecs.engine.IntEntity.setState(IntEntity.java:168)
at dev.dominion.ecs.engine/dev.dominion.ecs.engine.FixBug.lambda$main$0(FixBug.java:35)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
at java.base/java.util.AbstractList$RandomAccessSpliterator.forEachRemaining(AbstractList.java:720)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
at java.base/java.util.stream.ForEachOps$ForEachTask.compute(ForEachOps.java:290)
at java.base/java.util.concurrent.CountedCompleter.exec(CountedCompleter.java:754)
... 5 more
During development, I got an exception log that looked like it was looping to a null value. So I wrote a piece of test code to try to restore the error. Judging from the test code, this should be a concurrency issue.
Is this result expected?
dominion.SystemScheduler invoke
java.lang.NullPointerException
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:480)
at java.base/java.util.concurrent.ForkJoinTask.getThrowableException(ForkJoinTask.java:564)
at java.base/java.util.concurrent.ForkJoinTask.reportException(ForkJoinTask.java:591)
at java.base/java.util.concurrent.ForkJoinTask.joinForPoolInvoke(ForkJoinTask.java:1042)
at java.base/java.util.concurrent.ForkJoinPool.invoke(ForkJoinPool.java:2639)
at dev.dominion.ecs.engine/dev.dominion.ecs.engine.SystemScheduler.forkAndJoin(SystemScheduler.java:113)
at dev.dominion.ecs.engine/dev.dominion.ecs.engine.SystemScheduler$Single.call(SystemScheduler.java:280)
at dev.dominion.ecs.engine/dev.dominion.ecs.engine.SystemScheduler$Single.call(SystemScheduler.java:257)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: java.lang.NullPointerException: Cannot invoke "dev.dominion.ecs.engine.collections.ChunkedPool$Item.getChunk()" because "item" is null
at dev.dominion.ecs.engine/dev.dominion.ecs.engine.collections.ChunkedPool$PoolDataIteratorWithState.next(ChunkedPool.java:754)
at dev.dominion.ecs.engine/dev.dominion.ecs.engine.DataComposition$IteratorWith1Next.next(DataComposition.java:306)
at dev.dominion.ecs.engine/dev.dominion.ecs.engine.DataComposition$IteratorWith1Next.next(DataComposition.java:294)
at java.base/java.lang.Iterable.forEach(Iterable.java:74)
at dev.dominion.ecs.engine/dev.dominion.ecs.engine.Test.lambda$main$0(Test.java:34)
at dev.dominion.ecs.engine/dev.dominion.ecs.engine.SystemScheduler$2.compute(SystemScheduler.java:116)
at java.base/java.util.concurrent.RecursiveAction.exec(RecursiveAction.java:194)
at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:373)
at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1182)
at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1655)
at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1622)
at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:165)
Test code:
public class Test {
public enum S {
A, B
}
public record A(int id) {
}
public static void consume(Object c) {
try {
TimeUnit.MILLISECONDS.sleep(10);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
public static void main(String[] args) {
EntityRepository entityRepository = (EntityRepository) new EntityRepository.Factory().create("test");
final var list = new ArrayList<Entity>(1000);
for (int i = 0; i < 1000; i++) {
list.add(entityRepository.createEntity(new A(i)).setState(S.A));
}
Scheduler scheduler = entityRepository.createScheduler();
scheduler.schedule(() -> entityRepository.findEntitiesWith(A.class).withState(S.A).forEach(Test::consume));
new Thread(() -> {
while (true) {
try {
TimeUnit.MILLISECONDS.sleep(10);
for (int i = 0; i < 1000; i++) {
list.get(i).setState(S.B);
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}).start();
scheduler.tickAtFixedRate(20);
}
}
I'm trying to implement a basic Transform component like in Godot or Unity.
The main idea is that the parent should affect the children, for that I need some way to reference them and then query the component.
I saw that there is an IntEntity
with getId()
, but this is not a public API and requests cannot be made using these identifiers. Also Entity
doesn't have methods to access components.
Can we expect such functionality in the future or is there some other way to implement it?
Through my time of attempting to use this ecs I noticed one glaring problem. That problem being that this ecs does not play nicely with components that utilize inheritance. In the example below we create two entities where one uses the super class component and the other uses the subclass component.
public class Main {
public static void main(String[] args) {
Dominion dom = Dominion.create();
dom.createEntity(new DemoA());
dom.createEntity(new DemoB());
Scheduler scheduler = dom.createScheduler();
scheduler.schedule(() -> {
System.out.println("ALL DEMOA COMPONENTS");
dom.findCompositionsWith(DemoA.class)
.stream().forEach(r -> r.onExec());
});
scheduler.schedule(() -> {
System.out.println("ALL DEMOB COMPONENTS");
dom.findCompositionsWith(DemoB.class)
.stream().forEach(r -> r.onExec());
});
scheduler.tick();
scheduler.shutDown();
}
private static class DemoA {
public void onExec() {
System.out.println("A");
}
}
private static class DemoB extends DemoA {
@Override
public void onExec() {
System.out.println("B");
}
}
}
Now the expected result is that since DemoB inheriets from DemoA, when we query for compositions utalizing DemoA, the entitiy that has DemoB would be type casted into DemoA producing the result below:
ALL DEMOA COMPONENTS
A
B
ALL DEMOB COMPONENTS
B
However when the example is run it produces the following result:
ALL DEMOA COMPONENTS
A
ALL DEMOB COMPONENTS
B
Regardless of if this is a bug or the intended implementation by the author I believe that dominion needs to support inheritance as it is a must have in more complex systems that benefits from the ECS paradigm such as physics and graphics engines.
Hi @enricostara , this is my test code
var d = Dominion.create();
var entity = d.createEntity(new A());
var s = d.createScheduler();
s.schedule(() -> {
d.findEntitiesWith(A.class, C.class).stream().forEach(rs -> {
try {
System.out.println("AAAA");
if (!rs.entity().has(B.class)) {
rs.entity().add(new B());
}
} finally {
rs.entity().removeType(C.class);
}
});
});
s.schedule(() -> {
d.findEntitiesWith(A.class, B.class).stream().forEach(rs -> {
System.out.println("BBBBBB");
});
});
/// always handle the A.class
s.schedule(() -> {
System.out.println("Before CCCC");
d.findEntitiesWith(A.class).stream().forEach(rs -> {
System.out.println("CCCCCCCCCCCC");
});
});
s.tickAtFixedRate(1);
TimeUnit.SECONDS.sleep(2);
entity.add(new C());
I have three component (A,B,C)and three system, always have a system to handle A.class. In the initial situation, the system operation is normal,but when I add C.class and add B.class then remove C.class, the system is not working
My version is 0.9.0-SNAPSHOT, you can run my test code and see the output.
Hi @enricostara I get a new error when I add a second component B
public static void main(String[] args) {
var d = Dominion.create();
var s = d.createScheduler();
s.schedule(() -> {
d.findEntitiesWith(A.class, B.class).iterator();
});
for(var i = 0; i < 50; i++) {
new Thread(()-> {
for(var j = 0; j< 100; j++) {
d.createEntity(new A(), new B());
}
}).start();
}
s.tickAtFixedRate(3);
}
Exception in thread "Thread-0" Exception in thread "Thread-9" Exception in thread "Thread-13" Exception in thread "Thread-2" Exception in thread "Thread-4" Exception in thread "Thread-10" Exception in thread "Thread-15" Exception in thread "Thread-1" java.lang.ArrayIndexOutOfBoundsException: Index 6 out of bounds for length 4
at dev.dominion.ecs.engine.system.ClassIndex.getIndexKey(ClassIndex.java:153)
at dev.dominion.ecs.engine.CompositionRepository.getOrCreate(CompositionRepository.java:92)
at dev.dominion.ecs.engine.EntityRepository.createEntity(EntityRepository.java:44)
at dev.dominion.ecs.engine.TestClass.lambda$main$1(VirtualWorld.java:53)
at java.base/java.lang.Thread.run(Thread.java:833)
Exception in thread "Thread-12" Exception in thread "Thread-14" Exception in thread "Thread-7" java.lang.ArrayIndexOutOfBoundsException: Index 6 out of bounds for length 4
at dev.dominion.ecs.engine.system.ClassIndex.getIndexKey(ClassIndex.java:153)
at dev.dominion.ecs.engine.CompositionRepository.getOrCreate(CompositionRepository.java:92)
at dev.dominion.ecs.engine.EntityRepository.createEntity(EntityRepository.java:44)
at dev.dominion.ecs.engine.TestClass.lambda$main$1(VirtualWorld.java:53)
at java.base/java.lang.Thread.run(Thread.java:833)
Exception in thread "Thread-8" java.lang.ArrayIndexOutOfBoundsException: Index 6 out of bounds for length 4
at dev.dominion.ecs.engine.system.ClassIndex.getIndexKey(ClassIndex.java:153)
at dev.dominion.ecs.engine.CompositionRepository.getOrCreate(CompositionRepository.java:92)
at dev.dominion.ecs.engine.EntityRepository.createEntity(EntityRepository.java:44)
at dev.dominion.ecs.engine.TestClass.lambda$main$1(VirtualWorld.java:53)
at java.base/java.lang.Thread.run(Thread.java:833)
Exception in thread "Thread-5" Exception in thread "Thread-11" Exception in thread "Thread-6" java.lang.ArrayIndexOutOfBoundsException: Index 6 out of bounds for length 4
at dev.dominion.ecs.engine.system.ClassIndex.getIndexKey(ClassIndex.java:153)
at dev.dominion.ecs.engine.CompositionRepository.getOrCreate(CompositionRepository.java:92)
at dev.dominion.ecs.engine.EntityRepository.createEntity(EntityRepository.java:44)
at dev.dominion.ecs.engine.TestClass.lambda$main$1(VirtualWorld.java:53)
at java.base/java.lang.Thread.run(Thread.java:833)
Exception in thread "Thread-3" java.lang.ArrayIndexOutOfBoundsException: Index 6 out of bounds for length 4
at dev.dominion.ecs.engine.system.ClassIndex.getIndexKey(ClassIndex.java:153)
at dev.dominion.ecs.engine.CompositionRepository.getOrCreate(CompositionRepository.java:92)
at dev.dominion.ecs.engine.EntityRepository.createEntity(EntityRepository.java:44)
at dev.dominion.ecs.engine.TestClass.lambda$main$1(VirtualWorld.java:53)
at java.base/java.lang.Thread.run(Thread.java:833)
java.lang.ArrayIndexOutOfBoundsException: Index 6 out of bounds for length 4
at dev.dominion.ecs.engine.system.ClassIndex.getIndexKey(ClassIndex.java:153)
at dev.dominion.ecs.engine.CompositionRepository.getOrCreate(CompositionRepository.java:92)
at dev.dominion.ecs.engine.EntityRepository.createEntity(EntityRepository.java:44)
at dev.dominion.ecs.engine.TestClass.lambda$main$1(VirtualWorld.java:53)
at java.base/java.lang.Thread.run(Thread.java:833)
java.lang.ArrayIndexOutOfBoundsException: Index 6 out of bounds for length 4
at dev.dominion.ecs.engine.system.ClassIndex.getIndexKey(ClassIndex.java:153)
at dev.dominion.ecs.engine.CompositionRepository.getOrCreate(CompositionRepository.java:92)
at dev.dominion.ecs.engine.EntityRepository.createEntity(EntityRepository.java:44)
at dev.dominion.ecs.engine.TestClass.lambda$main$1(VirtualWorld.java:53)
at java.base/java.lang.Thread.run(Thread.java:833)
java.lang.ArrayIndexOutOfBoundsException: Index 6 out of bounds for length 4
at dev.dominion.ecs.engine.system.ClassIndex.getIndexKey(ClassIndex.java:153)
at dev.dominion.ecs.engine.CompositionRepository.getOrCreate(CompositionRepository.java:92)
at dev.dominion.ecs.engine.EntityRepository.createEntity(EntityRepository.java:44)
at dev.dominion.ecs.engine.TestClass.lambda$main$1(VirtualWorld.java:53)
at java.base/java.lang.Thread.run(Thread.java:833)
java.lang.ArrayIndexOutOfBoundsException: Index 6 out of bounds for length 4
at dev.dominion.ecs.engine.system.ClassIndex.getIndexKey(ClassIndex.java:153)
at dev.dominion.ecs.engine.CompositionRepository.getOrCreate(CompositionRepository.java:92)
at dev.dominion.ecs.engine.EntityRepository.createEntity(EntityRepository.java:44)
at dev.dominion.ecs.engine.TestClass.lambda$main$1(VirtualWorld.java:53)
at java.base/java.lang.Thread.run(Thread.java:833)
java.lang.ArrayIndexOutOfBoundsException: Index 6 out of bounds for length 4
at dev.dominion.ecs.engine.system.ClassIndex.getIndexKey(ClassIndex.java:153)
at dev.dominion.ecs.engine.CompositionRepository.getOrCreate(CompositionRepository.java:92)
at dev.dominion.ecs.engine.EntityRepository.createEntity(EntityRepository.java:44)
at dev.dominion.ecs.engine.TestClass.lambda$main$1(VirtualWorld.java:53)
at java.base/java.lang.Thread.run(Thread.java:833)
java.lang.ArrayIndexOutOfBoundsException: Index 6 out of bounds for length 4
at dev.dominion.ecs.engine.system.ClassIndex.getIndexKey(ClassIndex.java:153)
at dev.dominion.ecs.engine.CompositionRepository.getOrCreate(CompositionRepository.java:92)
at dev.dominion.ecs.engine.EntityRepository.createEntity(EntityRepository.java:44)
at dev.dominion.ecs.engine.TestClass.lambda$main$1(VirtualWorld.java:53)
at java.base/java.lang.Thread.run(Thread.java:833)
java.lang.ArrayIndexOutOfBoundsException: Index 6 out of bounds for length 4
at dev.dominion.ecs.engine.system.ClassIndex.getIndexKey(ClassIndex.java:153)
at dev.dominion.ecs.engine.CompositionRepository.getOrCreate(CompositionRepository.java:92)
at dev.dominion.ecs.engine.EntityRepository.createEntity(EntityRepository.java:44)
at dev.dominion.ecs.engine.TestClass.lambda$main$1(VirtualWorld.java:53)
at java.base/java.lang.Thread.run(Thread.java:833)
java.lang.ArrayIndexOutOfBoundsException: Index 6 out of bounds for length 4
at dev.dominion.ecs.engine.system.ClassIndex.getIndexKey(ClassIndex.java:153)
at dev.dominion.ecs.engine.CompositionRepository.getOrCreate(CompositionRepository.java:92)
at dev.dominion.ecs.engine.EntityRepository.createEntity(EntityRepository.java:44)
at dev.dominion.ecs.engine.TestClass.lambda$main$1(VirtualWorld.java:53)
at java.base/java.lang.Thread.run(Thread.java:833)
java.lang.ArrayIndexOutOfBoundsException: Index 6 out of bounds for length 4
at dev.dominion.ecs.engine.system.ClassIndex.getIndexKey(ClassIndex.java:153)
at dev.dominion.ecs.engine.CompositionRepository.getOrCreate(CompositionRepository.java:92)
at dev.dominion.ecs.engine.EntityRepository.createEntity(EntityRepository.java:44)
at dev.dominion.ecs.engine.TestClass.lambda$main$1(VirtualWorld.java:53)
at java.base/java.lang.Thread.run(Thread.java:833)
java.lang.ArrayIndexOutOfBoundsException: Index 6 out of bounds for length 4
at dev.dominion.ecs.engine.system.ClassIndex.getIndexKey(ClassIndex.java:153)
at dev.dominion.ecs.engine.CompositionRepository.getOrCreate(CompositionRepository.java:92)
at dev.dominion.ecs.engine.EntityRepository.createEntity(EntityRepository.java:44)
at dev.dominion.ecs.engine.TestClass.lambda$main$1(VirtualWorld.java:53)
at java.base/java.lang.Thread.run(Thread.java:833)
java.lang.ArrayIndexOutOfBoundsException: Index 6 out of bounds for length 4
at dev.dominion.ecs.engine.system.ClassIndex.getIndexKey(ClassIndex.java:153)
at dev.dominion.ecs.engine.CompositionRepository.getOrCreate(CompositionRepository.java:92)
at dev.dominion.ecs.engine.EntityRepository.createEntity(EntityRepository.java:44)
at dev.dominion.ecs.engine.TestClass.lambda$main$1(VirtualWorld.java:53)
at java.base/java.lang.Thread.run(Thread.java:833)
Originally posted by @endison1986 in #117 (comment)
Would it be possible to add an option to the API to retrieve all entities?
I am currently using a workaround where I add a dummy component to all entities and then just do:
dominion.findEntitiesWith(FillerComponent.class).iterator();
And then just iterate through it to get a list of all my entities, while it works, it would be nicer if I did not have to add a dummy component.
I wanted to fetch all entities for a debug menu so that I could implement a GUI where I can just click to select an entity from the list to add or remove a component from UI during testing. This is a lot faster than having to make all component changes programmatically.
Hi @enricostara ,I have a question, are the Item interface and LinkedChunk generics necessary? Why not use the IntEntity array directly, so that there is no performance loss of unpacking?
This is an enum I'm using to categorize entities.
package components;
public enum EntityType {
CUE, BALL, POCKET, WALL;
}
When I do
List<With1<EntityType>> cueResult = GameWorld.get().getDominion()
.findEntitiesWith(EntityType.class)
.stream().collect(Collectors.toList());
cueResult has size() 18 and contains With1[comp=CUE, entity=Entity={id=|0:5:0|-> [CUE, java.awt.Color[r=255,g=255,b=255], models.Transform2@3d75a2cf, colliders.ColliderComponent@788dcd3c, bodies.Body@55dc666e, components.TagCue@6ef8985a], stateId=|1:0:0|, enabled=true}]
When I do
List<With1<EntityType>> cueResult = GameWorld.get().getDominion()
.findEntitiesWith(EntityType.class)
.withState(EntityType.CUE)
.stream().collect(Collectors.toList());
cueResult has size 0
Either I don't understand what withState() is intended to do or there is a bug.
In the meantime I've just used a tag class to accomplish the same goal
With1<TagCue> cueResult = GameWorld.get().getDominion().findEntitiesWith(TagCue.class).stream().findFirst().orElse(null);
I use dominion on the server side,so there are some question about thread safe.
I need createEntity, addComponent or removeComponent, above action must run in System?
If I want to do above action in network thread,will there be any thread safety issues?
Hi @enricostara , I pull a request, but I'm not sure which branch should be merged into, please help me to have a look, please forgive me if there is any inappropriateness.
Right now, the Dominion.findEntitiesWith()
method accepts up to 6 component types. The returned Results
object maps the types for each component by position and allows for their retrieval. Is there a mechanism in place to enable finding and working with entities with more than 6 components? Is this something that will come at a later stage?
I may be wrong, but ClassIndex
does not seem to handle System.identityHashCode
returning the same for two distinct classes, as collision detection is only implemented based on the even smaller hashBits
field. Which is an unlikely scenario, but not impossible.
how to get component from entity?
Dominion dominion= Dominion.create();
dominion.createEntity(comp1, comp2);
/// ....
final var scheduler = dominion.createSchduler();
scheduler.schedule(()->{
dominion.findEntitiesWith(Component1.class, Component2.class).stream().forEach(rs->{
final var entity = rs.entity();
///...
if(entity.has(Component3.class)) {
final var comp3 = entity.get(Component3.class);
} else {
fianl var comp3 = new Component3();
///... to config comp3
entity.add(comp3);
}
});
});
scheduler.tickAtFixedRate(3);
@enricostara I define three component, A,B,C
public static class A{}
public static class B{}
public static class C{}
it's fine.
public static void main(String[] args) {
var w = Dominion.create();
var s = w.createScheduler();
s.schedule(()-> w.findEntitiesWith(A.class).stream().forEach((rs)-> System.out.println(rs.entity())));
w.createEntity(new A());
s.tickAtFixedRate(60);
}
I get NullPointerException
public static void main(String[] args) {
var w = Dominion.create();
var s = w.createScheduler();
s.schedule(()-> w.findEntitiesWith(A.class, B.class).stream().forEach((rs)-> System.out.println(rs.entity())));
w.createEntity(new A());
s.tickAtFixedRate(60);
}
dominion.SystemScheduler invoke
java.lang.NullPointerException
at java.base/jdk.internal.reflect.GeneratedConstructorAccessor1.newInstance(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:480)
at java.base/java.util.concurrent.ForkJoinTask.getThrowableException(ForkJoinTask.java:564)
at java.base/java.util.concurrent.ForkJoinTask.reportException(ForkJoinTask.java:591)
at java.base/java.util.concurrent.ForkJoinTask.joinForPoolInvoke(ForkJoinTask.java:1042)
at java.base/java.util.concurrent.ForkJoinPool.invoke(ForkJoinPool.java:2639)
at dev.dominion.ecs.engine.SystemScheduler.forkAndJoin(SystemScheduler.java:113)
at dev.dominion.ecs.engine.SystemScheduler$Single.call(SystemScheduler.java:262)
at dev.dominion.ecs.engine.SystemScheduler$Single.call(SystemScheduler.java:239)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: java.lang.NullPointerException: Cannot load from int array because "this.componentIndex" is null
at dev.dominion.ecs.engine.DataComposition.fetchComponentIndex(DataComposition.java:69)
at dev.dominion.ecs.engine.DataComposition.select(DataComposition.java:173)
at dev.dominion.ecs.engine.ResultSet$With2.compositionIterator(ResultSet.java:208)
at dev.dominion.ecs.engine.ResultSet.iterator(ResultSet.java:56)
at dev.dominion.ecs.engine.ResultSet.stream(ResultSet.java:85)
at com.yunzhi.ancientsecrets.server.common.VirtualWorld.lambda$main$1(VirtualWorld.java:37)
at dev.dominion.ecs.engine.SystemScheduler$2.compute(SystemScheduler.java:116)
at java.base/java.util.concurrent.RecursiveAction.exec(RecursiveAction.java:194)
at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:373)
at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1182)
at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1655)
at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1622)
at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:165)
it's fine
public static void main(String[] args) {
var w = Dominion.create();
var s = w.createScheduler();
s.schedule(()-> w.findEntitiesWith(A.class, B.class).stream().forEach((rs)-> System.out.println(rs.entity())));
w.createEntity(new A(), new B());
s.tickAtFixedRate(60);
}
I get ArrayIndexOutOfBoundsException
public static void main(String[] args) {
var w = Dominion.create();
var s = w.createScheduler();
s.schedule(()-> w.findEntitiesWith(A.class, B.class, C.class).stream().forEach((rs)-> System.out.println(rs.entity())));
w.createEntity(new A(), new B());
s.tickAtFixedRate(60);
}
dominion.SystemScheduler invoke
java.lang.ArrayIndexOutOfBoundsException
at java.base/jdk.internal.reflect.GeneratedConstructorAccessor1.newInstance(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:480)
at java.base/java.util.concurrent.ForkJoinTask.getThrowableException(ForkJoinTask.java:564)
at java.base/java.util.concurrent.ForkJoinTask.reportException(ForkJoinTask.java:591)
at java.base/java.util.concurrent.ForkJoinTask.joinForPoolInvoke(ForkJoinTask.java:1042)
at java.base/java.util.concurrent.ForkJoinPool.invoke(ForkJoinPool.java:2639)
at dev.dominion.ecs.engine.SystemScheduler.forkAndJoin(SystemScheduler.java:113)
at dev.dominion.ecs.engine.SystemScheduler$Single.call(SystemScheduler.java:262)
at dev.dominion.ecs.engine.SystemScheduler$Single.call(SystemScheduler.java:239)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: java.lang.ArrayIndexOutOfBoundsException: Index -1 out of bounds for length 2
at dev.dominion.ecs.engine.collections.ChunkedPool$PoolMultiDataIterator.data(ChunkedPool.java:587)
at dev.dominion.ecs.engine.DataComposition$IteratorWith3.next(DataComposition.java:356)
at dev.dominion.ecs.engine.DataComposition$IteratorWith3.next(DataComposition.java:342)
at java.base/java.util.Iterator.forEachRemaining(Iterator.java:133)
at java.base/java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1845)
at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:762)
at com.yunzhi.ancientsecrets.server.common.VirtualWorld.lambda$main$1(VirtualWorld.java:37)
at dev.dominion.ecs.engine.SystemScheduler$2.compute(SystemScheduler.java:116)
at java.base/java.util.concurrent.RecursiveAction.exec(RecursiveAction.java:194)
at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:373)
at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1182)
at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1655)
at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1622)
at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:165)
it's fine.
public static void main(String[] args) {
var w = Dominion.create();
var s = w.createScheduler();
s.schedule(()-> w.findEntitiesWith(A.class, B.class).stream().forEach((rs)-> System.out.println(rs.entity())));
w.createEntity(new A(), new B(), new C());
s.tickAtFixedRate(60);
}
I get ArrayIndexOutOfBoundsException
public static void main(String[] args) {
var w = Dominion.create();
var s = w.createScheduler();
s.schedule(()-> w.findEntitiesWith(A.class, B.class).stream().forEach((rs)-> System.out.println(rs.entity())));
w.createEntity(new A(), new C());
s.tickAtFixedRate(60);
}
dominion.SystemScheduler invoke
java.lang.ArrayIndexOutOfBoundsException
at java.base/jdk.internal.reflect.GeneratedConstructorAccessor1.newInstance(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:480)
at java.base/java.util.concurrent.ForkJoinTask.getThrowableException(ForkJoinTask.java:564)
at java.base/java.util.concurrent.ForkJoinTask.reportException(ForkJoinTask.java:591)
at java.base/java.util.concurrent.ForkJoinTask.joinForPoolInvoke(ForkJoinTask.java:1042)
at java.base/java.util.concurrent.ForkJoinPool.invoke(ForkJoinPool.java:2639)
at dev.dominion.ecs.engine.SystemScheduler.forkAndJoin(SystemScheduler.java:113)
at dev.dominion.ecs.engine.SystemScheduler$Single.call(SystemScheduler.java:262)
at dev.dominion.ecs.engine.SystemScheduler$Single.call(SystemScheduler.java:239)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: java.lang.ArrayIndexOutOfBoundsException: Index -1 out of bounds for length 2
at dev.dominion.ecs.engine.collections.ChunkedPool$PoolMultiDataIterator.data(ChunkedPool.java:587)
at dev.dominion.ecs.engine.DataComposition$IteratorWith2.next(DataComposition.java:321)
at dev.dominion.ecs.engine.DataComposition$IteratorWith2.next(DataComposition.java:307)
at java.base/java.util.Iterator.forEachRemaining(Iterator.java:133)
at java.base/java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1845)
at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:762)
at com.yunzhi.ancientsecrets.server.common.VirtualWorld.lambda$main$1(VirtualWorld.java:37)
at dev.dominion.ecs.engine.SystemScheduler$2.compute(SystemScheduler.java:116)
at java.base/java.util.concurrent.RecursiveAction.exec(RecursiveAction.java:194)
at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:373)
at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1182)
at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1655)
at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1622)
at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:165)
I'm tring to test a situation when i add entities and remove all after that, it occurs exception,
I fount when outer loop time less than 3 will not occurs, is this some kind of thread problem?
// creates your world
Dominion hello = Dominion.create();
// creates a scheduler
Scheduler scheduler = hello.createScheduler();
// a system removes all entities with component Position
Runnable s = () -> {
hello.findEntitiesWith(Position.class).stream().forEach(e -> {
hello.deleteEntity(e.entity());
});
};
scheduler.schedule(s);
for (int i = 0; i < 10; i++) {
// add entities
for (int j = 0; j < 1000; j++) {
var e = hello.createEntity(
"my-entity",
new Position(0, 0),
new Velocity(1, 1)
);
}
// tick to remove all entities
scheduler.tick();
}
Exception stacktrace:
dominion.SystemScheduler invoke
java.lang.NullPointerException
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:480)
at java.base/java.util.concurrent.ForkJoinTask.getThrowableException(ForkJoinTask.java:564)
at java.base/java.util.concurrent.ForkJoinTask.reportException(ForkJoinTask.java:591)
at java.base/java.util.concurrent.ForkJoinTask.joinForPoolInvoke(ForkJoinTask.java:1042)
at java.base/java.util.concurrent.ForkJoinPool.invoke(ForkJoinPool.java:2639)
at dev.dominion.ecs.engine.SystemScheduler.forkAndJoin(SystemScheduler.java:113)
at dev.dominion.ecs.engine.SystemScheduler$Single.call(SystemScheduler.java:262)
at dev.dominion.ecs.engine.SystemScheduler$Single.call(SystemScheduler.java:239)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: java.lang.NullPointerException: Cannot invoke "dev.dominion.ecs.engine.IntEntity$Data.composition()" because the return value of "dev.dominion.ecs.engine.IntEntity.getData()" is null
at dev.dominion.ecs.engine.Composition$IteratorWith1.next(Composition.java:352)
at dev.dominion.ecs.engine.Composition$IteratorWith1.next(Composition.java:340)
at java.base/java.util.Iterator.forEachRemaining(Iterator.java:133)
at java.base/java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1845)
at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:762)
at com.example.demo1.Demo1Application.lambda$main$1(Demo1Application.java:24)
at dev.dominion.ecs.engine.SystemScheduler$2.compute(SystemScheduler.java:116)
at java.base/java.util.concurrent.RecursiveAction.exec(RecursiveAction.java:194)
at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:373)
at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1182)
at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1655)
at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1622)
at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:165)
When I run 'mvn package', some tests are failing;
[ERROR] SystemSchedulerTest.deltaTime:164 expected: <0.5> but was: <0.5152623>
[ERROR] SystemSchedulerTest.tickAtFixedRate:148 expected: <6> but was: <7>
I'm using Microsoft OpenJDK21.
Hi, great lib! I’m using it for my Clojure small game and it has been a breeze :D
Do you think that we could support optional, not, relationships (as in https://ajmmertens.medium.com/building-games-in-ecs-with-entity-relationships-657275ba2c6c) in Dominion?
Keep the good work o/
What's the best way to save the state and restore it? I can iterate over all entities, but how to recreate the state so that the IDs of the new entities are the same as in the saved state?
@enricostara hello friend, I have a question
This api ClassIndex.getIndexOrAddClasses(Class<?> klass)
used for get or create index for component type. If hash codes for component types collide,Does it always return the index of the first component?
@enricostara hi friend, I have another question about IndexKey
I read the source code of IndexKey
,why the constructor IndexKey(int value)
donot initialize the data
field.
Will it cause it to obtain or overwrite the value of other IndexKey when it is used as the Key of the Map?
public final class IndexKey {
private final int hashCode;
private final byte[] data;
public IndexKey(int value) {
this.hashCode = value;
data = null;
}
public IndexKey(int[] array) {...}
public IndexKey(boolean[] checkArray, int min, int max, int length) {...}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
return Arrays.equals(((IndexKey) o).data, data);
}
@Override
public int hashCode() {
return hashCode;
}
@Override
public String toString() {...}
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.