summaryrefslogtreecommitdiff
path: root/NET/worlds/scape/Material.java
diff options
context:
space:
mode:
authorFuwn <[email protected]>2026-02-12 22:33:32 -0800
committerFuwn <[email protected]>2026-02-12 22:33:32 -0800
commitc7a9d4a6bd53ed7d61731770f2f10e8b9fd435f9 (patch)
treedf9f48bf128a6c0186a8e91857d6ff30fe0e9f18 /NET/worlds/scape/Material.java
downloadworldsplayer-c7a9d4a6bd53ed7d61731770f2f10e8b9fd435f9.tar.xz
worldsplayer-c7a9d4a6bd53ed7d61731770f2f10e8b9fd435f9.zip
Initial commit
Diffstat (limited to 'NET/worlds/scape/Material.java')
-rw-r--r--NET/worlds/scape/Material.java783
1 files changed, 783 insertions, 0 deletions
diff --git a/NET/worlds/scape/Material.java b/NET/worlds/scape/Material.java
new file mode 100644
index 0000000..36e4a45
--- /dev/null
+++ b/NET/worlds/scape/Material.java
@@ -0,0 +1,783 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.Main;
+import NET.worlds.console.MainCallback;
+import NET.worlds.core.IniFile;
+import NET.worlds.network.NetUpdate;
+import NET.worlds.network.URL;
+import java.awt.Color;
+import java.io.IOException;
+
+public class Material extends SuperRoot implements BGLoaded, MainCallback {
+ static int serial = 0;
+ public static boolean botMode = false;
+ private boolean keepLoaded = false;
+ private int[] ids;
+ private Texture[] textures;
+ private int vRes = 1;
+ private int hRes = 1;
+ private int sPos = -1;
+ private final boolean loResMode = false;
+ URL textureName;
+ protected URL[] subnames;
+ private boolean doReclump;
+ private static boolean tryBMP = IniFile.gamma().getIniInt("TRYBMP", 0) != 0;
+ private float ambient;
+ private float diffuse;
+ private float specular;
+ private float opacity;
+ private boolean smooth;
+ private boolean filter;
+ private int r;
+ private int g;
+ private int b;
+ private Color color;
+ private static Object classCookie = new Object();
+
+ static {
+ nativeInit();
+ }
+
+ public static native void nativeInit();
+
+ public Material(float ambient, float diffuse, float specular, Color color, Texture texture, float opacity, boolean smooth, boolean filter) {
+ if (botMode) {
+ texture = null;
+ }
+
+ this.ambient = ambient;
+ this.diffuse = diffuse;
+ this.specular = specular;
+ this.setColor(color);
+ if (texture != null) {
+ this.textures = new Texture[1];
+ this.textures[0] = texture;
+ }
+
+ this.opacity = opacity;
+ this.smooth = smooth;
+ this.filter = filter;
+ }
+
+ public Material(Color color) {
+ this(0.75F, 0.0F, 0.0F, color, null, 1.0F, false, false);
+ }
+
+ public Material(Texture texture) {
+ this(0.75F, 0.0F, 0.0F, Color.black, texture, 1.0F, false, false);
+ }
+
+ public Material(Color initialColor, URL textureName) {
+ this(initialColor != null ? initialColor : new Color(128, 128, 128));
+ if (!botMode) {
+ this.loadTexture(textureName);
+ }
+ }
+
+ public Material(URL tileTexture, int x, int y) {
+ this(0.75F, 0.0F, 0.0F, Color.black, null, 1.0F, false, false);
+ this.hRes = x;
+ this.vRes = y;
+ serial++;
+ int numSubs = this.getHRes() * this.getVRes();
+ this.textures = new Texture[numSubs];
+ this.makeMaterials();
+ this.subnames = new URL[numSubs];
+ String lowResBaseName = tileTexture.getBase();
+ int nextSubname = 0;
+
+ for (int v = this.vRes; v > 0; v--) {
+ String vExt = "" + v;
+
+ for (int h = 0; h < this.hRes; nextSubname++) {
+ URL subname = URL.make(tileTexture, lowResBaseName + serial + vExt + (h + 1) + ".cmp");
+ this.subnames[nextSubname] = subname;
+ this.syncBackgroundLoad(tileTexture.unalias(), subname);
+ h++;
+ }
+ }
+ }
+
+ public Material(URL textureName) {
+ this(null, textureName);
+ }
+
+ public Material() {
+ }
+
+ @Override
+ protected void noteAddingTo(SuperRoot owner) {
+ if (((WObject)owner).hasClump()) {
+ this.addRwChildren();
+ }
+ }
+
+ @Override
+ public void detach() {
+ if (this.ids != null) {
+ this.markVoid();
+ }
+
+ super.detach();
+ }
+
+ public Texture[] getTextures() {
+ return this.textures;
+ }
+
+ public void addRwChildren() {
+ if (this.ids == null) {
+ if (this.textures == null && this.textureName != null) {
+ this.loadTextures();
+ } else {
+ this.makeMaterials();
+ if (this.textures != null) {
+ for (int i = 0; i < this.ids.length; i++) {
+ this.nativeSetTexture(i, this.textures[i]);
+ }
+ }
+ }
+ }
+ }
+
+ public void markVoid() {
+ if (!this.keepLoaded) {
+ if (this.textureName != null) {
+ this.removeTextures();
+ }
+
+ this.closeMaterials();
+ }
+ }
+
+ public void setKeepLoaded(boolean f) {
+ boolean klWas = this.keepLoaded;
+ this.keepLoaded = f;
+ if (!f && klWas) {
+ SuperRoot o = this.getOwner();
+ if (o == null || !((WObject)o).hasClump()) {
+ this.markVoid();
+ }
+ }
+ }
+
+ public static Material restore(Restorer r) throws IOException, TooNewException {
+ Material m = (Material)r.restoreMaybeNull();
+ if (m != null && r.version() < 6 && m.getOwner() != null) {
+ m = (Material)m.clone();
+ }
+
+ return m;
+ }
+
+ private native void nativeSetTexture(int var1, Texture var2);
+
+ private synchronized void setTexture(int texNum, Texture texture) {
+ if (this.textures[texNum] != null) {
+ Texture t = this.extractTexture(texNum);
+ if (t != null) {
+ t.decRef();
+ }
+ }
+
+ this.textures[texNum] = texture;
+ this.nativeSetTexture(texNum, texture);
+ if (!this.doReclump) {
+ this.doReclump = true;
+ Main.register(this);
+ }
+ }
+
+ @Override
+ public void mainCallback() {
+ Main.unregister(this);
+ if (this.doReclump) {
+ this.propagateTextureChange();
+ }
+
+ this.doReclump = false;
+ }
+
+ private void propagateTextureChange() {
+ if (this.ids != null) {
+ Object o = this.getOwner();
+ if (o instanceof WObject) {
+ if (o instanceof Surface && ((Surface)o).getMaterial() == this) {
+ ((Surface)o).setMaterial(this, true);
+ } else if (o instanceof Shape && ((Shape)o).getMaterial() == this) {
+ ((Shape)o).setMaterial(this);
+ } else {
+ ((WObject)o).reclump();
+ }
+ }
+ }
+
+ this.doReclump = false;
+ }
+
+ public synchronized void setTexture(Texture texture) {
+ this.textureName = null;
+ if (this.textures != null && this.textures.length != 1) {
+ this.removeTextures();
+ this.textures = new Texture[1];
+ this.setTexture(0, texture);
+ } else {
+ if (this.textures == null) {
+ this.textures = new Texture[1];
+ } else if (texture == this.textures[0]) {
+ return;
+ }
+
+ this.setTexture(0, texture);
+ }
+ }
+
+ synchronized native Texture extractTexture(int var1);
+
+ private void removeTextures() {
+ if (this.textures != null) {
+ for (int i = 0; i < this.textures.length; i++) {
+ Texture t = this.extractTexture(i);
+ if (t != null) {
+ t.decRef();
+ }
+ }
+
+ this.textures = null;
+ }
+
+ this.hRes = this.vRes = 1;
+ this.sPos = -1;
+ this.closeMaterials();
+ }
+
+ @Override
+ protected void finalize() {
+ this.removeTextures();
+ super.finalize();
+ }
+
+ private native void closeMaterial(int var1);
+
+ private void closeMaterials() {
+ if (this.ids != null) {
+ for (int i = 0; i < this.ids.length; i++) {
+ this.closeMaterial(i);
+ }
+
+ this.ids = null;
+ }
+ }
+
+ private int calcRes() {
+ this.hRes = 1;
+ this.vRes = 1;
+ this.sPos = -1;
+ if (this.textureName == null) {
+ return -1;
+ } else {
+ String name = this.textureName.getInternal();
+ int len = name.length();
+ if (len >= 4 && name.regionMatches(true, len - 4, ".mov", 0, 4)) {
+ this.sPos = 0;
+ }
+
+ if (len > 7 && name.regionMatches(true, len - 5, "*.", 0, 2)) {
+ int num;
+ int nextStarIndex;
+ for (nextStarIndex = len - 5;
+ nextStarIndex > 2 && name.charAt(nextStarIndex) == '*' && (num = name.charAt(nextStarIndex - 2) - '0') > 0 && num <= 9;
+ nextStarIndex -= 3
+ ) {
+ char control = Character.toLowerCase(name.charAt(nextStarIndex - 1));
+ if (control == 'h') {
+ this.hRes = num;
+ } else if (control == 'v') {
+ this.vRes = num;
+ } else if (control == 's' && this.sPos >= 0) {
+ this.sPos = num - 1;
+ }
+ }
+
+ return len - (nextStarIndex + 1);
+ } else {
+ return -1;
+ }
+ }
+ }
+
+ private void loadTextures() {
+ int endLen = this.calcRes();
+ if (endLen >= 0) {
+ String lowResBaseName = this.textureName.getBase();
+ int baseEnd = lowResBaseName.length() - endLen;
+ lowResBaseName = lowResBaseName.substring(0, baseEnd);
+ int numSubs = this.getHRes() * this.getVRes();
+ this.textures = new Texture[numSubs];
+ this.makeMaterials();
+ if (this.sPos >= 0) {
+ this.subnames = new URL[1];
+ this.subnames[0] = URL.make(this.textureName, lowResBaseName + ".mov");
+ BackgroundLoader.get(this, this.subnames[0]);
+ } else {
+ this.subnames = new URL[numSubs];
+ int nextSubname = 0;
+
+ for (int v = this.vRes; v > 0; v--) {
+ String vExt = "" + v;
+
+ for (int h = 0; h < this.hRes; nextSubname++) {
+ URL subname = URL.make(this.textureName, lowResBaseName + vExt + (h + 1) + ".cmp");
+ this.subnames[nextSubname] = subname;
+ BackgroundLoader.get(this, subname);
+ h++;
+ }
+ }
+ }
+ } else {
+ this.subnames = null;
+ this.textures = new Texture[1];
+ this.makeMaterials();
+ BackgroundLoader.get(this, this.textureName);
+ }
+ }
+
+ public void loadTexture(URL textureName) {
+ boolean vis = this.ids != null;
+ this.removeTextures();
+ this.textureName = textureName;
+ this.calcRes();
+ if (vis) {
+ this.addRwChildren();
+ }
+
+ Object o = this.getOwner();
+ if (o instanceof WObject) {
+ ((WObject)o).reclump();
+ }
+ }
+
+ private static native int makeMaterial(float var0, float var1, float var2, float var3, int var4, int var5, int var6, boolean var7);
+
+ private void makeMaterials() {
+ int numSubs = this.getHRes() * this.getVRes();
+ this.ids = new int[numSubs];
+
+ for (int i = 0; i < numSubs; i++) {
+ this.ids[i] = makeMaterial(
+ this.ambient, this.diffuse, this.specular, this.opacity, this.color.getRed(), this.color.getGreen(), this.color.getBlue(), this.smooth
+ );
+ }
+ }
+
+ private void loadError(URL name) {
+ SuperRoot owner = this.getOwner();
+ System.out.println("Unable to load texture " + name + (owner == null ? "" : " for " + owner.getName()) + ".");
+ }
+
+ public float getAmbient() {
+ return this.ambient;
+ }
+
+ public float getDiffuse() {
+ return this.diffuse;
+ }
+
+ public float getSpecular() {
+ return this.specular;
+ }
+
+ public float getOpacity() {
+ return this.opacity;
+ }
+
+ public boolean getSmooth() {
+ return this.smooth;
+ }
+
+ public boolean getFilter() {
+ return this.filter;
+ }
+
+ public boolean getHiRes() {
+ return this.vRes > 1 || this.hRes > 1;
+ }
+
+ public int getVRes() {
+ return this.vRes;
+ }
+
+ public int getHRes() {
+ return this.hRes;
+ }
+
+ public int getRed() {
+ return this.r;
+ }
+
+ public int getGreen() {
+ return this.g;
+ }
+
+ public int getBlue() {
+ return this.b;
+ }
+
+ public Color getColor() {
+ return this.color;
+ }
+
+ public native void paramChange();
+
+ public void setAmbient(float ambient) {
+ this.ambient = ambient;
+ this.paramChange();
+ }
+
+ public void setDiffuse(float diffuse) {
+ this.diffuse = diffuse;
+ this.paramChange();
+ }
+
+ public void setSpecular(float specular) {
+ this.specular = specular;
+ this.paramChange();
+ }
+
+ public void setOpacity(float opacity) {
+ this.opacity = opacity;
+ this.paramChange();
+ }
+
+ public void setSmooth(boolean smooth) {
+ this.smooth = smooth;
+ this.paramChange();
+ }
+
+ public void setFilter(boolean filter) {
+ this.filter = filter;
+ this.paramChange();
+ }
+
+ public void setColor(Color color) {
+ this.color = color;
+ this.r = color.getRed();
+ this.g = color.getGreen();
+ this.b = color.getBlue();
+ this.paramChange();
+ }
+
+ @Override
+ public Object asyncBackgroundLoad(String localName, URL remoteURL) {
+ return localName;
+ }
+
+ @Override
+ public boolean syncBackgroundLoad(Object obj, URL remoteURL) {
+ int texNum = 0;
+ if (this.textures == null) {
+ return false;
+ } else {
+ String urlString = remoteURL.getAbsolute();
+ String avatarDir = IniFile.gamma().getIniString("avatarDir", "avatar/");
+ if (!avatarDir.endsWith("/")) {
+ avatarDir = avatarDir + "/";
+ }
+
+ String avStart = URL.make(NetUpdate.getUpgradeServerURL() + avatarDir).getAbsolute();
+ String remoteBase = remoteURL == null ? null : remoteURL.getBase();
+ String textureBase = this.textureName == null ? null : this.textureName.getBase();
+ if (!remoteBase.equals(textureBase)) {
+ if (this.textureName != null && this.textureName.endsWith(".mov")) {
+ String rawBase = this.textureName.getBaseWithoutExt();
+ String rawRemote = remoteURL.getBaseWithoutExt();
+ if (!rawBase.startsWith(rawRemote)) {
+ return false;
+ }
+ } else {
+ if (this.subnames == null) {
+ return false;
+ }
+
+ while (texNum < this.subnames.length) {
+ String subBase = this.subnames[texNum].getBase();
+ if (remoteBase.equals(subBase)) {
+ break;
+ }
+
+ texNum++;
+ }
+
+ if (texNum == this.textures.length) {
+ return false;
+ }
+ }
+ }
+
+ String localName = (String)obj;
+ if (this.ids == null) {
+ return false;
+ } else {
+ if (localName != null) {
+ if (this.sPos < 0) {
+ Texture t = TextureDecoder.decode(remoteURL, localName);
+ if (t != null && t.textureID != 0) {
+ this.setTexture(texNum, t);
+ } else {
+ localName = null;
+ }
+ } else {
+ Texture[] ts = new ScapePicMovie(localName, remoteURL).getTextures();
+ if (ts != null && this.hRes * this.vRes * (this.sPos + 1) <= ts.length) {
+ int i = this.hRes * this.vRes * this.sPos;
+
+ for (int v = (this.vRes - 1) * this.hRes; v >= 0; v -= this.hRes) {
+ for (int h = 0; h < this.hRes; i++) {
+ this.setTexture(v + h, ts[i]);
+ h++;
+ }
+ }
+ } else {
+ localName = null;
+ }
+ }
+ } else {
+ int len = urlString.length();
+ if (tryBMP && this.sPos == -1 && len > 4 && urlString.regionMatches(true, len - 4, ".cmp", 0, 4) && !remoteURL.isRemote()) {
+ String lName = urlString.substring(0, len - 4) + ".bmp";
+ Texture t = TextureDecoder.decode(URL.make(lName), lName);
+ if (t != null && t.textureID != 0) {
+ this.setTexture(texNum, t);
+ localName = lName;
+ }
+ }
+ }
+
+ if (localName == null) {
+ if (urlString.startsWith("avatar:")) {
+ BackgroundLoader.get(this, URL.make(avStart + urlString.substring(7)));
+ return false;
+ }
+
+ this.loadError(remoteURL);
+ }
+
+ return false;
+ }
+ }
+ }
+
+ @Override
+ public Room getBackgroundLoadRoom() {
+ WObject owner = (WObject)this.getOwner();
+ return owner == null ? null : owner.getRoom();
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(4, classCookie);
+ super.saveState(s);
+ s.saveFloat(this.getAmbient());
+ s.saveFloat(this.getDiffuse());
+ s.saveFloat(this.getSpecular());
+ s.saveFloat(this.getOpacity());
+ s.saveBoolean(this.getSmooth());
+ s.saveBoolean(this.getFilter());
+ s.saveInt(this.getRed());
+ s.saveInt(this.getGreen());
+ s.saveInt(this.getBlue());
+ URL.save(s, this.textureName);
+ s.saveBoolean(this.keepLoaded);
+ if (this.textureName == null) {
+ if (this.textures != null && this.textures.length != 1) {
+ s.saveMaybeNull(null);
+ } else {
+ s.saveMaybeNull(this.textures == null ? null : this.textures[0]);
+ }
+ }
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ Texture texture = null;
+ int vers = r.restoreVersion(classCookie);
+ switch (vers) {
+ case 1:
+ super.restoreState(r);
+ case 0: {
+ this.ambient = r.restoreFloat();
+ this.diffuse = r.restoreFloat();
+ this.specular = r.restoreFloat();
+ this.opacity = r.restoreFloat();
+ int red = r.restoreInt();
+ int green = r.restoreInt();
+ int blue = r.restoreInt();
+ this.setColor(new Color(red, green, blue));
+ texture = (Texture)r.restoreMaybeNull();
+ break;
+ }
+ case 2:
+ case 3:
+ case 4: {
+ super.restoreState(r);
+ this.ambient = r.restoreFloat();
+ this.diffuse = r.restoreFloat();
+ this.specular = r.restoreFloat();
+ this.opacity = r.restoreFloat();
+ if (vers > 3) {
+ this.smooth = r.restoreBoolean();
+ this.filter = r.restoreBoolean();
+ }
+
+ int red = r.restoreInt();
+ int green = r.restoreInt();
+ int blue = r.restoreInt();
+ this.setColor(new Color(red, green, blue));
+ URL name = URL.restore(r);
+ if (vers > 2) {
+ this.setKeepLoaded(r.restoreBoolean());
+ }
+
+ if (name == null) {
+ texture = (Texture)r.restoreMaybeNull();
+ } else {
+ this.loadTexture(name);
+ }
+ break;
+ }
+ default:
+ throw new TooNewException();
+ }
+
+ if (texture != null) {
+ this.textures = new Texture[1];
+ this.textures[0] = texture;
+ }
+
+ assert r.version() >= 6 || this.getOwner() == null;
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = new Property(this, index, "Texture").allowSetNull();
+ } else if (mode == 1) {
+ MaterialTexture mt;
+ if (this.textures != null && this.textures[0] instanceof StringTexture) {
+ mt = new MaterialTexture((StringTexture)this.textures[0]);
+ } else {
+ mt = new MaterialTexture(this.textureName);
+ }
+
+ this.add(mt);
+ ret = mt;
+ } else if (mode == 2) {
+ if (value == null) {
+ this.loadTexture(null);
+ } else {
+ Console.println(Console.message("Cant-undo-tex"));
+ }
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = ColorPropertyEditor.make(new Property(this, index, "Color"));
+ } else if (mode == 1) {
+ ret = this.getColor();
+ } else if (mode == 2) {
+ this.setColor((Color)value);
+ }
+ break;
+ case 2:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Ambient Reflection Coefficient"), 0.0F, 1.0F);
+ } else if (mode == 1) {
+ ret = new Float(this.getAmbient());
+ } else if (mode == 2) {
+ this.setAmbient((Float)value);
+ }
+ break;
+ case 3:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Diffuse Reflection Coefficient"), 0.0F, 1.0F);
+ } else if (mode == 1) {
+ ret = new Float(this.getDiffuse());
+ } else if (mode == 2) {
+ this.setDiffuse((Float)value);
+ }
+ break;
+ case 4:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Specular Reflection Coefficient"), 0.0F, 1.0F);
+ } else if (mode == 1) {
+ ret = new Float(this.getSpecular());
+ } else if (mode == 2) {
+ this.setSpecular((Float)value);
+ }
+ break;
+ case 5:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Opacity"), 0.0F, 1.0F);
+ } else if (mode == 1) {
+ ret = new Float(this.getOpacity());
+ } else if (mode == 2) {
+ this.setOpacity((Float)value);
+ }
+ break;
+ case 6:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Smooth"), "No", "Yes");
+ } else if (mode == 1) {
+ ret = new Boolean(this.getSmooth());
+ } else if (mode == 2) {
+ this.setSmooth((Boolean)value);
+ }
+ break;
+ case 7:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Filter"), "No", "Yes");
+ } else if (mode == 1) {
+ ret = new Boolean(this.getFilter());
+ } else if (mode == 2) {
+ this.setFilter((Boolean)value);
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 8, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public String toString() {
+ return this.getName()
+ + "["
+ + (this.textureName != null ? this.textureName.toString() : (this.textures == null ? null : this.textures.toString()))
+ + ", "
+ + this.getColor()
+ + ", Ambient "
+ + this.getAmbient()
+ + ", Diffuse "
+ + this.getDiffuse()
+ + ", Specular "
+ + this.getSpecular()
+ + ", Opacity "
+ + this.getOpacity()
+ + ", Smooth "
+ + this.getSmooth()
+ + ", Filter "
+ + this.getFilter()
+ + ", hRes "
+ + this.hRes
+ + ", vRes "
+ + this.vRes
+ + ", loResMode "
+ + false
+ + "]";
+ }
+}