Massively improved thread safety

This commit is contained in:
Anuken
2018-10-20 11:25:58 -04:00
parent 22328772ca
commit b1cda57174
8 changed files with 69 additions and 31 deletions

View File

@@ -27,7 +27,7 @@ allprojects {
appName = 'Mindustry' appName = 'Mindustry'
gdxVersion = '1.9.8' gdxVersion = '1.9.8'
roboVMVersion = '2.3.0' roboVMVersion = '2.3.0'
uCoreVersion = '03c4093f724e63069e097393991592db308728e0' uCoreVersion = '89250a4ec499609329c52e7742a251b9f4c6bd5b'
getVersionString = { getVersionString = {
String buildVersion = getBuildVersion() String buildVersion = getBuildVersion()

View File

@@ -23,7 +23,6 @@ import io.anuke.mindustry.type.ItemStack;
import io.anuke.mindustry.type.Recipe; import io.anuke.mindustry.type.Recipe;
import io.anuke.mindustry.ui.dialogs.FloatingDialog; import io.anuke.mindustry.ui.dialogs.FloatingDialog;
import io.anuke.ucore.core.*; import io.anuke.ucore.core.*;
import io.anuke.ucore.entities.Entities;
import io.anuke.ucore.entities.EntityQuery; import io.anuke.ucore.entities.EntityQuery;
import io.anuke.ucore.modules.Module; import io.anuke.ucore.modules.Module;
import io.anuke.ucore.util.Atlas; import io.anuke.ucore.util.Atlas;
@@ -382,10 +381,6 @@ public class Control extends Module{
} }
} }
if(!state.is(State.paused) || Net.active()){
Entities.update(effectGroup);
Entities.update(groundEffectGroup);
}
}else{ }else{
if(!state.is(State.paused) || Net.active()){ if(!state.is(State.paused) || Net.active()){
Timers.update(); Timers.update();

View File

@@ -147,6 +147,10 @@ public class Logic extends Module{
if(!Entities.defaultGroup().isEmpty()) if(!Entities.defaultGroup().isEmpty())
throw new RuntimeException("Do not add anything to the default group!"); throw new RuntimeException("Do not add anything to the default group!");
if(!headless){
Entities.update(effectGroup);
Entities.update(groundEffectGroup);
}
for(EntityGroup group : unitGroups){ for(EntityGroup group : unitGroups){
Entities.update(group); Entities.update(group);

View File

@@ -11,6 +11,7 @@ import io.anuke.ucore.entities.EntityGroup;
import io.anuke.ucore.entities.EntityQuery; import io.anuke.ucore.entities.EntityQuery;
import io.anuke.ucore.function.Consumer; import io.anuke.ucore.function.Consumer;
import io.anuke.ucore.function.Predicate; import io.anuke.ucore.function.Predicate;
import io.anuke.ucore.util.Threads;
import io.anuke.ucore.util.EnumSet; import io.anuke.ucore.util.EnumSet;
import static io.anuke.mindustry.Vars.*; import static io.anuke.mindustry.Vars.*;
@@ -20,10 +21,11 @@ import static io.anuke.mindustry.Vars.*;
*/ */
public class Units{ public class Units{
private static Rectangle rect = new Rectangle(); private static Rectangle rect = new Rectangle();
private static Rectangle rectGraphics = new Rectangle();
private static Rectangle hitrect = new Rectangle(); private static Rectangle hitrect = new Rectangle();
private static Unit result; private static Unit result;
private static float cdist; private static float cdist;
private static boolean boolResult; private static boolean boolResult, boolResultGraphics;
/** /**
* Validates a target. * Validates a target.
@@ -63,22 +65,43 @@ public class Units{
return anyEntities(rect); return anyEntities(rect);
} }
/**Can be called from any thread.*/
public static boolean anyEntities(Rectangle rect){ public static boolean anyEntities(Rectangle rect){
if(Threads.isLogic()){
boolResult = false;
boolResult = false; Units.getNearby(rect, unit -> {
if(boolResult) return;
if(!unit.isFlying()){
unit.getHitbox(hitrect);
Units.getNearby(rect, unit -> { if(hitrect.overlaps(rect)){
if(boolResult) return; boolResult = true;
if(!unit.isFlying()){ }
unit.getHitbox(hitrect);
if(hitrect.overlaps(rect)){
boolResult = true;
} }
} });
});
return boolResult; return boolResult;
}else{
for(EntityGroup<? extends BaseUnit> g : unitGroups){
g.forEach(u -> {
u.getHitbox(rectGraphics);
if(rectGraphics.overlaps(rect)){
boolResultGraphics = true;
}
});
if(boolResultGraphics) return true;
}
playerGroup.forEach(u -> {
u.getHitbox(rectGraphics);
if(rectGraphics.overlaps(rect)){
boolResultGraphics = true;
}
});
return boolResultGraphics;
}
} }
/**Returns whether there are any entities on this tile, with the hitbox expanded.*/ /**Returns whether there are any entities on this tile, with the hitbox expanded.*/

View File

@@ -254,7 +254,6 @@ public abstract class InputHandler extends InputAdapter{
&& tile.floor().drops != null && tile.floor().drops.item.hardness <= player.mech.drillPower && tile.floor().drops != null && tile.floor().drops.item.hardness <= player.mech.drillPower
&& !tile.floor().playerUnmineable && !tile.floor().playerUnmineable
&& player.inventory.canAcceptItem(tile.floor().drops.item) && player.inventory.canAcceptItem(tile.floor().drops.item)
&& Units.getClosestEnemy(player.getTeam(), tile.worldx(), tile.worldy(), 40f, e -> true) == null //don't being mining when an enemy is near
&& tile.block() == Blocks.air && player.distanceTo(tile.worldx(), tile.worldy()) <= Player.mineDistance; && tile.block() == Blocks.air && player.distanceTo(tile.worldx(), tile.worldy()) <= Player.mineDistance;
} }
@@ -330,12 +329,8 @@ public abstract class InputHandler extends InputAdapter{
public boolean validPlace(int x, int y, Block type, int rotation){ public boolean validPlace(int x, int y, Block type, int rotation){
for(Tile tile : state.teams.get(player.getTeam()).cores){ for(Tile tile : state.teams.get(player.getTeam()).cores){
if(tile.distanceTo(x * tilesize, y * tilesize) < coreBuildRange){ if(tile.distanceTo(x * tilesize, y * tilesize) < coreBuildRange){
//TODO terrible hack return Build.validPlace(player.getTeam(), x, y, type, rotation) &&
//this might actually screw things up on the logic thread. Vector2.dst(player.x, player.y, x * tilesize, y * tilesize) < Player.placeDistance;
try{
return Build.validPlace(player.getTeam(), x, y, type, rotation) &&
Vector2.dst(player.x, player.y, x * tilesize, y * tilesize) < Player.placeDistance;
}catch(Exception e){return false;}
} }
} }

View File

@@ -1,6 +1,5 @@
package io.anuke.mindustry.ui.dialogs; package io.anuke.mindustry.ui.dialogs;
import io.anuke.mindustry.entities.Player;
import io.anuke.mindustry.net.Administration.PlayerInfo; import io.anuke.mindustry.net.Administration.PlayerInfo;
import io.anuke.ucore.scene.ui.ScrollPane; import io.anuke.ucore.scene.ui.ScrollPane;
import io.anuke.ucore.scene.ui.layout.Table; import io.anuke.ucore.scene.ui.layout.Table;
@@ -43,12 +42,18 @@ public class AdminsDialog extends FloatingDialog{
res.addImageButton("icon-cancel", 14 * 3, () -> { res.addImageButton("icon-cancel", 14 * 3, () -> {
ui.showConfirm("$text.confirm", "$text.confirmunadmin", () -> { ui.showConfirm("$text.confirm", "$text.confirmunadmin", () -> {
netServer.admins.unAdminPlayer(info.id); netServer.admins.unAdminPlayer(info.id);
playerGroup.forEach(player -> {
if(player.uuid.equals(info.id)){
player.isAdmin = false;
}
});
/*
for(Player player : playerGroup.all()){ for(Player player : playerGroup.all()){
if(player.con != null){ if(player.con != null){
player.isAdmin = false; player.isAdmin = false;
break; break;
} }
} }*/
setup(); setup();
}); });
}).size(h).pad(-14f); }).size(h).pad(-14f);

View File

@@ -66,10 +66,10 @@ public class PlayerListFragment extends Fragment{
float h = 74f; float h = 74f;
for(Player player : playerGroup.all()){ playerGroup.forEach(player -> {
NetConnection connection = gwt ? null : player.con; NetConnection connection = gwt ? null : player.con;
if(connection == null && Net.server() && !player.isLocal) continue; if(connection == null && Net.server() && !player.isLocal) return;
Table button = new Table("button"); Table button = new Table("button");
button.left(); button.left();
@@ -134,7 +134,7 @@ public class PlayerListFragment extends Fragment{
content.add(button).padBottom(-6).width(350f).maxHeight(h + 14); content.add(button).padBottom(-6).width(350f).maxHeight(h + 14);
content.row(); content.row();
} });
content.marginBottom(5); content.marginBottom(5);
} }

View File

@@ -1,11 +1,27 @@
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.util.Threads;
import io.anuke.ucore.util.Threads.ThreadInfoProvider;
import io.anuke.ucore.util.Log; import io.anuke.ucore.util.Log;
public class DefaultThreadImpl implements ThreadProvider { public class DefaultThreadImpl implements ThreadProvider, ThreadInfoProvider{
private Thread thread; private Thread thread;
public DefaultThreadImpl(){
Threads.setThreadInfoProvider(this);
}
@Override
public boolean isOnLogicThread(){
return thread == null || isOnThread();
}
@Override
public boolean isOnGraphicsThread(){
return thread == null || !isOnThread();
}
@Override @Override
public boolean isOnThread() { public boolean isOnThread() {
return Thread.currentThread() == thread; return Thread.currentThread() == thread;