Merged in better multithreading
This commit is contained in:
@@ -113,7 +113,6 @@ public class WaveSpawner{
|
|||||||
|
|
||||||
if(group.type.isFlying){
|
if(group.type.isFlying){
|
||||||
FlyerSpawn spawn = flySpawns.get(flyCount);
|
FlyerSpawn spawn = flySpawns.get(flyCount);
|
||||||
//TODO verify flyer spawn
|
|
||||||
|
|
||||||
float margin = 40f; //how far away from the edge flying units spawn
|
float margin = 40f; //how far away from the edge flying units spawn
|
||||||
spawnX = world.width() * tilesize / 2f + Mathf.sqrwavex(spawn.angle) * (world.width() / 2f * tilesize + margin);
|
spawnX = world.width() * tilesize / 2f + Mathf.sqrwavex(spawn.angle) * (world.width() / 2f * tilesize + margin);
|
||||||
|
|||||||
@@ -176,7 +176,7 @@ public class ContentLoader{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void dispose(){
|
public void dispose(){
|
||||||
//TODO clear all content.
|
//clear all content, currently not needed
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handleContent(Content content){
|
public void handleContent(Content content){
|
||||||
|
|||||||
@@ -24,14 +24,10 @@ 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;
|
||||||
import io.anuke.ucore.util.Bundles;
|
import io.anuke.ucore.util.Timer;
|
||||||
import io.anuke.ucore.util.Strings;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import static io.anuke.mindustry.Vars.*;
|
import static io.anuke.mindustry.Vars.*;
|
||||||
|
|
||||||
@@ -48,6 +44,7 @@ public class Control extends Module{
|
|||||||
public final Saves saves;
|
public final Saves saves;
|
||||||
public final Unlocks unlocks;
|
public final Unlocks unlocks;
|
||||||
|
|
||||||
|
private Timer timerRPC= new Timer(), timerUnlock = new Timer();
|
||||||
private boolean hiscore = false;
|
private boolean hiscore = false;
|
||||||
private boolean wasPaused = false;
|
private boolean wasPaused = false;
|
||||||
private InputHandler[] inputs = {};
|
private InputHandler[] inputs = {};
|
||||||
@@ -364,12 +361,12 @@ public class Control extends Module{
|
|||||||
}
|
}
|
||||||
|
|
||||||
//auto-update rpc every 5 seconds
|
//auto-update rpc every 5 seconds
|
||||||
if(Timers.get("rpcUpdate", 60 * 5)){
|
if(timerRPC.get(60 * 5)){
|
||||||
Platform.instance.updateRPC();
|
Platform.instance.updateRPC();
|
||||||
}
|
}
|
||||||
|
|
||||||
//check unlocks every 2 seconds
|
//check unlocks every 2 seconds
|
||||||
if(!state.mode.infiniteResources && Timers.get("timerCheckUnlock", 120)){
|
if(!state.mode.infiniteResources && timerUnlock.get(120)){
|
||||||
checkUnlockableBlocks();
|
checkUnlockableBlocks();
|
||||||
|
|
||||||
//save if the unlocks changed
|
//save if the unlocks changed
|
||||||
@@ -396,10 +393,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();
|
||||||
|
|||||||
@@ -164,6 +164,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);
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ public class UI extends SceneModule{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void update(){
|
public void update(){
|
||||||
if(Graphics.drawing()) Graphics.end();
|
if(Graphics.drawing()) Graphics.end();
|
||||||
|
|
||||||
act();
|
act();
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ public class Damage{
|
|||||||
for(int i = 0; i < waves; i++){
|
for(int i = 0; i < waves; i++){
|
||||||
int f = i;
|
int f = i;
|
||||||
Timers.run(i * 2f, () -> {
|
Timers.run(i * 2f, () -> {
|
||||||
Damage.damage(x, y, Mathf.clamp(radius + explosiveness, 0, 50f) * ((f + 1f) / waves), explosiveness / 2f);
|
threads.run(() -> Damage.damage(x, y, Mathf.clamp(radius + explosiveness, 0, 50f) * ((f + 1f) / waves), explosiveness / 2f));
|
||||||
Effects.effect(ExplosionFx.blockExplosionSmoke, x + Mathf.range(radius), y + Mathf.range(radius));
|
Effects.effect(ExplosionFx.blockExplosionSmoke, x + Mathf.range(radius), y + Mathf.range(radius));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.
|
||||||
@@ -53,33 +55,57 @@ public class Units{
|
|||||||
return invalidateTarget(target, targeter.team, targeter.x, targeter.y, targeter.getWeapon().getAmmo().getRange());
|
return invalidateTarget(target, targeter.team, targeter.x, targeter.y, targeter.getWeapon().getAmmo().getRange());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**Returns whether there are any entities on this tile.*/
|
||||||
* Returns whether there are any entities on this tile.
|
|
||||||
*/
|
|
||||||
public static boolean anyEntities(Tile tile){
|
public static boolean anyEntities(Tile tile){
|
||||||
Block type = tile.block();
|
Block type = tile.block();
|
||||||
rect.setSize(type.size * tilesize, type.size * tilesize);
|
rect.setSize(type.size * tilesize, type.size * tilesize);
|
||||||
rect.setCenter(tile.drawx(), tile.drawy());
|
rect.setCenter(tile.drawx(), tile.drawy());
|
||||||
|
|
||||||
boolResult = false;
|
return anyEntities(rect);
|
||||||
|
|
||||||
Units.getNearby(rect, unit -> {
|
|
||||||
if(boolResult) return;
|
|
||||||
if(!unit.isFlying()){
|
|
||||||
unit.getHitbox(hitrect);
|
|
||||||
|
|
||||||
if(hitrect.overlaps(rect)){
|
|
||||||
boolResult = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return boolResult;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**Can be called from any thread.*/
|
||||||
* Returns whether there are any entities on this tile, with the hitbox expanded.
|
public static boolean anyEntities(Rectangle rect){
|
||||||
*/
|
if(Threads.isLogic()){
|
||||||
|
boolResult = false;
|
||||||
|
|
||||||
|
Units.getNearby(rect, unit -> {
|
||||||
|
if(boolResult) return;
|
||||||
|
if(!unit.isFlying()){
|
||||||
|
unit.getHitbox(hitrect);
|
||||||
|
|
||||||
|
if(hitrect.overlaps(rect)){
|
||||||
|
boolResult = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return boolResult;
|
||||||
|
}else{
|
||||||
|
boolResultGraphics = false;
|
||||||
|
|
||||||
|
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.*/
|
||||||
public static boolean anyEntities(Tile tile, float expansion, Predicate<Unit> pred){
|
public static boolean anyEntities(Tile tile, float expansion, Predicate<Unit> pred){
|
||||||
Block type = tile.block();
|
Block type = tile.block();
|
||||||
rect.setSize(type.size * tilesize + expansion, type.size * tilesize + expansion);
|
rect.setSize(type.size * tilesize + expansion, type.size * tilesize + expansion);
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import io.anuke.ucore.graphics.Lines;
|
|||||||
import io.anuke.ucore.util.Mathf;
|
import io.anuke.ucore.util.Mathf;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class that renders a trail.
|
* Class that renders a colored trail.
|
||||||
*/
|
*/
|
||||||
public class Trail{
|
public class Trail{
|
||||||
private final static float maxJump = 15f;
|
private final static float maxJump = 15f;
|
||||||
|
|||||||
@@ -267,7 +267,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -354,7 +353,7 @@ public abstract class InputHandler extends InputAdapter{
|
|||||||
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){
|
||||||
return Build.validPlace(player.getTeam(), x, y, type, rotation) &&
|
return Build.validPlace(player.getTeam(), x, y, type, rotation) &&
|
||||||
Vector2.dst(player.x, player.y, x * tilesize, y * tilesize) < Player.placeDistance;
|
Vector2.dst(player.x, player.y, x * tilesize, y * tilesize) < Player.placeDistance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -366,12 +365,10 @@ public abstract class InputHandler extends InputAdapter{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void placeBlock(int x, int y, Recipe recipe, int rotation){
|
public void placeBlock(int x, int y, Recipe recipe, int rotation){
|
||||||
//todo multiplayer support
|
|
||||||
player.addBuildRequest(new BuildRequest(x, y, rotation, recipe));
|
player.addBuildRequest(new BuildRequest(x, y, rotation, recipe));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void breakBlock(int x, int y){
|
public void breakBlock(int x, int y){
|
||||||
//todo multiplayer support
|
|
||||||
Tile tile = world.tile(x, y).target();
|
Tile tile = world.tile(x, y).target();
|
||||||
player.addBuildRequest(new BuildRequest(tile.x, tile.y));
|
player.addBuildRequest(new BuildRequest(tile.x, tile.y));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ import io.anuke.mindustry.ui.dialogs.FloatingDialog;
|
|||||||
import io.anuke.mindustry.world.Block;
|
import io.anuke.mindustry.world.Block;
|
||||||
import io.anuke.mindustry.world.Tile;
|
import io.anuke.mindustry.world.Tile;
|
||||||
import io.anuke.ucore.core.*;
|
import io.anuke.ucore.core.*;
|
||||||
import io.anuke.ucore.entities.Entities;
|
|
||||||
import io.anuke.ucore.graphics.Draw;
|
import io.anuke.ucore.graphics.Draw;
|
||||||
import io.anuke.ucore.graphics.Lines;
|
import io.anuke.ucore.graphics.Lines;
|
||||||
import io.anuke.ucore.scene.Group;
|
import io.anuke.ucore.scene.Group;
|
||||||
@@ -84,19 +83,17 @@ public class MobileInput extends InputHandler implements GestureListener{
|
|||||||
|
|
||||||
/** Check and assign targets for a specific position. */
|
/** Check and assign targets for a specific position. */
|
||||||
void checkTargets(float x, float y){
|
void checkTargets(float x, float y){
|
||||||
synchronized(Entities.entityLock){
|
Unit unit = Units.getClosestEnemy(player.getTeam(), x, y, 20f, u -> !u.isDead());
|
||||||
Unit unit = Units.getClosestEnemy(player.getTeam(), x, y, 20f, u -> !u.isDead() && u.isAdded());
|
|
||||||
|
|
||||||
if(unit != null){
|
if(unit != null){
|
||||||
threads.run(() -> player.target = unit);
|
threads.run(() -> player.target = unit);
|
||||||
}else{
|
}else{
|
||||||
Tile tile = world.tileWorld(x, y);
|
Tile tile = world.tileWorld(x, y);
|
||||||
if(tile != null) tile = tile.target();
|
if(tile != null) tile = tile.target();
|
||||||
|
|
||||||
if(tile != null && state.teams.areEnemies(player.getTeam(), tile.getTeam())){
|
if(tile != null && state.teams.areEnemies(player.getTeam(), tile.getTeam())){
|
||||||
TileEntity entity = tile.entity;
|
TileEntity entity = tile.entity;
|
||||||
threads.run(() -> player.target = entity);
|
threads.run(() -> player.target = entity);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -555,7 +552,7 @@ public class MobileInput extends InputHandler implements GestureListener{
|
|||||||
//ignore off-screen taps
|
//ignore off-screen taps
|
||||||
if(cursor == null || ui.hasMouse(x, y)) return false;
|
if(cursor == null || ui.hasMouse(x, y)) return false;
|
||||||
|
|
||||||
checkTargets(worldx, worldy);
|
threads.run(() -> checkTargets(worldx, worldy));
|
||||||
|
|
||||||
//remove if request present
|
//remove if request present
|
||||||
if(hasRequest(cursor)){
|
if(hasRequest(cursor)){
|
||||||
|
|||||||
@@ -1,267 +0,0 @@
|
|||||||
package io.anuke.mindustry.maps.generation.pathfinding;
|
|
||||||
|
|
||||||
import com.badlogic.gdx.math.GridPoint2;
|
|
||||||
import com.badlogic.gdx.utils.Array;
|
|
||||||
import com.badlogic.gdx.utils.BinaryHeap;
|
|
||||||
import io.anuke.mindustry.content.fx.Fx;
|
|
||||||
import io.anuke.mindustry.world.Tile;
|
|
||||||
import io.anuke.ucore.core.Effects;
|
|
||||||
import io.anuke.ucore.function.Consumer;
|
|
||||||
import io.anuke.ucore.function.Predicate;
|
|
||||||
import io.anuke.ucore.util.Structs;
|
|
||||||
import io.anuke.ucore.util.Geometry;
|
|
||||||
|
|
||||||
//TODO
|
|
||||||
public class AStarPathFinder extends TilePathfinder{
|
|
||||||
NodeRecord[] records;
|
|
||||||
BinaryHeap<NodeRecord> openList;
|
|
||||||
NodeRecord current;
|
|
||||||
Predicate<Tile> goal;
|
|
||||||
|
|
||||||
private int searchId;
|
|
||||||
private Tile end;
|
|
||||||
|
|
||||||
private static final byte UNVISITED = 0;
|
|
||||||
private static final byte OPEN = 1;
|
|
||||||
private static final byte CLOSED = 2;
|
|
||||||
|
|
||||||
private static final boolean debug = false;
|
|
||||||
|
|
||||||
public AStarPathFinder(Tile[][] tiles) {
|
|
||||||
super(tiles);
|
|
||||||
this.records = new NodeRecord[tiles.length * tiles[0].length];
|
|
||||||
this.openList = new BinaryHeap<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void search(Tile start, Tile end, Array<Tile> out){
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void search(Tile start, Tile end, Predicate<Tile> pred, Array<Tile> out){
|
|
||||||
this.goal = pred;
|
|
||||||
searchNodePath(start, end, out);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean searchNodePath(Tile startNode, Tile endNode, Array<Tile> outPath) {
|
|
||||||
this.end = endNode;
|
|
||||||
|
|
||||||
// Perform AStar
|
|
||||||
boolean found = search(startNode, endNode);
|
|
||||||
|
|
||||||
if (found) {
|
|
||||||
// Create a path made of nodes
|
|
||||||
generateNodePath(startNode, outPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
return found;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean search(Tile startNode, Tile endNode) {
|
|
||||||
|
|
||||||
initSearch(startNode, endNode);
|
|
||||||
|
|
||||||
// Iterate through processing each node
|
|
||||||
do {
|
|
||||||
// Retrieve the node with smallest estimated total cost from the open list
|
|
||||||
current = openList.pop();
|
|
||||||
current.category = CLOSED;
|
|
||||||
|
|
||||||
// Terminate if we reached the goal node
|
|
||||||
if (current.node == endNode || goal.test(current.node)) return true;
|
|
||||||
|
|
||||||
visitChildren(endNode);
|
|
||||||
|
|
||||||
} while (openList.size > 0);
|
|
||||||
|
|
||||||
// We've run out of nodes without finding the goal, so there's no solution
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
public boolean search(PathFinderRequest<Tile> request, long timeToRun) {
|
|
||||||
|
|
||||||
long lastTime = TimeUtils.nanoTime();
|
|
||||||
|
|
||||||
// We have to initialize the search if the status has just changed
|
|
||||||
if (request.statusChanged) {
|
|
||||||
initSearch(request.startNode, request.endNode);
|
|
||||||
request.statusChanged = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Iterate through processing each node
|
|
||||||
do {
|
|
||||||
|
|
||||||
// Check the available time
|
|
||||||
long currentTime = TimeUtils.nanoTime();
|
|
||||||
timeToRun -= currentTime - lastTime;
|
|
||||||
if (timeToRun <= PathFinderQueue.TIME_TOLERANCE) return false;
|
|
||||||
|
|
||||||
// Retrieve the node with smallest estimated total cost from the open list
|
|
||||||
current = openList.pop();
|
|
||||||
current.category = CLOSED;
|
|
||||||
|
|
||||||
// Terminate if we reached the goal node; we've found a path.
|
|
||||||
if (current.node == request.endNode) {
|
|
||||||
request.pathFound = true;
|
|
||||||
|
|
||||||
generateNodePath(request.startNode, request.resultPath);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Visit current node's children
|
|
||||||
visitChildren(request.endNode);
|
|
||||||
|
|
||||||
// Store the current time
|
|
||||||
lastTime = currentTime;
|
|
||||||
|
|
||||||
} while (openList.size > 0);
|
|
||||||
|
|
||||||
// The open list is empty and we've not found a path.
|
|
||||||
request.pathFound = false;
|
|
||||||
return true;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
protected void initSearch(Tile startNode, Tile endNode) {
|
|
||||||
|
|
||||||
// Increment the search id
|
|
||||||
if (++searchId < 0) searchId = 1;
|
|
||||||
|
|
||||||
// Initialize the open list
|
|
||||||
openList.clear();
|
|
||||||
|
|
||||||
// Initialize the record for the start node and add it to the open list
|
|
||||||
NodeRecord startRecord = getNodeRecord(startNode);
|
|
||||||
startRecord.node = startNode;
|
|
||||||
startRecord.from = null;
|
|
||||||
startRecord.costSoFar = 0;
|
|
||||||
addToOpenList(startRecord, estimate(startNode, endNode));
|
|
||||||
|
|
||||||
current = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void visitChildren(Tile endNode) {
|
|
||||||
if(debug) Effects.effect(Fx.spawn, current.node.worldx(), current.node.worldy());
|
|
||||||
|
|
||||||
nodes(current.node, node -> {
|
|
||||||
float addCost = estimate(current.node, node);
|
|
||||||
|
|
||||||
float nodeCost = current.costSoFar + addCost;
|
|
||||||
|
|
||||||
float nodeHeuristic;
|
|
||||||
NodeRecord nodeRecord = getNodeRecord(node);
|
|
||||||
|
|
||||||
if (nodeRecord.category == CLOSED) { // The node is closed
|
|
||||||
|
|
||||||
// If we didn't find a shorter route, skip
|
|
||||||
if (nodeRecord.costSoFar <= nodeCost){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We can use the node's old cost values to calculate its heuristic
|
|
||||||
// without calling the possibly expensive heuristic function
|
|
||||||
nodeHeuristic = nodeRecord.getEstimatedTotalCost() - nodeRecord.costSoFar;
|
|
||||||
} else if (nodeRecord.category == OPEN) { // The node is open
|
|
||||||
|
|
||||||
//If our route is no better, then skip
|
|
||||||
if (nodeRecord.costSoFar <= nodeCost){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove it from the open list (it will be re-added with the new cost)
|
|
||||||
openList.remove(nodeRecord);
|
|
||||||
|
|
||||||
// We can use the node's old cost values to calculate its heuristic
|
|
||||||
// without calling the possibly expensive heuristic function
|
|
||||||
nodeHeuristic = nodeRecord.getEstimatedTotalCost() - nodeRecord.costSoFar;
|
|
||||||
} else { // the node is unvisited
|
|
||||||
|
|
||||||
// We'll need to calculate the heuristic value using the function,
|
|
||||||
// since we don't have a node record with a previously calculated value
|
|
||||||
nodeHeuristic = estimate(node, endNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update node record's cost and connection
|
|
||||||
nodeRecord.costSoFar = nodeCost;
|
|
||||||
nodeRecord.from = current.node;
|
|
||||||
|
|
||||||
// Add it to the open list with the estimated total cost
|
|
||||||
addToOpenList(nodeRecord, nodeCost + nodeHeuristic);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void nodes(Tile current, Consumer<Tile> cons){
|
|
||||||
if(obstacle(current)) return;
|
|
||||||
for(GridPoint2 p : Geometry.d4){
|
|
||||||
int wx = current.x + p.x, wy = current.y + p.y;
|
|
||||||
Tile n = Structs.inBounds(wx, wy, tiles) ? tiles[wx][wy] : null;
|
|
||||||
if(!obstacle(n)) cons.accept(n);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean obstacle(Tile tile){
|
|
||||||
return tile == null || (tile.solid() && end.target() != tile && tile.target() != end) || !tile.block().alwaysReplace;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected float estimate(Tile tile, Tile other){
|
|
||||||
return goal.test(other) || goal.test(tile) ? Float.MIN_VALUE : Math.abs(tile.worldx() - other.worldx()) + Math.abs(tile.worldy() - other.worldy());
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void generateNodePath(Tile startNode, Array<Tile> outPath) {
|
|
||||||
|
|
||||||
// Work back along the path, accumulating nodes
|
|
||||||
outPath.clear();
|
|
||||||
while (current.from != null) {
|
|
||||||
outPath.add(current.node);
|
|
||||||
current = records[(indexOf(current.from))];
|
|
||||||
}
|
|
||||||
outPath.add(startNode);
|
|
||||||
|
|
||||||
// Reverse the path
|
|
||||||
outPath.reverse();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void addToOpenList(NodeRecord nodeRecord, float estimatedTotalCost) {
|
|
||||||
openList.add(nodeRecord, estimatedTotalCost);
|
|
||||||
nodeRecord.category = OPEN;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected NodeRecord getNodeRecord(Tile node) {
|
|
||||||
if(records[indexOf(node)] == null){
|
|
||||||
NodeRecord record = new NodeRecord();
|
|
||||||
record.node = node;
|
|
||||||
record.searchId = searchId;
|
|
||||||
records[indexOf(node)] = record;
|
|
||||||
return record;
|
|
||||||
}else{
|
|
||||||
NodeRecord record = records[indexOf(node)];
|
|
||||||
if(record.searchId != searchId){
|
|
||||||
record.category = UNVISITED;
|
|
||||||
record.searchId = searchId;
|
|
||||||
}
|
|
||||||
return record;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private int indexOf(Tile node){
|
|
||||||
return node.packedPosition();
|
|
||||||
}
|
|
||||||
|
|
||||||
static class NodeRecord extends BinaryHeap.Node {
|
|
||||||
Tile node;
|
|
||||||
Tile from;
|
|
||||||
|
|
||||||
float costSoFar;
|
|
||||||
byte category;
|
|
||||||
|
|
||||||
int searchId;
|
|
||||||
|
|
||||||
public NodeRecord() {
|
|
||||||
super(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public float getEstimatedTotalCost() {
|
|
||||||
return getValue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -26,8 +26,6 @@ import static io.anuke.mindustry.Vars.headless;
|
|||||||
import static io.anuke.mindustry.Vars.ui;
|
import static io.anuke.mindustry.Vars.ui;
|
||||||
|
|
||||||
public class Net{
|
public class Net{
|
||||||
public static final Object packetPoolLock = new Object();
|
|
||||||
|
|
||||||
private static boolean server;
|
private static boolean server;
|
||||||
private static boolean active;
|
private static boolean active;
|
||||||
private static boolean clientLoaded;
|
private static boolean clientLoaded;
|
||||||
@@ -239,16 +237,12 @@ public class Net{
|
|||||||
if(clientLoaded || ((object instanceof Packet) && ((Packet) object).isImportant())){
|
if(clientLoaded || ((object instanceof Packet) && ((Packet) object).isImportant())){
|
||||||
if(clientListeners.get(object.getClass()) != null)
|
if(clientListeners.get(object.getClass()) != null)
|
||||||
clientListeners.get(object.getClass()).accept(object);
|
clientListeners.get(object.getClass()).accept(object);
|
||||||
synchronized(packetPoolLock){
|
Pooling.free(object);
|
||||||
Pooling.free(object);
|
|
||||||
}
|
|
||||||
}else if(!((object instanceof Packet) && ((Packet) object).isUnimportant())){
|
}else if(!((object instanceof Packet) && ((Packet) object).isUnimportant())){
|
||||||
packetQueue.add(object);
|
packetQueue.add(object);
|
||||||
Log.info("Queuing packet {0}", object);
|
Log.info("Queuing packet {0}", object);
|
||||||
}else{
|
}else{
|
||||||
synchronized(packetPoolLock){
|
Pooling.free(object);
|
||||||
Pooling.free(object);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
Log.err("Unhandled packet type: '{0}'!", object);
|
Log.err("Unhandled packet type: '{0}'!", object);
|
||||||
@@ -263,9 +257,7 @@ public class Net{
|
|||||||
if(serverListeners.get(object.getClass()) != null){
|
if(serverListeners.get(object.getClass()) != null){
|
||||||
if(serverListeners.get(object.getClass()) != null)
|
if(serverListeners.get(object.getClass()) != null)
|
||||||
serverListeners.get(object.getClass()).accept(connection, object);
|
serverListeners.get(object.getClass()).accept(connection, object);
|
||||||
synchronized(packetPoolLock){
|
Pooling.free(object);
|
||||||
Pooling.free(object);
|
|
||||||
}
|
|
||||||
}else{
|
}else{
|
||||||
Log.err("Unhandled packet type: '{0}'!", object.getClass());
|
Log.err("Unhandled packet type: '{0}'!", object.getClass());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -153,8 +153,6 @@ public class NetworkIO{
|
|||||||
|
|
||||||
Player player = players[0];
|
Player player = players[0];
|
||||||
|
|
||||||
//TODO !! use map name as the network map in Maps, so getMap() isn't null.
|
|
||||||
|
|
||||||
try(DataInputStream stream = new DataInputStream(is)){
|
try(DataInputStream stream = new DataInputStream(is)){
|
||||||
float timerTime = stream.readFloat();
|
float timerTime = stream.readFloat();
|
||||||
long timestamp = stream.readLong();
|
long timestamp = stream.readLong();
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -19,12 +19,14 @@ import io.anuke.ucore.scene.ui.Image;
|
|||||||
import io.anuke.ucore.scene.ui.layout.Table;
|
import io.anuke.ucore.scene.ui.layout.Table;
|
||||||
import io.anuke.ucore.scene.ui.layout.Unit;
|
import io.anuke.ucore.scene.ui.layout.Unit;
|
||||||
import io.anuke.ucore.util.Bundles;
|
import io.anuke.ucore.util.Bundles;
|
||||||
|
import io.anuke.ucore.util.Timer;
|
||||||
|
|
||||||
import static io.anuke.mindustry.Vars.*;
|
import static io.anuke.mindustry.Vars.*;
|
||||||
|
|
||||||
public class PlayerListFragment extends Fragment{
|
public class PlayerListFragment extends Fragment{
|
||||||
private boolean visible = false;
|
private boolean visible = false;
|
||||||
private Table content = new Table().marginRight(13f).marginLeft(13f);
|
private Table content = new Table().marginRight(13f).marginLeft(13f);
|
||||||
|
private Timer timer = new Timer();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void build(Group parent){
|
public void build(Group parent){
|
||||||
@@ -36,7 +38,7 @@ public class PlayerListFragment extends Fragment{
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(visible && Timers.get("player-list-rebuild", 20)){
|
if(visible && timer.get(20)){
|
||||||
rebuild();
|
rebuild();
|
||||||
content.pack();
|
content.pack();
|
||||||
content.act(Gdx.graphics.getDeltaTime());
|
content.act(Gdx.graphics.getDeltaTime());
|
||||||
@@ -48,8 +50,7 @@ public class PlayerListFragment extends Fragment{
|
|||||||
cont.table("pane", pane -> {
|
cont.table("pane", pane -> {
|
||||||
pane.label(() -> Bundles.format(playerGroup.size() == 1 ? "text.players.single" : "text.players", playerGroup.size()));
|
pane.label(() -> Bundles.format(playerGroup.size() == 1 ? "text.players.single" : "text.players", playerGroup.size()));
|
||||||
pane.row();
|
pane.row();
|
||||||
pane.pane("clear", content)
|
pane.pane("clear", content).grow().get().setScrollingDisabled(true, false);
|
||||||
.grow().get().setScrollingDisabled(true, false);
|
|
||||||
pane.row();
|
pane.row();
|
||||||
|
|
||||||
pane.table("pane", menu -> {
|
pane.table("pane", menu -> {
|
||||||
@@ -71,10 +72,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();
|
||||||
@@ -139,7 +140,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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import io.anuke.mindustry.type.ContentType;
|
|||||||
import io.anuke.mindustry.type.Recipe;
|
import io.anuke.mindustry.type.Recipe;
|
||||||
import io.anuke.mindustry.world.blocks.BuildBlock.BuildEntity;
|
import io.anuke.mindustry.world.blocks.BuildBlock.BuildEntity;
|
||||||
import io.anuke.ucore.core.Events;
|
import io.anuke.ucore.core.Events;
|
||||||
import io.anuke.ucore.entities.Entities;
|
|
||||||
import io.anuke.ucore.util.Geometry;
|
import io.anuke.ucore.util.Geometry;
|
||||||
|
|
||||||
import static io.anuke.mindustry.Vars.*;
|
import static io.anuke.mindustry.Vars.*;
|
||||||
@@ -113,30 +112,9 @@ public class Build{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
rect.setSize(type.size * tilesize, type.size * tilesize);
|
if((type.solid || type.solidifes) &&
|
||||||
rect.setCenter(type.offset() + x * tilesize, type.offset() + y * tilesize);
|
Units.anyEntities(rect.setSize(tilesize * type.size).setCenter(x * tilesize + type.offset(), y * tilesize + type.offset()))){
|
||||||
|
return false;
|
||||||
if(type.solid || type.solidifes){
|
|
||||||
synchronized(Entities.entityLock){
|
|
||||||
try{
|
|
||||||
|
|
||||||
rect.setSize(tilesize * type.size).setCenter(x * tilesize + type.offset(), y * tilesize + type.offset());
|
|
||||||
boolean[] result = {false};
|
|
||||||
|
|
||||||
Units.getNearby(rect, e -> {
|
|
||||||
if(e == null) return; //not sure why this happens?
|
|
||||||
e.getHitbox(hitrect);
|
|
||||||
|
|
||||||
if(rect.overlaps(hitrect) && !e.isFlying()){
|
|
||||||
result[0] = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if(result[0]) return false;
|
|
||||||
}catch(Exception e){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//check for enemy cores
|
//check for enemy cores
|
||||||
|
|||||||
@@ -64,19 +64,15 @@ public class Edges{
|
|||||||
return polygons[(int) (radius * 2) - 1];
|
return polygons[(int) (radius * 2) - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
public static synchronized GridPoint2[] getEdges(int size){
|
public static GridPoint2[] getEdges(int size){
|
||||||
if(size < 0 || size > maxSize) throw new RuntimeException("Block size must be between 0 and " + maxSize);
|
if(size < 0 || size > maxSize) throw new RuntimeException("Block size must be between 0 and " + maxSize);
|
||||||
|
|
||||||
return edges[size - 1];
|
return edges[size - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
public static synchronized GridPoint2[] getInsideEdges(int size){
|
public static GridPoint2[] getInsideEdges(int size){
|
||||||
if(size < 0 || size > maxSize) throw new RuntimeException("Block size must be between 0 and " + maxSize);
|
if(size < 0 || size > maxSize) throw new RuntimeException("Block size must be between 0 and " + maxSize);
|
||||||
|
|
||||||
return edgeInside[size - 1];
|
return edgeInside[size - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
public static synchronized int getEdgeAmount(int size){
|
|
||||||
return getEdges(size).length;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -198,7 +198,7 @@ public class Conveyor extends Block{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void update(Tile tile){
|
public void update(Tile tile){
|
||||||
|
|
||||||
ConveyorEntity entity = tile.entity();
|
ConveyorEntity entity = tile.entity();
|
||||||
entity.minitem = 1f;
|
entity.minitem = 1f;
|
||||||
@@ -274,7 +274,7 @@ public class Conveyor extends Block{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized int removeStack(Tile tile, Item item, int amount){
|
public int removeStack(Tile tile, Item item, int amount){
|
||||||
ConveyorEntity entity = tile.entity();
|
ConveyorEntity entity = tile.entity();
|
||||||
entity.noSleep();
|
entity.noSleep();
|
||||||
int removed = 0;
|
int removed = 0;
|
||||||
@@ -300,13 +300,13 @@ public class Conveyor extends Block{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized int acceptStack(Item item, int amount, Tile tile, Unit source){
|
public int acceptStack(Item item, int amount, Tile tile, Unit source){
|
||||||
ConveyorEntity entity = tile.entity();
|
ConveyorEntity entity = tile.entity();
|
||||||
return Math.min((int)(entity.minitem / itemSpace), amount);
|
return Math.min((int)(entity.minitem / itemSpace), amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void handleStack(Item item, int amount, Tile tile, Unit source){
|
public void handleStack(Item item, int amount, Tile tile, Unit source){
|
||||||
ConveyorEntity entity = tile.entity();
|
ConveyorEntity entity = tile.entity();
|
||||||
|
|
||||||
for(int i = amount - 1; i >= 0; i--){
|
for(int i = amount - 1; i >= 0; i--){
|
||||||
|
|||||||
@@ -9,8 +9,6 @@ import io.anuke.ucore.util.Pooling;
|
|||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
import static io.anuke.mindustry.net.Net.packetPoolLock;
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public class ByteSerializer implements Serialization {
|
public class ByteSerializer implements Serialization {
|
||||||
|
|
||||||
@@ -36,11 +34,9 @@ public class ByteSerializer implements Serialization {
|
|||||||
if(id == -2){
|
if(id == -2){
|
||||||
return FrameworkSerializer.read(byteBuffer);
|
return FrameworkSerializer.read(byteBuffer);
|
||||||
}else{
|
}else{
|
||||||
synchronized (packetPoolLock) {
|
Packet packet = Pooling.obtain((Class<Packet>) Registrator.getByID(id).type, (Supplier<Packet>) Registrator.getByID(id).constructor);
|
||||||
Packet packet = Pooling.obtain((Class<Packet>) Registrator.getByID(id).type, (Supplier<Packet>) Registrator.getByID(id).constructor);
|
packet.read(byteBuffer);
|
||||||
packet.read(byteBuffer);
|
return packet;
|
||||||
return packet;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ import java.nio.ByteBuffer;
|
|||||||
import java.nio.channels.ClosedSelectorException;
|
import java.nio.channels.ClosedSelectorException;
|
||||||
|
|
||||||
import static io.anuke.mindustry.Vars.*;
|
import static io.anuke.mindustry.Vars.*;
|
||||||
import static io.anuke.mindustry.net.Net.packetPoolLock;
|
|
||||||
|
|
||||||
public class KryoClient implements ClientProvider{
|
public class KryoClient implements ClientProvider{
|
||||||
Client client;
|
Client client;
|
||||||
@@ -159,9 +158,7 @@ public class KryoClient implements ClientProvider{
|
|||||||
client.sendUDP(object);
|
client.sendUDP(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized (packetPoolLock) {
|
Pooling.free(object);
|
||||||
Pooling.free(object);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
Reference in New Issue
Block a user