diff --git a/assets/bundles/bundle.properties b/assets/bundles/bundle.properties index 9b37417..326d166 100644 --- a/assets/bundles/bundle.properties +++ b/assets/bundles/bundle.properties @@ -1,5 +1,23 @@ confictura = Confictura +block.confictura-ludellyte.name = Ludellyte +block.confictura-eroded-slate.name = Eroded Slate +block.confictura-infused-eroded-slate.name = Infused Eroded Slate +block.confictura-archaic-eroded-slate.name = Archaic Eroded Slate +block.confictura-eroded-eneraphyte-vent.name = Eroded Eneraphyte Vent +block.confictura-eroded-slate-wall.name = Eroded Slate Wall +block.confictura-infused-eroded-slate-wall.name = Infused Eroded Slate Wall +block.confictura-archaic-eroded-slate-wall.name = Archaic Eroded Slate Wall +block.confictura-sharp-slate.name = Sharp Slate +block.confictura-infused-sharp-slate.name = Infused Sharp Slate +block.confictura-archaic-sharp-slate.name = Archaic Sharp Slate +block.confictura-eneraphyte-vent.name = Eneraphyte Vent +block.confictura-sharp-slate-wall.name = Sharp Slate Wall +block.confictura-infused-sharp-slate-wall.name = Infused Sharp Slate Wall +block.confictura-archaic-sharp-slate-wall.name = Archaic Sharp Slate Wall +block.confictura-eroded-spire.name = Eroded Slate Spire +block.confictura-sharp-spire.name = Slate Spire + planet.confictura-portal.name = Portal planet.confictura-portal.description = diff --git a/assets/maps/confictura-test.msav b/assets/maps/confictura-test.msav index 078af6d..b2010d7 100644 Binary files a/assets/maps/confictura-test.msav and b/assets/maps/confictura-test.msav differ diff --git a/assets/scenes/confictura/spires.bin b/assets/scenes/confictura/spires.bin index ef8ed1f..3d4a9e7 100644 Binary files a/assets/scenes/confictura/spires.bin and b/assets/scenes/confictura/spires.bin differ diff --git a/assets/scenes/confictura/spires.gltf b/assets/scenes/confictura/spires.gltf index 0fb77c0..55ba519 100644 --- a/assets/scenes/confictura/spires.gltf +++ b/assets/scenes/confictura/spires.gltf @@ -9,27 +9,48 @@ { "name":"Scene", "nodes":[ - 0 + 0, + 1 ] } ], "nodes":[ { "mesh":0, - "name":"Spire" + "name":"SpireSmall1" + }, + { + "mesh":1, + "name":"SpireSmall2", + "translation":[ + 3, + 0, + 0 + ] } ], "meshes":[ { - "name":"Spire", + "name":"SpireSmall1", "primitives":[ { "attributes":{ - "COLOR_0":0, - "POSITION":1, - "NORMAL":2 + "POSITION":0, + "NORMAL":1 }, - "indices":3 + "indices":2 + } + ] + }, + { + "name":"SpireSmall2", + "primitives":[ + { + "attributes":{ + "POSITION":3, + "NORMAL":4 + }, + "indices":5 } ] } @@ -37,18 +58,39 @@ "accessors":[ { "bufferView":0, - "componentType":5123, - "count":67, - "normalized":true, - "type":"VEC4" + "componentType":5126, + "count":70, + "max":[ + 1, + 4, + 1 + ], + "min":[ + -1, + 0, + -1 + ], + "type":"VEC3" }, { "bufferView":1, "componentType":5126, - "count":67, + "count":70, + "type":"VEC3" + }, + { + "bufferView":2, + "componentType":5123, + "count":90, + "type":"SCALAR" + }, + { + "bufferView":3, + "componentType":5126, + "count":38, "max":[ 1, - 4, + 2, 1 ], "min":[ @@ -59,47 +101,59 @@ "type":"VEC3" }, { - "bufferView":2, + "bufferView":4, "componentType":5126, - "count":67, + "count":38, "type":"VEC3" }, { - "bufferView":3, + "bufferView":5, "componentType":5123, - "count":84, + "count":42, "type":"SCALAR" } ], "bufferViews":[ { "buffer":0, - "byteLength":536, + "byteLength":840, "byteOffset":0, "target":34962 }, { "buffer":0, - "byteLength":804, - "byteOffset":536, + "byteLength":840, + "byteOffset":840, + "target":34962 + }, + { + "buffer":0, + "byteLength":180, + "byteOffset":1680, + "target":34963 + }, + { + "buffer":0, + "byteLength":456, + "byteOffset":1860, "target":34962 }, { "buffer":0, - "byteLength":804, - "byteOffset":1340, + "byteLength":456, + "byteOffset":2316, "target":34962 }, { "buffer":0, - "byteLength":168, - "byteOffset":2144, + "byteLength":84, + "byteOffset":2772, "target":34963 } ], "buffers":[ { - "byteLength":2312, + "byteLength":2856, "uri":"spires.bin" } ] diff --git a/assets/shaders/confictura/model-prop.vert b/assets/shaders/confictura/model-prop.vert index 61ed103..c8d9ba6 100644 --- a/assets/shaders/confictura/model-prop.vert +++ b/assets/shaders/confictura/model-prop.vert @@ -1,6 +1,6 @@ -attribute vec4 a_color; attribute vec3 a_position; attribute vec3 a_normal; +attribute vec4 a_color; uniform mat4 u_proj; uniform vec3 u_lightDir; diff --git a/assets/sprites-raw/blocks/props/eroded-spire.png b/assets/sprites-raw/blocks/props/eroded-spire.png new file mode 100644 index 0000000..a87b190 Binary files /dev/null and b/assets/sprites-raw/blocks/props/eroded-spire.png differ diff --git a/assets/sprites-raw/blocks/props/sharp-spire.png b/assets/sprites-raw/blocks/props/sharp-spire.png new file mode 100644 index 0000000..54992ce Binary files /dev/null and b/assets/sprites-raw/blocks/props/sharp-spire.png differ diff --git a/assets/sprites-raw/blocks/props/slate-spire.png b/assets/sprites-raw/blocks/props/slate-spire.png deleted file mode 100644 index dfbe6fd..0000000 Binary files a/assets/sprites-raw/blocks/props/slate-spire.png and /dev/null differ diff --git a/proc/src/confictura/proc/list/BlockProc.java b/proc/src/confictura/proc/list/BlockProc.java index 2b0fe0f..d168487 100644 --- a/proc/src/confictura/proc/list/BlockProc.java +++ b/proc/src/confictura/proc/list/BlockProc.java @@ -5,15 +5,16 @@ import arc.util.*; import arc.util.serialization.*; import arc.util.serialization.Jval.*; -import confictura.*; import confictura.proc.*; import confictura.proc.GenAtlas.*; +import confictura.world.blocks.*; import confictura.world.blocks.environment.*; import mindustry.world.blocks.environment.*; import java.io.*; import java.nio.charset.*; +import static confictura.ConficturaMod.*; import static confictura.proc.ConficturaProc.*; import static confictura.util.StructUtils.*; import static mindustry.Vars.*; @@ -26,7 +27,7 @@ public void init(Cons async){ blockColors = Jval.newObject(); var packer = new GenPacker(); - content.blocks().each(ConficturaMod::isConfictura, block -> async.get(() -> { + content.blocks().each(b -> isConfictura(b) && b.generateIcons, block -> async.get(() -> { try{ block.init(); block.loadIcon(); @@ -60,37 +61,49 @@ public void init(Cons async){ } block.load(); - var icon = atlas.conv(block.fullIcon).pixmap(); - - boolean hollow = false; - Color average = new Color(), col = new Color(); - - for(int x = 0, width = icon.width; x < width; x++){ - for(int y = 0, height = icon.height; y < height; y++){ - col.set(icon.getRaw(x, y)); - average.r += col.r; - average.g += col.g; - average.b += col.b; - average.a += col.a; - if(col.a < 0.9f) hollow = true; + + if(block instanceof DelegateMapColor map){ + synchronized(BlockProc.class){ + var sub = map.substitute(); + if(isConfictura(sub)){ + blockColors.put(block.name.substring("confictura-".length()), sub.name.substring("confictura-".length())); + }else{ + throw new IllegalArgumentException(Strings.format("Block '@' has non-Confictura map color substitution '@'.", block.name, sub.name)); + } + } + }else{ + var icon = atlas.conv(block.fullIcon).pixmap(); + + boolean hollow = false; + Color average = new Color(), col = new Color(); + + for(int x = 0, width = icon.width; x < width; x++){ + for(int y = 0, height = icon.height; y < height; y++){ + col.set(icon.getRaw(x, y)); + average.r += col.r; + average.g += col.g; + average.b += col.b; + average.a += col.a; + if(col.a < 0.9f) hollow = true; + } } - } - float a = average.a; - average.mul(1f / a); + float a = average.a; + average.mul(1f / a); - if(block instanceof Floor floor && !floor.wallOre){ - average.mul(0.77f); - }else{ - average.mul(1.1f); - } + if(block instanceof Floor floor && !floor.wallOre){ + average.mul(0.77f); + }else{ + average.mul(1.1f); + } - average.a = hollow ? 0f : 1f; - synchronized(BlockProc.class){ - blockColors.put(block.name.substring("confictura-".length()), average.rgba()); + average.a = hollow ? 0f : 1f; + synchronized(BlockProc.class){ + blockColors.put(block.name.substring("confictura-".length()), average.rgba()); + } } }catch(Throwable t){ - Log.warn("Skipping '@': @", block.name, Strings.getFinalMessage(t)); + Log.warn("Skipping '@': @", block.name.substring("confictura-".length()), Strings.getFinalMessage(t)); } })); } @@ -98,6 +111,11 @@ public void init(Cons async){ @Override public void finish(){ synchronized(BlockProc.class){ + var map = blockColors.asObject(); + for(var e : map){ + if(e.value.isString()) map.put(e.key, map.get(e.value.asString())); + } + var out = assetsDir.child("meta").child("confictura").child("block-colors.json"); try(var writer = new OutputStreamWriter(out.write(false, 4096), StandardCharsets.UTF_8)){ blockColors.writeTo(writer, Jformat.formatted); diff --git a/src/confictura/DevBuildImpl.java b/src/confictura/DevBuildImpl.java index cf83af6..6e04be8 100644 --- a/src/confictura/DevBuildImpl.java +++ b/src/confictura/DevBuildImpl.java @@ -3,8 +3,13 @@ import arc.util.*; import arc.util.Log.*; import confictura.util.*; +import mindustry.ctype.*; import mindustry.ui.dialogs.*; +import static arc.Core.*; +import static confictura.ConficturaMod.*; +import static mindustry.Vars.*; + /** * Implementation class for {@link DevBuild}. This class is excluded in the built JARs for non-developer builds. * @author GlennFolker @@ -18,5 +23,13 @@ public DevBuildImpl(){ @Override public void init(){ ScriptUtils.importDefaults(ScriptUtils.vanillaScope); + for(var type : ContentType.all) content.getBy(type).each(c -> c instanceof MappableContent && isConfictura(c), (MappableContent c) -> { + if(!bundle.has(type.name() + "." + c.name + ".name")){ + Log.debug("Content '@' of type '@' has no localized name.", c.name, type.name()); + } + if(c instanceof UnlockableContent u && !u.isHidden() && !bundle.has(type.name() + "." + c.name + ".description")){ + Log.debug("Content '@' of type '@' has no localized description.", c.name, type.name()); + } + }); } } diff --git a/src/confictura/content/CBlocks.java b/src/confictura/content/CBlocks.java index 20b6e0d..b777276 100644 --- a/src/confictura/content/CBlocks.java +++ b/src/confictura/content/CBlocks.java @@ -1,5 +1,6 @@ package confictura.content; +import arc.graphics.*; import confictura.*; import confictura.graphics.*; import confictura.world.blocks.environment.*; @@ -18,7 +19,7 @@ public final class CBlocks{ ludellyte, erodedSlate, infErodedSlate, archErodedSlate, erodedEneraphyteVent, erodedSlateWall, infErodedSlateWall, archErodedSlateWall, sharpSlate, infSharpSlate, archSharpSlate, eneraphyteVent, sharpSlateWall, infSharpSlateWall, archSharpSlateWall, - slateSpire, + erodedSpire, sharpSpire, eneraphyteCrystal; private CBlocks(){ @@ -105,6 +106,7 @@ public static void load(){ lightRadius = 48f; }}; - slateSpire = new ModelProp("slate-spire", () -> CModels.slateSpire); + erodedSpire = new ModelProp("eroded-spire", erodedSlateWall, new Color(0x454858ff), () -> CModels.spireSmall1, () -> CModels.spireSmall2); + sharpSpire = new ModelProp("sharp-spire", sharpSlateWall, new Color(0x6e7080ff), () -> CModels.spireSmall1, () -> CModels.spireSmall2); } } diff --git a/src/confictura/graphics/CModels.java b/src/confictura/graphics/CModels.java index 56ce462..9a96e1d 100644 --- a/src/confictura/graphics/CModels.java +++ b/src/confictura/graphics/CModels.java @@ -17,7 +17,7 @@ public final class CModels{ public static Scenes3D portal; public static Node portalBase, portalCage; - public static Mesh slateSpire; + public static Mesh spireSmall1, spireSmall2; private CModels(){ throw new AssertionError(); @@ -37,9 +37,11 @@ public static void load(){ assets .load("scenes/confictura/portal.gltf#Cage", Node.class) .loaded = node -> portalCage = node; - assets - .load("scenes/confictura/spires.gltf#Spire", MeshSet.class) - .loaded = set -> slateSpire = set.containers.first().mesh; + .load("scenes/confictura/spires.gltf", Scenes3D.class) + .loaded = scene -> { + spireSmall1 = scene.meshNames.get("SpireSmall1").containers.first().mesh; + spireSmall2 = scene.meshNames.get("SpireSmall2").containers.first().mesh; + }; } } diff --git a/src/confictura/graphics/CPal.java b/src/confictura/graphics/CPal.java index 81bfb23..20c6d3d 100644 --- a/src/confictura/graphics/CPal.java +++ b/src/confictura/graphics/CPal.java @@ -8,13 +8,14 @@ */ public final class CPal{ public static final Color - monolithLighter = new Color(0x9cd4f8ff), - monolithLight = new Color(0x72a2d7ff), - monolithMid = new Color(0x5379b7ff), - monolithDark = new Color(0x354d97ff), - monolithDarker = new Color(0x253080ff), - monolithOutline = new Color(0x38383dff); + monolithLighter = new Color(0x9cd4f8ff), + monolithLight = new Color(0x72a2d7ff), + monolithMid = new Color(0x5379b7ff), + monolithDark = new Color(0x354d97ff), + monolithDarker = new Color(0x253080ff), + + monolithOutline = new Color(0x38383dff); private CPal(){ throw new AssertionError(); diff --git a/src/confictura/graphics/g3d/ModelPropDrawer.java b/src/confictura/graphics/g3d/ModelPropDrawer.java index 8b353a6..57e8a23 100644 --- a/src/confictura/graphics/g3d/ModelPropDrawer.java +++ b/src/confictura/graphics/g3d/ModelPropDrawer.java @@ -20,7 +20,7 @@ import static mindustry.Vars.*; public class ModelPropDrawer implements Disposable{ - public static final VertexAttribute[] attributes = {new VertexAttribute(4, Gl.unsignedShort, true, "a_color"), VertexAttribute.position3, VertexAttribute.normal}; + public static final VertexAttribute[] attributes = {VertexAttribute.position3, VertexAttribute.normal}; public static final int attribStride = sumi(attributes, attrib -> attrib.size / Float.BYTES); public static final Boolf2 attribEq = (a, b) -> a.components == b.components && @@ -55,7 +55,7 @@ public class ModelPropDrawer implements Disposable{ protected int vertexOffset, indexOffset; public ModelPropDrawer(ModelPropShader shader, int maxVertices, int maxIndices){ - batch = new Mesh(false, maxVertices, maxIndices, attributes); + batch = new Mesh(false, maxVertices, maxIndices, VertexAttribute.position3, VertexAttribute.normal, VertexAttribute.color); this.shader = shader; vertices = new float[maxVertices * batch.vertexSize]; indices = new short[maxIndices]; @@ -77,9 +77,10 @@ public PropData getData(Mesh mesh){ }); } - public void draw(Mesh mesh, float x, float y, float rotation){ + public void draw(Mesh mesh, float x, float y, float rotation, Color color){ var req = pool.obtain(); req.trns.set(pos.set(x, 0f, -y), quat.setFromAxis(Vec3.Y, rotation), scl.set(tilesize, tilesize, tilesize).scl(0.5f)); + req.color.set(color); req.data = getData(mesh); requests.add(req); } @@ -105,27 +106,29 @@ public void render(){ Gl.clearColor(0f, 0f, 0f, 0f); Gl.clear(Gl.colorBufferBit | Gl.depthBufferBit); + int vertStride = batch.vertexSize / Float.BYTES; for(var req : requests){ var trns = req.trns; + var color = req.color; var data = req.data; var input = data.vertices; - if(input.length >= vertices.length - vertexOffset * attribStride || data.indices.length >= indices.length - indexOffset) flush(); - - int offset = vertexOffset * attribStride; - for(int i = 0; i < input.length; i += attribStride){ - int index = offset + i; - System.arraycopy(input, i, vertices, index, Short.BYTES * 4 / Float.BYTES); - - var p = Mat3D.prj(vec.set(input[i + 2], input[i + 3], input[i + 4]), trns); - vertices[index + 2] = p.x; - vertices[index + 3] = p.y; - vertices[index + 4] = p.z; - - var n = Mat3D.prj(vec.set(input[i + 5], input[i + 6], input[i + 7]), nor.set(trns).toNormalMatrix()).nor(); - vertices[index + 5] = n.x; - vertices[index + 6] = n.y; - vertices[index + 7] = n.z; + if(input.length >= vertices.length - vertexOffset * vertStride || data.indices.length >= indices.length - indexOffset) flush(); + + int offset = vertexOffset * vertStride; + for(int i = 0; i < input.length / attribStride; i++){ + int src = i * attribStride, dst = offset + i * vertStride; + + var p = Mat3D.prj(vec.set(input[src], input[src + 1], input[src + 2]), trns); + vertices[dst] = p.x; + vertices[dst + 1] = p.y; + vertices[dst + 2] = p.z; + + var n = Mat3D.prj(vec.set(input[src + 3], input[src + 4], input[src + 5]), nor.set(trns).toNormalMatrix()).nor(); + vertices[dst + 3] = n.x; + vertices[dst + 4] = n.y; + vertices[dst + 5] = n.z; + vertices[dst + 6] = color.toFloatBits(); } for(short index : data.indices) indices[indexOffset++] = (short)(vertexOffset + index); @@ -153,7 +156,7 @@ protected void flush(){ shader.lightDir.set(-1f, -1f, 1f).nor(); shader.apply(); - batch.setVertices(vertices, 0, vertexOffset * attribStride); + batch.setVertices(vertices, 0, vertexOffset * batch.vertexSize / Float.BYTES); batch.setIndices(indices, 0, indexOffset); batch.render(shader, Gl.triangles, 0, indexOffset); @@ -179,6 +182,7 @@ public PropData(float[] vertices, short[] indices){ public static class Req{ public Mat3D trns = new Mat3D(); + public Color color = new Color(); public PropData data; } } diff --git a/src/confictura/world/blocks/DelegateMapColor.java b/src/confictura/world/blocks/DelegateMapColor.java new file mode 100644 index 0000000..8015c04 --- /dev/null +++ b/src/confictura/world/blocks/DelegateMapColor.java @@ -0,0 +1,11 @@ +package confictura.world.blocks; + +import mindustry.world.*; + +/** + * Uses another block's {@link Block#mapColor mapColor}. + * @author GlennFolker + */ +public interface DelegateMapColor{ + Block substitute(); +} diff --git a/src/confictura/world/blocks/environment/ModelProp.java b/src/confictura/world/blocks/environment/ModelProp.java index a1b84d3..3227b1b 100644 --- a/src/confictura/world/blocks/environment/ModelProp.java +++ b/src/confictura/world/blocks/environment/ModelProp.java @@ -5,23 +5,49 @@ import arc.graphics.g2d.*; import arc.math.*; import confictura.graphics.g3d.*; +import confictura.world.blocks.*; import mindustry.world.*; +import static arc.Core.*; import static confictura.ConficturaMod.*; -public class ModelProp extends Block{ - public Prov mesh; +public class ModelProp extends Block implements DelegateMapColor{ + public Block parent; + public Color color; + public Prov[] meshes; - public ModelProp(String name, Prov mesh){ + @SafeVarargs + public ModelProp(String name, Block parent, Color color, Prov... meshes){ super(name); - this.mesh = mesh; + this.parent = parent; + this.color = color; + this.meshes = meshes; destructible = breakable = false; } + @Override + public Block substitute(){ + return parent; + } + @Override public void drawBase(Tile tile){ + parent.drawBase(tile); + float z = Draw.z(); - Draw.draw(ModelPropDrawer.accumLayer, () -> modelPropDrawer.draw(mesh.get(), tile.drawx(), tile.drawy(), Mathf.randomSeed(tile.pos(), 0, 4) * 90f)); + Draw.z(ModelPropDrawer.accumLayer); + + var reg = atlas.find("square-shadow"); + float size = Math.max(reg.width, reg.height) * 1.75f * reg.scl(); + + Draw.color(0f, 0f, 0f, 0.65f); + Draw.rect(reg, tile.worldx(), tile.worldy(), size * Draw.xscl, size * Draw.yscl); + Draw.reset(); + + Draw.draw(Draw.z(), () -> modelPropDrawer.draw( + meshes[Mathf.randomSeed(tile.pos(), 0, meshes.length - 1)].get(), tile.worldx(), tile.worldy(), + Mathf.randomSeed(tile.pos() + 1, 0, 4) * 90f, color + )); Draw.z(z); } } diff --git a/src/confictura/world/blocks/environment/SizedVent.java b/src/confictura/world/blocks/environment/SizedVent.java index 3eccb81..116bbd4 100644 --- a/src/confictura/world/blocks/environment/SizedVent.java +++ b/src/confictura/world/blocks/environment/SizedVent.java @@ -3,6 +3,7 @@ import arc.graphics.g2d.*; import arc.math.geom.*; import arc.util.*; +import confictura.world.blocks.*; import mindustry.content.*; import mindustry.entities.*; import mindustry.world.*; @@ -16,7 +17,7 @@ * the bottom-left middle) should update and draw the actual sprite. * @author GlennFolker */ -public class SizedVent extends Floor{ +public class SizedVent extends Floor implements DelegateMapColor{ protected static Point2[][] offsets = new Point2[0][]; public int border; @@ -31,6 +32,11 @@ public SizedVent(String name, int size, int border){ this.border = border; } + @Override + public Block substitute(){ + return parent; + } + @Override public void drawBase(Tile tile){ parent.drawBase(tile);