From 237c187ce8c34cb33186564420144b14284e68e6 Mon Sep 17 00:00:00 2001 From: Pazaz Date: Mon, 25 Apr 2022 18:42:32 -0400 Subject: [PATCH] Export frame buffer to PNG, allow transparency --- .gitignore | 1 + client/src/main/java/rt4/Keyboard.java | 4 + client/src/main/java/rt4/Npc.java | 8 +- client/src/main/java/rt4/SoftwareRaster.java | 6 ++ .../java/com/itspazaz/rt4/Playground.java | 74 +++++++++++++++---- 5 files changed, 74 insertions(+), 19 deletions(-) diff --git a/.gitignore b/.gitignore index 2a2b3df..0550d26 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ bin/ build/ +dump/ diff --git a/client/src/main/java/rt4/Keyboard.java b/client/src/main/java/rt4/Keyboard.java index ee95646..5c4e5c4 100644 --- a/client/src/main/java/rt4/Keyboard.java +++ b/client/src/main/java/rt4/Keyboard.java @@ -128,6 +128,10 @@ public final class Keyboard implements KeyListener, FocusListener { CODE_MAP[KeyEvent.VK_INSERT] = 100; } + public static boolean getKey(int key) { + return pressedKeys[CODE_MAP[key]]; + } + @OriginalMember(owner = "client!s", name = "e", descriptor = "[I") public static final int[] typedCodeQueue = new int[128]; diff --git a/client/src/main/java/rt4/Npc.java b/client/src/main/java/rt4/Npc.java index f86dede..a9ec534 100644 --- a/client/src/main/java/rt4/Npc.java +++ b/client/src/main/java/rt4/Npc.java @@ -24,7 +24,7 @@ public final class Npc extends PathingEntity { @OriginalMember(owner = "client!km", name = "a", descriptor = "(IIIIIIIIJILclient!ga;)V") @Override - public final void render(@OriginalArg(0) int orientation, @OriginalArg(1) int arg1, @OriginalArg(2) int arg2, @OriginalArg(3) int arg3, @OriginalArg(4) int arg4, @OriginalArg(5) int x, @OriginalArg(6) int z, @OriginalArg(7) int y, @OriginalArg(8) long arg8, @OriginalArg(9) int arg9, @OriginalArg(10) ParticleSystem arg10) { + public final void render(@OriginalArg(0) int orientation, @OriginalArg(1) int arg1, @OriginalArg(2) int arg2, @OriginalArg(3) int arg3, @OriginalArg(4) int arg4, @OriginalArg(5) int x, @OriginalArg(6) int z, @OriginalArg(7) int y, @OriginalArg(8) long key, @OriginalArg(9) int arg9, @OriginalArg(10) ParticleSystem arg10) { if (this.type == null) { return; } @@ -91,7 +91,7 @@ public final class Npc extends PathingEntity { body.aBoolean303 = true; } - body.render(orientation, arg1, arg2, arg3, arg4, x, z, y, arg8, arg9, this.aClass47_Sub1_5); + body.render(orientation, arg1, arg2, arg3, arg4, x, z, y, key, arg9, this.aClass47_Sub1_5); return; } @@ -99,13 +99,13 @@ public final class Npc extends PathingEntity { body.aBoolean303 = true; } - body.render(orientation, arg1, arg2, arg3, arg4, x, z, y, arg8, arg9, this.aClass47_Sub1_5); + body.render(orientation, arg1, arg2, arg3, arg4, x, z, y, key, arg9, this.aClass47_Sub1_5); if (model != null) { if (this.type.size == 1) { model.aBoolean303 = true; } - model.render(orientation, arg1, arg2, arg3, arg4, x, z, y, arg8, arg9, this.aClass47_Sub1_5); + model.render(orientation, arg1, arg2, arg3, arg4, x, z, y, key, arg9, this.aClass47_Sub1_5); } } diff --git a/client/src/main/java/rt4/SoftwareRaster.java b/client/src/main/java/rt4/SoftwareRaster.java index 7c2c934..d17cf5b 100644 --- a/client/src/main/java/rt4/SoftwareRaster.java +++ b/client/src/main/java/rt4/SoftwareRaster.java @@ -179,6 +179,12 @@ public final class SoftwareRaster { } } + public static void clear(int color) { + for (int i = 0; i < width * height; ++i) { + pixels[i] = color; + } + } + @OriginalMember(owner = "client!kb", name = "b", descriptor = "(IIIII)V") private static void method2493(@OriginalArg(0) int arg0, @OriginalArg(1) int arg1, @OriginalArg(2) int arg2, @OriginalArg(3) int arg3, @OriginalArg(4) int arg4) { if (arg1 < clipTop || arg1 >= clipBottom) { diff --git a/playground/src/main/java/com/itspazaz/rt4/Playground.java b/playground/src/main/java/com/itspazaz/rt4/Playground.java index f6c77e1..93f4783 100644 --- a/playground/src/main/java/com/itspazaz/rt4/Playground.java +++ b/playground/src/main/java/com/itspazaz/rt4/Playground.java @@ -2,7 +2,12 @@ package com.itspazaz.rt4; import rt4.*; -import java.awt.image.Raster; +import javax.imageio.ImageIO; +import java.awt.*; +import java.awt.color.ColorSpace; +import java.awt.event.KeyEvent; +import java.awt.image.*; +import java.io.File; import java.io.IOException; import java.net.Socket; @@ -75,13 +80,7 @@ public class Playground extends GameShell { public NpcType npcType; public Npc npc; - @Override - protected void mainLoop() { - Keyboard.loop(); - Mouse.loop(); - - js5NetLoop(); - + public void stateLoop() { if (state == 0) { LoadingBarAwt.render(null, true, JagString.parse("Connecting to update server"), 1); @@ -166,7 +165,7 @@ public class Playground extends GameShell { Sprites.load(archives[8]); state++; } - }else if (state == 7) { + } else if (state == 7) { LoadingBarAwt.render(null, true, JagString.parse("Preparing to draw model"), 1); Js5GlTextureProvider textureProvider = new Js5GlTextureProvider(archives[9], archives[26], archives[8], 20, false); LoadingBarAwt.clear(); @@ -182,8 +181,53 @@ public class Playground extends GameShell { npc.setNpcType(npcType); state++; } + } - GameShell.frame.setTitle(state + ""); + private void exportImage(int[] pixels, String filename) { + byte[] raw = new byte[pixels.length * 4]; + int offset = 0; + for (int rgb : pixels) { + raw[offset++] = (byte) (rgb >> 16); // red + raw[offset++] = (byte) (rgb >> 8); // green + raw[offset++] = (byte) (rgb); // blue + + // set transparency for background color + if (rgb >> 24 == 0x7F) { + raw[offset++] = (byte) 0; + } else { + raw[offset++] = (byte) 0xFF; + } + } + + try { + DataBuffer buffer = new DataBufferByte(raw, raw.length); + int samplesPerPixel = 4; + int[] bandOffsets = { 0, 1, 2, 3 }; + ColorModel colorModel = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), true, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE); + WritableRaster raster = Raster.createInterleavedRaster(buffer, GameShell.canvasWidth, GameShell.canvasHeight, samplesPerPixel * GameShell.canvasWidth, samplesPerPixel, bandOffsets, null); + BufferedImage image = new BufferedImage(colorModel, raster, colorModel.isAlphaPremultiplied(), null); + ImageIO.write(image, "PNG", new File(filename + ".png")); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + int exportCounter = 0; + + public void inputLoop() { + if (Keyboard.getKey(KeyEvent.VK_BACK_SLASH)) { + exportImage(SoftwareRaster.pixels, "dump/" + exportCounter++); + } + } + + @Override + protected void mainLoop() { + Keyboard.loop(); + Mouse.loop(); + + js5NetLoop(); + stateLoop(); + inputLoop(); } public int js5ConnectState = 0; @@ -254,13 +298,13 @@ public class Playground extends GameShell { @Override protected void mainRedraw() { if (state == 8) { - SoftwareRaster.clear(); + SoftwareRaster.clear(0x7F333333); if (npc != null) { - int orientation = 512; - int x = 256; - int z = 256; - int y = 256; + int orientation = 384; + int x = 128; + int z = 192; + int y = 128; npc.render(orientation, 25079, 60547, -44308, 48222, x, z, y, 0L, 0, null); }