Added experimental site export mod.
This commit is contained in:
+16
-1
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user