From cf02a75846c4d823c272094f087412ae11183c33 Mon Sep 17 00:00:00 2001 From: Anuken Date: Fri, 5 Jun 2020 13:23:24 -0400 Subject: [PATCH] Support for schematic random rotation --- core/assets/baseparts/1591368647700.msch | 2 + core/assets/baseparts/1591368658042.msch | 4 + core/assets/baseparts/1591368707268.msch | 2 + core/assets/baseparts/1591368730003.msch | 2 + core/assets/baseparts/1591368779629.msch | Bin 0 -> 201 bytes core/assets/baseparts/1591369683871.msch | Bin 0 -> 295 bytes core/assets/baseparts/1591369726023.msch | Bin 0 -> 94 bytes core/src/mindustry/ai/BaseRegistry.java | 23 +++ core/src/mindustry/game/Schematic.java | 21 ++- .../maps/generators/BaseGenerator.java | 172 +++++++++++++----- gradle.properties | 2 +- 11 files changed, 180 insertions(+), 48 deletions(-) create mode 100644 core/assets/baseparts/1591368647700.msch create mode 100644 core/assets/baseparts/1591368658042.msch create mode 100644 core/assets/baseparts/1591368707268.msch create mode 100644 core/assets/baseparts/1591368730003.msch create mode 100644 core/assets/baseparts/1591368779629.msch create mode 100644 core/assets/baseparts/1591369683871.msch create mode 100644 core/assets/baseparts/1591369726023.msch diff --git a/core/assets/baseparts/1591368647700.msch b/core/assets/baseparts/1591368647700.msch new file mode 100644 index 0000000000..4235369db1 --- /dev/null +++ b/core/assets/baseparts/1591368647700.msch @@ -0,0 +1,2 @@ +mschx- + EUB>ć}aZՍv 9$|&Lj{(N}|J."̱QvG5}}5yG[Be. "ꒁSIPƊaΙ -hY +zd:hAM \ No newline at end of file diff --git a/core/assets/baseparts/1591368658042.msch b/core/assets/baseparts/1591368658042.msch new file mode 100644 index 0000000000..d1e42464a1 --- /dev/null +++ b/core/assets/baseparts/1591368658042.msch @@ -0,0 +1,4 @@ +mschx% + EZB>ė2[Օr)!9 L + 8bue_?fVӻR1O9"c}-֔3E +07,y+aJHgׁ71@sXFoHIc \ No newline at end of file diff --git a/core/assets/baseparts/1591368707268.msch b/core/assets/baseparts/1591368707268.msch new file mode 100644 index 0000000000..ee88f4b397 --- /dev/null +++ b/core/assets/baseparts/1591368707268.msch @@ -0,0 +1,2 @@ +mschx%L + <*A>ħ}kC+VߟYIrw%`<0or!%lq1+\M3܎PWk,UK0o}.aeF%uKAwB*?X=V"5~[ \ No newline at end of file diff --git a/core/assets/baseparts/1591368730003.msch b/core/assets/baseparts/1591368730003.msch new file mode 100644 index 0000000000..f7974af4e2 --- /dev/null +++ b/core/assets/baseparts/1591368730003.msch @@ -0,0 +1,2 @@ +mschx%L + <*A>ķkC+VߟYIrw%`<0or!%lq1+\M3܎PWk,UK0o}.aeF%uKAwB*?X=V"5~[ \ No newline at end of file diff --git a/core/assets/baseparts/1591368779629.msch b/core/assets/baseparts/1591368779629.msch new file mode 100644 index 0000000000000000000000000000000000000000..2254a17355ab9412ce9520980b5e099468dfa012 GIT binary patch literal 201 zcmc~TPR?Mgn4{ZwFzASafQxinE9;lwZx0Ugdu8TjZxZFN+cRy(!${3b2A6H~zpU{N zxHYXm^x@T%(;t`p+j)Qb<8Kk$zOMUrWB;|s+upuky=3}l4J|g-{jEP|{{PqQW|%px zrDbN|9<}_Q_lA4S>z>Z^P@80E^ei|=DM@5Ux8V3~#_|KQ-t2## LJg}D*5WfKcMB!x_ literal 0 HcmV?d00001 diff --git a/core/assets/baseparts/1591369683871.msch b/core/assets/baseparts/1591369683871.msch new file mode 100644 index 0000000000000000000000000000000000000000..6a03cd7f4e983d7bbed6704f87de0ef79cd6aec6 GIT binary patch literal 295 zcmc~TPR?MgnBzMkJFnS5poLvpT3uj~%#l~?726=*I52eFks)Q;K!GaSMr^#FMIsrxZYi+SM_>RzUN6K2H&|hpVU;H)Y z6)LNpV|OUrr{MkVE9;%-T(}oxe!t!Hhh=MOV{Fo`?)#St_OkvD5Ar^DSijJ_mf?ev zzDNk8oGWisSNn7|lUBBVt*2QFcr?nkG_)=ZO)M7{+a)4nER~^r!#H={<}D^#Wu{Ck ziIrg`YitWpY2ls Dwq=G+ literal 0 HcmV?d00001 diff --git a/core/assets/baseparts/1591369726023.msch b/core/assets/baseparts/1591369726023.msch new file mode 100644 index 0000000000000000000000000000000000000000..eb87221260f456bde627734026b422617b339e65 GIT binary patch literal 94 zcmc~TPR?Mgn4{X|&DWqH;B4Knq2QtCjY`F)%?gYrHSgB<==*-YBqBB~Axnd&xGrOd z++m431vXRDIh9@Ow@xwsX0qc)-FY#|hUNtsSG$;U88U^YU)3@E@BN3BIYYn)03y*Q A-~a#s literal 0 HcmV?d00001 diff --git a/core/src/mindustry/ai/BaseRegistry.java b/core/src/mindustry/ai/BaseRegistry.java index 7161995c3a..b2fa4f29dc 100644 --- a/core/src/mindustry/ai/BaseRegistry.java +++ b/core/src/mindustry/ai/BaseRegistry.java @@ -8,12 +8,15 @@ import mindustry.game.*; import mindustry.game.Schematic.*; import mindustry.type.*; import mindustry.world.*; +import mindustry.world.blocks.production.*; import mindustry.world.blocks.sandbox.*; import mindustry.world.blocks.storage.*; import mindustry.world.meta.*; import java.io.*; +import static mindustry.Vars.tilesize; + public class BaseRegistry{ public Array cores = new Array<>(); public Array parts = new Array<>(); @@ -35,6 +38,8 @@ public class BaseRegistry{ Schematic schem = Schematics.read(Core.files.internal("baseparts/" + name)); BasePart part = new BasePart(schem); + Tmp.v1.setZero(); + int drills = 0; for(Stile tile : schem.tiles){ //make note of occupied positions @@ -56,6 +61,12 @@ public class BaseRegistry{ Liquid config = (Liquid)tile.config; if(config != null) part.requiredLiquid = config; } + + //calculate averages + if(tile.block instanceof Drill){ + Tmp.v1.add(tile.x*tilesize + tile.block.offset(), tile.y*tilesize + tile.block.offset()); + drills ++; + } } schem.tiles.removeAll(s -> s.block.buildVisibility == BuildVisibility.sandboxOnly); @@ -63,6 +74,15 @@ public class BaseRegistry{ (part.core != null ? cores : parts).add(part); + if(drills > 0){ + Tmp.v1.scl(1f / drills).scl(1f / tilesize); + part.centerX = (int)Tmp.v1.x; + part.centerY = (int)Tmp.v1.y; + }else{ + part.centerX = part.schematic.width/2; + part.centerY = part.schematic.height/2; + } + if(part.requiredItem != null){ itemParts.get(part.requiredItem, Array::new).add(part); } @@ -80,6 +100,9 @@ public class BaseRegistry{ public final Schematic schematic; public final GridBits occupied; + //offsets for drills + public int centerX, centerY; + public @Nullable Liquid requiredLiquid; public @Nullable Item requiredItem; public @Nullable Block core; diff --git a/core/src/mindustry/game/Schematic.java b/core/src/mindustry/game/Schematic.java index eeeda0fbd7..f573c8d029 100644 --- a/core/src/mindustry/game/Schematic.java +++ b/core/src/mindustry/game/Schematic.java @@ -1,10 +1,11 @@ package mindustry.game; +import arc.files.*; import arc.struct.*; import arc.struct.IntIntMap.*; -import arc.files.*; import arc.util.ArcAnnotate.*; import mindustry.*; +import mindustry.content.*; import mindustry.mod.Mods.*; import mindustry.type.*; import mindustry.world.*; @@ -125,5 +126,23 @@ public class Schematic implements Publishable, Comparable{ this.config = config; this.rotation = rotation; } + + //pooling only + public Stile(){ + block = Blocks.air; + } + + public Stile set(Stile other){ + block = other.block; + x = other.x; + y = other.y; + config = other.config; + rotation = other.rotation; + return this; + } + + public Stile copy(){ + return new Stile(block, x, y, config, rotation); + } } } diff --git a/core/src/mindustry/maps/generators/BaseGenerator.java b/core/src/mindustry/maps/generators/BaseGenerator.java index 5607036a1b..e708bfe255 100644 --- a/core/src/mindustry/maps/generators/BaseGenerator.java +++ b/core/src/mindustry/maps/generators/BaseGenerator.java @@ -3,8 +3,10 @@ package mindustry.maps.generators; import arc.math.*; import arc.math.geom.*; import arc.struct.*; +import arc.util.pooling.*; import mindustry.ai.BaseRegistry.*; import mindustry.content.*; +import mindustry.entities.units.*; import mindustry.game.*; import mindustry.game.Schematic.*; import mindustry.gen.*; @@ -17,6 +19,10 @@ import mindustry.world.blocks.production.*; import static mindustry.Vars.*; public class BaseGenerator{ + private static final Schematic tmpSchem = new Schematic(new Array<>(), new StringMap(), 0, 0); + private static final Schematic tmpSchem2 = new Schematic(new Array<>(), new StringMap(), 0, 0); + private static final Vec2 axis = new Vec2(), rotator = new Vec2(); + private Tiles tiles; private Team team; private ObjectMap ores = new ObjectMap<>(); @@ -36,12 +42,12 @@ public class BaseGenerator{ float bracket = 0.1f; int range = 200; - int wallAngle = 180; + int wallAngle = 70; //180 for full coverage BasePart coreschem = bases.cores.getFrac(bracket); Block wall = wallsSmall.getFrac(bracket), wallLarge = wallsLarge.getFrac(bracket); - //TODO random flipping and rotation + //TODO random rotation for(Tile tile : cores){ tile.clearOverlay(); @@ -67,67 +73,81 @@ public class BaseGenerator{ }); } - //second pass: small walls - for(Tile core : cores){ - core.circle(range, (x, y) -> { - Tile tile = tiles.getn(x, y); - if(tile.block().alwaysReplace){ - boolean any = false; + if(wallAngle > 0){ + //second pass: small walls + for(Tile core : cores){ + core.circle(range, (x, y) -> { + Tile tile = tiles.getn(x, y); + if(tile.block().alwaysReplace){ + boolean any = false; - for(Point2 p : Geometry.d8){ - if(Angles.angleDist(Angles.angle(p.x, p.y), spawn.angleTo(core)) > wallAngle){ - continue; + for(Point2 p : Geometry.d8){ + if(Angles.angleDist(Angles.angle(p.x, p.y), spawn.angleTo(core)) > wallAngle){ + continue; + } + + Tile o = tiles.get(tile.x + p.x, tile.y + p.y); + if(o != null && o.team() == team && !(o.block() instanceof Wall)){ + any = true; + break; + } } - Tile o = tiles.get(tile.x + p.x, tile.y + p.y); - if(o != null && o.team() == team && !(o.block() instanceof Wall)){ - any = true; - break; + if(any){ + tile.setBlock(wall, team); + } + } + }); + } + + //third pass: large walls + for(Tile core : cores){ + core.circle(range, (x, y) -> { + int walls = 0; + for(int cx = 0; cx < 2; cx++){ + for(int cy = 0; cy < 2; cy++){ + Tile tile = tiles.get(x + cx, y + cy); + if(tile == null || tile.block().size != 1 || (tile.block() != wall && !tile.block().alwaysReplace)) return; + + if(tile.block() == wall){ + walls ++; + } } } - if(any){ - tile.setBlock(wall, team); + if(walls >= 3){ + tiles.getn(x, y).setBlock(wallLarge, team); } - } - }); - } - - //third pass: large walls - for(Tile core : cores){ - core.circle(range, (x, y) -> { - int walls = 0; - for(int cx = 0; cx < 2; cx++){ - for(int cy = 0; cy < 2; cy++){ - Tile tile = tiles.get(x + cx, y + cy); - if(tile == null || tile.block().size != 1 || (tile.block() != wall && !tile.block().alwaysReplace)) return; - - if(tile.block() == wall){ - walls ++; - } - } - } - - if(walls >= 3){ - tiles.getn(x, y).setBlock(wallLarge, team); - } - }); + }); + } } } boolean tryPlace(BasePart part, int x, int y){ - int cx = x - part.schematic.width/2, cy = y - part.schematic.height/2; - for(int rx = cx; rx <= cx + part.schematic.width; rx++){ - for(int ry = cy; ry <= cy + part.schematic.height; ry++){ + int rotation = 0; + axis.set((int)(part.schematic.width / 2f), (int)(part.schematic.height / 2f)); + Schematic result = rotate(part.schematic, rotation); + + rotator.set(part.centerX, part.centerY).rotateAround(axis, rotation * 90); + int cx = x - (int)rotator.x; + int cy = y - (int)rotator.y; + + for(int rx = cx; rx <= cx + result.width; rx++){ + for(int ry = cy; ry <= cy + result.height; ry++){ Tile tile = tiles.get(rx, ry); - if(tile == null || ((!tile.block().alwaysReplace || world.getDarkness(rx, ry) > 0) && part.occupied.get(rx - cx, ry - cy))){ + int ox = rx - cx, oy = ry - cy; + rotator.set(ox, oy).rotateAround(axis, rotation * 90); + ox = (int)rotator.x; + oy = (int)rotator.y; + + if(tile == null || ((!tile.block().alwaysReplace || world.getDarkness(rx, ry) > 0) && part.occupied.get(ox, oy))){ return false; } } } if(part.requiredItem != null){ - for(Stile tile : part.schematic.tiles){ + for(Stile tile : result.tiles){ if(tile.block instanceof Drill){ tile.block.iterateTaken(tile.x + cx, tile.y + cy, (ex, ey) -> { tiles.getn(ex, ey).setOverlay(ores.get(part.requiredItem)); @@ -136,8 +156,68 @@ public class BaseGenerator{ } } - Schematics.place(part.schematic, x, y, team); + Schematics.place(result, cx + result.width/2, cy + result.height/2, team); return true; } + + Schematic rotate(Schematic input, int times){ + if(times == 0) return input; + + boolean sign = times < 0; + for(int i = 0; i < Math.abs(times); i++){ + input = rotated(input, sign); + } + return input; + } + + Schematic rotated(Schematic input, boolean counter){ + int direction = Mathf.sign(counter); + Schematic schem = input == tmpSchem ? tmpSchem2 : tmpSchem2; + schem.width = input.width; + schem.height = input.height; + Pools.freeAll(schem.tiles); + schem.tiles.clear(); + for(Stile tile : input.tiles){ + schem.tiles.add(Pools.obtain(Stile.class, Stile::new).set(tile)); + } + + int ox = schem.width/2, oy = schem.height/2; + + schem.tiles.each(req -> { + req.config = BuildRequest.pointConfig(req.config, p -> { + int cx = p.x, cy = p.y; + int lx = cx; + + if(direction >= 0){ + cx = -cy; + cy = lx; + }else{ + cx = cy; + cy = -lx; + } + p.set(cx, cy); + }); + + //rotate actual request, centered on its multiblock position + float wx = (req.x - ox) * tilesize + req.block.offset(), wy = (req.y - oy) * tilesize + req.block.offset(); + float x = wx; + if(direction >= 0){ + wx = -wy; + wy = x; + }else{ + wx = wy; + wy = -x; + } + req.x = (short)(world.toTile(wx - req.block.offset()) + ox); + req.y = (short)(world.toTile(wy - req.block.offset()) + oy); + req.rotation = (byte)Mathf.mod(req.rotation + direction, 4); + }); + + //assign flipped values, since it's rotated + schem.width = input.height; + schem.height = input.width; + + return schem; + } } diff --git a/gradle.properties b/gradle.properties index 6d96d5473a..722a1885f4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,3 +1,3 @@ org.gradle.daemon=true org.gradle.jvmargs=-Xms256m -Xmx1024m -archash=1fc9e8ef5ecca01e058eab1ff4d7fd673aa5431d +archash=02f15d353cddc9725ad46bafeeae77c3f2719bac