Added experimental site export mod.

This commit is contained in:
Sebastian Hartte
2020-08-15 17:33:59 +02:00
parent b1feeca41c
commit 0f100341d3
6 changed files with 411 additions and 2 deletions
+16 -1
View File
@@ -82,11 +82,19 @@ sourceSets {
compileClasspath += sourceSets.api.output
runtimeClasspath += sourceSets.api.output
}
siteexport {
compileClasspath += sourceSets.api.output
runtimeClasspath += sourceSets.api.output
compileClasspath += sourceSets.main.output
runtimeClasspath += sourceSets.main.output
}
}
configurations {
apiCompile.extendsFrom(compileClasspath)
datagenCompile.extendsFrom(compileClasspath)
siteexportCompile.extendsFrom(compileClasspath)
siteexportRuntime.extendsFrom(runtimeClasspath)
}
apply from: 'gradle/scripts/spotless.gradle'
@@ -177,7 +185,7 @@ publishing {
import net.fabricmc.loom.task.RunClientTask;
task generateData(type: RunClientTask, dependsOn: downloadAssets, group: "ae2") {
task generateData(type: RunClientTask, dependsOn: downloadAssets, group: "ae2", description: "Generates various JSON assets for the mod") {
classpath = configurations.runtimeClasspath
classpath sourceSets.api.output
classpath sourceSets.main.output
@@ -185,3 +193,10 @@ task generateData(type: RunClientTask, dependsOn: downloadAssets, group: "ae2")
systemProperty "appeng.generateData", "true"
}
build.dependsOn generateData
task runSiteExport(type: RunClientTask, dependsOn: downloadAssets, group: "ae2", description: "Export game assets for the website") {
classpath = configurations.runtimeClasspath
classpath sourceSets.api.output
classpath sourceSets.main.output
classpath sourceSets.siteexport.output
}
@@ -334,7 +334,7 @@ public class CachedPlane {
}
// FIXME check if this makes any sense at all to send changes to players asap
ServerChunkManager serverChunkProvider = (ServerChunkManager) world.getChunkManager();
ServerChunkManager serverChunkProvider = world.getChunkManager();
serverChunkProvider.tick(() -> false);
}
@@ -0,0 +1,126 @@
package appeng.siteexport;
import java.io.IOException;
import java.nio.file.Paths;
import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.systems.RenderSystem;
import org.lwjgl.opengl.GL12;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gl.Framebuffer;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.render.DiffuseLighting;
import net.minecraft.client.texture.NativeImage;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.item.ItemStack;
import net.minecraft.text.Text;
import net.minecraft.util.collection.DefaultedList;
import appeng.api.definitions.IDefinitions;
import appeng.core.Api;
import appeng.core.CreativeTab;
public class Entrypoint implements ClientModInitializer {
private static final int FB_WIDTH = 128;
private static final int FB_HEIGHT = 128;
@Override
public void onInitializeClient() {
ClientLifecycleEvents.CLIENT_STARTED.register(client -> {
client.currentScreen = new Screen(Text.of("DUMMY")) {
@Override
protected void init() {
while (true) {
runExport(client);
}
// client.getWindow().close();
}
};
});
}
private void runExport(MinecraftClient client) {
// Set up GL state for GUI rendering
RenderSystem.matrixMode(GL12.GL_PROJECTION);
RenderSystem.loadIdentity();
RenderSystem.ortho(0.0D, 16, 16, 0.0D, 1000.0D, 3000.0D);
RenderSystem.matrixMode(GL12.GL_MODELVIEW);
RenderSystem.loadIdentity();
RenderSystem.translatef(0.0F, 0.0F, -2000.0F);
DiffuseLighting.enableGuiDepthLighting();
MatrixStack matrixStack = new MatrixStack();
IDefinitions definitions = Api.instance().definitions();
NativeImage nativeImage = new NativeImage(FB_WIDTH, FB_HEIGHT, true);
Framebuffer fb = new Framebuffer(FB_WIDTH, FB_HEIGHT, true, false);
fb.setClearColor(0, 0, 0, 0);
fb.clear(false);
// Iterate over all Applied Energistics items
DefaultedList<ItemStack> stacks = DefaultedList.of();
CreativeTab.INSTANCE.appendStacks(stacks);
// Compute the square grid size needed to have enough cells for the number of
// items we
// want to render
int s = (int) Math.ceil(Math.sqrt(stacks.size()));
// Add a transparent margin to avoid problems with texture interpolation
// grabbing pixels
// from adjacent items.
final int MARGIN = 1;
final int CELL_WIDTH = FB_WIDTH + 2 * MARGIN;
final int CELL_HEIGHT = FB_HEIGHT + 2 * MARGIN;
NativeImage result = new NativeImage(s * CELL_WIDTH, s * CELL_HEIGHT, true);
SpriteIndexWriter indexWriter = new SpriteIndexWriter(result.getWidth(), result.getHeight(), s, s, MARGIN);
int idx = 0;
for (ItemStack stack : stacks) {
// Render the item normally
fb.beginWrite(true);
GlStateManager.clear(GL12.GL_COLOR_BUFFER_BIT | GL12.GL_DEPTH_BUFFER_BIT, false);
client.getItemRenderer().renderInGui(stack, 0, 0);
fb.endWrite();
// Load the rendered item back into CPU memory
fb.beginRead();
nativeImage.loadFromTextureImage(0, false);
nativeImage.mirrorVertically();
fb.endRead();
// Copy it to the sprite-sheet
int xIdx = idx % s;
int xOut = xIdx * CELL_WIDTH + MARGIN;
int yIdx = idx / s;
int yOut = yIdx * CELL_HEIGHT + MARGIN;
idx++;
for (int y = 0; y < FB_HEIGHT; y++) {
for (int x = 0; x < FB_WIDTH; x++) {
result.setPixelColor(xOut + x, yOut + y, nativeImage.getPixelColor(x, y));
}
}
// Add it to the index
indexWriter.add(stack, xIdx, yIdx);
}
try {
result.writeFile(Paths.get("item_sheet.png"));
indexWriter.write(Paths.get("item_sheet.json"));
} catch (IOException e) {
e.printStackTrace();
}
nativeImage.close();
result.close();
fb.delete();
}
}
@@ -0,0 +1,61 @@
package appeng.siteexport;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.concurrent.TimeUnit;
public final class ModVersion {
private static boolean initialized;
private static String modVersion;
private ModVersion() {
}
public static String get() {
if (initialized) {
return modVersion;
}
initialized = true;
// GHETTO!
Process process = null;
Path tempOutput = null;
try {
tempOutput = Files.createTempFile("gitoutput", ".txt");
process = new ProcessBuilder("git", "rev-parse", "--short", "HEAD")
.redirectError(ProcessBuilder.Redirect.INHERIT).redirectInput(ProcessBuilder.Redirect.PIPE)
.redirectOutput(tempOutput.toFile()).start();
if (process.waitFor(10, TimeUnit.SECONDS)) {
String version = new String(Files.readAllBytes(tempOutput), StandardCharsets.UTF_8).trim();
if (version.isEmpty()) {
throw new Exception("Empty git output");
}
modVersion = version;
return version;
}
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
if (tempOutput != null) {
try {
Files.deleteIfExists(tempOutput);
} catch (Exception e) {
e.printStackTrace();
}
}
if (process != null) {
try {
process.destroyForcibly();
} catch (Exception e) {
e.printStackTrace();
}
}
}
return null;
}
}
@@ -0,0 +1,184 @@
package appeng.siteexport;
import java.io.IOException;
import java.io.Writer;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.mojang.serialization.JsonOps;
import net.minecraft.MinecraftVersion;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NbtOps;
import net.minecraft.util.registry.Registry;
public class SpriteIndexWriter {
private final SpriteIndexJson spriteIndex = new SpriteIndexJson();
public SpriteIndexWriter(int width, int height, int rows, int cols, int margin) {
spriteIndex.modVersion = ModVersion.get();
spriteIndex.width = width;
spriteIndex.height = height;
spriteIndex.cols = cols;
spriteIndex.rows = rows;
spriteIndex.margin = margin;
}
public void add(ItemStack stack, int x, int y) {
SpriteIndexEntryJson entry = new SpriteIndexEntryJson(stack, x, y);
spriteIndex.sprites.add(entry);
}
public void write(Path file) throws IOException {
Gson gson = new GsonBuilder().setPrettyPrinting().create();
try (Writer writer = Files.newBufferedWriter(file, StandardCharsets.UTF_8)) {
gson.toJson(spriteIndex, writer);
}
}
private static class SpriteIndexJson {
private String generated;
private String gameVersion;
private String modVersion;
private String filename;
private int width;
private int height;
private int cols;
private int rows;
private int margin;
private List<SpriteIndexEntryJson> sprites = new ArrayList<>();
public SpriteIndexJson() {
generated = Instant.now().toString();
gameVersion = MinecraftVersion.create().getName();
}
public String getGenerated() {
return generated;
}
public void setGenerated(String generated) {
this.generated = generated;
}
public String getGameVersion() {
return gameVersion;
}
public void setGameVersion(String gameVersion) {
this.gameVersion = gameVersion;
}
public String getModVersion() {
return modVersion;
}
public void setModVersion(String modVersion) {
this.modVersion = modVersion;
}
public String getFilename() {
return filename;
}
public void setFilename(String filename) {
this.filename = filename;
}
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public int getCols() {
return cols;
}
public void setCols(int cols) {
this.cols = cols;
}
public int getRows() {
return rows;
}
public void setRows(int rows) {
this.rows = rows;
}
public List<SpriteIndexEntryJson> getSprites() {
return sprites;
}
public int getMargin() {
return margin;
}
public void setMargin(int margin) {
this.margin = margin;
}
}
private static class SpriteIndexEntryJson {
private String itemId;
private JsonElement tag;
private int x;
private int y;
public SpriteIndexEntryJson(ItemStack is, int x, int y) {
this.itemId = Registry.ITEM.getId(is.getItem()).toString();
if (is.hasTag()) {
this.tag = NbtOps.INSTANCE.convertMap(JsonOps.INSTANCE, is.getTag());
}
this.x = x;
this.y = y;
}
public String getItemId() {
return itemId;
}
public JsonElement getTag() {
return tag;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
}
}
+23
View File
@@ -0,0 +1,23 @@
{
"schemaVersion": 1,
"id": "appliedenergistics2siteexport",
"version": "1.0.0",
"name": "Applied Energistics 2 Site Export",
"description": "",
"authors": ["TeamAppliedEnergistics"],
"contact": {
"homepage": "https://ae-mod.info/",
"sources": "https://github.com/AppliedEnergistics/Applied-Energistics-2/"
},
"license": "LGPL",
"icon": "assets/appliedenergistics2/icon.png",
"environment": "client",
"entrypoints": {
"client": ["appeng.siteexport.Entrypoint"]
},
"depends": {
"fabricloader": ">=0.7.1",
"fabric": "*",
"minecraft": "1.16.x"
}
}