TiledFloor and TiledWall implementation classes
This commit is contained in:
@@ -32,18 +32,18 @@ public class World{
|
|||||||
|
|
||||||
public Tiles tiles = new Tiles(0, 0);
|
public Tiles tiles = new Tiles(0, 0);
|
||||||
/** The number of times tiles have changed in this session. Used for blocks that need to poll world state, but not frequently. */
|
/** The number of times tiles have changed in this session. Used for blocks that need to poll world state, but not frequently. */
|
||||||
public int tileChanges = -1;
|
public int tileChanges = 1, floorChanges = 1;
|
||||||
|
|
||||||
private boolean generating, invalidMap;
|
private boolean generating, invalidMap;
|
||||||
private ObjectMap<Map, Runnable> customMapLoaders = new ObjectMap<>();
|
private ObjectMap<Map, Runnable> customMapLoaders = new ObjectMap<>();
|
||||||
|
|
||||||
public World(){
|
public World(){
|
||||||
Events.on(TileChangeEvent.class, e -> {
|
Events.on(TileChangeEvent.class, e -> tileChanges ++);
|
||||||
tileChanges ++;
|
Events.on(TileFloorChangeEvent.class, e -> floorChanges ++);
|
||||||
});
|
|
||||||
|
|
||||||
Events.on(WorldLoadEvent.class, e -> {
|
Events.on(WorldLoadEvent.class, e -> {
|
||||||
tileChanges = -1;
|
tileChanges = -1;
|
||||||
|
floorChanges = -1;
|
||||||
|
|
||||||
//make each building check if it can update in the given map area
|
//make each building check if it can update in the given map area
|
||||||
for(var build : Groups.build){
|
for(var build : Groups.build){
|
||||||
|
|||||||
@@ -36,6 +36,8 @@ public class EditorTile extends Tile{
|
|||||||
|
|
||||||
op(DrawOperation.opFloor, floor.id);
|
op(DrawOperation.opFloor, floor.id);
|
||||||
|
|
||||||
|
world.floorChanges ++;
|
||||||
|
|
||||||
this.floor = type;
|
this.floor = type;
|
||||||
type.floorChanged(this);
|
type.floorChanged(this);
|
||||||
}
|
}
|
||||||
@@ -85,6 +87,10 @@ public class EditorTile extends Tile{
|
|||||||
if(build != null){
|
if(build != null){
|
||||||
build.wasVisible = true;
|
build.wasVisible = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
world.tileChanges ++;
|
||||||
|
|
||||||
|
type.blockChanged(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -112,6 +118,10 @@ public class EditorTile extends Tile{
|
|||||||
if(this.overlay == overlay) return;
|
if(this.overlay == overlay) return;
|
||||||
op(DrawOperation.opOverlay, this.overlay.id);
|
op(DrawOperation.opOverlay, this.overlay.id);
|
||||||
super.setOverlay(overlay);
|
super.setOverlay(overlay);
|
||||||
|
|
||||||
|
world.floorChanges ++;
|
||||||
|
|
||||||
|
((Floor)overlay).floorChanged(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -938,6 +938,8 @@ public class LExecutor{
|
|||||||
exec.graphicsBuffer.add(DisplayCmd.get(LogicDisplay.commandPrint, packSign(curX + xOffset), packSign(curY + yOffset), next, 0, 0, 0));
|
exec.graphicsBuffer.add(DisplayCmd.get(LogicDisplay.commandPrint, packSign(curX + xOffset), packSign(curY + yOffset), next, 0, 0, 0));
|
||||||
}
|
}
|
||||||
curX += advance;
|
curX += advance;
|
||||||
|
|
||||||
|
if(exec.graphicsBuffer.size >= maxGraphicsBuffer) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
exec.textBuffer.setLength(0);
|
exec.textBuffer.setLength(0);
|
||||||
@@ -1010,7 +1012,7 @@ public class LExecutor{
|
|||||||
if(value.isobj){
|
if(value.isobj){
|
||||||
String strValue = toString(value.objval);
|
String strValue = toString(value.objval);
|
||||||
|
|
||||||
exec.textBuffer.append(strValue);
|
exec.textBuffer.append(strValue, 0, Math.min(strValue.length(), maxTextBuffer - exec.textBuffer.length()));
|
||||||
}else{
|
}else{
|
||||||
//display integer version when possible
|
//display integer version when possible
|
||||||
if(Math.abs(value.numval - Math.round(value.numval)) < 0.00001){
|
if(Math.abs(value.numval - Math.round(value.numval)) < 0.00001){
|
||||||
@@ -1122,7 +1124,6 @@ public class LExecutor{
|
|||||||
if(target.building() instanceof MessageBuild d && d.isValid() && (exec.privileged || (d.team == exec.team && !d.block.privileged))){
|
if(target.building() instanceof MessageBuild d && d.isValid() && (exec.privileged || (d.team == exec.team && !d.block.privileged))){
|
||||||
d.message.setLength(0);
|
d.message.setLength(0);
|
||||||
d.message.append(exec.textBuffer, 0, Math.min(exec.textBuffer.length(), maxTextBuffer));
|
d.message.append(exec.textBuffer, 0, Math.min(exec.textBuffer.length(), maxTextBuffer));
|
||||||
|
|
||||||
}
|
}
|
||||||
exec.textBuffer.setLength(0);
|
exec.textBuffer.setLength(0);
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ public class Tiles implements Iterable<Tile>{
|
|||||||
final Puddle[] puddles;
|
final Puddle[] puddles;
|
||||||
final Fire[] fires;
|
final Fire[] fires;
|
||||||
|
|
||||||
|
@Nullable long[] tmpFloorState, tmpBlockState;
|
||||||
|
|
||||||
public Tiles(int width, int height){
|
public Tiles(int width, int height){
|
||||||
this.array = new Tile[width * height];
|
this.array = new Tile[width * height];
|
||||||
this.width = width;
|
this.width = width;
|
||||||
@@ -24,6 +26,24 @@ public class Tiles implements Iterable<Tile>{
|
|||||||
this.fires = new Fire[width * height];
|
this.fires = new Fire[width * height];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long getTmpFloorState(int pos){
|
||||||
|
return tmpFloorState == null ? 0 : tmpFloorState[pos];
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTmpFloorState(int pos, long value){
|
||||||
|
if(tmpFloorState == null || tmpFloorState.length != array.length) tmpFloorState = new long[array.length];
|
||||||
|
tmpFloorState[pos] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getTmpBlockState(int pos){
|
||||||
|
return tmpBlockState == null ? 0 : tmpBlockState[pos];
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTmpBlockState(int pos, long value){
|
||||||
|
if(tmpBlockState == null || tmpBlockState.length != array.length) tmpBlockState = new long[array.length];
|
||||||
|
tmpBlockState[pos] = value;
|
||||||
|
}
|
||||||
|
|
||||||
public Puddle getPuddle(int pos){
|
public Puddle getPuddle(int pos){
|
||||||
return puddles[pos];
|
return puddles[pos];
|
||||||
}
|
}
|
||||||
|
|||||||
131
core/src/mindustry/world/blocks/environment/TiledFloor.java
Normal file
131
core/src/mindustry/world/blocks/environment/TiledFloor.java
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
package mindustry.world.blocks.environment;
|
||||||
|
|
||||||
|
import arc.*;
|
||||||
|
import arc.graphics.g2d.*;
|
||||||
|
import arc.math.*;
|
||||||
|
import mindustry.annotations.Annotations.*;
|
||||||
|
import mindustry.gen.*;
|
||||||
|
import mindustry.world.*;
|
||||||
|
|
||||||
|
import static mindustry.Vars.*;
|
||||||
|
|
||||||
|
public class TiledFloor extends Floor{
|
||||||
|
public TextureRegion[][][][] sizedRegions;
|
||||||
|
public int maxSize = 3;
|
||||||
|
|
||||||
|
public TiledFloor(String name){
|
||||||
|
super(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TiledFloor(String name, int variants, int maxSize){
|
||||||
|
super(name);
|
||||||
|
this.variants = variants;
|
||||||
|
this.maxSize = maxSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void load(){
|
||||||
|
super.load();
|
||||||
|
|
||||||
|
sizedRegions = new TextureRegion[maxSize + 1][variants][][];
|
||||||
|
|
||||||
|
for(int size = 1; size <= maxSize; size++){
|
||||||
|
for(int v = 0; v < variants; v++){
|
||||||
|
TextureRegion base = Core.atlas.find(name + "-" + size + "-" + v);
|
||||||
|
int actualSize = size;
|
||||||
|
if(!base.found()) base = Core.atlas.find(name + "-" + size);
|
||||||
|
if(!base.found()){
|
||||||
|
actualSize = 1; //the 1x1 sprite should not be split like a larger region
|
||||||
|
base = region;
|
||||||
|
}
|
||||||
|
|
||||||
|
sizedRegions[size][v] = base.split(base.width / actualSize, base.height / actualSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
long state(Tile tile){
|
||||||
|
return world.tiles.getTmpFloorState(tile.array());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void floorChanged(Tile tile){
|
||||||
|
|
||||||
|
if(TiledState.changes(state(tile)) != world.floorChanges && !world.isGenerating()){
|
||||||
|
scan(tile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void scan(Tile tile){
|
||||||
|
//max size possible
|
||||||
|
int size = maxSize;
|
||||||
|
int changes = world.floorChanges;
|
||||||
|
boolean isOverlay = tile.floor() != this;
|
||||||
|
|
||||||
|
//scan to the top right for the biggest size possible
|
||||||
|
for(int cx = 0; cx < size; cx++){
|
||||||
|
for(int cy = 0; cy < size; cy++){
|
||||||
|
Tile other = tile.nearby(cx, cy);
|
||||||
|
if(other == null || ((isOverlay ? other.overlay() : other.floor()) != this) || TiledState.changes(state(other)) == changes){
|
||||||
|
int max = Math.max(cx, cy);
|
||||||
|
size = Math.min(max, size);
|
||||||
|
size = Math.min(max, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//assign roots based on max value
|
||||||
|
for(int cx = 0; cx < size; cx++){
|
||||||
|
for(int cy = 0; cy < size; cy++){
|
||||||
|
Tile other = tile.nearby(cx, cy);
|
||||||
|
if(other != null){
|
||||||
|
long otherState = state(other);
|
||||||
|
|
||||||
|
if(!headless && TiledState.changes(otherState) != 0){
|
||||||
|
Tile otherRoot = other.nearby(-TiledState.x(otherState), -TiledState.y(otherState));
|
||||||
|
if(otherRoot != null){
|
||||||
|
Core.app.post(() -> renderer.blocks.floor.recacheTile(otherRoot));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//mark as updated
|
||||||
|
world.tiles.setTmpFloorState(other.array(), TiledState.get(cx, cy, size, changes));
|
||||||
|
if(!headless && otherState != 0){
|
||||||
|
Core.app.post(() -> renderer.blocks.floor.recacheTile(other));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void drawMain(Tile tile){
|
||||||
|
long state = state(tile);
|
||||||
|
//stale state, start scanning.
|
||||||
|
if(TiledState.changes(state) != world.floorChanges){
|
||||||
|
scan(tile);
|
||||||
|
//state has most likely updated
|
||||||
|
state = state(tile);
|
||||||
|
}
|
||||||
|
|
||||||
|
int size = Mathf.clamp(TiledState.size(state), 1, maxSize);
|
||||||
|
int cx = TiledState.x(state), cy = TiledState.y(state);
|
||||||
|
int variant = variant(tile.x - cx, tile.y - cy, variants);
|
||||||
|
|
||||||
|
TextureRegion[][] regions = sizedRegions[size][variant];
|
||||||
|
|
||||||
|
Draw.rect(regions[Mathf.clamp(cx, 0, regions.length - 1)][Mathf.clamp(size - 1 - cy, 0, regions[0].length - 1)], tile.worldx(), tile.worldy());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Struct
|
||||||
|
class TiledStateStruct{
|
||||||
|
@StructField(4)
|
||||||
|
int x;
|
||||||
|
@StructField(4)
|
||||||
|
int y;
|
||||||
|
@StructField(8)
|
||||||
|
int size;
|
||||||
|
|
||||||
|
int changes;
|
||||||
|
}
|
||||||
|
}
|
||||||
118
core/src/mindustry/world/blocks/environment/TiledWall.java
Normal file
118
core/src/mindustry/world/blocks/environment/TiledWall.java
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
package mindustry.world.blocks.environment;
|
||||||
|
|
||||||
|
import arc.*;
|
||||||
|
import arc.graphics.g2d.*;
|
||||||
|
import arc.math.*;
|
||||||
|
import mindustry.gen.*;
|
||||||
|
import mindustry.world.*;
|
||||||
|
|
||||||
|
import static mindustry.Vars.*;
|
||||||
|
|
||||||
|
public class TiledWall extends StaticWall{
|
||||||
|
public TextureRegion[][][][] sizedRegions;
|
||||||
|
public int maxSize = 3;
|
||||||
|
|
||||||
|
public TiledWall(String name){
|
||||||
|
super(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TiledWall(String name, int variants, int maxSize){
|
||||||
|
super(name);
|
||||||
|
this.variants = variants;
|
||||||
|
this.maxSize = maxSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void load(){
|
||||||
|
super.load();
|
||||||
|
|
||||||
|
sizedRegions = new TextureRegion[maxSize + 1][variants][][];
|
||||||
|
|
||||||
|
for(int size = 1; size <= maxSize; size++){
|
||||||
|
for(int v = 0; v < variants; v++){
|
||||||
|
TextureRegion base = Core.atlas.find(name + "-" + size + "-" + v);
|
||||||
|
int actualSize = size;
|
||||||
|
if(!base.found()) base = Core.atlas.find(name + "-" + size);
|
||||||
|
if(!base.found()){
|
||||||
|
actualSize = 1; //the 1x1 sprite should not be split like a larger region
|
||||||
|
base = region;
|
||||||
|
}
|
||||||
|
|
||||||
|
sizedRegions[size][v] = base.split(base.width / actualSize, base.height / actualSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
long state(Tile tile){
|
||||||
|
return world.tiles.getTmpBlockState(tile.array());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void blockChanged(Tile tile){
|
||||||
|
super.blockChanged(tile);
|
||||||
|
|
||||||
|
if(TiledState.changes(state(tile)) != world.tileChanges && !world.isGenerating()){
|
||||||
|
scan(tile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void scan(Tile tile){
|
||||||
|
//max size possible
|
||||||
|
int size = maxSize;
|
||||||
|
int changes = world.tileChanges;
|
||||||
|
|
||||||
|
//scan to the top right for the biggest size possible
|
||||||
|
for(int cx = 0; cx < size; cx++){
|
||||||
|
for(int cy = 0; cy < size; cy++){
|
||||||
|
Tile other = tile.nearby(cx, cy);
|
||||||
|
if(other == null || other.block() != this || TiledState.changes(state(other)) == changes){
|
||||||
|
int max = Math.max(cx, cy);
|
||||||
|
size = Math.min(max, size);
|
||||||
|
size = Math.min(max, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//assign roots based on max value
|
||||||
|
for(int cx = 0; cx < size; cx++){
|
||||||
|
for(int cy = 0; cy < size; cy++){
|
||||||
|
Tile other = tile.nearby(cx, cy);
|
||||||
|
if(other != null){
|
||||||
|
long otherState = state(other);
|
||||||
|
|
||||||
|
if(!headless && TiledState.changes(otherState) != 0){
|
||||||
|
Tile otherRoot = other.nearby(-TiledState.x(otherState), -TiledState.y(otherState));
|
||||||
|
if(otherRoot != null){
|
||||||
|
Core.app.post(() -> renderer.blocks.floor.recacheTile(otherRoot));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//mark as updated
|
||||||
|
world.tiles.setTmpBlockState(other.array(), TiledState.get(cx, cy, size, changes));
|
||||||
|
if(!headless && otherState != 0){
|
||||||
|
Core.app.post(() -> renderer.blocks.floor.recacheTile(other));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void drawBase(Tile tile){
|
||||||
|
long state = state(tile);
|
||||||
|
//stale state, start scanning.
|
||||||
|
if(TiledState.changes(state) != world.tileChanges){
|
||||||
|
scan(tile);
|
||||||
|
//state has most likely updated
|
||||||
|
state = state(tile);
|
||||||
|
}
|
||||||
|
|
||||||
|
int size = Mathf.clamp(TiledState.size(state), 1, maxSize);
|
||||||
|
int cx = TiledState.x(state), cy = TiledState.y(state);
|
||||||
|
int variant = variant(tile.x - cx, tile.y - cy, variants);
|
||||||
|
|
||||||
|
TextureRegion[][] regions = sizedRegions[size][variant];
|
||||||
|
|
||||||
|
Draw.rect(regions[Mathf.clamp(cx, 0, regions.length - 1)][Mathf.clamp(size - 1 - cy, 0, regions[0].length - 1)], tile.worldx(), tile.worldy());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -24,7 +24,7 @@ import static mindustry.Vars.*;
|
|||||||
|
|
||||||
public class MessageBlock extends Block{
|
public class MessageBlock extends Block{
|
||||||
//don't change this too much unless you want to run into issues with packet sizes
|
//don't change this too much unless you want to run into issues with packet sizes
|
||||||
public int maxTextLength = 220;
|
public int maxTextLength = 300;
|
||||||
public int maxNewlines = 24;
|
public int maxNewlines = 24;
|
||||||
|
|
||||||
public MessageBlock(String name){
|
public MessageBlock(String name){
|
||||||
|
|||||||
Reference in New Issue
Block a user