diff options
| author | Fuwn <[email protected]> | 2026-02-12 22:33:32 -0800 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2026-02-12 22:33:32 -0800 |
| commit | c7a9d4a6bd53ed7d61731770f2f10e8b9fd435f9 (patch) | |
| tree | df9f48bf128a6c0186a8e91857d6ff30fe0e9f18 /NET/worlds/scape/Material.java | |
| download | worldsplayer-c7a9d4a6bd53ed7d61731770f2f10e8b9fd435f9.tar.xz worldsplayer-c7a9d4a6bd53ed7d61731770f2f10e8b9fd435f9.zip | |
Initial commit
Diffstat (limited to 'NET/worlds/scape/Material.java')
| -rw-r--r-- | NET/worlds/scape/Material.java | 783 |
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 + + "]"; + } +} |