Fixes to many multithreading crashes and freezes
This commit is contained in:
@@ -24,7 +24,7 @@ allprojects {
|
|||||||
appName = 'Mindustry'
|
appName = 'Mindustry'
|
||||||
gdxVersion = '1.9.8'
|
gdxVersion = '1.9.8'
|
||||||
aiVersion = '1.8.1'
|
aiVersion = '1.8.1'
|
||||||
uCoreVersion = '91b310b'
|
uCoreVersion = '1deab5e'
|
||||||
|
|
||||||
getVersionString = {
|
getVersionString = {
|
||||||
String buildVersion = getBuildVersion()
|
String buildVersion = getBuildVersion()
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#Autogenerated file. Do not modify.
|
#Autogenerated file. Do not modify.
|
||||||
#Tue Feb 13 17:19:41 EST 2018
|
#Tue Feb 13 18:19:15 EST 2018
|
||||||
version=beta
|
version=beta
|
||||||
androidBuildCode=183
|
androidBuildCode=190
|
||||||
name=Mindustry
|
name=Mindustry
|
||||||
code=3.3
|
code=3.3
|
||||||
build=custom build
|
build=custom build
|
||||||
|
|||||||
@@ -227,7 +227,7 @@ public class NetServer extends Module{
|
|||||||
if(timer.get(timerEntitySync, serverSyncTime)){
|
if(timer.get(timerEntitySync, serverSyncTime)){
|
||||||
//scan through all groups with syncable entities
|
//scan through all groups with syncable entities
|
||||||
for(EntityGroup<?> group : Entities.getAllGroups()) {
|
for(EntityGroup<?> group : Entities.getAllGroups()) {
|
||||||
if(group.size() == 0 || !(group.all().first() instanceof SyncEntity)) continue;
|
if(group.size() == 0 || !(group.all().iterator().next() instanceof SyncEntity)) continue;
|
||||||
|
|
||||||
//get write size for one entity (adding 4, as you need to write the ID as well)
|
//get write size for one entity (adding 4, as you need to write the ID as well)
|
||||||
int writesize = SyncEntity.getWriteSize((Class<? extends SyncEntity>)group.getType()) + 4;
|
int writesize = SyncEntity.getWriteSize((Class<? extends SyncEntity>)group.getType()) + 4;
|
||||||
|
|||||||
@@ -241,16 +241,16 @@ public class Renderer extends RendererModule{
|
|||||||
Mathf.round(camera.position.y - ch/2, tilesize),
|
Mathf.round(camera.position.y - ch/2, tilesize),
|
||||||
(cw - vw) /2,
|
(cw - vw) /2,
|
||||||
ch + tilesize,
|
ch + tilesize,
|
||||||
0, ch / tilesize + 1,
|
0, 0,
|
||||||
((cw - vw) / 2 / tilesize), 0);
|
((cw - vw) / 2 / tilesize), -ch / tilesize + 1);
|
||||||
|
|
||||||
batch.draw(background,
|
batch.draw(background,
|
||||||
camera.position.x - vw/2,
|
camera.position.x - vw/2,
|
||||||
Mathf.round(camera.position.y - ch/2, tilesize),
|
Mathf.round(camera.position.y - ch/2, tilesize),
|
||||||
-(cw - vw) /2,
|
-(cw - vw) /2,
|
||||||
ch + tilesize,
|
ch + tilesize,
|
||||||
0, ch / tilesize + 1,
|
0, 0,
|
||||||
-((cw - vw) / 2 / tilesize), 0);
|
-((cw - vw) / 2 / tilesize), -ch / tilesize + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -539,7 +539,7 @@ public class Renderer extends RendererModule{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void clampScale(){
|
public void clampScale(){
|
||||||
targetscale = Mathf.clamp(targetscale, Math.round(Unit.dp.scl(1)), Math.round(Unit.dp.scl((5))));
|
targetscale = Mathf.clamp(targetscale, Math.round(Unit.dp.scl(2)), Math.round(Unit.dp.scl((5))));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,10 @@ import com.badlogic.gdx.Gdx;
|
|||||||
import com.badlogic.gdx.utils.Array;
|
import com.badlogic.gdx.utils.Array;
|
||||||
import com.badlogic.gdx.utils.TimeUtils;
|
import com.badlogic.gdx.utils.TimeUtils;
|
||||||
import io.anuke.ucore.core.Timers;
|
import io.anuke.ucore.core.Timers;
|
||||||
|
import io.anuke.ucore.entities.Entities;
|
||||||
|
import io.anuke.ucore.entities.Entity;
|
||||||
|
import io.anuke.ucore.entities.EntityGroup;
|
||||||
|
import io.anuke.ucore.entities.EntityGroup.ArrayContainer;
|
||||||
import io.anuke.ucore.util.Log;
|
import io.anuke.ucore.util.Log;
|
||||||
|
|
||||||
import static io.anuke.mindustry.Vars.logic;
|
import static io.anuke.mindustry.Vars.logic;
|
||||||
@@ -57,6 +61,9 @@ public class ThreadHandler {
|
|||||||
public void setEnabled(boolean enabled){
|
public void setEnabled(boolean enabled){
|
||||||
if(enabled){
|
if(enabled){
|
||||||
logic.doUpdate = false;
|
logic.doUpdate = false;
|
||||||
|
for(EntityGroup<?> group : Entities.getAllGroups()){
|
||||||
|
impl.switchContainer(group);
|
||||||
|
}
|
||||||
Timers.runTask(2f, () -> {
|
Timers.runTask(2f, () -> {
|
||||||
impl.start(this::runLogic);
|
impl.start(this::runLogic);
|
||||||
this.enabled = true;
|
this.enabled = true;
|
||||||
@@ -64,6 +71,9 @@ public class ThreadHandler {
|
|||||||
}else{
|
}else{
|
||||||
this.enabled = false;
|
this.enabled = false;
|
||||||
impl.stop();
|
impl.stop();
|
||||||
|
for(EntityGroup<?> group : Entities.getAllGroups()){
|
||||||
|
group.setContainer(new ArrayContainer<>());
|
||||||
|
}
|
||||||
Timers.runTask(2f, () -> {
|
Timers.runTask(2f, () -> {
|
||||||
logic.doUpdate = true;
|
logic.doUpdate = true;
|
||||||
});
|
});
|
||||||
@@ -110,7 +120,7 @@ public class ThreadHandler {
|
|||||||
} catch (InterruptedException ex) {
|
} catch (InterruptedException ex) {
|
||||||
Log.info("Stopping logic thread.");
|
Log.info("Stopping logic thread.");
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
Gdx.app.postRunnable(() -> {
|
Timers.run(0f, () -> {
|
||||||
throw new RuntimeException(ex);
|
throw new RuntimeException(ex);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -123,5 +133,6 @@ public class ThreadHandler {
|
|||||||
void stop();
|
void stop();
|
||||||
void wait(Object object) throws InterruptedException;
|
void wait(Object object) throws InterruptedException;
|
||||||
void notify(Object object);
|
void notify(Object object);
|
||||||
|
<T extends Entity> void switchContainer(EntityGroup<T> group);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package io.anuke.mindustry.io;
|
package io.anuke.mindustry.io;
|
||||||
|
|
||||||
import io.anuke.mindustry.core.ThreadHandler.ThreadProvider;
|
import io.anuke.mindustry.core.ThreadHandler.ThreadProvider;
|
||||||
|
import io.anuke.ucore.entities.Entity;
|
||||||
|
import io.anuke.ucore.entities.EntityGroup;
|
||||||
import io.anuke.ucore.scene.ui.TextField;
|
import io.anuke.ucore.scene.ui.TextField;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
@@ -36,6 +38,7 @@ public abstract class Platform {
|
|||||||
@Override public void stop() {}
|
@Override public void stop() {}
|
||||||
@Override public void notify(Object object) {}
|
@Override public void notify(Object object) {}
|
||||||
@Override public void wait(Object object) {}
|
@Override public void wait(Object object) {}
|
||||||
|
@Override public <T extends Entity> void switchContainer(EntityGroup<T> group) {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import io.anuke.mindustry.world.Tile;
|
|||||||
import io.anuke.mindustry.world.blocks.Blocks;
|
import io.anuke.mindustry.world.blocks.Blocks;
|
||||||
import io.anuke.ucore.core.Core;
|
import io.anuke.ucore.core.Core;
|
||||||
import io.anuke.ucore.entities.Entities;
|
import io.anuke.ucore.entities.Entities;
|
||||||
|
import io.anuke.ucore.entities.EntityGroup.EntityContainer;
|
||||||
|
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
@@ -216,11 +217,11 @@ public class Save12 extends SaveFileVersion {
|
|||||||
|
|
||||||
//--ENEMIES--
|
//--ENEMIES--
|
||||||
|
|
||||||
Array<Enemy> enemies = enemyGroup.all();
|
EntityContainer<Enemy> enemies = enemyGroup.all();
|
||||||
|
|
||||||
stream.writeInt(enemies.size); //enemy amount
|
stream.writeInt(enemies.size()); //enemy amount
|
||||||
|
|
||||||
for(int i = 0; i < enemies.size; i ++){
|
for(int i = 0; i < enemies.size(); i ++){
|
||||||
Enemy enemy = enemies.get(i);
|
Enemy enemy = enemies.get(i);
|
||||||
stream.writeByte(enemy.type.id); //type
|
stream.writeByte(enemy.type.id); //type
|
||||||
stream.writeByte(enemy.lane); //lane
|
stream.writeByte(enemy.lane); //lane
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import io.anuke.mindustry.world.blocks.types.BlockPart;
|
|||||||
import io.anuke.mindustry.world.blocks.types.Rock;
|
import io.anuke.mindustry.world.blocks.types.Rock;
|
||||||
import io.anuke.ucore.core.Core;
|
import io.anuke.ucore.core.Core;
|
||||||
import io.anuke.ucore.entities.Entities;
|
import io.anuke.ucore.entities.Entities;
|
||||||
|
import io.anuke.ucore.entities.EntityGroup.EntityContainer;
|
||||||
|
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
@@ -229,11 +230,11 @@ public class Save13 extends SaveFileVersion {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//--ENEMIES--
|
//--ENEMIES--
|
||||||
Array<Enemy> enemies = enemyGroup.all();
|
EntityContainer<Enemy> enemies = enemyGroup.all();
|
||||||
|
|
||||||
stream.writeInt(enemies.size); //enemy amount
|
stream.writeInt(enemies.size()); //enemy amount
|
||||||
|
|
||||||
for(int i = 0; i < enemies.size; i ++){
|
for(int i = 0; i < enemies.size(); i ++){
|
||||||
Enemy enemy = enemies.get(i);
|
Enemy enemy = enemies.get(i);
|
||||||
stream.writeByte(enemy.type.id); //type
|
stream.writeByte(enemy.type.id); //type
|
||||||
stream.writeByte(enemy.lane); //lane
|
stream.writeByte(enemy.lane); //lane
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import io.anuke.mindustry.world.blocks.types.BlockPart;
|
|||||||
import io.anuke.mindustry.world.blocks.types.Rock;
|
import io.anuke.mindustry.world.blocks.types.Rock;
|
||||||
import io.anuke.ucore.core.Core;
|
import io.anuke.ucore.core.Core;
|
||||||
import io.anuke.ucore.entities.Entities;
|
import io.anuke.ucore.entities.Entities;
|
||||||
|
import io.anuke.ucore.entities.EntityGroup.EntityContainer;
|
||||||
|
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
@@ -255,11 +256,11 @@ public class Save14 extends SaveFileVersion{
|
|||||||
|
|
||||||
//--ENEMIES--
|
//--ENEMIES--
|
||||||
|
|
||||||
Array<Enemy> enemies = enemyGroup.all();
|
EntityContainer<Enemy> enemies = enemyGroup.all();
|
||||||
|
|
||||||
stream.writeInt(enemies.size); //enemy amount
|
stream.writeInt(enemies.size()); //enemy amount
|
||||||
|
|
||||||
for(int i = 0; i < enemies.size; i ++){
|
for(int i = 0; i < enemies.size(); i ++){
|
||||||
Enemy enemy = enemies.get(i);
|
Enemy enemy = enemies.get(i);
|
||||||
stream.writeByte(enemy.type.id); //type
|
stream.writeByte(enemy.type.id); //type
|
||||||
stream.writeByte(enemy.lane); //lane
|
stream.writeByte(enemy.lane); //lane
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import io.anuke.mindustry.world.blocks.Blocks;
|
|||||||
import io.anuke.mindustry.world.blocks.types.BlockPart;
|
import io.anuke.mindustry.world.blocks.types.BlockPart;
|
||||||
import io.anuke.mindustry.world.blocks.types.Rock;
|
import io.anuke.mindustry.world.blocks.types.Rock;
|
||||||
import io.anuke.ucore.core.Core;
|
import io.anuke.ucore.core.Core;
|
||||||
|
import io.anuke.ucore.entities.EntityGroup.EntityContainer;
|
||||||
|
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
@@ -280,11 +281,11 @@ public class Save15 extends SaveFileVersion {
|
|||||||
|
|
||||||
//--ENEMIES--
|
//--ENEMIES--
|
||||||
|
|
||||||
Array<Enemy> enemies = enemyGroup.all();
|
EntityContainer<Enemy> enemies = enemyGroup.all();
|
||||||
|
|
||||||
stream.writeInt(enemies.size); //enemy amount
|
stream.writeInt(enemies.size()); //enemy amount
|
||||||
|
|
||||||
for(int i = 0; i < enemies.size; i ++){
|
for(int i = 0; i < enemies.size(); i ++){
|
||||||
Enemy enemy = enemies.get(i);
|
Enemy enemy = enemies.get(i);
|
||||||
stream.writeByte(enemy.type.id); //type
|
stream.writeByte(enemy.type.id); //type
|
||||||
stream.writeByte(enemy.lane); //lane
|
stream.writeByte(enemy.lane); //lane
|
||||||
|
|||||||
@@ -1,8 +1,14 @@
|
|||||||
package io.anuke.kryonet;
|
package io.anuke.kryonet;
|
||||||
|
|
||||||
import io.anuke.mindustry.core.ThreadHandler.ThreadProvider;
|
import io.anuke.mindustry.core.ThreadHandler.ThreadProvider;
|
||||||
|
import io.anuke.ucore.entities.Entity;
|
||||||
|
import io.anuke.ucore.entities.EntityGroup;
|
||||||
|
import io.anuke.ucore.entities.EntityGroup.EntityContainer;
|
||||||
import io.anuke.ucore.util.Log;
|
import io.anuke.ucore.util.Log;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
|
|
||||||
public class DefaultThreadImpl implements ThreadProvider {
|
public class DefaultThreadImpl implements ThreadProvider {
|
||||||
private Thread thread;
|
private Thread thread;
|
||||||
|
|
||||||
@@ -47,4 +53,43 @@ public class DefaultThreadImpl implements ThreadProvider {
|
|||||||
public void notify(Object object) {
|
public void notify(Object object) {
|
||||||
object.notify();
|
object.notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T extends Entity> void switchContainer(EntityGroup<T> group) {
|
||||||
|
group.setContainer(new ConcurrentContainer<>());
|
||||||
|
}
|
||||||
|
|
||||||
|
static class ConcurrentContainer<T> implements EntityContainer<T>{
|
||||||
|
private CopyOnWriteArrayList<T> list = new CopyOnWriteArrayList<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return list.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void add(T item) {
|
||||||
|
list.add(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clear() {
|
||||||
|
list.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove(T item) {
|
||||||
|
list.remove(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T get(int index) {
|
||||||
|
return list.get(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<T> iterator() {
|
||||||
|
return list.iterator();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import io.anuke.mindustry.net.Streamable;
|
|||||||
import io.anuke.mindustry.net.Streamable.StreamBegin;
|
import io.anuke.mindustry.net.Streamable.StreamBegin;
|
||||||
import io.anuke.mindustry.net.Streamable.StreamChunk;
|
import io.anuke.mindustry.net.Streamable.StreamChunk;
|
||||||
import io.anuke.ucore.UCore;
|
import io.anuke.ucore.UCore;
|
||||||
|
import io.anuke.ucore.core.Timers;
|
||||||
import io.anuke.ucore.util.Log;
|
import io.anuke.ucore.util.Log;
|
||||||
import org.java_websocket.WebSocket;
|
import org.java_websocket.WebSocket;
|
||||||
import org.java_websocket.exceptions.WebsocketNotConnectedException;
|
import org.java_websocket.exceptions.WebsocketNotConnectedException;
|
||||||
@@ -296,7 +297,7 @@ public class KryoServer implements ServerProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void handleException(Throwable e){
|
private void handleException(Throwable e){
|
||||||
Gdx.app.postRunnable(() -> { throw new RuntimeException(e);});
|
Timers.run(0f, () -> { throw new RuntimeException(e);});
|
||||||
}
|
}
|
||||||
|
|
||||||
KryoConnection getByKryoID(int id){
|
KryoConnection getByKryoID(int id){
|
||||||
|
|||||||
Reference in New Issue
Block a user