mirror of
https://github.com/lexi-lambda/shattered-plans.git
synced 2024-11-22 02:52:23 +03:00
Initial public commit
This commit is contained in:
commit
a32a523931
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
.idea/
|
||||
*.iml
|
||||
target
|
50
README.md
Normal file
50
README.md
Normal file
@ -0,0 +1,50 @@
|
||||
# Shattered Plans
|
||||
|
||||
Shattered Plans is a turn-based strategy game by [Jagex Ltd.][jagex] It was originally released in 2008 as part of [FunOrb][], which was sadly shut down in 2018 without any successor. This repository is a fan project that restores Shattered Plans to a playable state. Based on a decompiled archive of the original Shattered Plans client, it includes a reimplementation of the original FunOrb server, which makes Shattered Plans playable again in both singleplayer and multiplayer modes.
|
||||
|
||||
[![Screenshot of Shattered Plans gameplay.][screenshot.png]][screenshot.png]
|
||||
|
||||
## Running the game
|
||||
|
||||
Running Shattered Plans requires [Java 17 or newer][download-java] and the latest version of the game JAR. You can then run the game by running the following command:
|
||||
|
||||
```sh
|
||||
java -jar shattered-plans-0.0.5.jar --local-server
|
||||
```
|
||||
|
||||
As the name suggests, passing the `--local-server` flag will run a Shattered Plans server locally, allowing you to play the game in singleplayer mode. Other players can connect to your server by running
|
||||
|
||||
```sh
|
||||
java -jar shattered-plans-0.0.5.jar --host <HOST>
|
||||
```
|
||||
|
||||
replacing `<HOST>` with your IP address. By default, the server runs on port 43594, but you can specify a different port using the `--port` flag. A few other options are also available, pass `--help` to see them all.
|
||||
|
||||
## What works, what doesn’t, and other limitations
|
||||
|
||||
All singleplayer functionality should work flawlessly. Most multiplayer functionality works as well. However, there are some bugs, unimplemented features, and other limitations:
|
||||
|
||||
* When you start the game, you will be presented with a login screen. You may enter any username/password combination you like, and the server will not check it. In fact, attempting to create an account will not work: the server does not record any persistent user state.
|
||||
|
||||
* Lobby and in-game chat are supported, but adding users to your friends or ignore list is not, so there is no way to send private messages.
|
||||
|
||||
* Resigning is implemented, but offering a draw or a rematch is not currently supported.
|
||||
|
||||
* Rated games are not implemented.
|
||||
|
||||
* Achievements are not implemented.
|
||||
|
||||
* There may be bugs in the server protocol, which can lead to disconnects or desyncs. Please report any bugs you come across, providing as much information as possible, and I will do my best to fix them.
|
||||
|
||||
There are also some very minor improvements over the original game, but these will most likely not even be noticeable to most players.
|
||||
|
||||
## Community
|
||||
|
||||
If you’d like to find people to play with, or if you have any questions, [join the FunOrb discord server!][funorb-discord] This is obviously a small hobby project, so I cannot guarantee my time, but I’ll do my best to be helpful.
|
||||
|
||||
[screenshot.png]: docs/screenshot.png
|
||||
|
||||
[download-java]: https://www.oracle.com/java/technologies/downloads/
|
||||
[FunOrb]: https://en.wikipedia.org/wiki/FunOrb
|
||||
[funorb-discord]: https://discord.gg/MGfDrDf
|
||||
[jagex]: https://www.jagex.com/
|
45
docs/cache.md
Normal file
45
docs/cache.md
Normal file
@ -0,0 +1,45 @@
|
||||
# The resource cache
|
||||
|
||||
All game resources are identified by an integer triple consisting of a page id, a group id, and an item id. A *page id* is an integer in the range [0, 254] that identifies a *resource page*, which is a group of broadly related resources. Shattered Plans uses the following resource pages:
|
||||
|
||||
| page id | contents |
|
||||
| ------: | ---------------------------------------------------------------- |
|
||||
| `0x00` | common string constants |
|
||||
| `0x01` | common graphics |
|
||||
| `0x02` | common font data |
|
||||
| `0x03` | huffman codes |
|
||||
| `0x04` | Shattered Plans string constants |
|
||||
| `0x05` | Shattered Plans graphics |
|
||||
| `0x06` | Shattered Plans JPEG graphics |
|
||||
| `0x07` | Shattered Plans font data |
|
||||
| `0x08` | Shattered Plans sound effects 1 |
|
||||
| `0x09` | Shattered Plans sound effects 2 |
|
||||
| `0x0A` | Shattered Plans music 1 |
|
||||
| `0x0B` | Shattered Plans music 2 |
|
||||
| `0x0C` | Shattered Plans extra strings (tutorial messages and star names) |
|
||||
| `0x0D` | Quick Chat data |
|
||||
| `0x0E` | Jagex logo animation data |
|
||||
|
||||
On the server, pages are stored in a set of `res_xx_yyyy.dat` files, where `xx` is a (hexadecimal) page id and `yyyy` is a group id. Many pages only have a single group, which is usually (but not always) `0000`, but some pages are split into multiple groups.
|
||||
|
||||
Each page has an associated *page index*, which maps string group and item names to integer group and item ids. On disk, page indexes are stored in special `res_FF_00xx.dat` files, where `xx` is the page id. This is why there are only 254 page ids: the special `0xFF` pseudo-page id is reserved for index data.
|
||||
|
||||
Finally, the special `res_FF_00FF.dat` file stores the *master index*. The master index stores a table of all the page ids known to the server, and it includes a version number for the page, along with a CRC32 and a Whirlpool hash of the page index file.
|
||||
|
||||
## `MasterIndex` format
|
||||
|
||||
| type | description |
|
||||
| ------------------------------- | ------------------------------------------ |
|
||||
| 5 bytes | unknown |
|
||||
| `u8` | `pageCount` |
|
||||
| `MasterIndexEntry[pageCount]` | |
|
||||
| 1 byte | unknown |
|
||||
| `u8[64]` | whirlpool hash of the master index entries |
|
||||
|
||||
### `MasterIndexEntry` format
|
||||
|
||||
| type | description |
|
||||
| ------------------ | ------------------------------------------ |
|
||||
| `u32` | CRC32 of the page index data |
|
||||
| `u32` | page version |
|
||||
| `u8[64]` | whirlpool hash of the page index data |
|
BIN
docs/screenshot.png
Normal file
BIN
docs/screenshot.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 389 KiB |
122
pom.xml
Normal file
122
pom.xml
Normal file
@ -0,0 +1,122 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>net.alterorb</groupId>
|
||||
<artifactId>shatteredplans</artifactId>
|
||||
<version>0.0.5</version>
|
||||
|
||||
<name>Shattered Plans</name>
|
||||
<url>https://alterorb.net</url>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.compiler.release>17</maven.compiler.release>
|
||||
<netty.version>4.1.79.Final</netty.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains</groupId>
|
||||
<artifactId>annotations</artifactId>
|
||||
<version>23.0.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.xerial</groupId>
|
||||
<artifactId>sqlite-jdbc</artifactId>
|
||||
<version>3.36.0.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-transport</artifactId>
|
||||
<version>${netty.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-handler</artifactId>
|
||||
<version>${netty.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-cli</groupId>
|
||||
<artifactId>commons-cli</artifactId>
|
||||
<version>1.5.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.1</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>default-jar</id>
|
||||
<configuration>
|
||||
<forceCreation>true</forceCreation>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.3.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||
<filters>
|
||||
<filter>
|
||||
<artifact>*:*</artifact>
|
||||
<excludes>
|
||||
<exclude>META-INF/**/module-info.class</exclude>
|
||||
<exclude>META-INF/MANIFEST.MF</exclude>
|
||||
<exclude>META-INF/**/pom.xml</exclude>
|
||||
<exclude>META-INF/**/*.properties</exclude>
|
||||
</excludes>
|
||||
</filter>
|
||||
</filters>
|
||||
<transformers>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
|
||||
<mainClass>launcher.ShatteredPlansLauncher</mainClass>
|
||||
</transformer>
|
||||
</transformers>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>se.eris</groupId>
|
||||
<artifactId>notnull-instrumenter-maven-plugin</artifactId>
|
||||
<version>1.1.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>instrument</goal>
|
||||
<goal>tests-instrument</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains</groupId>
|
||||
<artifactId>annotations</artifactId>
|
||||
<version>23.0.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
441
src/main/java/funorb/Strings.java
Normal file
441
src/main/java/funorb/Strings.java
Normal file
@ -0,0 +1,441 @@
|
||||
package funorb;
|
||||
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Range;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
public final class Strings {
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public static final char NON_BREAKING_SPACE = '\u00A0';
|
||||
public static final char EM_DASH = '\u2014';
|
||||
|
||||
/**
|
||||
* Contains the characters encoded as {@code 0x80}–{@code 0x9F} under
|
||||
* Windows-1252 (commonly known as “Latin-1”). These are the only characters
|
||||
* in the Windows-1252 code page that are not encoded the same way in Unicode.
|
||||
*/
|
||||
public static final char[] WINDOWS_1252_CHARS = {'€', 0, '‚', 'ƒ', '„', '…', '†', '‡', 'ˆ', '‰', 'Š', '‹', 'Œ', 0, 'Ž', 0, 0, '‘', '’', '“', '”', '•', '–', '—', '˜', '™', 'š', '›', 'œ', 0, 'ž', 'Ÿ'};
|
||||
private static final int WINDOWS_1252_SPECIALS_START = 0x80;
|
||||
private static final int WINDOWS_1252_SPECIALS_END = 0x9f;
|
||||
|
||||
private static final char[] NORMALIZABLE_CHARS = {' ', NON_BREAKING_SPACE, '_', '-', 'à', 'á', 'â', 'ä', 'ã', 'À', 'Á', 'Â', 'Ä', 'Ã', 'è', 'é', 'ê', 'ë', 'È', 'É', 'Ê', 'Ë', 'í', 'î', 'ï', 'Í', 'Î', 'Ï', 'ò', 'ó', 'ô', 'ö', 'õ', 'Ò', 'Ó', 'Ô', 'Ö', 'Õ', 'ù', 'ú', 'û', 'ü', 'Ù', 'Ú', 'Û', 'Ü', 'ç', 'Ç', 'ÿ', 'Ÿ', 'ñ', 'Ñ', 'ß'};
|
||||
private static final char[] EXTRA_NORMALIZABLE_CHARS = {'[', ']', '#'};
|
||||
|
||||
private static boolean isSpecialWindows1252Byte(final int n) {
|
||||
return n >= WINDOWS_1252_SPECIALS_START && n <= WINDOWS_1252_SPECIALS_END;
|
||||
}
|
||||
|
||||
@Contract(pure = true)
|
||||
public static char decode1252Char(final byte b) {
|
||||
final int n = b & 255;
|
||||
if (n == 0) {
|
||||
throw new IllegalArgumentException("unexpected NUL char");
|
||||
}
|
||||
if (isSpecialWindows1252Byte(n)) {
|
||||
final char c = WINDOWS_1252_CHARS[n - 128];
|
||||
if (c == 0) {
|
||||
return '?';
|
||||
} else {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
return (char) n;
|
||||
}
|
||||
|
||||
@Contract(value = "_, _, _ -> new", pure = true)
|
||||
public static @NotNull String decode1252String(final byte[] bytes, final int startPos, final int byteLen) {
|
||||
final char[] chars = new char[byteLen];
|
||||
int strLen = 0;
|
||||
for (int i = 0; i < byteLen; ++i) {
|
||||
final byte encoded = bytes[i + startPos];
|
||||
if (encoded == 0) continue; // ignore NULs
|
||||
chars[strLen++] = decode1252Char(encoded);
|
||||
}
|
||||
return new String(chars, 0, strLen);
|
||||
}
|
||||
|
||||
public static String decode1252String(final byte[] bytes) {
|
||||
return decode1252String(bytes, 0, bytes.length);
|
||||
}
|
||||
|
||||
public static byte encode1252Char(final char c) {
|
||||
if (c == 0) {
|
||||
return '?';
|
||||
} else if (c < WINDOWS_1252_SPECIALS_START || (c > WINDOWS_1252_SPECIALS_END && c <= 0xff)) {
|
||||
return (byte) c;
|
||||
} else {
|
||||
return switch (c) {
|
||||
case 0x20ac -> 0xffffff80;
|
||||
case 0x201a -> 0xffffff82;
|
||||
case 0x0192 -> 0xffffff83;
|
||||
case 0x201e -> 0xffffff84;
|
||||
case 0x2026 -> 0xffffff85;
|
||||
case 0x2020 -> 0xffffff86;
|
||||
case 0x2021 -> 0xffffff87;
|
||||
case 0x02c6 -> 0xffffff88;
|
||||
case 0x2030 -> 0xffffff89;
|
||||
case 0x0160 -> 0xffffff8a;
|
||||
case 0x2039 -> 0xffffff8b;
|
||||
case 0x0152 -> 0xffffff8c;
|
||||
case 0x017d -> 0xffffff8e;
|
||||
case 0x2018 -> 0xffffff91;
|
||||
case 0x2019 -> 0xffffff92;
|
||||
case 0x201c -> 0xffffff93;
|
||||
case 0x201d -> 0xffffff94;
|
||||
case 0x2022 -> 0xffffff95;
|
||||
case 0x2013 -> 0xffffff96;
|
||||
case 0x2014 -> 0xffffff97;
|
||||
case 0x02dc -> 0xffffff98;
|
||||
case 0x2122 -> 0xffffff99;
|
||||
case 0x0161 -> 0xffffff9a;
|
||||
case 0x203a -> 0xffffff9b;
|
||||
case 0x0153 -> 0xffffff9c;
|
||||
case 0x017e -> 0xffffff9e;
|
||||
case 0x0178 -> 0xffffff9f;
|
||||
default -> '?';
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public static int encode1252String(final CharSequence src, final byte[] dest, final int destOffset, final int len) {
|
||||
for (int i = 0; i < len; ++i) {
|
||||
final char c = src.charAt(i);
|
||||
dest[destOffset + i] = encode1252Char(c);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
@Contract(value = "_ -> new", pure = true)
|
||||
public static byte[] encode1252String(final CharSequence cs) {
|
||||
final byte[] bs = new byte[cs.length()];
|
||||
encode1252String(cs, bs, 0, cs.length());
|
||||
return bs;
|
||||
}
|
||||
|
||||
public static boolean isAlphanumeric(final char c) {
|
||||
return c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z';
|
||||
}
|
||||
|
||||
private static char normalize(final char c) {
|
||||
if (c == ' ' || c == NON_BREAKING_SPACE || c == '_' || c == '-') {
|
||||
return '_';
|
||||
} else if (c == '[' || c == ']' || c == '#') {
|
||||
return c;
|
||||
} else if (c == 224 || c == 225 || c == 226 || c == 228 || c == 227 || c == 192 || c == 193 || c == 194 || c == 196 || c == 195) {
|
||||
return 'a';
|
||||
} else if (c == 232 || c == 233 || c == 234 || c == 235 || c == 200 || c == 201 || c == 202 || c == 203) {
|
||||
return 'e';
|
||||
} else if (c == 237 || c == 238 || c == 239 || c == 205 || c == 206 || c == 207) {
|
||||
return 'i';
|
||||
} else if (c == 242 || c == 243 || c == 244 || c == 246 || c == 245 || c == 210 || c == 211 || c == 212 || c == 214 || c == 213) {
|
||||
return 'o';
|
||||
} else if (c == 249 || c == 250 || c == 251 || c == 252 || c == 217 || c == 218 || c == 219 || c == 220) {
|
||||
return 'u';
|
||||
} else if (c == 231 || c == 199) {
|
||||
return 'c';
|
||||
} else if (c == 255 || c == 376) {
|
||||
return 'y';
|
||||
} else if (c == 241 || c == 209) {
|
||||
return 'n';
|
||||
} else if (c == 223) {
|
||||
return 'b';
|
||||
} else {
|
||||
return Character.toLowerCase(c);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isNormalizable(final char c) {
|
||||
if (Character.isISOControl(c)) {
|
||||
return false;
|
||||
} else if (isAlphanumeric(c)) {
|
||||
return true;
|
||||
} else {
|
||||
for (final char item : NORMALIZABLE_CHARS) {
|
||||
if (c == item) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
for (final char item : EXTRA_NORMALIZABLE_CHARS) {
|
||||
if (c == item) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Contract(value = "null -> null", pure = true)
|
||||
public static String normalize(final CharSequence str) {
|
||||
if (str == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int startPos = 0;
|
||||
int endPos = str.length();
|
||||
while (startPos < endPos && isSpaceLikeUsernameChar(str.charAt(startPos))) {
|
||||
++startPos;
|
||||
}
|
||||
while (endPos > startPos && isSpaceLikeUsernameChar(str.charAt(endPos - 1))) {
|
||||
--endPos;
|
||||
}
|
||||
|
||||
final int len = endPos - startPos;
|
||||
if (len < 1 || len > 12) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final StringBuilder sb = new StringBuilder(len);
|
||||
for (int i = startPos; i < endPos; ++i) {
|
||||
final char c = str.charAt(i);
|
||||
if (isNormalizable(c)) {
|
||||
final char normalized = normalize(c);
|
||||
if (normalized != 0) {
|
||||
sb.append(normalized);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sb.isEmpty()) {
|
||||
return null;
|
||||
} else {
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
public static @NotNull String normalizeIfPossible(final @NotNull String str) {
|
||||
return Objects.requireNonNullElse(normalize(str), str);
|
||||
}
|
||||
|
||||
public static boolean isSpaceLikeUsernameChar(final char c) {
|
||||
return c == ' ' || c == NON_BREAKING_SPACE || c == '_' || c == '-';
|
||||
}
|
||||
|
||||
public static boolean isAlpha(final char var1) {
|
||||
return var1 >= 'A' && var1 <= 'Z' || var1 >= 'a' && var1 <= 'z';
|
||||
}
|
||||
|
||||
public static boolean isDigit(final char c) {
|
||||
return c >= '0' && c <= '9';
|
||||
}
|
||||
|
||||
@Contract(pure = true)
|
||||
public static String format(final String template, final String... params) {
|
||||
final int var3 = template.length();
|
||||
int var4 = var3;
|
||||
int var5 = 0;
|
||||
|
||||
while (true) {
|
||||
final int var6 = template.indexOf("<%", var5);
|
||||
int var8;
|
||||
if (var6 < 0) {
|
||||
|
||||
final StringBuilder var11 = new StringBuilder(var4);
|
||||
var5 = 0;
|
||||
int var12 = 0;
|
||||
|
||||
while (true) {
|
||||
var8 = template.indexOf("<%", var5);
|
||||
if (var8 < 0) {
|
||||
var11.append(template.substring(var12));
|
||||
return var11.toString();
|
||||
}
|
||||
|
||||
var5 = 2 + var8;
|
||||
while (var3 > var5 && isDigit(template.charAt(var5))) {
|
||||
++var5;
|
||||
}
|
||||
|
||||
final String var9 = template.substring(var8 + 2, var5);
|
||||
if (a783wk(var9) && var5 < var3 && template.charAt(var5) == '>') {
|
||||
++var5;
|
||||
final int var10 = parseDecimalInteger(var9);
|
||||
var11.append(template, var12, var8);
|
||||
var11.append(params[var10]);
|
||||
var12 = var5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var5 = var6 + 2;
|
||||
while (var5 < var3 && isDigit(template.charAt(var5))) {
|
||||
++var5;
|
||||
}
|
||||
|
||||
final String var7 = template.substring(2 + var6, var5);
|
||||
if (a783wk(var7) && var5 < var3 && template.charAt(var5) == '>') {
|
||||
++var5;
|
||||
var8 = parseDecimalInteger(var7);
|
||||
var4 += params[var8].length() - var5 + var6;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static int parseDecimalInteger(final CharSequence var0) {
|
||||
return parseInteger(10, var0);
|
||||
}
|
||||
|
||||
@Contract(pure = true)
|
||||
private static int parseInteger(@Range(from = 2, to = 36) final int base, final CharSequence var1) {
|
||||
boolean var3 = false;
|
||||
boolean var5 = false;
|
||||
int var6 = 0;
|
||||
final int var7 = var1.length();
|
||||
|
||||
for (int var8 = 0; var7 > var8; ++var8) {
|
||||
final char var9 = var1.charAt(var8);
|
||||
if (var8 == 0) {
|
||||
if (var9 == '-') {
|
||||
var3 = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (var9 == '+') {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
int var11;
|
||||
if (var9 >= '0' && var9 <= '9') {
|
||||
var11 = var9 - 48;
|
||||
} else if (var9 >= 'A' && var9 <= 'Z') {
|
||||
var11 = var9 - 55;
|
||||
} else {
|
||||
if (var9 < 'a' || var9 > 'z') {
|
||||
throw new NumberFormatException();
|
||||
}
|
||||
|
||||
var11 = var9 - 87;
|
||||
}
|
||||
|
||||
if (var11 >= base) {
|
||||
throw new NumberFormatException();
|
||||
}
|
||||
|
||||
if (var3) {
|
||||
var11 = -var11;
|
||||
}
|
||||
|
||||
final int var10 = var6 * base + var11;
|
||||
if (var10 / base != var6) {
|
||||
throw new NumberFormatException();
|
||||
}
|
||||
|
||||
var5 = true;
|
||||
var6 = var10;
|
||||
}
|
||||
|
||||
if (var5) {
|
||||
return var6;
|
||||
} else {
|
||||
throw new NumberFormatException();
|
||||
}
|
||||
}
|
||||
|
||||
@Contract(pure = true)
|
||||
public static boolean a783wk(final CharSequence var1) {
|
||||
boolean var4 = false;
|
||||
boolean var5 = false;
|
||||
int var6 = 0;
|
||||
final int var7 = var1.length();
|
||||
|
||||
for (int var9 = 0; var9 < var7; ++var9) {
|
||||
final char var10 = var1.charAt(var9);
|
||||
if (var9 == 0) {
|
||||
if (var10 == '-') {
|
||||
var4 = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (var10 == '+') {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
int var12;
|
||||
if (var10 >= '0' && var10 <= '9') {
|
||||
var12 = var10 - 48;
|
||||
} else if (var10 >= 'A' && var10 <= 'Z') {
|
||||
var12 = var10 - 55;
|
||||
} else {
|
||||
if (var10 < 'a' || var10 > 'z') {
|
||||
return false;
|
||||
}
|
||||
|
||||
var12 = var10 - 87;
|
||||
}
|
||||
|
||||
if (var12 >= 10) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (var4) {
|
||||
var12 = -var12;
|
||||
}
|
||||
|
||||
final int var11 = var6 * 10 + var12;
|
||||
if (var11 / 10 != var6) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var6 = var11;
|
||||
var5 = true;
|
||||
}
|
||||
|
||||
return var5;
|
||||
}
|
||||
|
||||
public static int parseHexInteger(final CharSequence var0) {
|
||||
return parseInteger(16, var0);
|
||||
}
|
||||
|
||||
public static String formatNamed(final String template, final String paramName, final String paramValue) {
|
||||
int var5 = template.length();
|
||||
int var6 = 0;
|
||||
final String var7 = "<%" + paramName + ">";
|
||||
|
||||
while (true) {
|
||||
final int var8 = template.indexOf(var7, var6);
|
||||
if (var8 < 0) {
|
||||
var6 = 0;
|
||||
final StringBuilder var10 = new StringBuilder(var5);
|
||||
|
||||
while (true) {
|
||||
final int var9 = template.indexOf(var7, var6);
|
||||
if (var9 < 0) {
|
||||
var10.append(template, var6, template.length());
|
||||
return var10.toString();
|
||||
}
|
||||
|
||||
var10.append(template, var6, var9);
|
||||
var10.append(paramValue);
|
||||
var6 = var7.length() + var9;
|
||||
}
|
||||
}
|
||||
|
||||
var6 = var8 + var7.length();
|
||||
var5 += paramValue.length() - var7.length();
|
||||
}
|
||||
}
|
||||
|
||||
public static String[] splitLines(final String str) {
|
||||
final String[] lines = str.split("\n");
|
||||
Arrays.setAll(lines, var4 -> lines[var4].trim());
|
||||
return lines;
|
||||
}
|
||||
|
||||
public static int lastIndexOf(final String str, final String sub) {
|
||||
int nextIndex = str.indexOf(sub);
|
||||
int prevIndex = nextIndex;
|
||||
while (nextIndex != -1) {
|
||||
prevIndex = nextIndex;
|
||||
nextIndex = str.indexOf(sub, 1 + nextIndex);
|
||||
}
|
||||
return prevIndex;
|
||||
}
|
||||
}
|
38
src/main/java/funorb/audio/AudioThread.java
Normal file
38
src/main/java/funorb/audio/AudioThread.java
Normal file
@ -0,0 +1,38 @@
|
||||
package funorb.audio;
|
||||
|
||||
import funorb.client.JagexBaseApplet;
|
||||
import funorb.shatteredplans.client.MessagePumpThread;
|
||||
|
||||
public final class AudioThread implements Runnable {
|
||||
public static final int NUM_CHANNELS = 2;
|
||||
public static AudioThread instance;
|
||||
|
||||
public final SampledAudioChannel[] channels = new SampledAudioChannel[NUM_CHANNELS];
|
||||
private final MessagePumpThread messagePumpThread;
|
||||
public volatile boolean shutdownRequested = false;
|
||||
public volatile boolean isRunning = false;
|
||||
|
||||
public AudioThread(final MessagePumpThread messagePumpThread) {
|
||||
this.messagePumpThread = messagePumpThread;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
this.isRunning = true;
|
||||
try {
|
||||
while (!this.shutdownRequested) {
|
||||
for (int i = 0; i < NUM_CHANNELS; ++i) {
|
||||
final SampledAudioChannel channel = this.channels[i];
|
||||
if (channel != null) {
|
||||
channel.doSomethingThatSeemsRelatedToAudio();
|
||||
}
|
||||
}
|
||||
|
||||
JagexBaseApplet.maybeSleep(10L);
|
||||
this.messagePumpThread.postEvent(null);
|
||||
}
|
||||
} finally {
|
||||
this.isRunning = false;
|
||||
}
|
||||
}
|
||||
}
|
408
src/main/java/funorb/audio/MusicTrack.java
Normal file
408
src/main/java/funorb/audio/MusicTrack.java
Normal file
@ -0,0 +1,408 @@
|
||||
package funorb.audio;
|
||||
|
||||
import funorb.cache.ResourceLoader;
|
||||
import funorb.io.Buffer;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public final class MusicTrack {
|
||||
public byte[] _h;
|
||||
public Map<Integer, byte[]> _i;
|
||||
|
||||
private MusicTrack(final Buffer var1) {
|
||||
var1.pos = var1.data.length - 3;
|
||||
final int var2 = var1.readUByte();
|
||||
final int var3 = var1.readUShort();
|
||||
int var4 = 14 + var2 * 10;
|
||||
var1.pos = 0;
|
||||
int var5 = 0;
|
||||
int var6 = 0;
|
||||
int var7 = 0;
|
||||
int var8 = 0;
|
||||
int var9 = 0;
|
||||
int var10 = 0;
|
||||
int var11 = 0;
|
||||
int var12 = 0;
|
||||
|
||||
int var13;
|
||||
int var14;
|
||||
int var15;
|
||||
for (var13 = 0; var13 < var2; ++var13) {
|
||||
var14 = -1;
|
||||
|
||||
while (true) {
|
||||
var15 = var1.readUByte();
|
||||
if (var15 != var14) {
|
||||
++var4;
|
||||
}
|
||||
|
||||
var14 = var15 & 15;
|
||||
if (var15 == 7) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (var15 == 23) {
|
||||
++var5;
|
||||
} else if (var14 == 0) {
|
||||
++var7;
|
||||
} else if (var14 == 1) {
|
||||
++var8;
|
||||
} else if (var14 == 2) {
|
||||
++var6;
|
||||
} else if (var14 == 3) {
|
||||
++var9;
|
||||
} else if (var14 == 4) {
|
||||
++var10;
|
||||
} else if (var14 == 5) {
|
||||
++var11;
|
||||
} else {
|
||||
if (var14 != 6) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
|
||||
++var12;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var4 += 5 * var5;
|
||||
var4 += 2 * (var7 + var8 + var6 + var9 + var11);
|
||||
var4 += var10 + var12;
|
||||
var13 = var1.pos;
|
||||
var14 = var2 + var5 + var6 + var7 + var8 + var9 + var10 + var11 + var12;
|
||||
|
||||
for (var15 = 0; var15 < var14; ++var15) {
|
||||
var1.readVariableInt();
|
||||
}
|
||||
|
||||
var4 += var1.pos - var13;
|
||||
var15 = var1.pos;
|
||||
int var16 = 0;
|
||||
int var17 = 0;
|
||||
int var18 = 0;
|
||||
int var19 = 0;
|
||||
int var20 = 0;
|
||||
int var21 = 0;
|
||||
int var22 = 0;
|
||||
int var23 = 0;
|
||||
int var24 = 0;
|
||||
int var25 = 0;
|
||||
int var26 = 0;
|
||||
int var27 = 0;
|
||||
int var28 = 0;
|
||||
|
||||
int var29;
|
||||
for (var29 = 0; var29 < var6; ++var29) {
|
||||
var28 = var28 + var1.readUByte() & 127;
|
||||
if (var28 == 0 || var28 == 32) {
|
||||
++var12;
|
||||
} else if (var28 == 1) {
|
||||
++var16;
|
||||
} else if (var28 == 33) {
|
||||
++var17;
|
||||
} else if (var28 == 7) {
|
||||
++var18;
|
||||
} else if (var28 == 39) {
|
||||
++var19;
|
||||
} else if (var28 == 10) {
|
||||
++var20;
|
||||
} else if (var28 == 42) {
|
||||
++var21;
|
||||
} else if (var28 == 99) {
|
||||
++var22;
|
||||
} else if (var28 == 98) {
|
||||
++var23;
|
||||
} else if (var28 == 101) {
|
||||
++var24;
|
||||
} else if (var28 == 100) {
|
||||
++var25;
|
||||
} else if (var28 == 64 || var28 == 65 || var28 == 120 || var28 == 121 || var28 == 123) {
|
||||
++var26;
|
||||
} else {
|
||||
++var27;
|
||||
}
|
||||
}
|
||||
|
||||
var29 = 0;
|
||||
int var30 = var1.pos;
|
||||
var1.pos += var26;
|
||||
int var31 = var1.pos;
|
||||
var1.pos += var11;
|
||||
int var32 = var1.pos;
|
||||
var1.pos += var10;
|
||||
int var33 = var1.pos;
|
||||
var1.pos += var9;
|
||||
int var34 = var1.pos;
|
||||
var1.pos += var16;
|
||||
int var35 = var1.pos;
|
||||
var1.pos += var18;
|
||||
int var36 = var1.pos;
|
||||
var1.pos += var20;
|
||||
int var37 = var1.pos;
|
||||
var1.pos += var7 + var8 + var11;
|
||||
int var38 = var1.pos;
|
||||
var1.pos += var7;
|
||||
int var39 = var1.pos;
|
||||
var1.pos += var27;
|
||||
int var40 = var1.pos;
|
||||
var1.pos += var8;
|
||||
int var41 = var1.pos;
|
||||
var1.pos += var17;
|
||||
int var42 = var1.pos;
|
||||
var1.pos += var19;
|
||||
int var43 = var1.pos;
|
||||
var1.pos += var21;
|
||||
int var44 = var1.pos;
|
||||
var1.pos += var12;
|
||||
int var45 = var1.pos;
|
||||
var1.pos += var9;
|
||||
int var46 = var1.pos;
|
||||
var1.pos += var22;
|
||||
int var47 = var1.pos;
|
||||
var1.pos += var23;
|
||||
int var48 = var1.pos;
|
||||
var1.pos += var24;
|
||||
int var49 = var1.pos;
|
||||
var1.pos += var25;
|
||||
int var50 = var1.pos;
|
||||
var1.pos += var5 * 3;
|
||||
this._h = new byte[var4];
|
||||
final Buffer var51 = new Buffer(this._h);
|
||||
var51.writeInt(1297377380);
|
||||
var51.writeInt(6);
|
||||
var51.writeShort(var2 > 1 ? 1 : 0);
|
||||
var51.writeShort(var2);
|
||||
var51.writeShort(var3);
|
||||
var1.pos = var13;
|
||||
int var52 = 0;
|
||||
int var53 = 0;
|
||||
int var54 = 0;
|
||||
int var55 = 0;
|
||||
int var56 = 0;
|
||||
int var57 = 0;
|
||||
int var58 = 0;
|
||||
final int[] var59 = new int[128];
|
||||
int i = 0;
|
||||
|
||||
label221:
|
||||
for (int var60 = 0; var60 < var2; ++var60) {
|
||||
var51.writeInt(1297379947);
|
||||
var51.pos += 4;
|
||||
final int var61 = var51.pos;
|
||||
int var62 = -1;
|
||||
|
||||
while (true) {
|
||||
while (true) {
|
||||
final int var63 = var1.readVariableInt();
|
||||
var51.a556(var63);
|
||||
final int var64 = var1.data[var29++] & 255;
|
||||
final boolean var65 = var64 != var62;
|
||||
var62 = var64 & 15;
|
||||
if (var64 == 7) {
|
||||
if (var65) {
|
||||
var51.writeByte(255);
|
||||
}
|
||||
|
||||
var51.writeByte(47);
|
||||
var51.writeByte(0);
|
||||
var51.c093(var51.pos - var61);
|
||||
continue label221;
|
||||
}
|
||||
|
||||
if (var64 == 23) {
|
||||
if (var65) {
|
||||
var51.writeByte(255);
|
||||
}
|
||||
|
||||
var51.writeByte(81);
|
||||
var51.writeByte(3);
|
||||
var51.writeByte(var1.data[var50++]);
|
||||
var51.writeByte(var1.data[var50++]);
|
||||
var51.writeByte(var1.data[var50++]);
|
||||
} else {
|
||||
var52 ^= var64 >> 4;
|
||||
if (var62 == 0) {
|
||||
if (var65) {
|
||||
var51.writeByte(144 + var52);
|
||||
}
|
||||
|
||||
var53 += var1.data[var37++];
|
||||
var54 += var1.data[var38++];
|
||||
var51.writeByte(var53 & 127);
|
||||
var51.writeByte(var54 & 127);
|
||||
} else if (var62 == 1) {
|
||||
if (var65) {
|
||||
var51.writeByte(128 + var52);
|
||||
}
|
||||
|
||||
var53 += var1.data[var37++];
|
||||
var55 += var1.data[var40++];
|
||||
var51.writeByte(var53 & 127);
|
||||
var51.writeByte(var55 & 127);
|
||||
} else if (var62 == 2) {
|
||||
if (var65) {
|
||||
var51.writeByte(176 + var52);
|
||||
}
|
||||
|
||||
i = i + var1.data[var15++] & 127;
|
||||
var51.writeByte(i);
|
||||
final byte var66;
|
||||
if (i == 0 || i == 32) {
|
||||
var66 = var1.data[var44++];
|
||||
} else if (i == 1) {
|
||||
var66 = var1.data[var34++];
|
||||
} else if (i == 33) {
|
||||
var66 = var1.data[var41++];
|
||||
} else if (i == 7) {
|
||||
var66 = var1.data[var35++];
|
||||
} else if (i == 39) {
|
||||
var66 = var1.data[var42++];
|
||||
} else if (i == 10) {
|
||||
var66 = var1.data[var36++];
|
||||
} else if (i == 42) {
|
||||
var66 = var1.data[var43++];
|
||||
} else if (i == 99) {
|
||||
var66 = var1.data[var46++];
|
||||
} else if (i == 98) {
|
||||
var66 = var1.data[var47++];
|
||||
} else if (i == 101) {
|
||||
var66 = var1.data[var48++];
|
||||
} else if (i == 100) {
|
||||
var66 = var1.data[var49++];
|
||||
} else if (i == 64 || i == 65 || i == 120 || i == 121 || i == 123) {
|
||||
var66 = var1.data[var30++];
|
||||
} else {
|
||||
var66 = var1.data[var39++];
|
||||
}
|
||||
|
||||
final int var67 = var66 + var59[i];
|
||||
var59[i] = var67;
|
||||
var51.writeByte(var67 & 127);
|
||||
} else if (var62 == 3) {
|
||||
if (var65) {
|
||||
var51.writeByte(224 + var52);
|
||||
}
|
||||
|
||||
var56 += var1.data[var45++];
|
||||
var56 += var1.data[var33++] << 7;
|
||||
var51.writeByte(var56 & 127);
|
||||
var51.writeByte(var56 >> 7 & 127);
|
||||
} else if (var62 == 4) {
|
||||
if (var65) {
|
||||
var51.writeByte(208 + var52);
|
||||
}
|
||||
|
||||
var57 += var1.data[var32++];
|
||||
var51.writeByte(var57 & 127);
|
||||
} else if (var62 == 5) {
|
||||
if (var65) {
|
||||
var51.writeByte(160 + var52);
|
||||
}
|
||||
|
||||
var53 += var1.data[var37++];
|
||||
var58 += var1.data[var31++];
|
||||
var51.writeByte(var53 & 127);
|
||||
var51.writeByte(var58 & 127);
|
||||
} else {
|
||||
if (var62 != 6) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
|
||||
if (var65) {
|
||||
var51.writeByte(192 + var52);
|
||||
}
|
||||
|
||||
var51.writeByte(var1.data[var44++]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static MusicTrack load(final ResourceLoader loader, final String item) {
|
||||
final byte[] data = loader.getResource("", item);
|
||||
return data == null ? null : new MusicTrack(new Buffer(data));
|
||||
}
|
||||
|
||||
public void a797() {
|
||||
if (this._i == null) {
|
||||
this._i = new HashMap<>();
|
||||
final int[] var1 = new int[16];
|
||||
final int[] var2 = new int[16];
|
||||
var2[9] = 128;
|
||||
var1[9] = 128;
|
||||
final pi_ var4 = new pi_(this._h);
|
||||
final int var5 = var4.c784();
|
||||
|
||||
int var6;
|
||||
for (var6 = 0; var6 < var5; ++var6) {
|
||||
var4.b150(var6);
|
||||
var4.d150(var6);
|
||||
var4.e150(var6);
|
||||
}
|
||||
|
||||
label53:
|
||||
do {
|
||||
while (true) {
|
||||
var6 = var4.g784();
|
||||
final int var7 = var4._b[var6];
|
||||
|
||||
while (var4._b[var6] == var7) {
|
||||
var4.b150(var6);
|
||||
final int var8 = var4.a137(var6);
|
||||
if (var8 == 1) {
|
||||
var4.e797();
|
||||
var4.e150(var6);
|
||||
continue label53;
|
||||
}
|
||||
|
||||
final int var9 = var8 & 240;
|
||||
int var10;
|
||||
int var11;
|
||||
int var12;
|
||||
if (var9 == 176) {
|
||||
var10 = var8 & 15;
|
||||
var11 = var8 >> 8 & 127;
|
||||
var12 = var8 >> 16 & 127;
|
||||
if (var11 == 0) {
|
||||
var1[var10] = (var1[var10] & -2080769) + (var12 << 14);
|
||||
}
|
||||
|
||||
if (var11 == 32) {
|
||||
var1[var10] = (var1[var10] & -16257) + (var12 << 7);
|
||||
}
|
||||
}
|
||||
|
||||
if (var9 == 192) {
|
||||
var10 = var8 & 15;
|
||||
var11 = var8 >> 8 & 127;
|
||||
var2[var10] = var1[var10] + var11;
|
||||
}
|
||||
|
||||
if (var9 == 144) {
|
||||
var10 = var8 & 15;
|
||||
var11 = var8 >> 8 & 127;
|
||||
var12 = var8 >> 16 & 127;
|
||||
if (var12 > 0) {
|
||||
final int var13 = var2[var10];
|
||||
final byte[] var14 = this._i.computeIfAbsent(var13, k -> new byte[128]);
|
||||
var14[var11] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
var4.d150(var6);
|
||||
var4.e150(var6);
|
||||
}
|
||||
}
|
||||
} while (!var4.a801());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void b797() {
|
||||
this._i = null;
|
||||
}
|
||||
}
|
19
src/main/java/funorb/audio/PlayingSound.java
Normal file
19
src/main/java/funorb/audio/PlayingSound.java
Normal file
@ -0,0 +1,19 @@
|
||||
package funorb.audio;
|
||||
|
||||
import funorb.shatteredplans.client.Sounds;
|
||||
|
||||
public final class PlayingSound {
|
||||
public final al_ _p;
|
||||
public int volume;
|
||||
|
||||
public PlayingSound(final al_ var1) {
|
||||
this._p = var1;
|
||||
this.volume = var1.getVolume();
|
||||
this._p.setVolume((128 + (this.volume * Sounds.soundVolume)) >> 8);
|
||||
}
|
||||
|
||||
public void setVolume(final int volume) {
|
||||
this.volume = volume;
|
||||
this._p.setVolume((128 + (volume * Sounds.soundVolume)) >> 8);
|
||||
}
|
||||
}
|
345
src/main/java/funorb/audio/SampledAudioChannel.java
Normal file
345
src/main/java/funorb/audio/SampledAudioChannel.java
Normal file
@ -0,0 +1,345 @@
|
||||
package funorb.audio;
|
||||
|
||||
import funorb.client.JagexBaseApplet;
|
||||
import funorb.util.BitMath;
|
||||
import funorb.util.PseudoMonotonicClock;
|
||||
|
||||
import javax.sound.sampled.AudioFormat;
|
||||
import javax.sound.sampled.AudioSystem;
|
||||
import javax.sound.sampled.DataLine.Info;
|
||||
import javax.sound.sampled.LineUnavailableException;
|
||||
import javax.sound.sampled.SourceDataLine;
|
||||
import java.io.Closeable;
|
||||
import java.util.Arrays;
|
||||
|
||||
public final class SampledAudioChannel implements Closeable {
|
||||
public static final int SAMPLES_PER_SECOND = 22050;
|
||||
private static final int BYTES_PER_CHANNEL_PER_WRITE = 512;
|
||||
|
||||
private final AudioFormat format = new AudioFormat(SAMPLES_PER_SECOND, 16, 2, true, false);
|
||||
private final byte[] buffer = new byte[1024];
|
||||
private final tn_[] _o = new tn_[8];
|
||||
private final tn_[] _s = new tn_[8];
|
||||
public int[] data;
|
||||
public int _g;
|
||||
public int _b;
|
||||
private SourceDataLine line;
|
||||
private int lineBufferSizeInInts;
|
||||
private boolean isShutdown = false;
|
||||
private long _m = PseudoMonotonicClock.currentTimeMillis();
|
||||
private tn_ source;
|
||||
private int _r = 0;
|
||||
private int _l = 0;
|
||||
private boolean _n = true;
|
||||
private int _e = 0;
|
||||
private int _a = 0;
|
||||
private long _p = 0L;
|
||||
private int _u;
|
||||
private long _q = 0L;
|
||||
|
||||
private static int a080lc(final int var1) {
|
||||
final int var2 = (var1 & 0x55555555) + ((var1 >>> 1) & 0xd5555555);
|
||||
final int var3 = (var2 & 0x33333333) + ((var2 & 0xcccccccc) >>> 2);
|
||||
final int var4 = (var3 + (var3 >>> 4)) & 0xf0f0f0f;
|
||||
final int var5 = var4 + (var4 >>> 8);
|
||||
final int var6 = var5 + (var5 >>> 16);
|
||||
return var6 & 255;
|
||||
}
|
||||
|
||||
private static void b446(final tn_ var0) {
|
||||
var0._j = false;
|
||||
if (var0._k != null) {
|
||||
var0._k._h = 0;
|
||||
}
|
||||
var0.forEach(SampledAudioChannel::b446);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
if (this.line != null) {
|
||||
this.line.close();
|
||||
this.line = null;
|
||||
}
|
||||
}
|
||||
|
||||
private int bufferedInts() {
|
||||
return this.lineBufferSizeInInts - (this.line.available() / 4);
|
||||
}
|
||||
|
||||
private void performWrite() {
|
||||
for (int i = 0; i < BYTES_PER_CHANNEL_PER_WRITE; ++i) {
|
||||
int var3 = this.data[i];
|
||||
if (((var3 + 0x80_00_00) & 0xff_00_00_00) != 0) {
|
||||
var3 = 0x7fffff ^ (var3 >> 31);
|
||||
}
|
||||
this.buffer[i * 2] = (byte) (var3 >> 8);
|
||||
this.buffer[i * 2 + 1] = (byte) (var3 >> 16);
|
||||
}
|
||||
|
||||
this.line.write(this.buffer, 0, BYTES_PER_CHANNEL_PER_WRITE * 2);
|
||||
}
|
||||
|
||||
public void open(final int size) throws LineUnavailableException {
|
||||
try {
|
||||
final Info var2 = new Info(SourceDataLine.class, this.format, size * 4);
|
||||
this.line = (SourceDataLine) AudioSystem.getLine(var2);
|
||||
this.line.open();
|
||||
this.line.start();
|
||||
this.lineBufferSizeInInts = size;
|
||||
} catch (final LineUnavailableException var3) {
|
||||
if (a080lc(size) == 1) {
|
||||
this.line = null;
|
||||
throw var3;
|
||||
} else {
|
||||
this.open(BitMath.nextLowestPowerOf2(size));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void a704(final int[] data) {
|
||||
Arrays.fill(data, 0, BYTES_PER_CHANNEL_PER_WRITE, 0);
|
||||
this._a -= 256;
|
||||
if (this.source != null && this._a <= 0) {
|
||||
this._a += 1378;
|
||||
b446(this.source);
|
||||
this.a607(this.source, this.source.c784());
|
||||
int var4 = 0;
|
||||
int var5 = 255;
|
||||
|
||||
tn_ var10;
|
||||
label106:
|
||||
for (int var6 = 7; var5 != 0; --var6) {
|
||||
int var7;
|
||||
int var8;
|
||||
if (var6 < 0) {
|
||||
var7 = var6 & 3;
|
||||
var8 = -(var6 >> 2);
|
||||
} else {
|
||||
var7 = var6;
|
||||
var8 = 0;
|
||||
}
|
||||
|
||||
for (int var9 = (var5 >>> var7) & 0x11111111; var9 != 0; var9 >>>= 4) {
|
||||
if ((var9 & 1) != 0) {
|
||||
var5 &= ~(1 << var7);
|
||||
var10 = null;
|
||||
tn_ var11 = this._o[var7];
|
||||
|
||||
label100:
|
||||
while (true) {
|
||||
while (true) {
|
||||
if (var11 == null) {
|
||||
break label100;
|
||||
}
|
||||
|
||||
final kk_ var12 = var11._k;
|
||||
if (var12 != null && var12._h > var8) {
|
||||
var5 |= 1 << var7;
|
||||
var10 = var11;
|
||||
var11 = var11._h;
|
||||
} else {
|
||||
var11._j = true;
|
||||
final int var13 = var11.a784();
|
||||
var4 += var13;
|
||||
if (var12 != null) {
|
||||
var12._h += var13;
|
||||
}
|
||||
|
||||
if (var4 >= 32) {
|
||||
break label106;
|
||||
}
|
||||
|
||||
final int var15 = var11._i;
|
||||
var11.forEach(var14 -> this.a607(var14, var15 * var14.c784() >> 8));
|
||||
|
||||
final tn_ var18 = var11._h;
|
||||
var11._h = null;
|
||||
if (var10 == null) {
|
||||
this._o[var7] = var18;
|
||||
} else {
|
||||
var10._h = var18;
|
||||
}
|
||||
|
||||
if (var18 == null) {
|
||||
this._s[var7] = var10;
|
||||
}
|
||||
|
||||
var11 = var18;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var7 += 4;
|
||||
++var8;
|
||||
}
|
||||
}
|
||||
|
||||
for (int var6 = 0; var6 < 8; ++var6) {
|
||||
tn_ var16 = this._o[var6];
|
||||
this._s[var6] = null;
|
||||
|
||||
for (this._o[var6] = null; var16 != null; var16 = var10) {
|
||||
var10 = var16._h;
|
||||
var16._h = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this._a < 0) {
|
||||
this._a = 0;
|
||||
}
|
||||
|
||||
if (this.source != null) {
|
||||
this.source.b397(data, 0, 256);
|
||||
}
|
||||
|
||||
this._m = PseudoMonotonicClock.currentTimeMillis();
|
||||
}
|
||||
|
||||
private void b150() {
|
||||
this._a -= 256;
|
||||
if (this._a < 0) {
|
||||
this._a = 0;
|
||||
}
|
||||
if (this.source != null) {
|
||||
this.source.a150(256);
|
||||
}
|
||||
}
|
||||
|
||||
private void a607(final tn_ var1, final int var2) {
|
||||
final int i = var2 >> 5;
|
||||
final tn_ var4 = this._s[i];
|
||||
if (var4 == null) {
|
||||
this._o[i] = var1;
|
||||
} else {
|
||||
var4._h = var1;
|
||||
}
|
||||
|
||||
this._s[i] = var1;
|
||||
var1._i = var2;
|
||||
}
|
||||
|
||||
public synchronized void doSomethingThatSeemsRelatedToAudio() {
|
||||
if (!this.isShutdown) {
|
||||
long var1 = PseudoMonotonicClock.currentTimeMillis();
|
||||
|
||||
try {
|
||||
if (var1 > this._m + 6000L) {
|
||||
this._m = var1 - 6000L;
|
||||
}
|
||||
|
||||
while (var1 > this._m + 5000L) {
|
||||
this.b150();
|
||||
this._m += 256000 / SAMPLES_PER_SECOND;
|
||||
var1 = PseudoMonotonicClock.currentTimeMillis();
|
||||
}
|
||||
} catch (final Exception var6) {
|
||||
this._m = var1;
|
||||
}
|
||||
|
||||
if (this.data != null) {
|
||||
try {
|
||||
if (this._p != 0L) {
|
||||
if (var1 < this._p) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.open(this._g);
|
||||
this._p = 0L;
|
||||
this._n = true;
|
||||
}
|
||||
|
||||
int var3 = this.bufferedInts();
|
||||
if (this._r - var3 > this._l) {
|
||||
this._l = this._r - var3;
|
||||
}
|
||||
|
||||
int var4 = this._b + this._u;
|
||||
if (var4 + 0x100 > 0x4000) {
|
||||
var4 = 0x3f00;
|
||||
}
|
||||
|
||||
if (var4 + 0x100 > this._g) {
|
||||
this._g += 0x400;
|
||||
if (this._g > 0x4000) {
|
||||
this._g = 0x4000;
|
||||
}
|
||||
|
||||
this.close();
|
||||
this.open(this._g);
|
||||
var3 = 0;
|
||||
this._n = true;
|
||||
if (var4 + 256 > this._g) {
|
||||
var4 = this._g - 256;
|
||||
this._u = var4 - this._b;
|
||||
}
|
||||
}
|
||||
|
||||
while (var3 < var4) {
|
||||
this.a704(this.data);
|
||||
this.performWrite();
|
||||
var3 += 256;
|
||||
}
|
||||
|
||||
if (var1 > this._q) {
|
||||
if (this._n) {
|
||||
this._n = false;
|
||||
} else {
|
||||
if (this._l == 0 && this._e == 0) {
|
||||
this.close();
|
||||
this._p = var1 + 2000L;
|
||||
return;
|
||||
}
|
||||
|
||||
this._u = Math.min(this._e, this._l);
|
||||
this._e = this._l;
|
||||
}
|
||||
|
||||
this._l = 0;
|
||||
this._q = var1 + 2000L;
|
||||
}
|
||||
|
||||
this._r = var3;
|
||||
} catch (final Exception var5) {
|
||||
this.close();
|
||||
this._p = var1 + 2000L;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void setSource(final tn_ source) {
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
public synchronized void shutdown() {
|
||||
if (AudioThread.instance != null) {
|
||||
boolean allChannelsShutdown = true;
|
||||
|
||||
for (int i = 0; i < AudioThread.NUM_CHANNELS; ++i) {
|
||||
if (AudioThread.instance.channels[i] == this) {
|
||||
AudioThread.instance.channels[i] = null;
|
||||
}
|
||||
|
||||
if (AudioThread.instance.channels[i] != null) {
|
||||
allChannelsShutdown = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (allChannelsShutdown) {
|
||||
AudioThread.instance.shutdownRequested = true;
|
||||
|
||||
while (AudioThread.instance.isRunning) {
|
||||
JagexBaseApplet.maybeSleep(50L);
|
||||
}
|
||||
|
||||
AudioThread.instance = null;
|
||||
}
|
||||
}
|
||||
|
||||
this.close();
|
||||
this.data = null;
|
||||
this.isShutdown = true;
|
||||
}
|
||||
}
|
21
src/main/java/funorb/audio/SoundEffect.java
Normal file
21
src/main/java/funorb/audio/SoundEffect.java
Normal file
@ -0,0 +1,21 @@
|
||||
package funorb.audio;
|
||||
|
||||
public final class SoundEffect {
|
||||
public final int volume;
|
||||
public final kk_ _f;
|
||||
|
||||
private SoundEffect(final kk_ var1, final int var2) {
|
||||
this.volume = var2;
|
||||
this._f = var1;
|
||||
}
|
||||
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
public static SoundEffect load1(final String item, final int var1) {
|
||||
return new SoundEffect(SoundLoader.globalLoader.load1(item), var1);
|
||||
}
|
||||
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
public static SoundEffect load2(final String item, final int var1) {
|
||||
return new SoundEffect(SoundLoader.globalLoader.load2(item), var1);
|
||||
}
|
||||
}
|
99
src/main/java/funorb/audio/SoundLoader.java
Normal file
99
src/main/java/funorb/audio/SoundLoader.java
Normal file
@ -0,0 +1,99 @@
|
||||
package funorb.audio;
|
||||
|
||||
import funorb.cache.ResourceLoader;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public final class SoundLoader {
|
||||
public static SoundLoader globalLoader;
|
||||
private final Map<Long, fd_> _a = new HashMap<>();
|
||||
private final Map<Long, kk_> _d = new HashMap<>();
|
||||
private final ResourceLoader loader1;
|
||||
private final ResourceLoader loader2;
|
||||
|
||||
public SoundLoader(final ResourceLoader loader1, final ResourceLoader loader2) {
|
||||
this.loader1 = loader1;
|
||||
this.loader2 = loader2;
|
||||
}
|
||||
|
||||
private kk_ load1(final int groupId, final int itemId) {
|
||||
final int var5 = (itemId ^ (((groupId << 4) & 0xfff3) | (groupId >>> 12))) | (groupId << 16);
|
||||
final kk_ var8 = this._d.get((long) var5);
|
||||
if (var8 == null) {
|
||||
final dq_ var9 = dq_.load(this.loader1, groupId, itemId);
|
||||
if (var9 == null) {
|
||||
return null;
|
||||
} else {
|
||||
final kk_ kk_ = var9.b720();
|
||||
this._d.put((long) var5, kk_);
|
||||
return kk_;
|
||||
}
|
||||
} else {
|
||||
return var8;
|
||||
}
|
||||
}
|
||||
|
||||
public kk_ loadSingleton2(final int var3) {
|
||||
if (this.loader2.groupCount() == 1) {
|
||||
return this.load2(0, var3);
|
||||
} else if (this.loader2.itemCount(var3) == 1) {
|
||||
return this.load2(var3, 0);
|
||||
} else {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
public kk_ loadSingleton1(final int var1) {
|
||||
if (this.loader1.groupCount() == 1) {
|
||||
return this.load1(0, var1);
|
||||
} else if (this.loader1.itemCount(var1) == 1) {
|
||||
return this.load1(var1, 0);
|
||||
} else {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
private kk_ load2(final int var3, final int var2) {
|
||||
final int var5 = (((var3 >>> 12) | (0xfff0 & (var3 << 4))) ^ var2) | (var3 << 16);
|
||||
final long var6 = 0x100000000L ^ (long) var5;
|
||||
kk_ var8 = this._d.get(var6);
|
||||
if (var8 == null) {
|
||||
fd_ var9 = this._a.get(var6);
|
||||
if (var9 == null) {
|
||||
var9 = fd_.a740(this.loader2, var3, var2);
|
||||
if (var9 == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
this._a.put(var6, var9);
|
||||
}
|
||||
|
||||
var8 = var9.a582();
|
||||
this._a.remove(var6);
|
||||
this._d.put(var6, var8);
|
||||
}
|
||||
return var8;
|
||||
}
|
||||
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
public kk_ load2(final String item) {
|
||||
final int groupId = this.loader2.lookupGroup("");
|
||||
if (groupId < 0) {
|
||||
return null;
|
||||
} else {
|
||||
final int itemId = this.loader2.lookupItem(groupId, item);
|
||||
return itemId < 0 ? null : this.load2(groupId, itemId);
|
||||
}
|
||||
}
|
||||
|
||||
public kk_ load1(final String item) {
|
||||
final int groupId = this.loader1.lookupGroup("");
|
||||
if (groupId >= 0) {
|
||||
final int itemId = this.loader1.lookupItem(groupId, item);
|
||||
return itemId >= 0 ? this.load1(groupId, itemId) : null;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
1110
src/main/java/funorb/audio/al_.java
Normal file
1110
src/main/java/funorb/audio/al_.java
Normal file
File diff suppressed because it is too large
Load Diff
490
src/main/java/funorb/audio/br_.java
Normal file
490
src/main/java/funorb/audio/br_.java
Normal file
@ -0,0 +1,490 @@
|
||||
package funorb.audio;
|
||||
|
||||
import funorb.io.Buffer;
|
||||
|
||||
public final class br_ {
|
||||
public final kk_[] _h = new kk_[128];
|
||||
public final kc_[] _j = new kc_[128];
|
||||
public final byte[] _t = new byte[128];
|
||||
public final int _q;
|
||||
public final short[] _k = new short[128];
|
||||
public final byte[] _r = new byte[128];
|
||||
public final byte[] _s = new byte[128];
|
||||
private int[] _n = new int[128];
|
||||
|
||||
public br_(final byte[] var1) {
|
||||
final Buffer var2 = new Buffer(var1);
|
||||
|
||||
int var3 = 0;
|
||||
while (var2.data[var3 + var2.pos] != 0) {
|
||||
++var3;
|
||||
}
|
||||
|
||||
final byte[] var4 = new byte[var3];
|
||||
|
||||
int var5;
|
||||
for (var5 = 0; var5 < var3; ++var5) {
|
||||
var4[var5] = var2.readByte();
|
||||
}
|
||||
|
||||
++var3;
|
||||
++var2.pos;
|
||||
var5 = var2.pos;
|
||||
var2.pos += var3;
|
||||
|
||||
int var6 = 0;
|
||||
while (var2.data[var6 + var2.pos] != 0) {
|
||||
++var6;
|
||||
}
|
||||
|
||||
final byte[] var7 = new byte[var6];
|
||||
|
||||
int var8;
|
||||
for (var8 = 0; var8 < var6; ++var8) {
|
||||
var7[var8] = var2.readByte();
|
||||
}
|
||||
|
||||
++var2.pos;
|
||||
++var6;
|
||||
var8 = var2.pos;
|
||||
var2.pos += var6;
|
||||
|
||||
int var9 = 0;
|
||||
while (var2.data[var9 + var2.pos] != 0) {
|
||||
++var9;
|
||||
}
|
||||
|
||||
final byte[] var10 = new byte[var9];
|
||||
|
||||
for (int var11 = 0; var11 < var9; ++var11) {
|
||||
var10[var11] = var2.readByte();
|
||||
}
|
||||
|
||||
++var9;
|
||||
++var2.pos;
|
||||
final byte[] var36 = new byte[var9];
|
||||
int var12;
|
||||
int var14;
|
||||
if (var9 <= 1) {
|
||||
var12 = var9;
|
||||
} else {
|
||||
var36[1] = 1;
|
||||
var12 = 2;
|
||||
int var13 = 1;
|
||||
|
||||
for (var14 = 2; var9 > var14; ++var14) {
|
||||
int var15 = var2.readUByte();
|
||||
if (var15 == 0) {
|
||||
var13 = var12++;
|
||||
} else {
|
||||
if (var13 >= var15) {
|
||||
--var15;
|
||||
}
|
||||
|
||||
var13 = var15;
|
||||
}
|
||||
|
||||
var36[var14] = (byte) var13;
|
||||
}
|
||||
}
|
||||
|
||||
final kc_[] var37 = new kc_[var12];
|
||||
|
||||
kc_ var38;
|
||||
for (var14 = 0; var14 < var37.length; ++var14) {
|
||||
var38 = var37[var14] = new kc_();
|
||||
final int var16 = var2.readUByte();
|
||||
if (var16 > 0) {
|
||||
var38._n = new byte[var16 * 2];
|
||||
}
|
||||
|
||||
final int j137 = var2.readUByte();
|
||||
if (j137 > 0) {
|
||||
var38._e = new byte[2 * j137 + 2];
|
||||
var38._e[1] = 64;
|
||||
}
|
||||
}
|
||||
|
||||
var14 = var2.readUByte();
|
||||
final byte[] var39 = var14 > 0 ? new byte[2 * var14] : null;
|
||||
var14 = var2.readUByte();
|
||||
final byte[] var40 = var14 <= 0 ? null : new byte[var14 * 2];
|
||||
|
||||
int var17 = 0;
|
||||
while (var2.data[var2.pos + var17] != 0) {
|
||||
++var17;
|
||||
}
|
||||
|
||||
final byte[] var18 = new byte[var17];
|
||||
|
||||
int var19;
|
||||
for (var19 = 0; var19 < var17; ++var19) {
|
||||
var18[var19] = var2.readByte();
|
||||
}
|
||||
|
||||
++var17;
|
||||
++var2.pos;
|
||||
var19 = 0;
|
||||
|
||||
int var20;
|
||||
for (var20 = 0; var20 < 128; ++var20) {
|
||||
var19 += var2.readUByte();
|
||||
this._k[var20] = (short) var19;
|
||||
}
|
||||
|
||||
var19 = 0;
|
||||
|
||||
for (var20 = 0; var20 < 128; ++var20) {
|
||||
var19 += var2.readUByte();
|
||||
this._k[var20] = (short) (this._k[var20] + (var19 << 8));
|
||||
}
|
||||
|
||||
var20 = 0;
|
||||
int var21 = 0;
|
||||
int var22 = 0;
|
||||
|
||||
int var23;
|
||||
for (var23 = 0; var23 < 128; ++var23) {
|
||||
if (var20 == 0) {
|
||||
if (var18.length <= var21) {
|
||||
var20 = -1;
|
||||
} else {
|
||||
var20 = var18[var21++];
|
||||
}
|
||||
|
||||
var22 = var2.readVariableInt();
|
||||
}
|
||||
|
||||
this._k[var23] = (short) (this._k[var23] + ((var22 - 1 & 2) << 14));
|
||||
--var20;
|
||||
this._n[var23] = var22;
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
var20 = 0;
|
||||
var23 = 0;
|
||||
|
||||
int var24;
|
||||
for (var24 = 0; var24 < 128; ++var24) {
|
||||
if (this._n[var24] != 0) {
|
||||
if (var20 == 0) {
|
||||
if (i < var4.length) {
|
||||
var20 = var4[i++];
|
||||
} else {
|
||||
var20 = -1;
|
||||
}
|
||||
|
||||
var23 = var2.data[var5++] - 1;
|
||||
}
|
||||
|
||||
--var20;
|
||||
this._r[var24] = (byte) var23;
|
||||
}
|
||||
}
|
||||
|
||||
int i1 = 0;
|
||||
var20 = 0;
|
||||
var24 = 0;
|
||||
|
||||
for (int var25 = 0; var25 < 128; ++var25) {
|
||||
if (this._n[var25] != 0) {
|
||||
if (var20 == 0) {
|
||||
if (i1 >= var7.length) {
|
||||
var20 = -1;
|
||||
} else {
|
||||
var20 = var7[i1++];
|
||||
}
|
||||
|
||||
var24 = 16 + var2.data[var8++] << 2;
|
||||
}
|
||||
|
||||
--var20;
|
||||
this._t[var25] = (byte) var24;
|
||||
}
|
||||
}
|
||||
|
||||
int i2 = 0;
|
||||
var20 = 0;
|
||||
kc_ var42 = null;
|
||||
|
||||
int var26;
|
||||
for (var26 = 0; var26 < 128; ++var26) {
|
||||
if (this._n[var26] != 0) {
|
||||
if (var20 == 0) {
|
||||
var42 = var37[var36[i2]];
|
||||
if (var10.length <= i2) {
|
||||
var20 = -1;
|
||||
} else {
|
||||
var20 = var10[i2++];
|
||||
}
|
||||
}
|
||||
|
||||
--var20;
|
||||
this._j[var26] = var42;
|
||||
}
|
||||
}
|
||||
|
||||
int i3 = 0;
|
||||
var20 = 0;
|
||||
var26 = 0;
|
||||
|
||||
int var27;
|
||||
for (var27 = 0; var27 < 128; ++var27) {
|
||||
if (var20 == 0) {
|
||||
if (i3 < var18.length) {
|
||||
var20 = var18[i3++];
|
||||
} else {
|
||||
var20 = -1;
|
||||
}
|
||||
|
||||
if (this._n[var27] > 0) {
|
||||
var26 = var2.readUByte() + 1;
|
||||
}
|
||||
}
|
||||
|
||||
--var20;
|
||||
this._s[var27] = (byte) var26;
|
||||
}
|
||||
|
||||
this._q = var2.readUByte() + 1;
|
||||
|
||||
kc_ var28;
|
||||
int var29;
|
||||
for (var27 = 0; var27 < var12; ++var27) {
|
||||
var28 = var37[var27];
|
||||
if (var28._n != null) {
|
||||
for (var29 = 1; var29 < var28._n.length; var29 += 2) {
|
||||
var28._n[var29] = var2.readByte();
|
||||
}
|
||||
}
|
||||
|
||||
if (var28._e != null) {
|
||||
for (var29 = 3; var28._e.length - 2 > var29; var29 += 2) {
|
||||
var28._e[var29] = var2.readByte();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (var39 != null) {
|
||||
for (var27 = 1; var39.length > var27; var27 += 2) {
|
||||
var39[var27] = var2.readByte();
|
||||
}
|
||||
}
|
||||
|
||||
if (var40 != null) {
|
||||
for (var27 = 1; var27 < var40.length; var27 += 2) {
|
||||
var40[var27] = var2.readByte();
|
||||
}
|
||||
}
|
||||
|
||||
for (var27 = 0; var27 < var12; ++var27) {
|
||||
var28 = var37[var27];
|
||||
if (var28._e != null) {
|
||||
var19 = 0;
|
||||
|
||||
for (var29 = 2; var29 < var28._e.length; var29 += 2) {
|
||||
var19 = var2.readUByte() + var19 + 1;
|
||||
var28._e[var29] = (byte) var19;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (var27 = 0; var12 > var27; ++var27) {
|
||||
var28 = var37[var27];
|
||||
if (var28._n != null) {
|
||||
var19 = 0;
|
||||
|
||||
for (var29 = 2; var29 < var28._n.length; var29 += 2) {
|
||||
var19 = var2.readUByte() + var19 + 1;
|
||||
var28._n[var29] = (byte) var19;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
byte var30;
|
||||
int var32;
|
||||
int var33;
|
||||
int var34;
|
||||
int var45;
|
||||
byte var47;
|
||||
if (var39 != null) {
|
||||
var19 = var2.readUByte();
|
||||
var39[0] = (byte) var19;
|
||||
|
||||
for (var27 = 2; var27 < var39.length; var27 += 2) {
|
||||
var19 = var2.readUByte() + var19 + 1;
|
||||
var39[var27] = (byte) var19;
|
||||
}
|
||||
|
||||
var47 = var39[0];
|
||||
byte var43 = var39[1];
|
||||
|
||||
for (var29 = 0; var29 < var47; ++var29) {
|
||||
this._s[var29] = (byte) (32 + this._s[var29] * var43 >> 6);
|
||||
}
|
||||
|
||||
for (var29 = 2; var29 < var39.length; var47 = var30) {
|
||||
var30 = var39[var29];
|
||||
final byte var31 = var39[var29 + 1];
|
||||
var32 = (-var47 + var30) / 2 + var43 * (var30 - var47);
|
||||
|
||||
for (var33 = var47; var30 > var33; ++var33) {
|
||||
var34 = a666ql(var32, var30 - var47);
|
||||
this._s[var33] = (byte) (32 + this._s[var33] * var34 >> 6);
|
||||
var32 += -var43 + var31;
|
||||
}
|
||||
|
||||
var43 = var31;
|
||||
var29 += 2;
|
||||
}
|
||||
|
||||
for (var45 = var47; var45 < 128; ++var45) {
|
||||
this._s[var45] = (byte) (32 + this._s[var45] * var43 >> 6);
|
||||
}
|
||||
}
|
||||
|
||||
if (var40 != null) {
|
||||
var19 = var2.readUByte();
|
||||
var40[0] = (byte) var19;
|
||||
|
||||
for (var27 = 2; var40.length > var27; var27 += 2) {
|
||||
var19 = 1 + var19 + var2.readUByte();
|
||||
var40[var27] = (byte) var19;
|
||||
}
|
||||
|
||||
var47 = var40[0];
|
||||
int var44 = var40[1] << 1;
|
||||
|
||||
for (var29 = 0; var29 < var47; ++var29) {
|
||||
var45 = (this._t[var29] & 255) + var44;
|
||||
if (var45 < 0) {
|
||||
var45 = 0;
|
||||
}
|
||||
|
||||
if (var45 > 128) {
|
||||
var45 = 128;
|
||||
}
|
||||
|
||||
this._t[var29] = (byte) var45;
|
||||
}
|
||||
|
||||
int var46;
|
||||
for (var29 = 2; var40.length > var29; var44 = var46) {
|
||||
var30 = var40[var29];
|
||||
var46 = var40[1 + var29] << 1;
|
||||
var32 = (-var47 + var30) / 2 + (var30 - var47) * var44;
|
||||
|
||||
for (var33 = var47; var33 < var30; ++var33) {
|
||||
var34 = a666ql(var32, -var47 + var30);
|
||||
int var35 = var34 + (255 & this._t[var33]);
|
||||
if (var35 < 0) {
|
||||
var35 = 0;
|
||||
}
|
||||
|
||||
if (var35 > 128) {
|
||||
var35 = 128;
|
||||
}
|
||||
|
||||
this._t[var33] = (byte) var35;
|
||||
var32 += -var44 + var46;
|
||||
}
|
||||
|
||||
var47 = var30;
|
||||
var29 += 2;
|
||||
}
|
||||
|
||||
for (var45 = var47; var45 < 128; ++var45) {
|
||||
var46 = var44 + (this._t[var45] & 255);
|
||||
if (var46 < 0) {
|
||||
var46 = 0;
|
||||
}
|
||||
|
||||
if (var46 > 128) {
|
||||
var46 = 128;
|
||||
}
|
||||
|
||||
this._t[var45] = (byte) var46;
|
||||
}
|
||||
}
|
||||
|
||||
for (var27 = 0; var12 > var27; ++var27) {
|
||||
var37[var27]._h = var2.readUByte();
|
||||
}
|
||||
|
||||
for (var27 = 0; var12 > var27; ++var27) {
|
||||
var28 = var37[var27];
|
||||
if (var28._n != null) {
|
||||
var28._k = var2.readUByte();
|
||||
}
|
||||
|
||||
if (var28._e != null) {
|
||||
var28._c = var2.readUByte();
|
||||
}
|
||||
|
||||
if (var28._h > 0) {
|
||||
var28._a = var2.readUByte();
|
||||
}
|
||||
}
|
||||
|
||||
for (var27 = 0; var27 < var12; ++var27) {
|
||||
var37[var27]._o = var2.readUByte();
|
||||
}
|
||||
|
||||
for (var27 = 0; var12 > var27; ++var27) {
|
||||
var28 = var37[var27];
|
||||
if (var28._o > 0) {
|
||||
var28._f = var2.readUByte();
|
||||
}
|
||||
}
|
||||
|
||||
for (var27 = 0; var12 > var27; ++var27) {
|
||||
var28 = var37[var27];
|
||||
if (var28._f > 0) {
|
||||
var28._j = var2.readUByte();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static int a666ql(final int var0, final int var1) {
|
||||
final int var2 = var0 >>> 31;
|
||||
return -var2 + (var0 + var2) / var1;
|
||||
}
|
||||
|
||||
public boolean a972(final SoundLoader var1, final byte[] var2) {
|
||||
boolean var5 = true;
|
||||
int var6 = 0;
|
||||
kk_ var7 = null;
|
||||
|
||||
for (int var8 = 0; var8 < 128; ++var8) {
|
||||
if (var2 == null || var2[var8] != 0) {
|
||||
int var9 = this._n[var8];
|
||||
if (var9 != 0) {
|
||||
if (var9 != var6) {
|
||||
var6 = var9--;
|
||||
if ((1 & var9) == 0) {
|
||||
var7 = var1.loadSingleton1(var9 >> 2);
|
||||
} else {
|
||||
var7 = var1.loadSingleton2(var9 >> 2);
|
||||
}
|
||||
|
||||
if (var7 == null) {
|
||||
var5 = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (var7 != null) {
|
||||
this._h[var8] = var7;
|
||||
this._n[var8] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return var5;
|
||||
}
|
||||
|
||||
public void e150() {
|
||||
this._n = null;
|
||||
}
|
||||
}
|
69
src/main/java/funorb/audio/dq_.java
Normal file
69
src/main/java/funorb/audio/dq_.java
Normal file
@ -0,0 +1,69 @@
|
||||
package funorb.audio;
|
||||
|
||||
import funorb.cache.ResourceLoader;
|
||||
import funorb.io.Buffer;
|
||||
|
||||
public final class dq_ {
|
||||
private final pk_[] _b = new pk_[10];
|
||||
private final int _c;
|
||||
private final int _a;
|
||||
|
||||
private dq_(final Buffer data) {
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
final int var3 = data.readUByte();
|
||||
if (var3 != 0) {
|
||||
--data.pos;
|
||||
this._b[i] = new pk_();
|
||||
this._b[i].initialize(data);
|
||||
}
|
||||
}
|
||||
|
||||
this._c = data.readUShort();
|
||||
this._a = data.readUShort();
|
||||
}
|
||||
|
||||
public static dq_ load(final ResourceLoader loader, final int groupId, final int itemId) {
|
||||
final byte[] data = loader.getResource(groupId, itemId);
|
||||
return data == null ? null : new dq_(new Buffer(data));
|
||||
}
|
||||
|
||||
private byte[] a928() {
|
||||
int var1 = 0;
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
if (this._b[i] != null && var1 < this._b[i]._a + this._b[i]._s) {
|
||||
var1 = this._b[i]._a + this._b[i]._s;
|
||||
}
|
||||
}
|
||||
|
||||
if (var1 == 0) {
|
||||
return new byte[0];
|
||||
}
|
||||
final int var2 = SampledAudioChannel.SAMPLES_PER_SECOND * var1 / 1000;
|
||||
final byte[] var3 = new byte[var2];
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
if (this._b[i] != null) {
|
||||
final int var5 = this._b[i]._a * SampledAudioChannel.SAMPLES_PER_SECOND / 1000;
|
||||
final int var6 = this._b[i]._s * SampledAudioChannel.SAMPLES_PER_SECOND / 1000;
|
||||
final int[] var7 = this._b[i].a111(var5, this._b[i]._a);
|
||||
|
||||
for (int j = 0; j < var5; ++j) {
|
||||
int var9 = var3[j + var6] + (var7[j] >> 8);
|
||||
if ((var9 + 128 & -256) != 0) {
|
||||
var9 = var9 >> 31 ^ 127;
|
||||
}
|
||||
|
||||
var3[j + var6] = (byte) var9;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return var3;
|
||||
}
|
||||
|
||||
public kk_ b720() {
|
||||
final byte[] var1 = this.a928();
|
||||
return new kk_(var1, SampledAudioChannel.SAMPLES_PER_SECOND * this._c / 1000, SampledAudioChannel.SAMPLES_PER_SECOND * this._a / 1000);
|
||||
}
|
||||
}
|
598
src/main/java/funorb/audio/fd_.java
Normal file
598
src/main/java/funorb/audio/fd_.java
Normal file
@ -0,0 +1,598 @@
|
||||
package funorb.audio;
|
||||
|
||||
import funorb.cache.ResourceLoader;
|
||||
import funorb.io.Buffer;
|
||||
import funorb.util.BitMath;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public final class fd_ {
|
||||
public static vb_[] _L;
|
||||
private static float[] _k;
|
||||
private static to_[] _o;
|
||||
private static int[] _J;
|
||||
private static int[] _D;
|
||||
private static fq_[] _O;
|
||||
private static float[] _u;
|
||||
private static float[] _C;
|
||||
private static boolean _x = false;
|
||||
private static byte[] _w;
|
||||
private static float[] _z;
|
||||
private static boolean[] _t;
|
||||
private static float[] _y;
|
||||
private static float[] _j;
|
||||
private static int _r;
|
||||
private static float[] _l;
|
||||
private static int _K;
|
||||
private static int[] _F;
|
||||
private static int _E;
|
||||
private static kn_[] _h;
|
||||
private static int _p;
|
||||
private int _q;
|
||||
private int _G;
|
||||
private boolean _I;
|
||||
private int _H;
|
||||
private int _i;
|
||||
private int _s;
|
||||
private boolean _A;
|
||||
private byte[][] _v;
|
||||
private int _M;
|
||||
private int _B;
|
||||
private byte[] _N;
|
||||
private float[] _n;
|
||||
private int _m;
|
||||
|
||||
private fd_(final byte[] var1) throws IOException {
|
||||
this.a604(var1);
|
||||
}
|
||||
|
||||
public static float d134(final int var0) {
|
||||
int var1 = var0 & 2097151;
|
||||
final int var2 = var0 & Integer.MIN_VALUE;
|
||||
final int var3 = (var0 & 2145386496) >> 21;
|
||||
if (var2 != 0) {
|
||||
var1 = -var1;
|
||||
}
|
||||
|
||||
return (float) ((double) var1 * Math.pow(2.0D, var3 - 788));
|
||||
}
|
||||
|
||||
public static int c784() {
|
||||
final int var0 = _w[_p] >> _K & 1;
|
||||
++_K;
|
||||
_p += _K >> 3;
|
||||
_K &= 7;
|
||||
return var0;
|
||||
}
|
||||
|
||||
public static void b604(final byte[] var0) {
|
||||
a167(var0);
|
||||
_E = 1 << a137(4);
|
||||
_r = 1 << a137(4);
|
||||
_k = new float[_r];
|
||||
|
||||
int var1;
|
||||
int var2;
|
||||
int var3;
|
||||
int var4;
|
||||
int var5;
|
||||
for (var1 = 0; var1 < 2; ++var1) {
|
||||
var2 = var1 != 0 ? _r : _E;
|
||||
var3 = var2 >> 1;
|
||||
var4 = var2 >> 2;
|
||||
var5 = var2 >> 3;
|
||||
final float[] var6 = new float[var3];
|
||||
|
||||
for (int var7 = 0; var7 < var4; ++var7) {
|
||||
var6[2 * var7] = (float) Math.cos((double) (4 * var7) * Math.PI / (double) var2);
|
||||
var6[2 * var7 + 1] = -((float) Math.sin((double) (4 * var7) * Math.PI / (double) var2));
|
||||
}
|
||||
|
||||
final float[] var13 = new float[var3];
|
||||
|
||||
for (int var8 = 0; var8 < var4; ++var8) {
|
||||
var13[2 * var8] = (float) Math.cos((double) (2 * var8 + 1) * Math.PI / (double) (2 * var2));
|
||||
var13[2 * var8 + 1] = (float) Math.sin((double) (2 * var8 + 1) * Math.PI / (double) (2 * var2));
|
||||
}
|
||||
|
||||
final float[] var14 = new float[var4];
|
||||
|
||||
for (int var9 = 0; var9 < var5; ++var9) {
|
||||
var14[2 * var9] = (float) Math.cos((double) (4 * var9 + 2) * Math.PI / (double) var2);
|
||||
var14[2 * var9 + 1] = -((float) Math.sin((double) (4 * var9 + 2) * Math.PI / (double) var2));
|
||||
}
|
||||
|
||||
final int var10 = BitMath.lastSet(var5 - 1);
|
||||
final int[] var15 = IntStream.range(0, var5).map(var11 -> a586js(var11, var10)).toArray();
|
||||
|
||||
if (var1 == 0) {
|
||||
_l = var6;
|
||||
_z = var13;
|
||||
_C = var14;
|
||||
_D = var15;
|
||||
} else {
|
||||
_j = var6;
|
||||
_y = var13;
|
||||
_u = var14;
|
||||
_F = var15;
|
||||
}
|
||||
}
|
||||
|
||||
var1 = a137(8) + 1;
|
||||
_L = new vb_[var1];
|
||||
|
||||
for (var2 = 0; var2 < var1; ++var2) {
|
||||
_L[var2] = new vb_();
|
||||
}
|
||||
|
||||
var2 = a137(6) + 1;
|
||||
|
||||
for (var3 = 0; var3 < var2; ++var3) {
|
||||
a137(16);
|
||||
}
|
||||
|
||||
var2 = a137(6) + 1;
|
||||
_h = new kn_[var2];
|
||||
|
||||
for (var3 = 0; var3 < var2; ++var3) {
|
||||
_h[var3] = new kn_();
|
||||
}
|
||||
|
||||
var3 = a137(6) + 1;
|
||||
_o = new to_[var3];
|
||||
|
||||
for (var4 = 0; var4 < var3; ++var4) {
|
||||
_o[var4] = new to_();
|
||||
}
|
||||
|
||||
var4 = a137(6) + 1;
|
||||
_O = new fq_[var4];
|
||||
|
||||
for (var5 = 0; var5 < var4; ++var5) {
|
||||
_O[var5] = new fq_();
|
||||
}
|
||||
|
||||
var5 = a137(6) + 1;
|
||||
_t = new boolean[var5];
|
||||
_J = new int[var5];
|
||||
|
||||
for (int var12 = 0; var12 < var5; ++var12) {
|
||||
_t[var12] = c784() != 0;
|
||||
a137(16);
|
||||
a137(16);
|
||||
_J[var12] = a137(8);
|
||||
}
|
||||
|
||||
_x = true;
|
||||
}
|
||||
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
public static fd_ a968(final ResourceLoader loader, final String group, final String item) {
|
||||
if (a521(loader)) {
|
||||
final byte[] var3 = loader.getResource(group, item);
|
||||
if (var3 == null) {
|
||||
return null;
|
||||
} else {
|
||||
fd_ var4 = null;
|
||||
|
||||
try {
|
||||
var4 = new fd_(var3);
|
||||
} catch (final IOException var6) {
|
||||
var6.printStackTrace();
|
||||
}
|
||||
|
||||
return var4;
|
||||
}
|
||||
} else {
|
||||
loader.loadGroupDataForItem(group, item);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean a521(final ResourceLoader var0) {
|
||||
if (!_x) {
|
||||
final byte[] var1 = var0.getResource(0, 0);
|
||||
if (var1 == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
b604(var1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void a167(final byte[] var0) {
|
||||
_w = var0;
|
||||
_p = 0;
|
||||
_K = 0;
|
||||
}
|
||||
|
||||
public static int a137(int var0) {
|
||||
int var1 = 0;
|
||||
|
||||
int var2;
|
||||
int var3;
|
||||
for (var2 = 0; var0 >= 8 - _K; var0 -= var3) {
|
||||
var3 = 8 - _K;
|
||||
final int var4 = (1 << var3) - 1;
|
||||
var1 += (_w[_p] >> _K & var4) << var2;
|
||||
_K = 0;
|
||||
++_p;
|
||||
var2 += var3;
|
||||
}
|
||||
|
||||
if (var0 > 0) {
|
||||
var3 = (1 << var0) - 1;
|
||||
var1 += (_w[_p] >> _K & var3) << var2;
|
||||
_K += var0;
|
||||
}
|
||||
|
||||
return var1;
|
||||
}
|
||||
|
||||
public static fd_ a740(final ResourceLoader var0, final int var1, final int var2) {
|
||||
if (a521(var0)) {
|
||||
final byte[] var3 = var0.getResource(var1, var2);
|
||||
if (var3 == null) {
|
||||
return null;
|
||||
} else {
|
||||
fd_ var4 = null;
|
||||
|
||||
try {
|
||||
var4 = new fd_(var3);
|
||||
} catch (final IOException var6) {
|
||||
var6.printStackTrace();
|
||||
}
|
||||
|
||||
return var4;
|
||||
}
|
||||
} else {
|
||||
var0.loadGroupDataForItem(var1, var2);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static int a586js(int var0, int var1) {
|
||||
int var2;
|
||||
for (var2 = 0; var1 > 0; var0 >>>= 1) {
|
||||
var2 = var2 << 1 | 1 & var0;
|
||||
--var1;
|
||||
}
|
||||
|
||||
return var2;
|
||||
}
|
||||
|
||||
public kk_ a582() {
|
||||
if (this._N == null) {
|
||||
this._M = 0;
|
||||
this._n = new float[_r];
|
||||
this._N = new byte[this._q];
|
||||
this._s = 0;
|
||||
this._m = 0;
|
||||
}
|
||||
|
||||
for (; this._m < this._v.length; ++this._m) {
|
||||
|
||||
final float[] var2 = this.e875(this._m);
|
||||
if (var2 != null) {
|
||||
int var3 = this._s;
|
||||
int var4 = var2.length;
|
||||
if (var4 > this._q - var3) {
|
||||
var4 = this._q - var3;
|
||||
}
|
||||
|
||||
for (int var5 = 0; var5 < var4; ++var5) {
|
||||
int var6 = (int) (128.0F + var2[var5] * 128.0F);
|
||||
if ((var6 & -256) != 0) {
|
||||
var6 = ~var6 >> 31;
|
||||
}
|
||||
|
||||
this._N[var3++] = (byte) (var6 - 128);
|
||||
}
|
||||
|
||||
this._s = var3;
|
||||
}
|
||||
}
|
||||
|
||||
this._n = null;
|
||||
final byte[] var7 = this._N;
|
||||
this._N = null;
|
||||
return new kk_(this._B, var7, this._H, this._G, this._I);
|
||||
}
|
||||
|
||||
private float[] e875(final int var1) {
|
||||
a167(this._v[var1]);
|
||||
c784();
|
||||
final int var2 = a137(BitMath.lastSet(_J.length - 1));
|
||||
final boolean var3 = _t[var2];
|
||||
final int var4 = var3 ? _r : _E;
|
||||
boolean var5 = false;
|
||||
boolean var6 = false;
|
||||
if (var3) {
|
||||
var5 = c784() != 0;
|
||||
var6 = c784() != 0;
|
||||
}
|
||||
|
||||
final int var7 = var4 >> 1;
|
||||
final int var8;
|
||||
final int var9;
|
||||
final int var10;
|
||||
if (var3 && !var5) {
|
||||
var8 = (var4 >> 2) - (_E >> 2);
|
||||
var9 = (var4 >> 2) + (_E >> 2);
|
||||
var10 = _E >> 1;
|
||||
} else {
|
||||
var8 = 0;
|
||||
var9 = var7;
|
||||
var10 = var4 >> 1;
|
||||
}
|
||||
|
||||
final int var11;
|
||||
final int var12;
|
||||
final int var13;
|
||||
if (var3 && !var6) {
|
||||
var11 = var4 - (var4 >> 2) - (_E >> 2);
|
||||
var12 = var4 - (var4 >> 2) + (_E >> 2);
|
||||
var13 = _E >> 1;
|
||||
} else {
|
||||
var11 = var7;
|
||||
var12 = var4;
|
||||
var13 = var4 >> 1;
|
||||
}
|
||||
|
||||
final fq_ var14 = _O[_J[var2]];
|
||||
final int var16 = var14._d;
|
||||
int var17 = var14._b[var16];
|
||||
final boolean var15 = !_h[var17].b801();
|
||||
|
||||
for (var17 = 0; var17 < var14._c; ++var17) {
|
||||
final to_ var18 = _o[var14._a[var17]];
|
||||
final float[] var19 = _k;
|
||||
var18.a623(var19, var4 >> 1, var15);
|
||||
}
|
||||
|
||||
int var41;
|
||||
if (!var15) {
|
||||
var17 = var14._d;
|
||||
var41 = var14._b[var17];
|
||||
_h[var41].a331(_k, var4 >> 1);
|
||||
}
|
||||
|
||||
int var42;
|
||||
if (var15) {
|
||||
for (var17 = var4 >> 1; var17 < var4; ++var17) {
|
||||
_k[var17] = 0.0F;
|
||||
}
|
||||
} else {
|
||||
final int i = var4 >> 1;
|
||||
var41 = var4 >> 2;
|
||||
var42 = var4 >> 3;
|
||||
final float[] var20 = _k;
|
||||
|
||||
int var21;
|
||||
for (var21 = 0; var21 < i; ++var21) {
|
||||
var20[var21] *= 0.5F;
|
||||
}
|
||||
|
||||
for (var21 = i; var21 < var4; ++var21) {
|
||||
var20[var21] = -var20[var4 - var21 - 1];
|
||||
}
|
||||
|
||||
final float[] var46 = var3 ? _j : _l;
|
||||
final float[] var22 = var3 ? _y : _z;
|
||||
final float[] var23 = var3 ? _u : _C;
|
||||
final int[] var24 = var3 ? _F : _D;
|
||||
|
||||
int var25;
|
||||
float var26;
|
||||
float var27;
|
||||
float var28;
|
||||
float var29;
|
||||
for (var25 = 0; var25 < var41; ++var25) {
|
||||
var26 = var20[4 * var25] - var20[var4 - 4 * var25 - 1];
|
||||
var27 = var20[4 * var25 + 2] - var20[var4 - 4 * var25 - 3];
|
||||
var28 = var46[2 * var25];
|
||||
var29 = var46[2 * var25 + 1];
|
||||
var20[var4 - 4 * var25 - 1] = var26 * var28 - var27 * var29;
|
||||
var20[var4 - 4 * var25 - 3] = var26 * var29 + var27 * var28;
|
||||
}
|
||||
|
||||
float var30;
|
||||
float var31;
|
||||
for (var25 = 0; var25 < var42; ++var25) {
|
||||
var26 = var20[i + 3 + 4 * var25];
|
||||
var27 = var20[i + 1 + 4 * var25];
|
||||
var28 = var20[4 * var25 + 3];
|
||||
var29 = var20[4 * var25 + 1];
|
||||
var20[i + 3 + 4 * var25] = var26 + var28;
|
||||
var20[i + 1 + 4 * var25] = var27 + var29;
|
||||
var30 = var46[i - 4 - 4 * var25];
|
||||
var31 = var46[i - 3 - 4 * var25];
|
||||
var20[4 * var25 + 3] = (var26 - var28) * var30 - (var27 - var29) * var31;
|
||||
var20[4 * var25 + 1] = (var27 - var29) * var30 + (var26 - var28) * var31;
|
||||
}
|
||||
|
||||
var25 = BitMath.lastSet(var4 - 1);
|
||||
|
||||
int var47;
|
||||
int var48;
|
||||
int var49;
|
||||
int var50;
|
||||
for (var47 = 0; var47 < var25 - 3; ++var47) {
|
||||
var48 = var4 >> var47 + 2;
|
||||
var49 = 8 << var47;
|
||||
|
||||
for (var50 = 0; var50 < 2 << var47; ++var50) {
|
||||
final int var51 = var4 - var48 * 2 * var50;
|
||||
final int var52 = var4 - var48 * (2 * var50 + 1);
|
||||
|
||||
for (int var32 = 0; var32 < var4 >> var47 + 4; ++var32) {
|
||||
final int var33 = 4 * var32;
|
||||
final float var34 = var20[var51 - 1 - var33];
|
||||
final float var35 = var20[var51 - 3 - var33];
|
||||
final float var36 = var20[var52 - 1 - var33];
|
||||
final float var37 = var20[var52 - 3 - var33];
|
||||
var20[var51 - 1 - var33] = var34 + var36;
|
||||
var20[var51 - 3 - var33] = var35 + var37;
|
||||
final float var38 = var46[var32 * var49];
|
||||
final float var39 = var46[var32 * var49 + 1];
|
||||
var20[var52 - 1 - var33] = (var34 - var36) * var38 - (var35 - var37) * var39;
|
||||
var20[var52 - 3 - var33] = (var35 - var37) * var38 + (var34 - var36) * var39;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (var47 = 1; var47 < var42 - 1; ++var47) {
|
||||
var48 = var24[var47];
|
||||
if (var47 < var48) {
|
||||
var49 = 8 * var47;
|
||||
var50 = 8 * var48;
|
||||
var30 = var20[var49 + 1];
|
||||
var20[var49 + 1] = var20[var50 + 1];
|
||||
var20[var50 + 1] = var30;
|
||||
var30 = var20[var49 + 3];
|
||||
var20[var49 + 3] = var20[var50 + 3];
|
||||
var20[var50 + 3] = var30;
|
||||
var30 = var20[var49 + 5];
|
||||
var20[var49 + 5] = var20[var50 + 5];
|
||||
var20[var50 + 5] = var30;
|
||||
var30 = var20[var49 + 7];
|
||||
var20[var49 + 7] = var20[var50 + 7];
|
||||
var20[var50 + 7] = var30;
|
||||
}
|
||||
}
|
||||
|
||||
for (var47 = 0; var47 < i; ++var47) {
|
||||
var20[var47] = var20[2 * var47 + 1];
|
||||
}
|
||||
|
||||
for (var47 = 0; var47 < var42; ++var47) {
|
||||
var20[var4 - 1 - 2 * var47] = var20[4 * var47];
|
||||
var20[var4 - 2 - 2 * var47] = var20[4 * var47 + 1];
|
||||
var20[var4 - var41 - 1 - 2 * var47] = var20[4 * var47 + 2];
|
||||
var20[var4 - var41 - 2 - 2 * var47] = var20[4 * var47 + 3];
|
||||
}
|
||||
|
||||
for (var47 = 0; var47 < var42; ++var47) {
|
||||
var27 = var23[2 * var47];
|
||||
var28 = var23[2 * var47 + 1];
|
||||
var29 = var20[i + 2 * var47];
|
||||
var30 = var20[i + 2 * var47 + 1];
|
||||
var31 = var20[var4 - 2 - 2 * var47];
|
||||
final float var53 = var20[var4 - 1 - 2 * var47];
|
||||
final float var54 = var28 * (var29 - var31) + var27 * (var30 + var53);
|
||||
var20[i + 2 * var47] = (var29 + var31 + var54) * 0.5F;
|
||||
var20[var4 - 2 - 2 * var47] = (var29 + var31 - var54) * 0.5F;
|
||||
final float v = var28 * (var30 + var53) - var27 * (var29 - var31);
|
||||
var20[i + 2 * var47 + 1] = (var30 - var53 + v) * 0.5F;
|
||||
var20[var4 - 1 - 2 * var47] = (-var30 + var53 + v) * 0.5F;
|
||||
}
|
||||
|
||||
for (var47 = 0; var47 < var41; ++var47) {
|
||||
var20[var47] = var20[2 * var47 + i] * var22[2 * var47] + var20[2 * var47 + 1 + i] * var22[2 * var47 + 1];
|
||||
var20[i - 1 - var47] = var20[2 * var47 + i] * var22[2 * var47 + 1] - var20[2 * var47 + 1 + i] * var22[2 * var47];
|
||||
}
|
||||
|
||||
for (var47 = 0; var47 < var41; ++var47) {
|
||||
var20[var4 - var41 + var47] = -var20[var47];
|
||||
}
|
||||
|
||||
for (var47 = 0; var47 < var41; ++var47) {
|
||||
var20[var47] = var20[var41 + var47];
|
||||
}
|
||||
|
||||
for (var47 = 0; var47 < var41; ++var47) {
|
||||
var20[var41 + var47] = -var20[var41 - var47 - 1];
|
||||
}
|
||||
|
||||
for (var47 = 0; var47 < var41; ++var47) {
|
||||
var20[i + var47] = var20[var4 - var47 - 1];
|
||||
}
|
||||
|
||||
float[] var10000;
|
||||
for (var47 = var8; var47 < var9; ++var47) {
|
||||
var27 = (float) Math.sin(((double) (var47 - var8) + 0.5D) / (double) var10 * 0.5D * Math.PI);
|
||||
var10000 = _k;
|
||||
var10000[var47] *= (float) Math.sin(1.5707963267948966D * (double) var27 * (double) var27);
|
||||
}
|
||||
|
||||
for (var47 = var11; var47 < var12; ++var47) {
|
||||
var27 = (float) Math.sin(((double) (var47 - var11) + 0.5D) / (double) var13 * 0.5D * Math.PI + (Math.PI / 2));
|
||||
var10000 = _k;
|
||||
var10000[var47] *= (float) Math.sin(1.5707963267948966D * (double) var27 * (double) var27);
|
||||
}
|
||||
}
|
||||
|
||||
float[] var43 = null;
|
||||
if (this._M > 0) {
|
||||
var41 = this._M + var4 >> 2;
|
||||
var43 = new float[var41];
|
||||
int var45;
|
||||
if (!this._A) {
|
||||
for (var42 = 0; var42 < this._i; ++var42) {
|
||||
var45 = (this._M >> 1) + var42;
|
||||
var43[var42] += this._n[var45];
|
||||
}
|
||||
}
|
||||
|
||||
if (!var15) {
|
||||
for (var42 = var8; var42 < var4 >> 1; ++var42) {
|
||||
var45 = var43.length - (var4 >> 1) + var42;
|
||||
var43[var45] += _k[var42];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final float[] var44 = this._n;
|
||||
this._n = _k;
|
||||
_k = var44;
|
||||
this._M = var4;
|
||||
this._i = var12 - (var4 >> 1);
|
||||
this._A = var15;
|
||||
return var43;
|
||||
}
|
||||
|
||||
private void a604(final byte[] var1) throws IOException {
|
||||
final Buffer var2 = new Buffer(var1);
|
||||
this._B = var2.readInt();
|
||||
this._q = var2.readInt();
|
||||
this._H = var2.readInt();
|
||||
this._G = var2.readInt();
|
||||
if (this._G < 0) {
|
||||
this._G = ~this._G;
|
||||
this._I = true;
|
||||
}
|
||||
|
||||
final int var3 = var2.readInt();
|
||||
if (var3 < 0) {
|
||||
throw new IOException();
|
||||
} else {
|
||||
this._v = new byte[var3][];
|
||||
|
||||
for (int var4 = 0; var4 < var3; ++var4) {
|
||||
int var5 = 0;
|
||||
|
||||
int var6;
|
||||
do {
|
||||
var6 = var2.readUByte();
|
||||
var5 += var6;
|
||||
} while (var6 >= 255);
|
||||
|
||||
final byte[] var7 = new byte[var5];
|
||||
var2.readBytes(var7, var5);
|
||||
this._v[var4] = var7;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void b720() {
|
||||
this._M = 0;
|
||||
this._n = new float[_r];
|
||||
for (int var3 = 0; var3 < this._v.length; ++var3) {
|
||||
this.e875(var3);
|
||||
}
|
||||
}
|
||||
}
|
119
src/main/java/funorb/audio/fh_.java
Normal file
119
src/main/java/funorb/audio/fh_.java
Normal file
@ -0,0 +1,119 @@
|
||||
package funorb.audio;
|
||||
|
||||
import funorb.io.Buffer;
|
||||
|
||||
public final class fh_ {
|
||||
public static final int[][] _e = new int[2][8];
|
||||
private static final float[][] _f = new float[2][8];
|
||||
public static int _g;
|
||||
private static float _h;
|
||||
public final int[] _d = new int[2];
|
||||
private final int[] _b = new int[2];
|
||||
private final int[][][] _a = new int[2][2][4];
|
||||
private final int[][][] _c = new int[2][2][4];
|
||||
|
||||
private static float a251(final float var0) {
|
||||
final float var1 = 32.703197F * (float) Math.pow(2.0D, var0);
|
||||
return var1 * 3.1415927F / 11025.0F;
|
||||
}
|
||||
|
||||
public void a086(final Buffer var1, final pn_ var2) {
|
||||
final int var3 = var1.readUByte();
|
||||
this._d[0] = var3 >> 4;
|
||||
this._d[1] = var3 & 15;
|
||||
if (var3 == 0) {
|
||||
this._b[1] = 0;
|
||||
this._b[0] = 0;
|
||||
} else {
|
||||
this._b[0] = var1.readUShort();
|
||||
this._b[1] = var1.readUShort();
|
||||
final int var4 = var1.readUByte();
|
||||
|
||||
int var5;
|
||||
int var6;
|
||||
for (var5 = 0; var5 < 2; ++var5) {
|
||||
for (var6 = 0; var6 < this._d[var5]; ++var6) {
|
||||
this._a[var5][0][var6] = var1.readUShort();
|
||||
this._c[var5][0][var6] = var1.readUShort();
|
||||
}
|
||||
}
|
||||
|
||||
for (var5 = 0; var5 < 2; ++var5) {
|
||||
for (var6 = 0; var6 < this._d[var5]; ++var6) {
|
||||
if ((var4 & 1 << var5 * 4 << var6) == 0) {
|
||||
this._a[var5][1][var6] = this._a[var5][0][var6];
|
||||
this._c[var5][1][var6] = this._c[var5][0][var6];
|
||||
} else {
|
||||
this._a[var5][1][var6] = var1.readUShort();
|
||||
this._c[var5][1][var6] = var1.readUShort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (var4 != 0 || this._b[1] != this._b[0]) {
|
||||
var2.read(var1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int a197(final int var1, final float var2) {
|
||||
float var3;
|
||||
if (var1 == 0) {
|
||||
var3 = (float) this._b[0] + (float) (this._b[1] - this._b[0]) * var2;
|
||||
var3 *= 0.0030517578F;
|
||||
_h = (float) Math.pow(0.1D, var3 / 20.0F);
|
||||
_g = (int) (_h * 65536.0F);
|
||||
}
|
||||
|
||||
if (this._d[var1] == 0) {
|
||||
return 0;
|
||||
} else {
|
||||
var3 = this.b427(var1, 0, var2);
|
||||
_f[var1][0] = -2.0f * var3 * (float) Math.cos(this.a427(var1, 0, var2));
|
||||
_f[var1][1] = var3 * var3;
|
||||
|
||||
int var4;
|
||||
for (var4 = 1; var4 < this._d[var1]; ++var4) {
|
||||
var3 = this.b427(var1, var4, var2);
|
||||
final float var5 = -2.0f * var3 * (float) Math.cos(this.a427(var1, var4, var2));
|
||||
final float var6 = var3 * var3;
|
||||
_f[var1][var4 * 2 + 1] = _f[var1][var4 * 2 - 1] * var6;
|
||||
_f[var1][var4 * 2] = _f[var1][var4 * 2 - 1] * var5 + _f[var1][var4 * 2 - 2] * var6;
|
||||
|
||||
for (int var7 = var4 * 2 - 1; var7 >= 2; --var7) {
|
||||
final float[] var10000 = _f[var1];
|
||||
var10000[var7] += _f[var1][var7 - 1] * var5 + _f[var1][var7 - 2] * var6;
|
||||
}
|
||||
|
||||
final float[] var10000 = _f[var1];
|
||||
var10000[1] += _f[var1][0] * var5 + var6;
|
||||
var10000[0] += var5;
|
||||
}
|
||||
|
||||
if (var1 == 0) {
|
||||
for (var4 = 0; var4 < this._d[0] * 2; ++var4) {
|
||||
final float[] var10000 = _f[0];
|
||||
var10000[var4] *= _h;
|
||||
}
|
||||
}
|
||||
|
||||
for (var4 = 0; var4 < this._d[var1] * 2; ++var4) {
|
||||
_e[var1][var4] = (int) (_f[var1][var4] * 65536.0F);
|
||||
}
|
||||
|
||||
return this._d[var1] * 2;
|
||||
}
|
||||
}
|
||||
|
||||
private float a427(final int var1, final int var2, final float var3) {
|
||||
float var4 = (float) this._a[var1][0][var2] + var3 * (float) (this._a[var1][1][var2] - this._a[var1][0][var2]);
|
||||
var4 *= 1.2207031E-4F;
|
||||
return a251(var4);
|
||||
}
|
||||
|
||||
private float b427(final int var1, final int var2, final float var3) {
|
||||
float var4 = (float) this._c[var1][0][var2] + var3 * (float) (this._c[var1][1][var2] - this._c[var1][0][var2]);
|
||||
var4 *= 0.0015258789F;
|
||||
return 1.0F - (float) Math.pow(10.0D, -var4 / 20.0F);
|
||||
}
|
||||
}
|
31
src/main/java/funorb/audio/fq_.java
Normal file
31
src/main/java/funorb/audio/fq_.java
Normal file
@ -0,0 +1,31 @@
|
||||
package funorb.audio;
|
||||
|
||||
public final class fq_ {
|
||||
public final int[] _b;
|
||||
public final int[] _a;
|
||||
public final int _c;
|
||||
public int _d;
|
||||
|
||||
public fq_() {
|
||||
fd_.a137(16);
|
||||
this._c = fd_.c784() != 0 ? fd_.a137(4) + 1 : 1;
|
||||
if (fd_.c784() != 0) {
|
||||
fd_.a137(8);
|
||||
}
|
||||
|
||||
fd_.a137(2);
|
||||
if (this._c > 1) {
|
||||
this._d = fd_.a137(4);
|
||||
}
|
||||
|
||||
this._b = new int[this._c];
|
||||
this._a = new int[this._c];
|
||||
|
||||
for (int var1 = 0; var1 < this._c; ++var1) {
|
||||
fd_.a137(8);
|
||||
this._b[var1] = fd_.a137(8);
|
||||
this._a[var1] = fd_.a137(8);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
843
src/main/java/funorb/audio/ga_.java
Normal file
843
src/main/java/funorb/audio/ga_.java
Normal file
@ -0,0 +1,843 @@
|
||||
package funorb.audio;
|
||||
|
||||
import funorb.cache.ResourceLoader;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
public final class ga_ extends tn_ {
|
||||
public final int[] _t = new int[16];
|
||||
public final int[] _F = new int[16];
|
||||
private final int[] _p = new int[16];
|
||||
private final int[] _y = new int[16];
|
||||
private final int[] _q = new int[16];
|
||||
private final qq_[][] _N = new qq_[16][128];
|
||||
private final int[] _r = new int[16];
|
||||
private final int[] _m = new int[16];
|
||||
private final Map<Integer, br_> _Q;
|
||||
private final int[] _G = new int[16];
|
||||
private final pi_ _x = new pi_();
|
||||
private final int[] _I = new int[16];
|
||||
private final int[] _P = new int[16];
|
||||
private final int[] _E = new int[16];
|
||||
private final int[] _J = new int[16];
|
||||
private final int[] _A = new int[16];
|
||||
private final int[] _T = new int[16];
|
||||
private final rc_ _l = new rc_(this);
|
||||
public final int[] _u = new int[16];
|
||||
private int volume = 256;
|
||||
private final qq_[][] _K = new qq_[16][128];
|
||||
private int _M = 1000000;
|
||||
private final int[] _s = new int[16];
|
||||
private int _C;
|
||||
private long _O;
|
||||
private int _D;
|
||||
private long _n;
|
||||
private boolean _v;
|
||||
private MusicTrack _z;
|
||||
|
||||
public ga_() {
|
||||
this._Q = new HashMap<>();
|
||||
this.a679();
|
||||
this.a430(true);
|
||||
}
|
||||
|
||||
@SuppressWarnings("CopyConstructorMissesField")
|
||||
public ga_(final ga_ var1) {
|
||||
this._Q = var1._Q;
|
||||
this.a679();
|
||||
this.a430(true);
|
||||
}
|
||||
|
||||
private static br_ a675cf(final ResourceLoader var0, final int var1) {
|
||||
final byte[] var2 = var0.getSingletonResource(var1);
|
||||
return var2 == null ? null : new br_(var2);
|
||||
}
|
||||
|
||||
public synchronized void e150() {
|
||||
this.b430(true);
|
||||
}
|
||||
|
||||
private void b789(final int var1, final int var3) {
|
||||
this._T[var1] = var3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Iterator<tn_> iterator() {
|
||||
return Collections.<tn_>singletonList(this._l).iterator();
|
||||
}
|
||||
|
||||
private void a326(final int var2, final int var3) {
|
||||
this._E[var3] = var2;
|
||||
this._u[var3] = (int) (0.5D + 2097152.0D * Math.pow(2.0D, 5.4931640625E-4D * (double) var2));
|
||||
}
|
||||
|
||||
private int b237(final qq_ var1) {
|
||||
int var3 = (var1._r * var1._G >> 12) + var1._J;
|
||||
var3 += this._r[var1._y] * (this._T[var1._y] - 8192) >> 12;
|
||||
final kc_ var4 = var1._u;
|
||||
int var6;
|
||||
if (var4._o > 0 && (var4._f > 0 || this._p[var1._y] > 0)) {
|
||||
var6 = var4._f << 2;
|
||||
final int var7 = var4._j << 1;
|
||||
if (var7 > var1._C) {
|
||||
var6 = var1._C * var6 / var7;
|
||||
}
|
||||
|
||||
var6 += this._p[var1._y] >> 7;
|
||||
final double var8 = Math.sin((double) (var1._i & 511) * 0.01227184630308513D);
|
||||
var3 += (int) ((double) var6 * var8);
|
||||
}
|
||||
|
||||
var6 = (int) ((double) (256 * var1._M._j) * Math.pow(2.0D, 3.255208333333333E-4D * (double) var3) / (double) SampledAudioChannel.SAMPLES_PER_SECOND + 0.5D);
|
||||
return Math.max(var6, 1);
|
||||
}
|
||||
|
||||
public synchronized void f150() {
|
||||
for (final br_ var2 : this._Q.values()) {
|
||||
var2.e150();
|
||||
}
|
||||
}
|
||||
|
||||
private void a093(final int var1) {
|
||||
for (final qq_ var3 : this._l._n) {
|
||||
if ((var1 < 0 || var3._y == var1) && var3._E < 0) {
|
||||
this._N[var3._y][var3._H] = null;
|
||||
var3._E = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void a172(final int var3, final int var4) {
|
||||
final qq_ var5 = this._N[var3][var4];
|
||||
if (var5 != null) {
|
||||
this._N[var3][var4] = null;
|
||||
if ((2 & this._F[var3]) == 0) {
|
||||
var5._E = 0;
|
||||
} else if (this._l._n.stream().anyMatch(var6 -> var5._y == var6._y && var6._E < 0 && var6 != var5)) {
|
||||
var5._E = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void c430() {
|
||||
this._M = 1000000;
|
||||
}
|
||||
|
||||
public synchronized void a679() {
|
||||
for (int var4 = 0; var4 < 16; ++var4) {
|
||||
this._A[var4] = 256;
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void a350(final SoundLoader soundLoader, final ResourceLoader loader, final MusicTrack track) {
|
||||
track.a797();
|
||||
|
||||
boolean var6 = true;
|
||||
|
||||
for (final Map.Entry<Integer, byte[]> var8 : track._i.entrySet()) {
|
||||
final int var9 = var8.getKey();
|
||||
br_ var10 = this._Q.get(var9);
|
||||
if (var10 == null) {
|
||||
var10 = a675cf(loader, var9);
|
||||
if (var10 == null) {
|
||||
var6 = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
this._Q.put(var9, var10);
|
||||
}
|
||||
|
||||
if (!var10.a972(soundLoader, var8.getValue())) {
|
||||
var6 = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (var6) {
|
||||
track.b797();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void a150(int len) {
|
||||
if (this._x.f801()) {
|
||||
final int var2 = this._x._e * this._M / SampledAudioChannel.SAMPLES_PER_SECOND;
|
||||
|
||||
do {
|
||||
final long var3 = (long) len * (long) var2 + this._O;
|
||||
if (this._n - var3 >= 0L) {
|
||||
this._O = var3;
|
||||
break;
|
||||
}
|
||||
|
||||
final int var5 = (int) ((-1L - this._O + this._n + (long) var2) / (long) var2);
|
||||
this._O += (long) var5 * (long) var2;
|
||||
this._l.a150(var5);
|
||||
len -= var5;
|
||||
this.a423();
|
||||
} while (this._x.f801());
|
||||
}
|
||||
|
||||
this._l.a150(len);
|
||||
}
|
||||
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
public synchronized void setVolume(final int volume) {
|
||||
this.volume = volume;
|
||||
}
|
||||
|
||||
private synchronized void b430(final boolean var2) {
|
||||
this._x.d797();
|
||||
this._z = null;
|
||||
this.a430(var2);
|
||||
}
|
||||
|
||||
private void b366(final int var1) {
|
||||
for (final qq_ var3 : this._l._n) {
|
||||
if (var1 < 0 || var1 == var3._y) {
|
||||
if (var3._K != null) {
|
||||
var3._K.g150(SampledAudioChannel.SAMPLES_PER_SECOND / 100);
|
||||
if (var3._K.e801()) {
|
||||
this._l._o.addFirst(var3._K);
|
||||
}
|
||||
|
||||
var3.d487();
|
||||
}
|
||||
|
||||
if (var3._E < 0) {
|
||||
this._N[var3._y][var3._H] = null;
|
||||
}
|
||||
|
||||
var3.unlink();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void a540(final int var2) {
|
||||
if ((2 & this._F[var2]) != 0) {
|
||||
for (final qq_ var3 : this._l._n) {
|
||||
if (var3._y == var2 && this._N[var2][var3._H] == null && var3._E < 0) {
|
||||
var3._E = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void a077(final MusicTrack var1, final boolean var3) {
|
||||
this.a918(var3, var1, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void b397(final int[] dest, int offset, int len) {
|
||||
if (this._x.f801()) {
|
||||
final int var4 = this._x._e * this._M / SampledAudioChannel.SAMPLES_PER_SECOND;
|
||||
|
||||
do {
|
||||
final long var5 = this._O + (long) len * (long) var4;
|
||||
if (this._n - var5 >= 0L) {
|
||||
this._O = var5;
|
||||
break;
|
||||
}
|
||||
|
||||
final int var7 = (int) ((-this._O + (this._n - (-((long) var4) + 1L))) / (long) var4);
|
||||
this._O += (long) var7 * (long) var4;
|
||||
this._l.b397(dest, offset, var7);
|
||||
offset += var7;
|
||||
len -= var7;
|
||||
this.a423();
|
||||
} while (this._x.f801());
|
||||
}
|
||||
|
||||
this._l.b397(dest, offset, len);
|
||||
}
|
||||
|
||||
private void a556(int var2) {
|
||||
if (var2 >= 0) {
|
||||
this._y[var2] = 12800;
|
||||
this._G[var2] = 8192;
|
||||
|
||||
this._s[var2] = 16383;
|
||||
this._T[var2] = 8192;
|
||||
this._p[var2] = 0;
|
||||
this._J[var2] = 8192;
|
||||
this.a540(var2);
|
||||
this.d093(var2);
|
||||
this._F[var2] = 0;
|
||||
this._q[var2] = 32767;
|
||||
this._r[var2] = 256;
|
||||
this._t[var2] = 0;
|
||||
this.a326(8192, var2);
|
||||
} else {
|
||||
for (var2 = 0; var2 < 16; ++var2) {
|
||||
this.a556(var2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void a430(final boolean var2) {
|
||||
if (var2) {
|
||||
this.b366(-1);
|
||||
} else {
|
||||
this.a093(-1);
|
||||
}
|
||||
|
||||
this.a556(-1);
|
||||
|
||||
int var3;
|
||||
for (var3 = 0; var3 < 16; ++var3) {
|
||||
this._I[var3] = this._m[var3];
|
||||
}
|
||||
|
||||
for (var3 = 0; var3 < 16; ++var3) {
|
||||
this._P[var3] = this._m[var3] & -128;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
|
||||
public boolean a258(final qq_ var2) {
|
||||
if (var2._K == null) {
|
||||
if (var2._E >= 0) {
|
||||
var2.unlink();
|
||||
if (var2._z > 0 && var2 == this._K[var2._y][var2._z]) {
|
||||
this._K[var2._y][var2._z] = null;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void a366(final int var1) {
|
||||
switch (var1 & 240) {
|
||||
case 128: {
|
||||
this.a172(15 & var1, (32672 & var1) >> 8);
|
||||
break;
|
||||
}
|
||||
case 144: {
|
||||
final int var5a = var1 & 15;
|
||||
final int var6a = var1 >> 8 & 127;
|
||||
final int var7a = 127 & var1 >> 16;
|
||||
if (var7a > 0) {
|
||||
this.a842(var6a, var5a, var7a);
|
||||
} else {
|
||||
this.a172(var5a, var6a);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 160:
|
||||
case 208:
|
||||
break;
|
||||
case 176: {
|
||||
final int var5a = 15 & var1;
|
||||
final int var6a = 127 & var1 >> 8;
|
||||
final int var7a = 127 & var1 >> 16;
|
||||
if (var6a == 0) {
|
||||
this._P[var5a] = (var7a << 14) + (-2080769 & this._P[var5a]);
|
||||
}
|
||||
|
||||
if (var6a == 32) {
|
||||
this._P[var5a] = (var7a << 7) + (-16257 & this._P[var5a]);
|
||||
}
|
||||
|
||||
if (var6a == 1) {
|
||||
this._p[var5a] = (-16257 & this._p[var5a]) + (var7a << 7);
|
||||
}
|
||||
|
||||
if (var6a == 33) {
|
||||
this._p[var5a] = var7a + (this._p[var5a] & -128);
|
||||
}
|
||||
|
||||
if (var6a == 5) {
|
||||
this._J[var5a] = (-16257 & this._J[var5a]) + (var7a << 7);
|
||||
}
|
||||
|
||||
if (var6a == 37) {
|
||||
this._J[var5a] = var7a + (this._J[var5a] & -128);
|
||||
}
|
||||
|
||||
if (var6a == 7) {
|
||||
this._y[var5a] = (var7a << 7) + (-16257 & this._y[var5a]);
|
||||
}
|
||||
|
||||
if (var6a == 39) {
|
||||
this._y[var5a] = (-128 & this._y[var5a]) + var7a;
|
||||
}
|
||||
|
||||
if (var6a == 10) {
|
||||
this._G[var5a] = (var7a << 7) + (this._G[var5a] & -16257);
|
||||
}
|
||||
|
||||
if (var6a == 42) {
|
||||
this._G[var5a] = (this._G[var5a] & -128) + var7a;
|
||||
}
|
||||
|
||||
if (var6a == 11) {
|
||||
this._s[var5a] = (var7a << 7) + (-16257 & this._s[var5a]);
|
||||
}
|
||||
|
||||
if (var6a == 43) {
|
||||
this._s[var5a] = var7a + (this._s[var5a] & -128);
|
||||
}
|
||||
|
||||
if (var6a == 64) {
|
||||
if (var7a >= 64) {
|
||||
this._F[var5a] = this._F[var5a] | 1;
|
||||
} else {
|
||||
this._F[var5a] = this._F[var5a] & -2;
|
||||
}
|
||||
}
|
||||
|
||||
if (var6a == 65) {
|
||||
if (var7a >= 64) {
|
||||
this._F[var5a] = this._F[var5a] | 2;
|
||||
} else {
|
||||
this.a540(var5a);
|
||||
this._F[var5a] = this._F[var5a] & -3;
|
||||
}
|
||||
}
|
||||
|
||||
if (var6a == 99) {
|
||||
this._q[var5a] = (var7a << 7) + (127 & this._q[var5a]);
|
||||
}
|
||||
|
||||
if (var6a == 98) {
|
||||
this._q[var5a] = var7a + (16256 & this._q[var5a]);
|
||||
}
|
||||
|
||||
if (var6a == 101) {
|
||||
this._q[var5a] = (this._q[var5a] & 127) + 16384 + (var7a << 7);
|
||||
}
|
||||
|
||||
if (var6a == 100) {
|
||||
this._q[var5a] = 16384 + (this._q[var5a] & 16256) + var7a;
|
||||
}
|
||||
|
||||
if (var6a == 120) {
|
||||
this.b366(var5a);
|
||||
}
|
||||
|
||||
if (var6a == 121) {
|
||||
this.a556(var5a);
|
||||
}
|
||||
|
||||
if (var6a == 123) {
|
||||
this.a093(var5a);
|
||||
}
|
||||
|
||||
int var8;
|
||||
if (var6a == 6) {
|
||||
var8 = this._q[var5a];
|
||||
if (var8 == 16384) {
|
||||
this._r[var5a] = (this._r[var5a] & -16257) + (var7a << 7);
|
||||
}
|
||||
}
|
||||
|
||||
if (var6a == 38) {
|
||||
var8 = this._q[var5a];
|
||||
if (var8 == 16384) {
|
||||
this._r[var5a] = var7a + (this._r[var5a] & -128);
|
||||
}
|
||||
}
|
||||
|
||||
if (var6a == 16) {
|
||||
this._t[var5a] = (var7a << 7) + (this._t[var5a] & -16257);
|
||||
}
|
||||
|
||||
if (var6a == 48) {
|
||||
this._t[var5a] = (this._t[var5a] & -128) + var7a;
|
||||
}
|
||||
|
||||
if (var6a == 81) {
|
||||
if (var7a >= 64) {
|
||||
this._F[var5a] = this._F[var5a] | 4;
|
||||
} else {
|
||||
this.d093(var5a);
|
||||
this._F[var5a] = this._F[var5a] & -5;
|
||||
}
|
||||
}
|
||||
|
||||
if (var6a == 17) {
|
||||
this.a326((var7a << 7) + (-16257 & this._E[var5a]), var5a);
|
||||
}
|
||||
|
||||
if (var6a == 49) {
|
||||
this.a326((this._E[var5a] & -128) + var7a, var5a);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case 192: {
|
||||
final int var5a = var1 & 15;
|
||||
final int var6a = (32569 & var1) >> 8;
|
||||
this.a599(var5a, this._P[var5a] + var6a);
|
||||
break;
|
||||
}
|
||||
case 224: {
|
||||
final int var5a = 15 & var1;
|
||||
final int var6a = (127 & var1 >> 8) + (var1 >> 9 & 16256);
|
||||
this.b789(var5a, var6a);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
if ((var1 & 255) == 255) {
|
||||
this.a430(true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized int a784() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
private synchronized void a918(final boolean var1, final MusicTrack var2, final boolean var4) {
|
||||
this.b430(var4);
|
||||
this._x.a604(var2._h);
|
||||
this._v = var1;
|
||||
this._O = 0L;
|
||||
final int var5 = this._x.c784();
|
||||
|
||||
for (int var6 = 0; var5 > var6; ++var6) {
|
||||
this._x.b150(var6);
|
||||
this._x.d150(var6);
|
||||
this._x.e150(var6);
|
||||
}
|
||||
|
||||
this._C = this._x.g784();
|
||||
this._D = this._x._b[this._C];
|
||||
this._n = this._x.c138(this._D);
|
||||
}
|
||||
|
||||
private void d093(final int var2) {
|
||||
if ((4 & this._F[var2]) != 0) {
|
||||
for (final qq_ var3 : this._l._n) {
|
||||
if (var3._y == var2) {
|
||||
var3._j = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void a842(final int var1, final int var2, final int var3) {
|
||||
this.a172(var2, var1);
|
||||
if ((this._F[var2] & 2) != 0) {
|
||||
for (final Iterator<qq_> it = this._l._n.descendingIterator(); it.hasNext(); ) {
|
||||
final qq_ var5 = it.next();
|
||||
if (var5._y == var2 && var5._E < 0) {
|
||||
this._N[var2][var5._H] = null;
|
||||
this._N[var2][var1] = var5;
|
||||
final int var6 = (var5._G * var5._r >> 12) + var5._J;
|
||||
var5._J += -var5._H + var1 << 8;
|
||||
var5._G = 4096;
|
||||
var5._r = -var5._J + var6;
|
||||
var5._H = var1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final br_ var10 = this._Q.get(this._I[var2]);
|
||||
if (var10 != null) {
|
||||
final kk_ var11 = var10._h[var1];
|
||||
if (var11 != null) {
|
||||
final qq_ var7 = new qq_();
|
||||
var7._y = var2;
|
||||
var7._A = var10;
|
||||
var7._M = var11;
|
||||
var7._u = var10._j[var1];
|
||||
var7._z = var10._r[var1];
|
||||
var7._H = var1;
|
||||
var7._k = var10._s[var1] * var3 * var3 * var10._q + 1024 >> 11;
|
||||
var7._q = var10._t[var1] & 255;
|
||||
var7._J = (var1 << 8) - (var10._k[var1] & 32767);
|
||||
var7._B = 0;
|
||||
var7._E = -1;
|
||||
var7._F = 0;
|
||||
var7._h = 0;
|
||||
var7._v = 0;
|
||||
if (this._t[var2] == 0) {
|
||||
var7._K = al_.a771(var11, this.b237(var7), this.a510(var7), this.a237(var7));
|
||||
} else {
|
||||
var7._K = al_.a771(var11, this.b237(var7), 0, this.a237(var7));
|
||||
this.a559(var7, var10._k[var1] < 0);
|
||||
}
|
||||
|
||||
if (var10._k[var1] < 0) {
|
||||
assert var7._K != null;
|
||||
var7._K.f150();
|
||||
}
|
||||
|
||||
if (var7._z >= 0) {
|
||||
final qq_ var9 = this._K[var2][var7._z];
|
||||
if (var9 != null && var9._E < 0) {
|
||||
this._N[var2][var9._H] = null;
|
||||
var9._E = 0;
|
||||
}
|
||||
|
||||
this._K[var2][var7._z] = var7;
|
||||
}
|
||||
|
||||
this._l._n.addLast(var7);
|
||||
this._N[var2][var1] = var7;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
|
||||
public boolean a543(final int var1, final int[] var2, final qq_ var4, final int var5) {
|
||||
var4._p = SampledAudioChannel.SAMPLES_PER_SECOND / 100;
|
||||
if (var4._E < 0 || var4._K != null && !var4._K.g801()) {
|
||||
int var6 = var4._G;
|
||||
if (var6 > 0) {
|
||||
var6 -= (int) (Math.pow(2.0D, (double) this._J[var4._y] * 4.921259842519685E-4D) * 16.0D + 0.5D);
|
||||
if (var6 < 0) {
|
||||
var6 = 0;
|
||||
}
|
||||
|
||||
var4._G = var6;
|
||||
}
|
||||
|
||||
var4._K.d150(this.b237(var4));
|
||||
final kc_ var7 = var4._u;
|
||||
var4._i += var7._o;
|
||||
++var4._C;
|
||||
boolean var8 = false;
|
||||
final double var9 = 5.086263020833333E-6D * (double) ((var4._H - 60 << 8) + (var4._G * var4._r >> 12));
|
||||
if (var7._h > 0) {
|
||||
if (var7._a > 0) {
|
||||
var4._h += (int) (Math.pow(2.0D, var9 * (double) var7._a) * 128.0D + 0.5D);
|
||||
} else {
|
||||
var4._h += 128;
|
||||
}
|
||||
|
||||
if (var7._h * var4._h >= 819200) {
|
||||
var8 = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (var7._n != null) {
|
||||
if (var7._k <= 0) {
|
||||
var4._F += 128;
|
||||
} else {
|
||||
var4._F += (int) (0.5D + Math.pow(2.0D, var9 * (double) var7._k) * 128.0D);
|
||||
}
|
||||
|
||||
while (var4._B < var7._n.length - 2 && ('\uff00' & var7._n[2 + var4._B] << 8) < var4._F) {
|
||||
var4._B += 2;
|
||||
}
|
||||
|
||||
if (var7._n.length - 2 == var4._B && var7._n[1 + var4._B] == 0) {
|
||||
var8 = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (var4._E >= 0 && var7._e != null && (1 & this._F[var4._y]) == 0 && (var4._z < 0 || this._K[var4._y][var4._z] != var4)) {
|
||||
if (var7._c <= 0) {
|
||||
var4._E += 128;
|
||||
} else {
|
||||
var4._E += (int) (0.5D + 128.0D * Math.pow(2.0D, (double) var7._c * var9));
|
||||
}
|
||||
|
||||
while (var4._v < var7._e.length - 2 && var4._E > (255 & var7._e[2 + var4._v]) << 8) {
|
||||
var4._v += 2;
|
||||
}
|
||||
|
||||
if (var7._e.length - 2 == var4._v) {
|
||||
var8 = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (var8) {
|
||||
var4._K.g150(var4._p);
|
||||
if (var2 == null) {
|
||||
var4._K.a150(var5);
|
||||
} else {
|
||||
var4._K.b397(var2, var1, var5);
|
||||
}
|
||||
|
||||
if (var4._K.e801()) {
|
||||
this._l._o.addFirst(var4._K);
|
||||
}
|
||||
|
||||
var4.d487();
|
||||
if (var4._E >= 0) {
|
||||
var4.unlink();
|
||||
if (var4._z > 0 && this._K[var4._y][var4._z] == var4) {
|
||||
this._K[var4._y][var4._z] = null;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
} else {
|
||||
|
||||
var4._K.a326(var4._p, this.a510(var4), this.a237(var4));
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
var4.d487();
|
||||
var4.unlink();
|
||||
if (var4._z > 0 && this._K[var4._y][var4._z] == var4) {
|
||||
this._K[var4._y][var4._z] = null;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private void a599(final int var1, final int var2) {
|
||||
if (var2 != this._I[var1]) {
|
||||
this._I[var1] = var2;
|
||||
for (int i = 0; i < 128; ++i) {
|
||||
this._K[var1][i] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int a237(final qq_ var1) {
|
||||
final int var3 = this._G[var1._y];
|
||||
return var3 >= 8192 ? -(32 + (128 - var1._q) * (-var3 + 16384) >> 6) + 16384 : 32 + var1._q * var3 >> 6;
|
||||
}
|
||||
|
||||
private void a423() {
|
||||
int var2 = this._C;
|
||||
int var3 = this._D;
|
||||
long var4 = this._n;
|
||||
if (this._z != null && var3 == 0) {
|
||||
this.a918(this._v, this._z, false);
|
||||
this.a423();
|
||||
} else {
|
||||
while (var3 == this._D) {
|
||||
while (this._x._b[var2] == var3) {
|
||||
this._x.b150(var2);
|
||||
final int var7 = this._x.a137(var2);
|
||||
if (var7 == 1) {
|
||||
this._x.e797();
|
||||
this._x.e150(var2);
|
||||
if (this._x.a801()) {
|
||||
if (this._z != null) {
|
||||
this.a077(this._z, this._v);
|
||||
this.a423();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this._v || var3 == 0) {
|
||||
this.a430(true);
|
||||
this._x.d797();
|
||||
return;
|
||||
}
|
||||
|
||||
this._x.a111(var4);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if ((var7 & 128) != 0) {
|
||||
this.a366(var7);
|
||||
}
|
||||
|
||||
this._x.d150(var2);
|
||||
this._x.e150(var2);
|
||||
}
|
||||
|
||||
var2 = this._x.g784();
|
||||
var3 = this._x._b[var2];
|
||||
var4 = this._x.c138(var3);
|
||||
}
|
||||
|
||||
this._C = var2;
|
||||
this._D = var3;
|
||||
this._n = var4;
|
||||
if (this._z != null && var3 > 0) {
|
||||
this._C = -1;
|
||||
this._D = 0;
|
||||
this._n = this._x.c138(this._D);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void a559(final qq_ var2, final boolean var3) {
|
||||
|
||||
int var4 = var2._M.data.length;
|
||||
int var5;
|
||||
if (var3 && var2._M._i) {
|
||||
final int var6 = -var2._M._l + var4 + var4;
|
||||
var5 = (int) ((long) this._t[var2._y] * (long) var6 >> 6);
|
||||
var4 <<= 8;
|
||||
if (var5 >= var4) {
|
||||
var2._K.c487();
|
||||
var5 = -var5 + var4 + var4 - 1;
|
||||
}
|
||||
} else {
|
||||
var5 = (int) ((long) this._t[var2._y] * (long) var4 >> 6);
|
||||
}
|
||||
|
||||
var2._K.h150(var5);
|
||||
}
|
||||
|
||||
private int a510(final qq_ var1) {
|
||||
if (this._A[var1._y] == 0) {
|
||||
return 0;
|
||||
} else {
|
||||
final kc_ var3 = var1._u;
|
||||
int var4 = this._y[var1._y] * this._s[var1._y] + 4096 >> 13;
|
||||
var4 = var4 * var4 + 16384 >> 15;
|
||||
var4 = var1._k * var4 + 16384 >> 15;
|
||||
var4 = 128 + this.volume * var4 >> 8;
|
||||
var4 = this._A[var1._y] * var4 + 128 >> 8;
|
||||
if (var3._h > 0) {
|
||||
var4 = (int) (0.5D + (double) var4 * Math.pow(0.5D, (double) var1._h * 1.953125E-5D * (double) var3._h));
|
||||
}
|
||||
|
||||
int var5;
|
||||
int var6;
|
||||
int var7;
|
||||
int var8;
|
||||
if (var3._n != null) {
|
||||
var5 = var1._F;
|
||||
var6 = var3._n[1 + var1._B];
|
||||
if (var1._B < var3._n.length - 2) {
|
||||
var7 = var3._n[var1._B] << 8 & '\uff00';
|
||||
var8 = (255 & var3._n[2 + var1._B]) << 8;
|
||||
var6 += (-var6 + var3._n[var1._B + 3]) * (-var7 + var5) / (-var7 + var8);
|
||||
}
|
||||
|
||||
var4 = var6 * var4 + 32 >> 6;
|
||||
}
|
||||
|
||||
if (var1._E > 0 && var3._e != null) {
|
||||
var5 = var1._E;
|
||||
var6 = var3._e[1 + var1._v];
|
||||
if (var3._e.length - 2 > var1._v) {
|
||||
var7 = (255 & var3._e[var1._v]) << 8;
|
||||
var8 = var3._e[2 + var1._v] << 8 & '\uff00';
|
||||
var6 += (var3._e[var1._v + 3] - var6) * (-var7 + var5) / (-var7 + var8);
|
||||
}
|
||||
|
||||
var4 = 32 + var4 * var6 >> 6;
|
||||
}
|
||||
|
||||
return var4;
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void initialize() {
|
||||
this._m[9] = 128;
|
||||
this._P[9] = 128;
|
||||
this.a599(9, 128);
|
||||
}
|
||||
|
||||
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
|
||||
public synchronized boolean h154() {
|
||||
return this._x.f801();
|
||||
}
|
||||
}
|
243
src/main/java/funorb/audio/h_.java
Normal file
243
src/main/java/funorb/audio/h_.java
Normal file
@ -0,0 +1,243 @@
|
||||
package funorb.audio;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
|
||||
public final class h_ extends tn_ {
|
||||
public final ga_ _r;
|
||||
public final ga_ _u;
|
||||
private int[] _D;
|
||||
private MusicTrack _E;
|
||||
private int _l;
|
||||
private int _n = 0x100000;
|
||||
private MusicTrack _z;
|
||||
private int[] _p;
|
||||
private int volume = 256;
|
||||
private boolean _C;
|
||||
|
||||
public h_() {
|
||||
final ga_ var1 = new ga_();
|
||||
this._u = var1;
|
||||
this._r = new ga_(var1);
|
||||
}
|
||||
|
||||
public boolean a419(final MusicTrack var1) {
|
||||
return var1 == this._z || var1 == this._E;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void b397(final int[] dest, final int offset, final int len) {
|
||||
if (this.volume <= 0) {
|
||||
this.a150(len);
|
||||
} else {
|
||||
if (this._C) {
|
||||
if (this._l > 0 && !this._u.h154()) {
|
||||
this._C = false;
|
||||
this._l = -this._l;
|
||||
this._z = null;
|
||||
} else if (this._l < 0 && !this._r.h154()) {
|
||||
this._E = null;
|
||||
this._C = false;
|
||||
this._l = -this._l;
|
||||
}
|
||||
}
|
||||
|
||||
final int var4 = (this._n >> 12) * this.volume / 256;
|
||||
final int var5 = this.volume - var4;
|
||||
if (this._l != 0) {
|
||||
this._n += this._l * len;
|
||||
if (this._n >= 1048576) {
|
||||
this._n = 1048576;
|
||||
if (!this._C) {
|
||||
this._l = 0;
|
||||
if (this._E != null) {
|
||||
this._r.e150();
|
||||
}
|
||||
|
||||
this._E = null;
|
||||
}
|
||||
} else if (this._n <= 0) {
|
||||
this._n = 0;
|
||||
if (!this._C) {
|
||||
this._l = 0;
|
||||
if (this._z != null) {
|
||||
this._u.e150();
|
||||
}
|
||||
|
||||
this._z = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final int var6 = len << 1;
|
||||
final int var7;
|
||||
int var8;
|
||||
if (this._z != null || this._E != null) {
|
||||
if (var4 == 256) {
|
||||
this._u.b397(dest, offset, len);
|
||||
} else if (var5 == 256) {
|
||||
this._r.b397(dest, offset, len);
|
||||
} else {
|
||||
if (this._D != null && this._D.length >= var6) {
|
||||
Arrays.fill(this._D, 0, var6, 0);
|
||||
Arrays.fill(this._p, 0, var6, 0);
|
||||
} else {
|
||||
this._p = new int[var6];
|
||||
this._D = new int[var6];
|
||||
}
|
||||
|
||||
this._u.b397(this._D, 0, len);
|
||||
this._r.b397(this._p, 0, len);
|
||||
var7 = offset << 1;
|
||||
|
||||
for (var8 = 0; var6 > var8; ++var8) {
|
||||
dest[var7 + var8] += this._p[var8] * var5 + this._D[var8] * var4 >> 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void a150(final int len) {
|
||||
if (this._n > 0 && this._z != null) {
|
||||
this._u.a150(len);
|
||||
}
|
||||
|
||||
if (this._n < 1048576 && this._E != null) {
|
||||
this._r.a150(len);
|
||||
}
|
||||
|
||||
if (this._C) {
|
||||
if (this._l > 0 && !this._u.h154()) {
|
||||
this._C = false;
|
||||
this._z = null;
|
||||
this._l = -this._l;
|
||||
} else if (this._l < 0 && !this._r.h154()) {
|
||||
this._C = false;
|
||||
this._l = -this._l;
|
||||
this._E = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (this._l != 0) {
|
||||
this._n += this._l * len;
|
||||
if (this._n >= 1048576) {
|
||||
this._n = 1048576;
|
||||
if (!this._C) {
|
||||
this._l = 0;
|
||||
if (this._E != null) {
|
||||
this._r.e150();
|
||||
}
|
||||
|
||||
this._E = null;
|
||||
}
|
||||
} else if (this._n <= 0) {
|
||||
this._n = 0;
|
||||
if (!this._C) {
|
||||
this._l = 0;
|
||||
if (this._z != null) {
|
||||
this._u.e150();
|
||||
}
|
||||
|
||||
this._z = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void a633(final ga_ var3) {
|
||||
var3.a679();
|
||||
var3.c430();
|
||||
}
|
||||
|
||||
public synchronized void setVolume(final int volume) {
|
||||
this.volume = volume;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized int a784() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Iterator<tn_> iterator() {
|
||||
return Collections.emptyIterator();
|
||||
}
|
||||
|
||||
public synchronized void a180(final MusicTrack track, final int var5, final boolean var4) {
|
||||
if (this._C && var4) {
|
||||
if (this._l > 0) {
|
||||
if (this._z != null) {
|
||||
this._u.e150();
|
||||
}
|
||||
|
||||
this._z = track;
|
||||
if (track != null) {
|
||||
this._u.a077(track, false);
|
||||
this.a633(this._u);
|
||||
}
|
||||
} else {
|
||||
if (this._E != null) {
|
||||
this._r.e150();
|
||||
}
|
||||
|
||||
this._E = track;
|
||||
if (track != null) {
|
||||
this._r.a077(track, false);
|
||||
this.a633(this._r);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
this._C = var4;
|
||||
if (this._z == track) {
|
||||
this._l = var5;
|
||||
this.a633(this._u);
|
||||
} else if (track == this._E) {
|
||||
this._l = -var5;
|
||||
this.a633(this._r);
|
||||
} else {
|
||||
final boolean var7;
|
||||
if (this._z == null) {
|
||||
var7 = true;
|
||||
} else if (this._E == null) {
|
||||
var7 = false;
|
||||
} else {
|
||||
var7 = this._n < 524288;
|
||||
}
|
||||
|
||||
if (var7) {
|
||||
if (this._z != null) {
|
||||
this._u.e150();
|
||||
}
|
||||
|
||||
this._z = track;
|
||||
if (track != null) {
|
||||
this._u.a077(track, !var4);
|
||||
this.a633(this._u);
|
||||
}
|
||||
|
||||
this._l = var5;
|
||||
} else {
|
||||
if (this._E != null) {
|
||||
this._r.e150();
|
||||
}
|
||||
|
||||
this._E = track;
|
||||
if (track != null) {
|
||||
this._r.a077(track, !var4);
|
||||
this.a633(this._r);
|
||||
}
|
||||
|
||||
this._l = -var5;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
13
src/main/java/funorb/audio/kc_.java
Normal file
13
src/main/java/funorb/audio/kc_.java
Normal file
@ -0,0 +1,13 @@
|
||||
package funorb.audio;
|
||||
|
||||
public final class kc_ {
|
||||
public int _j;
|
||||
public int _c;
|
||||
public int _a;
|
||||
public int _h;
|
||||
public byte[] _e;
|
||||
public int _k;
|
||||
public byte[] _n;
|
||||
public int _f;
|
||||
public int _o;
|
||||
}
|
22
src/main/java/funorb/audio/kk_.java
Normal file
22
src/main/java/funorb/audio/kk_.java
Normal file
@ -0,0 +1,22 @@
|
||||
package funorb.audio;
|
||||
|
||||
public final class kk_ {
|
||||
public final int _k;
|
||||
public final int _l;
|
||||
public final int _j;
|
||||
public final byte[] data;
|
||||
public final boolean _i;
|
||||
public int _h;
|
||||
|
||||
public kk_(final byte[] data, final int var3, final int var4) {
|
||||
this(SampledAudioChannel.SAMPLES_PER_SECOND, data, var3, var4, false);
|
||||
}
|
||||
|
||||
public kk_(final int var1, final byte[] data, final int var3, final int var4, final boolean var5) {
|
||||
this._j = var1;
|
||||
this.data = data;
|
||||
this._l = var3;
|
||||
this._k = var4;
|
||||
this._i = var5;
|
||||
}
|
||||
}
|
286
src/main/java/funorb/audio/kn_.java
Normal file
286
src/main/java/funorb/audio/kn_.java
Normal file
@ -0,0 +1,286 @@
|
||||
package funorb.audio;
|
||||
|
||||
import funorb.util.BitMath;
|
||||
|
||||
public final class kn_ {
|
||||
private static final float[] _j = new float[]{1.0649863E-7F, 1.1341951E-7F, 1.2079015E-7F, 1.2863978E-7F, 1.369995E-7F, 1.459025E-7F, 1.5538409E-7F, 1.6548181E-7F, 1.7623574E-7F, 1.8768856E-7F, 1.998856E-7F, 2.128753E-7F, 2.2670913E-7F, 2.4144197E-7F, 2.5713223E-7F, 2.7384212E-7F, 2.9163792E-7F, 3.1059022E-7F, 3.307741E-7F, 3.5226967E-7F, 3.7516213E-7F, 3.995423E-7F, 4.255068E-7F, 4.5315863E-7F, 4.8260745E-7F, 5.1397E-7F, 5.4737063E-7F, 5.829419E-7F, 6.208247E-7F, 6.611694E-7F, 7.041359E-7F, 7.4989464E-7F, 7.98627E-7F, 8.505263E-7F, 9.057983E-7F, 9.646621E-7F, 1.0273513E-6F, 1.0941144E-6F, 1.1652161E-6F, 1.2409384E-6F, 1.3215816E-6F, 1.4074654E-6F, 1.4989305E-6F, 1.5963394E-6F, 1.7000785E-6F, 1.8105592E-6F, 1.9282195E-6F, 2.053526E-6F, 2.1869757E-6F, 2.3290977E-6F, 2.4804558E-6F, 2.6416496E-6F, 2.813319E-6F, 2.9961443E-6F, 3.1908505E-6F, 3.39821E-6F, 3.619045E-6F, 3.8542307E-6F, 4.1047006E-6F, 4.371447E-6F, 4.6555283E-6F, 4.958071E-6F, 5.280274E-6F, 5.623416E-6F, 5.988857E-6F, 6.3780467E-6F, 6.7925284E-6F, 7.2339453E-6F, 7.704048E-6F, 8.2047E-6F, 8.737888E-6F, 9.305725E-6F, 9.910464E-6F, 1.0554501E-5F, 1.1240392E-5F, 1.1970856E-5F, 1.2748789E-5F, 1.3577278E-5F, 1.4459606E-5F, 1.5399271E-5F, 1.6400005E-5F, 1.7465769E-5F, 1.8600793E-5F, 1.9809577E-5F, 2.1096914E-5F, 2.2467912E-5F, 2.3928002E-5F, 2.5482977E-5F, 2.7139005E-5F, 2.890265E-5F, 3.078091E-5F, 3.2781227E-5F, 3.4911533E-5F, 3.718028E-5F, 3.9596467E-5F, 4.2169668E-5F, 4.491009E-5F, 4.7828602E-5F, 5.0936775E-5F, 5.424693E-5F, 5.7772202E-5F, 6.152657E-5F, 6.552491E-5F, 6.9783084E-5F, 7.4317984E-5F, 7.914758E-5F, 8.429104E-5F, 8.976875E-5F, 9.560242E-5F, 1.0181521E-4F, 1.0843174E-4F, 1.1547824E-4F, 1.2298267E-4F, 1.3097477E-4F, 1.3948625E-4F, 1.4855085E-4F, 1.5820454E-4F, 1.6848555E-4F, 1.7943469E-4F, 1.9109536E-4F, 2.0351382E-4F, 2.167393E-4F, 2.3082423E-4F, 2.4582449E-4F, 2.6179955E-4F, 2.7881275E-4F, 2.9693157E-4F, 3.1622787E-4F, 3.3677815E-4F, 3.5866388E-4F, 3.8197188E-4F, 4.0679457E-4F, 4.3323037E-4F, 4.613841E-4F, 4.913675E-4F, 5.2329927E-4F, 5.573062E-4F, 5.935231E-4F, 6.320936E-4F, 6.731706E-4F, 7.16917E-4F, 7.635063E-4F, 8.1312325E-4F, 8.6596457E-4F, 9.2223985E-4F, 9.821722E-4F, 0.0010459992F, 0.0011139743F, 0.0011863665F, 0.0012634633F, 0.0013455702F, 0.0014330129F, 0.0015261382F, 0.0016253153F, 0.0017309374F, 0.0018434235F, 0.0019632196F, 0.0020908006F, 0.0022266726F, 0.0023713743F, 0.0025254795F, 0.0026895993F, 0.0028643848F, 0.0030505287F, 0.003248769F, 0.0034598925F, 0.0036847359F, 0.0039241905F, 0.0041792067F, 0.004450795F, 0.004740033F, 0.005048067F, 0.0053761187F, 0.005725489F, 0.0060975635F, 0.0064938175F, 0.0069158226F, 0.0073652514F, 0.007843887F, 0.008353627F, 0.008896492F, 0.009474637F, 0.010090352F, 0.01074608F, 0.011444421F, 0.012188144F, 0.012980198F, 0.013823725F, 0.014722068F, 0.015678791F, 0.016697686F, 0.017782796F, 0.018938422F, 0.020169148F, 0.021479854F, 0.022875736F, 0.02436233F, 0.025945531F, 0.027631618F, 0.029427277F, 0.031339627F, 0.03337625F, 0.035545226F, 0.037855156F, 0.0403152F, 0.042935107F, 0.045725275F, 0.048696756F, 0.05186135F, 0.05523159F, 0.05882085F, 0.062643364F, 0.06671428F, 0.07104975F, 0.075666964F, 0.08058423F, 0.08582105F, 0.09139818F, 0.097337745F, 0.1036633F, 0.11039993F, 0.11757434F, 0.12521498F, 0.13335215F, 0.14201812F, 0.15124726F, 0.16107617F, 0.1715438F, 0.18269168F, 0.19456401F, 0.20720787F, 0.22067343F, 0.23501402F, 0.25028655F, 0.26655158F, 0.28387362F, 0.3023213F, 0.32196787F, 0.34289113F, 0.36517414F, 0.3889052F, 0.41417846F, 0.44109413F, 0.4697589F, 0.50028646F, 0.53279793F, 0.5674221F, 0.6042964F, 0.64356697F, 0.6853896F, 0.72993004F, 0.777365F, 0.8278826F, 0.88168305F, 0.9389798F, 1.0F};
|
||||
private static final int[] _a = new int[]{256, 128, 86, 64};
|
||||
private static boolean[] _g;
|
||||
private static int[] _i;
|
||||
private static int[] _d;
|
||||
private final int[] _f;
|
||||
private final int[] _c;
|
||||
private final int[][] _k;
|
||||
private final int[] _l;
|
||||
private final int[] _h;
|
||||
private final int _b;
|
||||
private final int[] _e;
|
||||
|
||||
public kn_() {
|
||||
final int var1 = fd_.a137(16);
|
||||
if (var1 == 1) {
|
||||
final int var2 = fd_.a137(5);
|
||||
int var3 = 0;
|
||||
this._l = new int[var2];
|
||||
|
||||
int var4;
|
||||
int var5;
|
||||
for (var4 = 0; var4 < var2; ++var4) {
|
||||
var5 = fd_.a137(4);
|
||||
this._l[var4] = var5;
|
||||
if (var5 >= var3) {
|
||||
var3 = var5 + 1;
|
||||
}
|
||||
}
|
||||
|
||||
this._e = new int[var3];
|
||||
this._c = new int[var3];
|
||||
this._h = new int[var3];
|
||||
this._k = new int[var3][];
|
||||
|
||||
int var7;
|
||||
for (var4 = 0; var4 < var3; ++var4) {
|
||||
this._e[var4] = fd_.a137(3) + 1;
|
||||
var5 = this._c[var4] = fd_.a137(2);
|
||||
if (var5 != 0) {
|
||||
this._h[var4] = fd_.a137(8);
|
||||
}
|
||||
|
||||
var5 = 1 << var5;
|
||||
final int[] var6 = new int[var5];
|
||||
this._k[var4] = var6;
|
||||
|
||||
for (var7 = 0; var7 < var5; ++var7) {
|
||||
var6[var7] = fd_.a137(8) - 1;
|
||||
}
|
||||
}
|
||||
|
||||
this._b = fd_.a137(2) + 1;
|
||||
var4 = fd_.a137(4);
|
||||
var5 = 2;
|
||||
|
||||
int var9;
|
||||
for (var9 = 0; var9 < var2; ++var9) {
|
||||
var5 += this._e[this._l[var9]];
|
||||
}
|
||||
|
||||
this._f = new int[var5];
|
||||
this._f[0] = 0;
|
||||
this._f[1] = 1 << var4;
|
||||
var5 = 2;
|
||||
|
||||
for (var9 = 0; var9 < var2; ++var9) {
|
||||
var7 = this._l[var9];
|
||||
|
||||
for (int var8 = 0; var8 < this._e[var7]; ++var8) {
|
||||
this._f[var5++] = fd_.a137(var4);
|
||||
}
|
||||
}
|
||||
|
||||
if (_d == null || _d.length < var5) {
|
||||
_d = new int[var5];
|
||||
_i = new int[var5];
|
||||
_g = new boolean[var5];
|
||||
}
|
||||
|
||||
} else {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
private static int b691(final int[] var0, final int var1) {
|
||||
final int var2 = var0[var1];
|
||||
int var3 = -1;
|
||||
int var4 = Integer.MAX_VALUE;
|
||||
|
||||
for (int var5 = 0; var5 < var1; ++var5) {
|
||||
final int var6 = var0[var5];
|
||||
if (var6 > var2 && var6 < var4) {
|
||||
var3 = var5;
|
||||
var4 = var6;
|
||||
}
|
||||
}
|
||||
|
||||
return var3;
|
||||
}
|
||||
|
||||
private static int a691(final int[] var0, final int var1) {
|
||||
final int var2 = var0[var1];
|
||||
int var3 = -1;
|
||||
int var4 = Integer.MIN_VALUE;
|
||||
|
||||
for (int var5 = 0; var5 < var1; ++var5) {
|
||||
final int var6 = var0[var5];
|
||||
if (var6 < var2 && var6 > var4) {
|
||||
var3 = var5;
|
||||
var4 = var6;
|
||||
}
|
||||
}
|
||||
|
||||
return var3;
|
||||
}
|
||||
|
||||
public boolean b801() {
|
||||
final boolean var1 = fd_.c784() != 0;
|
||||
if (var1) {
|
||||
final int var2 = this._f.length;
|
||||
|
||||
int var3;
|
||||
for (var3 = 0; var3 < var2; ++var3) {
|
||||
_d[var3] = this._f[var3];
|
||||
}
|
||||
|
||||
var3 = _a[this._b - 1];
|
||||
final int var4 = BitMath.lastSet(var3 - 1);
|
||||
_i[0] = fd_.a137(var4);
|
||||
_i[1] = fd_.a137(var4);
|
||||
int var5 = 2;
|
||||
|
||||
for (final int var7 : this._l) {
|
||||
final int var8 = this._e[var7];
|
||||
final int var9 = this._c[var7];
|
||||
final int var10 = (1 << var9) - 1;
|
||||
int var11 = 0;
|
||||
if (var9 > 0) {
|
||||
var11 = fd_._L[this._h[var7]].a784();
|
||||
}
|
||||
|
||||
for (int var12 = 0; var12 < var8; ++var12) {
|
||||
final int var13 = this._k[var7][var11 & var10];
|
||||
var11 >>>= var9;
|
||||
_i[var5++] = var13 >= 0 ? fd_._L[var13].a784() : 0;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void a093(final int var1, final int var2) {
|
||||
if (var1 < var2) {
|
||||
int var3 = var1;
|
||||
final int var4 = _d[var1];
|
||||
final int var5 = _i[var1];
|
||||
final boolean var6 = _g[var1];
|
||||
|
||||
for (int var7 = var1 + 1; var7 <= var2; ++var7) {
|
||||
final int var8 = _d[var7];
|
||||
if (var8 < var4) {
|
||||
_d[var3] = var8;
|
||||
_i[var3] = _i[var7];
|
||||
_g[var3] = _g[var7];
|
||||
++var3;
|
||||
_d[var7] = _d[var3];
|
||||
_i[var7] = _i[var3];
|
||||
_g[var7] = _g[var3];
|
||||
}
|
||||
}
|
||||
|
||||
_d[var3] = var4;
|
||||
_i[var3] = var5;
|
||||
_g[var3] = var6;
|
||||
this.a093(var1, var3 - 1);
|
||||
this.a093(var3 + 1, var2);
|
||||
}
|
||||
}
|
||||
|
||||
private int a063(final int var1, final int var2, final int var3, final int var4, final int var5) {
|
||||
final int var6 = var4 - var2;
|
||||
final int var7 = var3 - var1;
|
||||
final int var8 = var6 < 0 ? -var6 : var6;
|
||||
final int var9 = var8 * (var5 - var1);
|
||||
final int var10 = var9 / var7;
|
||||
return var6 < 0 ? var2 - var10 : var2 + var10;
|
||||
}
|
||||
|
||||
private void a365(final int var1, final int var2, int var3, final int var4, final float[] var5, final int var6) {
|
||||
final int var7 = var4 - var2;
|
||||
final int var8 = var3 - var1;
|
||||
int var9 = var7 < 0 ? -var7 : var7;
|
||||
final int var10 = var7 / var8;
|
||||
int var11 = var2;
|
||||
int var12 = 0;
|
||||
final int var13 = var7 < 0 ? var10 - 1 : var10 + 1;
|
||||
var9 -= (var10 < 0 ? -var10 : var10) * var8;
|
||||
var5[var1] *= _j[var2];
|
||||
if (var3 > var6) {
|
||||
var3 = var6;
|
||||
}
|
||||
|
||||
for (int var14 = var1 + 1; var14 < var3; ++var14) {
|
||||
var12 += var9;
|
||||
if (var12 >= var8) {
|
||||
var12 -= var8;
|
||||
var11 += var13;
|
||||
} else {
|
||||
var11 += var10;
|
||||
}
|
||||
|
||||
var5[var14] *= _j[var11];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void a331(final float[] var1, final int var2) {
|
||||
final int var3 = this._f.length;
|
||||
final int var4 = _a[this._b - 1];
|
||||
final boolean[] var5 = _g;
|
||||
_g[1] = true;
|
||||
var5[0] = true;
|
||||
|
||||
int var6;
|
||||
int var7;
|
||||
int var8;
|
||||
int var9;
|
||||
int var10;
|
||||
for (var6 = 2; var6 < var3; ++var6) {
|
||||
var7 = a691(_d, var6);
|
||||
var8 = b691(_d, var6);
|
||||
var9 = this.a063(_d[var7], _i[var7], _d[var8], _i[var8], _d[var6]);
|
||||
var10 = _i[var6];
|
||||
final int var11 = var4 - var9;
|
||||
final int var13 = (Math.min(var11, var9)) << 1;
|
||||
if (var10 == 0) {
|
||||
_g[var6] = false;
|
||||
_i[var6] = var9;
|
||||
} else {
|
||||
final boolean[] var14 = _g;
|
||||
_g[var8] = true;
|
||||
var14[var7] = true;
|
||||
_g[var6] = true;
|
||||
if (var10 >= var13) {
|
||||
_i[var6] = var11 > var9 ? var10 - var9 + var9 : var9 - var10 + var11 - 1;
|
||||
} else {
|
||||
_i[var6] = (var10 & 1) != 0 ? var9 - (var10 + 1) / 2 : var9 + var10 / 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.a093(0, var3 - 1);
|
||||
var6 = 0;
|
||||
var7 = _i[0] * this._b;
|
||||
|
||||
for (var8 = 1; var8 < var3; ++var8) {
|
||||
if (_g[var8]) {
|
||||
var9 = _d[var8];
|
||||
var10 = _i[var8] * this._b;
|
||||
this.a365(var6, var7, var9, var10, var1, var2);
|
||||
if (var9 >= var2) {
|
||||
return;
|
||||
}
|
||||
|
||||
var6 = var9;
|
||||
var7 = var10;
|
||||
}
|
||||
}
|
||||
|
||||
final float var16 = _j[var7];
|
||||
|
||||
for (var9 = var6; var9 < var2; ++var9) {
|
||||
var1[var9] *= var16;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
200
src/main/java/funorb/audio/pi_.java
Normal file
200
src/main/java/funorb/audio/pi_.java
Normal file
@ -0,0 +1,200 @@
|
||||
package funorb.audio;
|
||||
|
||||
import funorb.io.Buffer;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public final class pi_ {
|
||||
private static final byte[] _g = new byte[]{2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
private final Buffer _i = new Buffer(null);
|
||||
public int _e;
|
||||
public int[] _b;
|
||||
private int[] _h;
|
||||
private int[] _c;
|
||||
private int[] _d;
|
||||
private long _f;
|
||||
private int _a;
|
||||
|
||||
public pi_() {
|
||||
}
|
||||
|
||||
public pi_(final byte[] var1) {
|
||||
this.a604(var1);
|
||||
}
|
||||
|
||||
public boolean a801() {
|
||||
return Arrays.stream(this._h).noneMatch(i -> i >= 0);
|
||||
}
|
||||
|
||||
public int a137(final int var1) {
|
||||
return this.f137(var1);
|
||||
}
|
||||
|
||||
public void a111(final long var1) {
|
||||
this._f = var1;
|
||||
final int var3 = this._h.length;
|
||||
|
||||
for (int var4 = 0; var4 < var3; ++var4) {
|
||||
this._b[var4] = 0;
|
||||
this._d[var4] = 0;
|
||||
this._i.pos = this._c[var4];
|
||||
this.d150(var4);
|
||||
this._h[var4] = this._i.pos;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public long c138(final int var1) {
|
||||
return this._f + (long) var1 * (long) this._a;
|
||||
}
|
||||
|
||||
public void b150(final int var1) {
|
||||
this._i.pos = this._h[var1];
|
||||
}
|
||||
|
||||
private int a080(final int var1, final int var2) {
|
||||
int var4;
|
||||
if (var2 == 255) {
|
||||
final int var7 = this._i.readUByte();
|
||||
var4 = this._i.readVariableInt();
|
||||
final Buffer var10000;
|
||||
if (var7 == 47) {
|
||||
var10000 = this._i;
|
||||
var10000.pos += var4;
|
||||
return 1;
|
||||
} else if (var7 == 81) {
|
||||
final int var5 = this._i.readU24();
|
||||
var4 -= 3;
|
||||
final int var6 = this._b[var1];
|
||||
this._f += (long) var6 * (long) (this._a - var5);
|
||||
this._a = var5;
|
||||
var10000 = this._i;
|
||||
var10000.pos += var4;
|
||||
return 2;
|
||||
} else {
|
||||
var10000 = this._i;
|
||||
var10000.pos += var4;
|
||||
return 3;
|
||||
}
|
||||
} else {
|
||||
final byte var3 = _g[var2 - 128];
|
||||
var4 = var2;
|
||||
if (var3 >= 1) {
|
||||
var4 = var2 | this._i.readUByte() << 8;
|
||||
}
|
||||
|
||||
if (var3 >= 2) {
|
||||
var4 |= this._i.readUByte() << 16;
|
||||
}
|
||||
|
||||
return var4;
|
||||
}
|
||||
}
|
||||
|
||||
public int g784() {
|
||||
final int var1 = this._h.length;
|
||||
int var2 = -1;
|
||||
int var3 = Integer.MAX_VALUE;
|
||||
|
||||
for (int var4 = 0; var4 < var1; ++var4) {
|
||||
if (this._h[var4] >= 0 && this._b[var4] < var3) {
|
||||
var2 = var4;
|
||||
var3 = this._b[var4];
|
||||
}
|
||||
}
|
||||
|
||||
return var2;
|
||||
}
|
||||
|
||||
public void e797() {
|
||||
this._i.pos = -1;
|
||||
}
|
||||
|
||||
public void e150(final int var1) {
|
||||
this._h[var1] = this._i.pos;
|
||||
}
|
||||
|
||||
public int c784() {
|
||||
return this._h.length;
|
||||
}
|
||||
|
||||
private int f137(final int var1) {
|
||||
final byte var2 = this._i.data[this._i.pos];
|
||||
final int var5;
|
||||
if (var2 < 0) {
|
||||
var5 = var2 & 255;
|
||||
this._d[var1] = var5;
|
||||
++this._i.pos;
|
||||
} else {
|
||||
var5 = this._d[var1];
|
||||
}
|
||||
|
||||
if (var5 == 240 || var5 == 247) {
|
||||
final int var3 = this._i.readVariableInt();
|
||||
if (var5 == 247 && var3 > 0) {
|
||||
final int var4 = this._i.data[this._i.pos] & 255;
|
||||
if (var4 >= 241 && var4 <= 243 || var4 == 246 || var4 == 248 || var4 >= 250 && var4 <= 252 || var4 == 254) {
|
||||
++this._i.pos;
|
||||
this._d[var1] = var4;
|
||||
return this.a080(var1, var4);
|
||||
}
|
||||
}
|
||||
|
||||
this._i.pos += var3;
|
||||
return 0;
|
||||
} else {
|
||||
return this.a080(var1, var5);
|
||||
}
|
||||
}
|
||||
|
||||
public void d797() {
|
||||
this._i.data = null;
|
||||
this._c = null;
|
||||
this._h = null;
|
||||
this._b = null;
|
||||
this._d = null;
|
||||
}
|
||||
|
||||
public boolean f801() {
|
||||
return this._i.data != null;
|
||||
}
|
||||
|
||||
public void d150(final int var1) {
|
||||
final int var2 = this._i.readVariableInt();
|
||||
final int[] var10000 = this._b;
|
||||
var10000[var1] += var2;
|
||||
}
|
||||
|
||||
public void a604(final byte[] var1) {
|
||||
this._i.data = var1;
|
||||
this._i.pos = 10;
|
||||
final int var2 = this._i.readUShort();
|
||||
this._e = this._i.readUShort();
|
||||
this._a = 500000;
|
||||
this._c = new int[var2];
|
||||
|
||||
Buffer var10000;
|
||||
int var3;
|
||||
int var5;
|
||||
for (var3 = 0; var3 < var2; var10000.pos += var5) {
|
||||
final int var4 = this._i.readInt();
|
||||
var5 = this._i.readInt();
|
||||
if (var4 == 1297379947) {
|
||||
this._c[var3] = this._i.pos;
|
||||
++var3;
|
||||
}
|
||||
|
||||
var10000 = this._i;
|
||||
}
|
||||
|
||||
this._f = 0L;
|
||||
this._h = new int[var2];
|
||||
|
||||
for (var3 = 0; var3 < var2; ++var3) {
|
||||
this._h[var3] = this._c[var3];
|
||||
}
|
||||
|
||||
this._b = new int[var2];
|
||||
this._d = new int[var2];
|
||||
}
|
||||
}
|
312
src/main/java/funorb/audio/pk_.java
Normal file
312
src/main/java/funorb/audio/pk_.java
Normal file
@ -0,0 +1,312 @@
|
||||
package funorb.audio;
|
||||
|
||||
import funorb.io.Buffer;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Random;
|
||||
|
||||
public final class pk_ {
|
||||
private static final int[] NOISE = new int[0x8000];
|
||||
private static final int[] SINE = new int[0x8000];
|
||||
private static final int[] _u;
|
||||
private static final int[] _p;
|
||||
private static final int[] _q;
|
||||
private static final int[] _t;
|
||||
private static final int[] _c;
|
||||
private static final int[] _w;
|
||||
|
||||
static {
|
||||
final Random var0 = new Random(0L);
|
||||
for (int i = 0; i < 0x8000; ++i) {
|
||||
NOISE[i] = (var0.nextInt() & 2) - 1;
|
||||
}
|
||||
for (int i = 0; i < 0x8000; ++i) {
|
||||
SINE[i] = (int) (Math.sin((double) i * Math.PI / 0x4000) * 0x4000);
|
||||
}
|
||||
|
||||
_u = new int[220500];
|
||||
_q = new int[5];
|
||||
_t = new int[5];
|
||||
_p = new int[5];
|
||||
_w = new int[5];
|
||||
_c = new int[5];
|
||||
}
|
||||
|
||||
private final int[] _y = new int[]{0, 0, 0, 0, 0};
|
||||
private final int[] _x = new int[]{0, 0, 0, 0, 0};
|
||||
private final int[] _h = new int[]{0, 0, 0, 0, 0};
|
||||
public int _s = 0;
|
||||
public int _a = 500;
|
||||
private fh_ _k;
|
||||
private pn_ _o;
|
||||
private int _f = 0;
|
||||
private pn_ _r;
|
||||
private pn_ _g;
|
||||
private pn_ _d;
|
||||
private pn_ _m;
|
||||
private int _b = 100;
|
||||
private pn_ _n;
|
||||
private pn_ _e;
|
||||
private pn_ _l;
|
||||
private pn_ _i;
|
||||
|
||||
public int[] a111(final int var1, final int var2) {
|
||||
Arrays.fill(_u, 0, var1, 0);
|
||||
if (var2 >= 10) {
|
||||
final double var3 = (double) var1 / ((double) var2 + 0.0D);
|
||||
this._m.reset();
|
||||
this._i.reset();
|
||||
int var5 = 0;
|
||||
int var6 = 0;
|
||||
int var7 = 0;
|
||||
if (this._l != null) {
|
||||
this._l.reset();
|
||||
this._d.reset();
|
||||
var5 = (int) ((double) (this._l._i - this._l._d) * 32.768D / var3);
|
||||
var6 = (int) ((double) this._l._d * 32.768D / var3);
|
||||
}
|
||||
|
||||
int var8 = 0;
|
||||
int var9 = 0;
|
||||
int var10 = 0;
|
||||
if (this._g != null) {
|
||||
this._g.reset();
|
||||
this._o.reset();
|
||||
var8 = (int) ((double) (this._g._i - this._g._d) * 32.768D / var3);
|
||||
var9 = (int) ((double) this._g._d * 32.768D / var3);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
if (this._y[i] != 0) {
|
||||
_c[i] = 0;
|
||||
_q[i] = (int) ((double) this._h[i] * var3);
|
||||
_p[i] = (this._y[i] << 14) / 100;
|
||||
_t[i] = (int) ((double) (this._m._i - this._m._d) * 32.768D * Math.pow(1.0057929410678534D, this._x[i]) / var3);
|
||||
_w[i] = (int) ((double) this._m._d * 32.768D / var3);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < var1; ++i) {
|
||||
int var12 = this._m.next(var1);
|
||||
int var13 = this._i.next(var1);
|
||||
int var14;
|
||||
int var15;
|
||||
if (this._l != null) {
|
||||
var14 = this._l.next(var1);
|
||||
var15 = this._d.next(var1);
|
||||
var12 += this.sample(this._l.sampleType, var7, var15) >> 1;
|
||||
var7 += (var14 * var5 >> 16) + var6;
|
||||
}
|
||||
|
||||
if (this._g != null) {
|
||||
var14 = this._g.next(var1);
|
||||
var15 = this._o.next(var1);
|
||||
var13 = var13 * ((this.sample(this._g.sampleType, var10, var15) >> 1) + 0x8000) >> 15;
|
||||
var10 += (var14 * var8 >> 16) + var9;
|
||||
}
|
||||
|
||||
for (var14 = 0; var14 < 5; ++var14) {
|
||||
if (this._y[var14] != 0) {
|
||||
var15 = i + _q[var14];
|
||||
if (var15 < var1) {
|
||||
_u[var15] += this.sample(this._m.sampleType, _c[var14], var13 * _p[var14] >> 15);
|
||||
_c[var14] += (var12 * _t[var14] >> 16) + _w[var14];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this._e != null) {
|
||||
this._e.reset();
|
||||
this._r.reset();
|
||||
int var11 = 0;
|
||||
boolean var19 = true;
|
||||
|
||||
for (int i = 0; i < var1; ++i) {
|
||||
final int var15 = this._e.next(var1);
|
||||
final int var16 = this._r.next(var1);
|
||||
final int var12;
|
||||
if (var19) {
|
||||
var12 = this._e._d + ((this._e._i - this._e._d) * var15 >> 8);
|
||||
} else {
|
||||
var12 = this._e._d + ((this._e._i - this._e._d) * var16 >> 8);
|
||||
}
|
||||
|
||||
var11 += 256;
|
||||
if (var11 >= var12) {
|
||||
var11 = 0;
|
||||
var19 = !var19;
|
||||
}
|
||||
|
||||
if (var19) {
|
||||
_u[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this._f > 0 && this._b > 0) {
|
||||
final int var11 = (int) ((double) this._f * var3);
|
||||
for (int i = var11; i < var1; ++i) {
|
||||
_u[i] += _u[i - var11] * this._b / 100;
|
||||
}
|
||||
}
|
||||
|
||||
if (this._k._d[0] > 0 || this._k._d[1] > 0) {
|
||||
this._n.reset();
|
||||
int var11 = this._n.next(var1 + 1);
|
||||
int var12 = this._k.a197(0, (float) var11 / 65536.0F);
|
||||
int var13 = this._k.a197(1, (float) var11 / 65536.0F);
|
||||
if (var1 >= var12 + var13) {
|
||||
int var14 = 0;
|
||||
final int var15 = Math.min(var13, var1 - var12);
|
||||
|
||||
while (var14 < var15) {
|
||||
int var16 = (int) ((long) _u[var14 + var12] * (long) fh_._g >> 16);
|
||||
|
||||
for (int var17 = 0; var17 < var12; ++var17) {
|
||||
var16 += (int) ((long) _u[var14 + var12 - 1 - var17] * (long) fh_._e[0][var17] >> 16);
|
||||
}
|
||||
|
||||
for (int var17 = 0; var17 < var14; ++var17) {
|
||||
var16 -= (int) ((long) _u[var14 - 1 - var17] * (long) fh_._e[1][var17] >> 16);
|
||||
}
|
||||
|
||||
_u[var14] = var16;
|
||||
var11 = this._n.next(var1 + 1);
|
||||
++var14;
|
||||
}
|
||||
|
||||
int var15a = 128;
|
||||
while (true) {
|
||||
if (var15a > var1 - var12) {
|
||||
var15a = var1 - var12;
|
||||
}
|
||||
|
||||
while (var14 < var15a) {
|
||||
int var16 = (int) ((long) _u[var14 + var12] * (long) fh_._g >> 16);
|
||||
|
||||
for (int var17 = 0; var17 < var12; ++var17) {
|
||||
var16 += (int) ((long) _u[var14 + var12 - 1 - var17] * (long) fh_._e[0][var17] >> 16);
|
||||
}
|
||||
|
||||
for (int var17 = 0; var17 < var13; ++var17) {
|
||||
var16 -= (int) ((long) _u[var14 - 1 - var17] * (long) fh_._e[1][var17] >> 16);
|
||||
}
|
||||
|
||||
_u[var14] = var16;
|
||||
var11 = this._n.next(var1 + 1);
|
||||
++var14;
|
||||
}
|
||||
|
||||
if (var14 >= var1 - var12) {
|
||||
while (var14 < var1) {
|
||||
int var16 = 0;
|
||||
|
||||
for (int var17 = var14 + var12 - var1; var17 < var12; ++var17) {
|
||||
var16 += (int) ((long) _u[var14 + var12 - 1 - var17] * (long) fh_._e[0][var17] >> 16);
|
||||
}
|
||||
|
||||
for (int var17 = 0; var17 < var13; ++var17) {
|
||||
var16 -= (int) ((long) _u[var14 - 1 - var17] * (long) fh_._e[1][var17] >> 16);
|
||||
}
|
||||
|
||||
_u[var14] = var16;
|
||||
this._n.next(var1 + 1);
|
||||
++var14;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
var12 = this._k.a197(0, (float) var11 / 65536.0F);
|
||||
var13 = this._k.a197(1, (float) var11 / 65536.0F);
|
||||
var15a += 128;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < var1; ++i) {
|
||||
if (_u[i] < 0xffff8000) {
|
||||
_u[i] = 0xffff8000;
|
||||
}
|
||||
if (_u[i] > 0x7fff) {
|
||||
_u[i] = 0x7fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
return _u;
|
||||
}
|
||||
|
||||
public void initialize(final Buffer buffer) {
|
||||
this._m = new pn_();
|
||||
this._m.initialize(buffer);
|
||||
this._i = new pn_();
|
||||
this._i.initialize(buffer);
|
||||
final int var2 = buffer.readUByte();
|
||||
if (var2 != 0) {
|
||||
--buffer.pos;
|
||||
this._l = new pn_();
|
||||
this._l.initialize(buffer);
|
||||
this._d = new pn_();
|
||||
this._d.initialize(buffer);
|
||||
}
|
||||
|
||||
final int var2a = buffer.readUByte();
|
||||
if (var2a != 0) {
|
||||
--buffer.pos;
|
||||
this._g = new pn_();
|
||||
this._g.initialize(buffer);
|
||||
this._o = new pn_();
|
||||
this._o.initialize(buffer);
|
||||
}
|
||||
|
||||
final int j137 = buffer.readUByte();
|
||||
if (j137 != 0) {
|
||||
--buffer.pos;
|
||||
this._e = new pn_();
|
||||
this._e.initialize(buffer);
|
||||
this._r = new pn_();
|
||||
this._r.initialize(buffer);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
final int var4 = buffer.readVariable8_16();
|
||||
if (var4 == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
this._y[i] = var4;
|
||||
this._x[i] = buffer.d410();
|
||||
this._h[i] = buffer.readVariable8_16();
|
||||
}
|
||||
|
||||
this._f = buffer.readVariable8_16();
|
||||
this._b = buffer.readVariable8_16();
|
||||
this._a = buffer.readUShort();
|
||||
this._s = buffer.readUShort();
|
||||
this._k = new fh_();
|
||||
this._n = new pn_();
|
||||
this._k.a086(buffer, this._n);
|
||||
}
|
||||
|
||||
private int sample(final int type, final int time, final int volume) {
|
||||
if (type == SampleType.SQUARE) {
|
||||
return ((time & 0x7fff) < 0x4000) ? volume : -volume;
|
||||
} else if (type == SampleType.SINE) {
|
||||
return (SINE[time & 0x7fff] * volume) >> 14;
|
||||
} else if (type == SampleType.SAWTOOTH) {
|
||||
return (((time & 0x7fff) * volume) >> 14) - volume;
|
||||
} else if (type == SampleType.NOISE) {
|
||||
return NOISE[(time / 2607) & 0x7fff] * volume;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
private static final class SampleType {
|
||||
public static final int SQUARE = 1;
|
||||
public static final int SINE = 2;
|
||||
public static final int SAWTOOTH = 3;
|
||||
public static final int NOISE = 4;
|
||||
}
|
||||
}
|
65
src/main/java/funorb/audio/pn_.java
Normal file
65
src/main/java/funorb/audio/pn_.java
Normal file
@ -0,0 +1,65 @@
|
||||
package funorb.audio;
|
||||
|
||||
import funorb.io.Buffer;
|
||||
|
||||
public final class pn_ {
|
||||
public int _d;
|
||||
public int _i;
|
||||
public int sampleType;
|
||||
private int count = 2;
|
||||
private int[] values1 = new int[2];
|
||||
private int[] values2 = new int[2];
|
||||
private int _g;
|
||||
private int _e;
|
||||
private int _b;
|
||||
private int _j;
|
||||
private int pos;
|
||||
|
||||
public pn_() {
|
||||
this.values1[1] = 65535;
|
||||
this.values2[1] = 65535;
|
||||
}
|
||||
|
||||
public void initialize(final Buffer buffer) {
|
||||
this.sampleType = buffer.readUByte();
|
||||
this._d = buffer.readInt();
|
||||
this._i = buffer.readInt();
|
||||
this.read(buffer);
|
||||
}
|
||||
|
||||
public void read(final Buffer buffer) {
|
||||
this.count = buffer.readUByte();
|
||||
this.values1 = new int[this.count];
|
||||
this.values2 = new int[this.count];
|
||||
for (int i = 0; i < this.count; ++i) {
|
||||
this.values1[i] = buffer.readUShort();
|
||||
this.values2[i] = buffer.readUShort();
|
||||
}
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
this._e = 0;
|
||||
this.pos = 0;
|
||||
this._b = 0;
|
||||
this._j = 0;
|
||||
this._g = 0;
|
||||
}
|
||||
|
||||
public int next(final int var1) {
|
||||
if (this._g >= this._e) {
|
||||
this._j = this.values2[this.pos++] << 15;
|
||||
if (this.pos >= this.count) {
|
||||
this.pos = this.count - 1;
|
||||
}
|
||||
|
||||
this._e = (int) (((double) this.values1[this.pos] / 65536.0D) * (double) var1);
|
||||
if (this._e > this._g) {
|
||||
this._b = ((this.values2[this.pos] << 15) - this._j) / (this._e - this._g);
|
||||
}
|
||||
}
|
||||
|
||||
this._j += this._b;
|
||||
++this._g;
|
||||
return this._j - this._b >> 15;
|
||||
}
|
||||
}
|
34
src/main/java/funorb/audio/qq_.java
Normal file
34
src/main/java/funorb/audio/qq_.java
Normal file
@ -0,0 +1,34 @@
|
||||
package funorb.audio;
|
||||
|
||||
import funorb.data.NodeList;
|
||||
|
||||
public final class qq_ extends NodeList.Node {
|
||||
public int _E;
|
||||
public int _G;
|
||||
public int _v;
|
||||
public int _F;
|
||||
public int _H;
|
||||
public kk_ _M;
|
||||
public kc_ _u;
|
||||
public al_ _K;
|
||||
public br_ _A;
|
||||
public int _j;
|
||||
public int _r;
|
||||
public int _C;
|
||||
public int _q;
|
||||
public int _y;
|
||||
public int _J;
|
||||
public int _h;
|
||||
public int _z;
|
||||
public int _k;
|
||||
public int _p;
|
||||
public int _B;
|
||||
public int _i;
|
||||
|
||||
public void d487() {
|
||||
this._A = null;
|
||||
this._K = null;
|
||||
this._M = null;
|
||||
this._u = null;
|
||||
}
|
||||
}
|
147
src/main/java/funorb/audio/rc_.java
Normal file
147
src/main/java/funorb/audio/rc_.java
Normal file
@ -0,0 +1,147 @@
|
||||
package funorb.audio;
|
||||
|
||||
import funorb.data.NodeList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Objects;
|
||||
|
||||
public final class rc_ extends tn_ {
|
||||
public final NodeList<qq_> _n = new NodeList<>();
|
||||
public final vk_ _o = new vk_();
|
||||
private final ga_ _m;
|
||||
|
||||
public rc_(final ga_ var1) {
|
||||
this._m = var1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Iterator<tn_> iterator() {
|
||||
return this._n.stream().<tn_>map(var1 -> var1._K).filter(Objects::nonNull).iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int a784() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void a150(final int len) {
|
||||
this._o.a150(len);
|
||||
|
||||
for (final qq_ var3 : this._n) {
|
||||
if (!this._m.a258(var3)) {
|
||||
int var2 = len;
|
||||
|
||||
do {
|
||||
if (var3._p >= var2) {
|
||||
this.a222(var3, var2);
|
||||
var3._p -= var2;
|
||||
break;
|
||||
}
|
||||
|
||||
this.a222(var3, var3._p);
|
||||
var2 -= var3._p;
|
||||
} while (!this._m.a543(0, null, var3, var2));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void b397(final int[] dest, final int offset, final int len) {
|
||||
this._o.b397(dest, offset, len);
|
||||
|
||||
for (final qq_ var6 : this._n) {
|
||||
if (!this._m.a258(var6)) {
|
||||
int var4 = offset;
|
||||
int var5 = len;
|
||||
|
||||
do {
|
||||
if (var6._p >= var5) {
|
||||
this.a829(dest, var4, var6, var5, var4 + var5);
|
||||
var6._p -= var5;
|
||||
break;
|
||||
}
|
||||
|
||||
this.a829(dest, var4, var6, var6._p, var4 + var5);
|
||||
var5 -= var6._p;
|
||||
var4 += var6._p;
|
||||
} while (!this._m.a543(var4, dest, var6, var5));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void a222(final qq_ var2, int var3) {
|
||||
if ((4 & this._m._F[var2._y]) != 0 && var2._E < 0) {
|
||||
final int var4 = this._m._u[var2._y] / SampledAudioChannel.SAMPLES_PER_SECOND;
|
||||
final int var5 = (1048575 + var4 - var2._j) / var4;
|
||||
var2._j = 1048575 & var2._j + var3 * var4;
|
||||
if (var5 <= var3) {
|
||||
if (this._m._t[var2._y] == 0) {
|
||||
var2._K = al_.a771(var2._M, var2._K.f784(), var2._K.getVolume(), var2._K.l784());
|
||||
} else {
|
||||
var2._K = al_.a771(var2._M, var2._K.f784(), 0, var2._K.l784());
|
||||
this._m.a559(var2, var2._A._k[var2._H] < 0);
|
||||
}
|
||||
|
||||
if (var2._A._k[var2._H] < 0) {
|
||||
assert var2._K != null;
|
||||
var2._K.f150();
|
||||
}
|
||||
|
||||
var3 = var2._j / var4;
|
||||
}
|
||||
}
|
||||
|
||||
assert var2._K != null;
|
||||
var2._K.a150(var3);
|
||||
}
|
||||
|
||||
private void a829(final int[] var1, int var2, final qq_ var3, int var4, final int var6) {
|
||||
if ((4 & this._m._F[var3._y]) != 0 && var3._E < 0) {
|
||||
final int var7 = this._m._u[var3._y] / SampledAudioChannel.SAMPLES_PER_SECOND;
|
||||
|
||||
while (true) {
|
||||
final int var8 = (-var3._j + 1048575 + var7) / var7;
|
||||
if (var8 > var4) {
|
||||
var3._j += var7 * var4;
|
||||
break;
|
||||
}
|
||||
|
||||
var3._K.b397(var1, var2, var8);
|
||||
var3._j += var8 * var7 - 1048576;
|
||||
var2 += var8;
|
||||
var4 -= var8;
|
||||
int var9 = SampledAudioChannel.SAMPLES_PER_SECOND / 100;
|
||||
final int var10 = 262144 / var7;
|
||||
if (var10 < var9) {
|
||||
var9 = var10;
|
||||
}
|
||||
|
||||
final al_ var11 = var3._K;
|
||||
if (this._m._t[var3._y] == 0) {
|
||||
var3._K = al_.a771(var3._M, var11.f784(), var11.getVolume(), var11.l784());
|
||||
} else {
|
||||
var3._K = al_.a771(var3._M, var11.f784(), 0, var11.l784());
|
||||
this._m.a559(var3, var3._A._k[var3._H] < 0);
|
||||
var3._K.a093(var9, var11.getVolume());
|
||||
}
|
||||
|
||||
if (var3._A._k[var3._H] < 0) {
|
||||
assert var3._K != null;
|
||||
var3._K.f150();
|
||||
}
|
||||
|
||||
var11.g150(var9);
|
||||
var11.b397(var1, var2, var6 - var2);
|
||||
if (var11.e801()) {
|
||||
this._o.addFirst(var11);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var3._K.b397(var1, var2, var4);
|
||||
}
|
||||
}
|
30
src/main/java/funorb/audio/tn_.java
Normal file
30
src/main/java/funorb/audio/tn_.java
Normal file
@ -0,0 +1,30 @@
|
||||
package funorb.audio;
|
||||
|
||||
import funorb.data.NodeList;
|
||||
|
||||
public abstract class tn_ extends NodeList.Node implements Iterable<tn_> {
|
||||
public volatile boolean _j = true;
|
||||
public int _i;
|
||||
public tn_ _h;
|
||||
public kk_ _k;
|
||||
|
||||
protected tn_() {}
|
||||
|
||||
public abstract void b397(int[] dest, int offset, int len);
|
||||
|
||||
protected final void a397(final int[] dest, final int offset, final int len) {
|
||||
if (this._j) {
|
||||
this.b397(dest, offset, len);
|
||||
} else {
|
||||
this.a150(len);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void a150(int len);
|
||||
|
||||
public abstract int a784();
|
||||
|
||||
public int c784() {
|
||||
return 255;
|
||||
}
|
||||
}
|
106
src/main/java/funorb/audio/to_.java
Normal file
106
src/main/java/funorb/audio/to_.java
Normal file
@ -0,0 +1,106 @@
|
||||
package funorb.audio;
|
||||
|
||||
public final class to_ {
|
||||
private final int[] _e;
|
||||
private final int _c = fd_.a137(16);
|
||||
private final int _g = fd_.a137(24);
|
||||
private final int _d = fd_.a137(24);
|
||||
private final int _b = fd_.a137(24) + 1;
|
||||
private final int _a = fd_.a137(6) + 1;
|
||||
private final int _f = fd_.a137(8);
|
||||
|
||||
public to_() {
|
||||
final int[] var1 = new int[this._a];
|
||||
|
||||
int var2;
|
||||
for (var2 = 0; var2 < this._a; ++var2) {
|
||||
int var3 = 0;
|
||||
final int var4 = fd_.a137(3);
|
||||
final boolean var5 = fd_.c784() != 0;
|
||||
if (var5) {
|
||||
var3 = fd_.a137(5);
|
||||
}
|
||||
|
||||
var1[var2] = var3 << 3 | var4;
|
||||
}
|
||||
|
||||
this._e = new int[this._a * 8];
|
||||
|
||||
for (var2 = 0; var2 < this._a * 8; ++var2) {
|
||||
this._e[var2] = (var1[var2 >> 3] & 1 << (var2 & 7)) != 0 ? fd_.a137(8) : -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void a623(final float[] var1, final int var2, final boolean var3) {
|
||||
int var4;
|
||||
for (var4 = 0; var4 < var2; ++var4) {
|
||||
var1[var4] = 0.0F;
|
||||
}
|
||||
|
||||
if (!var3) {
|
||||
var4 = fd_._L[this._f]._a;
|
||||
final int var5 = this._d - this._g;
|
||||
final int var6 = var5 / this._b;
|
||||
final int[] var7 = new int[var6];
|
||||
|
||||
for (int var8 = 0; var8 < 8; ++var8) {
|
||||
int var9 = 0;
|
||||
|
||||
while (var9 < var6) {
|
||||
int var10;
|
||||
int var11;
|
||||
if (var8 == 0) {
|
||||
var10 = fd_._L[this._f].a784();
|
||||
|
||||
for (var11 = var4 - 1; var11 >= 0; --var11) {
|
||||
if (var9 + var11 < var6) {
|
||||
var7[var9 + var11] = var10 % this._a;
|
||||
}
|
||||
|
||||
var10 /= this._a;
|
||||
}
|
||||
}
|
||||
|
||||
for (var10 = 0; var10 < var4; ++var10) {
|
||||
var11 = var7[var9];
|
||||
final int var12 = this._e[var11 * 8 + var8];
|
||||
if (var12 >= 0) {
|
||||
final int var13 = this._g + var9 * this._b;
|
||||
final vb_ var14 = fd_._L[var12];
|
||||
int var15;
|
||||
if (this._c == 0) {
|
||||
var15 = this._b / var14._a;
|
||||
|
||||
for (int var19 = 0; var19 < var15; ++var19) {
|
||||
final float[] var20 = var14.c932();
|
||||
|
||||
for (int var18 = 0; var18 < var14._a; ++var18) {
|
||||
var1[var13 + var19 + var18 * var15] += var20[var18];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var15 = 0;
|
||||
|
||||
while (var15 < this._b) {
|
||||
final float[] var16 = var14.c932();
|
||||
|
||||
for (int var17 = 0; var17 < var14._a; ++var17) {
|
||||
var1[var13 + var15] += var16[var17];
|
||||
++var15;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
++var9;
|
||||
if (var9 >= var6) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
232
src/main/java/funorb/audio/vb_.java
Normal file
232
src/main/java/funorb/audio/vb_.java
Normal file
@ -0,0 +1,232 @@
|
||||
package funorb.audio;
|
||||
|
||||
import funorb.util.BitMath;
|
||||
|
||||
public final class vb_ {
|
||||
public final int _a;
|
||||
private final int _c;
|
||||
private final int[] _b;
|
||||
private float[][] _d;
|
||||
private int[] _f;
|
||||
|
||||
public vb_() {
|
||||
fd_.a137(24);
|
||||
this._a = fd_.a137(16);
|
||||
this._c = fd_.a137(24);
|
||||
this._b = new int[this._c];
|
||||
final boolean var1 = fd_.c784() != 0;
|
||||
int var2;
|
||||
int var3;
|
||||
int var5;
|
||||
if (var1) {
|
||||
var2 = 0;
|
||||
|
||||
for (var3 = fd_.a137(5) + 1; var2 < this._c; ++var3) {
|
||||
final int var4 = fd_.a137(BitMath.lastSet(this._c - var2));
|
||||
|
||||
for (var5 = 0; var5 < var4; ++var5) {
|
||||
this._b[var2++] = var3;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
final boolean var14 = fd_.c784() != 0;
|
||||
|
||||
for (var3 = 0; var3 < this._c; ++var3) {
|
||||
if (var14 && fd_.c784() == 0) {
|
||||
this._b[var3] = 0;
|
||||
} else {
|
||||
this._b[var3] = fd_.a137(5) + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.b797();
|
||||
var2 = fd_.a137(4);
|
||||
if (var2 > 0) {
|
||||
final float var15 = fd_.d134(fd_.a137(32));
|
||||
final float var16 = fd_.d134(fd_.a137(32));
|
||||
var5 = fd_.a137(4) + 1;
|
||||
final boolean var6 = fd_.c784() != 0;
|
||||
final int var7;
|
||||
if (var2 == 1) {
|
||||
var7 = a080(this._c, this._a);
|
||||
} else {
|
||||
var7 = this._c * this._a;
|
||||
}
|
||||
|
||||
final int[] _e = new int[var7];
|
||||
|
||||
int var8;
|
||||
for (var8 = 0; var8 < var7; ++var8) {
|
||||
_e[var8] = fd_.a137(var5);
|
||||
}
|
||||
|
||||
this._d = new float[this._c][this._a];
|
||||
float var9;
|
||||
int var10;
|
||||
int var11;
|
||||
if (var2 == 1) {
|
||||
for (var8 = 0; var8 < this._c; ++var8) {
|
||||
var9 = 0.0F;
|
||||
var10 = 1;
|
||||
|
||||
for (var11 = 0; var11 < this._a; ++var11) {
|
||||
final int var12 = var8 / var10 % var7;
|
||||
final float var13 = (float) _e[var12] * var16 + var15 + var9;
|
||||
this._d[var8][var11] = var13;
|
||||
if (var6) {
|
||||
var9 = var13;
|
||||
}
|
||||
|
||||
var10 *= var7;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (var8 = 0; var8 < this._c; ++var8) {
|
||||
var9 = 0.0F;
|
||||
var10 = var8 * this._a;
|
||||
|
||||
for (var11 = 0; var11 < this._a; ++var11) {
|
||||
final float var17 = (float) _e[var10] * var16 + var15 + var9;
|
||||
this._d[var8][var11] = var17;
|
||||
if (var6) {
|
||||
var9 = var17;
|
||||
}
|
||||
|
||||
++var10;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static int a080(final int var0, final int var1) {
|
||||
int var2 = (int) Math.pow(var0, 1.0D / (double) var1) + 1;
|
||||
while (a776em(var2, var1) > var0) {
|
||||
--var2;
|
||||
}
|
||||
return var2;
|
||||
}
|
||||
|
||||
private static int a776em(int var0, int var1) {
|
||||
int var2;
|
||||
for (var2 = 1; var1 > 1; var0 *= var0) {
|
||||
if ((var1 & 1) != 0) {
|
||||
var2 *= var0;
|
||||
}
|
||||
|
||||
var1 >>= 1;
|
||||
}
|
||||
|
||||
if (var1 == 1) {
|
||||
return var2 * var0;
|
||||
} else {
|
||||
return var2;
|
||||
}
|
||||
}
|
||||
|
||||
public float[] c932() {
|
||||
return this._d[this.a784()];
|
||||
}
|
||||
|
||||
public int a784() {
|
||||
int var1 = 0;
|
||||
while (this._f[var1] >= 0) {
|
||||
var1 = fd_.c784() != 0 ? this._f[var1] : var1 + 1;
|
||||
}
|
||||
return ~this._f[var1];
|
||||
}
|
||||
|
||||
private void b797() {
|
||||
final int[] var1 = new int[this._c];
|
||||
final int[] var2 = new int[33];
|
||||
|
||||
int var3;
|
||||
int var4;
|
||||
int var5;
|
||||
int var6;
|
||||
int var7;
|
||||
int var8;
|
||||
int var10;
|
||||
for (var3 = 0; var3 < this._c; ++var3) {
|
||||
var4 = this._b[var3];
|
||||
if (var4 != 0) {
|
||||
var5 = 1 << 32 - var4;
|
||||
var6 = var2[var4];
|
||||
var1[var3] = var6;
|
||||
int var9;
|
||||
if ((var6 & var5) == 0) {
|
||||
var7 = var6 | var5;
|
||||
|
||||
for (var8 = var4 - 1; var8 >= 1; --var8) {
|
||||
var9 = var2[var8];
|
||||
if (var9 != var6) {
|
||||
break;
|
||||
}
|
||||
|
||||
var10 = 1 << 32 - var8;
|
||||
if ((var9 & var10) != 0) {
|
||||
var2[var8] = var2[var8 - 1];
|
||||
break;
|
||||
}
|
||||
|
||||
var2[var8] = var9 | var10;
|
||||
}
|
||||
} else {
|
||||
var7 = var2[var4 - 1];
|
||||
}
|
||||
|
||||
var2[var4] = var7;
|
||||
|
||||
for (var8 = var4 + 1; var8 <= 32; ++var8) {
|
||||
var9 = var2[var8];
|
||||
if (var9 == var6) {
|
||||
var2[var8] = var7;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this._f = new int[8];
|
||||
int var11 = 0;
|
||||
|
||||
for (var3 = 0; var3 < this._c; ++var3) {
|
||||
var4 = this._b[var3];
|
||||
if (var4 != 0) {
|
||||
var5 = var1[var3];
|
||||
var6 = 0;
|
||||
|
||||
for (var7 = 0; var7 < var4; ++var7) {
|
||||
var8 = Integer.MIN_VALUE >>> var7;
|
||||
if ((var5 & var8) == 0) {
|
||||
++var6;
|
||||
} else {
|
||||
if (this._f[var6] == 0) {
|
||||
this._f[var6] = var11;
|
||||
}
|
||||
|
||||
var6 = this._f[var6];
|
||||
}
|
||||
|
||||
if (var6 >= this._f.length) {
|
||||
final int[] var12 = new int[this._f.length * 2];
|
||||
|
||||
for (var10 = 0; var10 < this._f.length; ++var10) {
|
||||
var12[var10] = this._f[var10];
|
||||
}
|
||||
|
||||
this._f = var12;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
this._f[var6] = ~var3;
|
||||
if (var6 >= var11) {
|
||||
var11 = var6 + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
38
src/main/java/funorb/audio/vk_.java
Normal file
38
src/main/java/funorb/audio/vk_.java
Normal file
@ -0,0 +1,38 @@
|
||||
package funorb.audio;
|
||||
|
||||
import funorb.data.NodeList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
public final class vk_ extends tn_ {
|
||||
private final NodeList<tn_> _l = new NodeList<>();
|
||||
|
||||
@Override
|
||||
public @NotNull Iterator<tn_> iterator() {
|
||||
return this._l.iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int a784() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void a150(final int len) {
|
||||
for (final tn_ var2 : this._l) {
|
||||
var2.a150(len);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void addFirst(final al_ var1) {
|
||||
this._l.addFirst(var1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void b397(final int[] dest, final int offset, final int len) {
|
||||
for (final tn_ var4 : this._l) {
|
||||
var4.a397(dest, offset, len);
|
||||
}
|
||||
}
|
||||
}
|
35
src/main/java/funorb/awt/CanvasScreenBuffer.java
Normal file
35
src/main/java/funorb/awt/CanvasScreenBuffer.java
Normal file
@ -0,0 +1,35 @@
|
||||
package funorb.awt;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.DataBufferInt;
|
||||
import java.awt.image.DirectColorModel;
|
||||
import java.awt.image.Raster;
|
||||
import java.awt.image.WritableRaster;
|
||||
import java.util.Hashtable;
|
||||
|
||||
public final class CanvasScreenBuffer extends ScreenBuffer {
|
||||
private Component canvas;
|
||||
|
||||
public CanvasScreenBuffer() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paint(final Graphics g) {
|
||||
g.drawImage(this.screenBufferImage, 0, 0, this.canvas);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(final Component canvas, final int width, final int height) {
|
||||
this.canvas = canvas;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.screenBuffer = new int[width * height + 1];
|
||||
final DataBufferInt dataBuffer = new DataBufferInt(this.screenBuffer, this.screenBuffer.length);
|
||||
final DirectColorModel colorModel = new DirectColorModel(32, 0xff0000, 0x00ff00, 0x0000ff);
|
||||
final WritableRaster raster = Raster.createWritableRaster(colorModel.createCompatibleSampleModel(super.width, super.height), dataBuffer, null);
|
||||
this.screenBufferImage = new BufferedImage(colorModel, raster, false, new Hashtable<>());
|
||||
this.makeGlobal();
|
||||
}
|
||||
}
|
23
src/main/java/funorb/awt/ComponentCanvas.java
Normal file
23
src/main/java/funorb/awt/ComponentCanvas.java
Normal file
@ -0,0 +1,23 @@
|
||||
package funorb.awt;
|
||||
|
||||
import java.awt.Canvas;
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics;
|
||||
|
||||
public final class ComponentCanvas extends Canvas {
|
||||
private final Component component;
|
||||
|
||||
public ComponentCanvas(final Component component) {
|
||||
this.component = component;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paint(final Graphics g) {
|
||||
this.component.paint(g);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(final Graphics g) {
|
||||
this.component.update(g);
|
||||
}
|
||||
}
|
35
src/main/java/funorb/awt/FullScreenCanvas.java
Normal file
35
src/main/java/funorb/awt/FullScreenCanvas.java
Normal file
@ -0,0 +1,35 @@
|
||||
package funorb.awt;
|
||||
|
||||
import funorb.shatteredplans.client.JagexApplet;
|
||||
|
||||
import java.awt.Canvas;
|
||||
import java.awt.Frame;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.FocusListener;
|
||||
|
||||
public final class FullScreenCanvas extends Canvas implements FocusListener {
|
||||
public Frame frame;
|
||||
public volatile boolean focusWasLost;
|
||||
|
||||
@Override
|
||||
public void update(final Graphics var1) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paint(final Graphics var1) {
|
||||
}
|
||||
|
||||
public void repeatedlyTryToExitFullScreen() {
|
||||
JagexApplet.repeatedlyTryToExitFullScreen(this.frame);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void focusLost(final FocusEvent var1) {
|
||||
this.focusWasLost = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void focusGained(final FocusEvent var1) {
|
||||
}
|
||||
}
|
87
src/main/java/funorb/awt/GraphicsBackend.java
Normal file
87
src/main/java/funorb/awt/GraphicsBackend.java
Normal file
@ -0,0 +1,87 @@
|
||||
package funorb.awt;
|
||||
|
||||
import java.awt.DisplayMode;
|
||||
import java.awt.Frame;
|
||||
import java.awt.GraphicsDevice;
|
||||
import java.awt.GraphicsEnvironment;
|
||||
|
||||
public final class GraphicsBackend {
|
||||
private GraphicsDevice device;
|
||||
private DisplayMode mode;
|
||||
|
||||
public GraphicsBackend() throws Exception {
|
||||
final GraphicsEnvironment environment = GraphicsEnvironment.getLocalGraphicsEnvironment();
|
||||
this.device = environment.getDefaultScreenDevice();
|
||||
if (!this.device.isFullScreenSupported()) {
|
||||
final GraphicsDevice[] devices = environment.getScreenDevices();
|
||||
for (final GraphicsDevice device : devices) {
|
||||
if (device != null && device.isFullScreenSupported()) {
|
||||
this.device = device;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
|
||||
public int[] listmodes() {
|
||||
final DisplayMode[] modes = this.device.getDisplayModes();
|
||||
final int[] values = new int[modes.length << 2];
|
||||
|
||||
for (int i = 0; i < modes.length; ++i) {
|
||||
values[i << 2] = modes[i].getWidth();
|
||||
values[(i << 2) + 1] = modes[i].getHeight();
|
||||
values[(i << 2) + 2] = modes[i].getBitDepth();
|
||||
values[(i << 2) + 3] = modes[i].getRefreshRate();
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
public void enter(final Frame var1, final int var2, final int var3, final int var4, int var5) {
|
||||
this.mode = this.device.getDisplayMode();
|
||||
if (this.mode == null) {
|
||||
throw new NullPointerException();
|
||||
} else {
|
||||
var1.setUndecorated(true);
|
||||
var1.enableInputMethods(false);
|
||||
|
||||
this.device.setFullScreenWindow(var1);
|
||||
if (var5 == 0) {
|
||||
final int var6 = this.mode.getRefreshRate();
|
||||
final DisplayMode[] var7 = this.device.getDisplayModes();
|
||||
boolean var8 = false;
|
||||
|
||||
for (final DisplayMode displayMode : var7) {
|
||||
if (var2 == displayMode.getWidth() && var3 == displayMode.getHeight() && displayMode.getBitDepth() == var4) {
|
||||
final int var10 = displayMode.getRefreshRate();
|
||||
if (!var8 || Math.abs(-var6 + var10) < Math.abs(-var6)) {
|
||||
var8 = true;
|
||||
var5 = var10;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!var8) {
|
||||
var5 = var6;
|
||||
}
|
||||
}
|
||||
|
||||
this.device.setDisplayMode(new DisplayMode(var2, var3, var4, var5));
|
||||
}
|
||||
}
|
||||
|
||||
public void exit() {
|
||||
if (this.mode != null) {
|
||||
this.device.setDisplayMode(this.mode);
|
||||
if (!this.device.getDisplayMode().equals(this.mode)) {
|
||||
throw new RuntimeException("");
|
||||
}
|
||||
|
||||
this.mode = null;
|
||||
}
|
||||
|
||||
this.device.setFullScreenWindow(null);
|
||||
}
|
||||
}
|
79
src/main/java/funorb/awt/ImageProducerScreenBuffer.java
Normal file
79
src/main/java/funorb/awt/ImageProducerScreenBuffer.java
Normal file
@ -0,0 +1,79 @@
|
||||
package funorb.awt;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Image;
|
||||
import java.awt.image.ColorModel;
|
||||
import java.awt.image.DirectColorModel;
|
||||
import java.awt.image.ImageConsumer;
|
||||
import java.awt.image.ImageObserver;
|
||||
import java.awt.image.ImageProducer;
|
||||
|
||||
public final class ImageProducerScreenBuffer extends ScreenBuffer implements ImageProducer, ImageObserver {
|
||||
private ImageConsumer consumer;
|
||||
private ColorModel colorModel;
|
||||
|
||||
@Override
|
||||
public void requestTopDownLeftRightResend(final ImageConsumer consumer) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean isConsumer(final ImageConsumer consumer) {
|
||||
return consumer == this.consumer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean imageUpdate(final Image var1, final int var2, final int var3, final int var4, final int var5, final int var6) {
|
||||
return true;
|
||||
}
|
||||
|
||||
private synchronized void pushFrame() {
|
||||
if (this.consumer != null) {
|
||||
this.consumer.setPixels(0, 0, this.width, this.height, this.colorModel, this.screenBuffer, 0, this.width);
|
||||
this.consumer.imageComplete(ImageConsumer.SINGLEFRAMEDONE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(final Component canvas, final int width, final int height) {
|
||||
this.height = height;
|
||||
this.width = width;
|
||||
this.screenBuffer = new int[height * width + 1];
|
||||
this.colorModel = new DirectColorModel(32, 16711680, 65280, 255);
|
||||
this.screenBufferImage = canvas.createImage(this);
|
||||
this.pushFrame();
|
||||
canvas.prepareImage(this.screenBufferImage, this);
|
||||
this.pushFrame();
|
||||
canvas.prepareImage(this.screenBufferImage, this);
|
||||
this.pushFrame();
|
||||
canvas.prepareImage(this.screenBufferImage, this);
|
||||
this.makeGlobal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void removeConsumer(final ImageConsumer consumer) {
|
||||
if (consumer == this.consumer) {
|
||||
this.consumer = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startProduction(final ImageConsumer consumer) {
|
||||
this.addConsumer(consumer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void addConsumer(final ImageConsumer consumer) {
|
||||
this.consumer = consumer;
|
||||
consumer.setDimensions(this.width, this.height);
|
||||
consumer.setProperties(null);
|
||||
consumer.setColorModel(this.colorModel);
|
||||
consumer.setHints(14);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paint(final Graphics g) {
|
||||
this.pushFrame();
|
||||
g.drawImage(this.screenBufferImage, 0, 0, this);
|
||||
}
|
||||
}
|
326
src/main/java/funorb/awt/KeyState.java
Normal file
326
src/main/java/funorb/awt/KeyState.java
Normal file
@ -0,0 +1,326 @@
|
||||
package funorb.awt;
|
||||
|
||||
import funorb.Strings;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.FocusListener;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.KeyListener;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static java.awt.event.InputEvent.ALT_MASK;
|
||||
import static java.awt.event.InputEvent.CTRL_MASK;
|
||||
|
||||
public final class KeyState implements KeyListener, FocusListener {
|
||||
public static final KeyState instance = new KeyState();
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public static final class Code {
|
||||
public static final int F1 = 1;
|
||||
public static final int F2 = 2;
|
||||
public static final int F3 = 3;
|
||||
public static final int F4 = 4;
|
||||
public static final int F5 = 5;
|
||||
public static final int F6 = 6;
|
||||
public static final int F7 = 7;
|
||||
public static final int F8 = 8;
|
||||
public static final int F9 = 9;
|
||||
public static final int F10 = 10;
|
||||
public static final int F11 = 11;
|
||||
public static final int F12 = 12;
|
||||
public static final int ESCAPE = 13;
|
||||
public static final int NUMBER_1 = 16;
|
||||
public static final int NUMBER_2 = 17;
|
||||
public static final int NUMBER_3 = 18;
|
||||
public static final int NUMBER_4 = 19;
|
||||
public static final int NUMBER_5 = 20;
|
||||
public static final int NUMBER_6 = 21;
|
||||
public static final int NUMBER_7 = 22;
|
||||
public static final int NUMBER_8 = 23;
|
||||
public static final int NUMBER_9 = 24;
|
||||
public static final int NUMBER_0 = 25;
|
||||
public static final int LETTER_Q = 32;
|
||||
public static final int LETTER_W = 33;
|
||||
public static final int LETTER_E = 34;
|
||||
public static final int LETTER_R = 35;
|
||||
public static final int LETTER_T = 36;
|
||||
public static final int LETTER_Y = 37;
|
||||
public static final int LETTER_U = 38;
|
||||
public static final int LETTER_I = 39;
|
||||
public static final int LETTER_O = 40;
|
||||
public static final int LETTER_P = 41;
|
||||
public static final int LETTER_A = 48;
|
||||
public static final int LETTER_S = 49;
|
||||
public static final int LETTER_D = 50;
|
||||
public static final int LETTER_F = 51;
|
||||
public static final int LETTER_G = 52;
|
||||
public static final int LETTER_H = 53;
|
||||
public static final int LETTER_B = 68;
|
||||
public static final int LETTER_J = 54;
|
||||
public static final int LETTER_K = 55;
|
||||
public static final int LETTER_L = 56;
|
||||
public static final int LETTER_Z = 64;
|
||||
public static final int LETTER_X = 65;
|
||||
public static final int LETTER_C = 66;
|
||||
public static final int LETTER_V = 67;
|
||||
public static final int LETTER_N = 69;
|
||||
public static final int LETTER_M = 70;
|
||||
public static final int FORWARD_SLASH = 73;
|
||||
public static final int TAB = 80;
|
||||
public static final int SHIFT = 81;
|
||||
public static final int CONTROL = 82;
|
||||
public static final int SPACE = 83;
|
||||
public static final int ENTER = 84;
|
||||
public static final int BACKSPACE = 85;
|
||||
public static final int ALT = 86;
|
||||
public static final int CLEAR = 91;
|
||||
public static final int LEFT = 96;
|
||||
public static final int RIGHT = 97;
|
||||
public static final int UP = 98;
|
||||
public static final int DOWN = 99;
|
||||
public static final int INSERT = 100;
|
||||
public static final int DELETE = 101;
|
||||
public static final int HOME = 102;
|
||||
public static final int END = 103;
|
||||
public static final int PAGE_UP = 104;
|
||||
public static final int PAGE_DOWN = 105;
|
||||
}
|
||||
|
||||
private static final int[] codeMapping = new int[521];
|
||||
|
||||
static {
|
||||
Arrays.fill(codeMapping, -1);
|
||||
codeMapping[ 8] = Code.BACKSPACE;
|
||||
codeMapping[ 9] = Code.TAB;
|
||||
codeMapping[ 10] = Code.ENTER;
|
||||
codeMapping[ 12] = Code.CLEAR;
|
||||
codeMapping[ 16] = Code.SHIFT;
|
||||
codeMapping[ 17] = Code.CONTROL;
|
||||
codeMapping[ 18] = Code.ALT;
|
||||
codeMapping[ 27] = Code.ESCAPE;
|
||||
codeMapping[ 32] = Code.SPACE;
|
||||
codeMapping[ 33] = Code.PAGE_UP;
|
||||
codeMapping[ 34] = Code.PAGE_DOWN;
|
||||
codeMapping[ 35] = Code.END;
|
||||
codeMapping[ 36] = Code.HOME;
|
||||
codeMapping[ 37] = Code.LEFT;
|
||||
codeMapping[ 38] = Code.UP;
|
||||
codeMapping[ 39] = Code.RIGHT;
|
||||
codeMapping[ 40] = Code.DOWN;
|
||||
codeMapping[ 48] = Code.NUMBER_0;
|
||||
codeMapping[ 49] = Code.NUMBER_1;
|
||||
codeMapping[ 50] = Code.NUMBER_2;
|
||||
codeMapping[ 51] = Code.NUMBER_3;
|
||||
codeMapping[ 52] = Code.NUMBER_4;
|
||||
codeMapping[ 53] = Code.NUMBER_5;
|
||||
codeMapping[ 54] = Code.NUMBER_6;
|
||||
codeMapping[ 55] = Code.NUMBER_7;
|
||||
codeMapping[ 56] = Code.NUMBER_8;
|
||||
codeMapping[ 57] = Code.NUMBER_9;
|
||||
codeMapping[ 65] = Code.LETTER_A;
|
||||
codeMapping[ 66] = Code.LETTER_B;
|
||||
codeMapping[ 67] = Code.LETTER_C;
|
||||
codeMapping[ 68] = Code.LETTER_D;
|
||||
codeMapping[ 69] = Code.LETTER_E;
|
||||
codeMapping[ 70] = Code.LETTER_F;
|
||||
codeMapping[ 71] = Code.LETTER_G;
|
||||
codeMapping[ 72] = Code.LETTER_H;
|
||||
codeMapping[ 73] = Code.LETTER_I;
|
||||
codeMapping[ 74] = Code.LETTER_J;
|
||||
codeMapping[ 75] = Code.LETTER_K;
|
||||
codeMapping[ 76] = Code.LETTER_L;
|
||||
codeMapping[ 77] = Code.LETTER_M;
|
||||
codeMapping[ 78] = Code.LETTER_N;
|
||||
codeMapping[ 79] = Code.LETTER_O;
|
||||
codeMapping[ 80] = Code.LETTER_P;
|
||||
codeMapping[ 81] = Code.LETTER_Q;
|
||||
codeMapping[ 82] = Code.LETTER_R;
|
||||
codeMapping[ 83] = Code.LETTER_S;
|
||||
codeMapping[ 84] = Code.LETTER_T;
|
||||
codeMapping[ 85] = Code.LETTER_U;
|
||||
codeMapping[ 86] = Code.LETTER_V;
|
||||
codeMapping[ 87] = Code.LETTER_W;
|
||||
codeMapping[ 88] = Code.LETTER_X;
|
||||
codeMapping[ 89] = Code.LETTER_Y;
|
||||
codeMapping[ 90] = Code.LETTER_Z;
|
||||
codeMapping[ 96] = 228;
|
||||
codeMapping[ 97] = 231;
|
||||
codeMapping[ 98] = 227;
|
||||
codeMapping[ 99] = 233;
|
||||
codeMapping[100] = 224;
|
||||
codeMapping[101] = 219;
|
||||
codeMapping[102] = 225;
|
||||
codeMapping[103] = 230;
|
||||
codeMapping[104] = 226;
|
||||
codeMapping[105] = 232;
|
||||
codeMapping[106] = 89;
|
||||
codeMapping[107] = 87;
|
||||
codeMapping[109] = 88;
|
||||
codeMapping[110] = 229;
|
||||
codeMapping[111] = 90;
|
||||
codeMapping[112] = Code.F1;
|
||||
codeMapping[113] = Code.F2;
|
||||
codeMapping[114] = Code.F3;
|
||||
codeMapping[115] = Code.F4;
|
||||
codeMapping[116] = Code.F5;
|
||||
codeMapping[117] = Code.F6;
|
||||
codeMapping[118] = Code.F7;
|
||||
codeMapping[119] = Code.F8;
|
||||
codeMapping[120] = Code.F9;
|
||||
codeMapping[121] = Code.F10;
|
||||
codeMapping[122] = Code.F11;
|
||||
codeMapping[123] = Code.F12;
|
||||
codeMapping[127] = Code.DELETE;
|
||||
codeMapping[155] = Code.INSERT;
|
||||
}
|
||||
|
||||
public static void initializeAdditionalCodeMappings() {
|
||||
codeMapping[ 44] = 71;
|
||||
codeMapping[ 45] = 26;
|
||||
codeMapping[ 46] = 72;
|
||||
codeMapping[ 47] = Code.FORWARD_SLASH;
|
||||
codeMapping[ 59] = 57;
|
||||
codeMapping[ 61] = 27;
|
||||
codeMapping[ 91] = 42;
|
||||
codeMapping[ 92] = 74;
|
||||
codeMapping[ 93] = 43;
|
||||
codeMapping[192] = 28;
|
||||
codeMapping[222] = 58;
|
||||
codeMapping[520] = 59;
|
||||
}
|
||||
|
||||
|
||||
public static volatile int ticksSinceLastKeyEvent = 0;
|
||||
|
||||
public static final int[] keyPressQueue = new int[128];
|
||||
|
||||
public static int keyPressQueueFront = 0;
|
||||
public static int keyPressQueueBack = 0;
|
||||
public static final int[] keyTypeCodeQueue = new int[128];
|
||||
|
||||
public static final char[] keyTypeCharQueue = new char[128];
|
||||
public static int keyTypeQueueFront = 0;
|
||||
public static int keyTypeQueueBack = 0;
|
||||
|
||||
private static boolean isCharAllowed(final char c) {
|
||||
if (c == 0) {
|
||||
return false;
|
||||
} else if (c >= 128 && (c < 160 || c > 255)) {
|
||||
for (final char knownChar : Strings.WINDOWS_1252_CHARS) {
|
||||
if (c == knownChar) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void keyPressed(final KeyEvent var1) {
|
||||
if (instance != null) {
|
||||
ticksSinceLastKeyEvent = 0;
|
||||
final int rawCode = var1.getKeyCode();
|
||||
final int mappedCode;
|
||||
if (rawCode >= 0 && rawCode < codeMapping.length) {
|
||||
final int var21 = codeMapping[rawCode];
|
||||
if ((var21 & 128) == 0) {
|
||||
mappedCode = var21;
|
||||
} else {
|
||||
mappedCode = -1;
|
||||
}
|
||||
} else {
|
||||
mappedCode = -1;
|
||||
}
|
||||
|
||||
if (mappedCode >= 0) {
|
||||
if (keyPressQueueBack >= 0) {
|
||||
keyPressQueue[keyPressQueueBack] = mappedCode;
|
||||
keyPressQueueBack = (keyPressQueueBack + 1) & 127;
|
||||
if (keyPressQueueFront == keyPressQueueBack) {
|
||||
keyPressQueueBack = -1;
|
||||
}
|
||||
}
|
||||
|
||||
final int i = (keyTypeQueueBack + 1) & 127;
|
||||
if (i != keyTypeQueueFront) {
|
||||
keyTypeCodeQueue[keyTypeQueueBack] = mappedCode;
|
||||
keyTypeCharQueue[keyTypeQueueBack] = 0;
|
||||
keyTypeQueueBack = i;
|
||||
}
|
||||
}
|
||||
|
||||
final int modifiers = var1.getModifiers();
|
||||
if ((modifiers & (CTRL_MASK | ALT_MASK)) != 0 || mappedCode == 10 || mappedCode == 85) {
|
||||
var1.consume();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void keyReleased(final KeyEvent event) {
|
||||
if (instance != null) {
|
||||
ticksSinceLastKeyEvent = 0;
|
||||
final int rawCode = event.getKeyCode();
|
||||
final int mappedCode;
|
||||
if (rawCode >= 0 && rawCode < codeMapping.length) {
|
||||
mappedCode = codeMapping[rawCode] & -129;
|
||||
} else {
|
||||
mappedCode = -1;
|
||||
}
|
||||
|
||||
if (keyPressQueueBack >= 0 && mappedCode >= 0) {
|
||||
keyPressQueue[keyPressQueueBack] = ~mappedCode;
|
||||
keyPressQueueBack = 1 + keyPressQueueBack & 127;
|
||||
if (keyPressQueueBack == keyPressQueueFront) {
|
||||
keyPressQueueBack = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
event.consume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyTyped(final KeyEvent event) {
|
||||
if (instance != null) {
|
||||
final char c = event.getKeyChar();
|
||||
if (c != 0 && c != '\uffff' && isCharAllowed(c)) {
|
||||
final int i = (keyTypeQueueBack + 1) & 127;
|
||||
if (i != keyTypeQueueFront) {
|
||||
keyTypeCodeQueue[keyTypeQueueBack] = -1;
|
||||
keyTypeCharQueue[keyTypeQueueBack] = c;
|
||||
keyTypeQueueBack = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
event.consume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void focusLost(final FocusEvent var1) {
|
||||
if (instance != null) {
|
||||
keyPressQueueBack = -1;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void focusGained(final FocusEvent var1) {
|
||||
}
|
||||
|
||||
public void attach(final Component c) {
|
||||
c.setFocusTraversalKeysEnabled(false);
|
||||
c.addKeyListener(this);
|
||||
c.addFocusListener(this);
|
||||
}
|
||||
|
||||
public void detach(final Component c) {
|
||||
c.removeKeyListener(this);
|
||||
c.removeFocusListener(this);
|
||||
keyPressQueueBack = -1;
|
||||
}
|
||||
}
|
48
src/main/java/funorb/awt/MouseControlBackend.java
Normal file
48
src/main/java/funorb/awt/MouseControlBackend.java
Normal file
@ -0,0 +1,48 @@
|
||||
package funorb.awt;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Robot;
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
public final class MouseControlBackend {
|
||||
private final Robot robot = new Robot();
|
||||
private Component cursorComponent;
|
||||
|
||||
public MouseControlBackend() throws Exception {
|
||||
}
|
||||
|
||||
public void movemouse(final int var1, final int var2) {
|
||||
this.robot.mouseMove(var1, var2);
|
||||
}
|
||||
|
||||
public void showcursor(Component var1, final boolean var2) {
|
||||
if (var2) {
|
||||
var1 = null;
|
||||
} else if (var1 == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
|
||||
if (this.cursorComponent != var1) {
|
||||
if (this.cursorComponent != null) {
|
||||
this.cursorComponent.setCursor(null);
|
||||
this.cursorComponent = null;
|
||||
}
|
||||
|
||||
if (var1 != null) {
|
||||
var1.setCursor(var1.getToolkit().createCustomCursor(new BufferedImage(1, 1, 2), new java.awt.Point(0, 0), null));
|
||||
this.cursorComponent = var1;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void setcustomcursor(final Component var1, final int[] var2, final int var3, final int var4, final java.awt.Point var5) {
|
||||
if (var2 == null) {
|
||||
var1.setCursor(null);
|
||||
} else {
|
||||
final BufferedImage var6 = new BufferedImage(var3, var4, 2);
|
||||
var6.setRGB(0, 0, var3, var4, var2, 0, var3);
|
||||
var1.setCursor(var1.getToolkit().createCustomCursor(var6, var5, null));
|
||||
}
|
||||
}
|
||||
}
|
164
src/main/java/funorb/awt/MouseState.java
Normal file
164
src/main/java/funorb/awt/MouseState.java
Normal file
@ -0,0 +1,164 @@
|
||||
package funorb.awt;
|
||||
|
||||
import funorb.client.JagexBaseApplet;
|
||||
import funorb.util.PseudoMonotonicClock;
|
||||
import org.intellij.lang.annotations.MagicConstant;
|
||||
|
||||
import javax.swing.SwingUtilities;
|
||||
import java.awt.Component;
|
||||
import java.awt.Point;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.FocusListener;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseListener;
|
||||
import java.awt.event.MouseMotionListener;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.NoninvertibleTransformException;
|
||||
|
||||
public final class MouseState implements MouseListener, MouseMotionListener, FocusListener {
|
||||
public static final MouseState instance = new MouseState();
|
||||
|
||||
@MagicConstant(valuesFromClass = Button.class)
|
||||
public static volatile int mouseButtonJustClicked = Button.NONE;
|
||||
@MagicConstant(valuesFromClass = Button.class)
|
||||
public static volatile int mouseButtonDown = Button.NONE;
|
||||
public static volatile int mouseX = -1;
|
||||
public static volatile int mouseY = -1;
|
||||
public static volatile int pressX = 0;
|
||||
public static volatile int pressY = 0;
|
||||
public static volatile int ticksSinceLastMouseEvent = 0;
|
||||
public static volatile boolean mouseEventReceived = false;
|
||||
|
||||
public void attach(final Component c) {
|
||||
c.addMouseListener(this);
|
||||
c.addMouseMotionListener(this);
|
||||
c.addFocusListener(this);
|
||||
}
|
||||
|
||||
public void detach(final Component c) {
|
||||
c.removeMouseListener(this);
|
||||
c.removeMouseMotionListener(this);
|
||||
c.removeFocusListener(this);
|
||||
mouseButtonDown = Button.NONE;
|
||||
}
|
||||
|
||||
private static Point transform(final MouseEvent event) {
|
||||
final AffineTransform transform = JagexBaseApplet.getTransform(event.getComponent());
|
||||
final Point result = new Point();
|
||||
try {
|
||||
transform.inverseTransform(event.getPoint(), result);
|
||||
} catch (final NoninvertibleTransformException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void mouseEntered(final MouseEvent var1) {
|
||||
if (instance != null) {
|
||||
ticksSinceLastMouseEvent = 0;
|
||||
mouseX = var1.getX();
|
||||
mouseY = var1.getY();
|
||||
mouseEventReceived = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void focusGained(final FocusEvent var1) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseClicked(final MouseEvent var1) {
|
||||
if (var1.isPopupTrigger()) {
|
||||
var1.consume();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void mouseMoved(final MouseEvent var1) {
|
||||
if (instance != null) {
|
||||
ticksSinceLastMouseEvent = 0;
|
||||
final Point point = transform(var1);
|
||||
mouseX = point.x;
|
||||
mouseY = point.y;
|
||||
mouseEventReceived = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void mouseDragged(final MouseEvent var1) {
|
||||
if (instance != null) {
|
||||
ticksSinceLastMouseEvent = 0;
|
||||
final Point point = transform(var1);
|
||||
mouseX = point.x;
|
||||
mouseY = point.y;
|
||||
mouseEventReceived = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void mouseExited(final MouseEvent var1) {
|
||||
if (instance != null) {
|
||||
ticksSinceLastMouseEvent = 0;
|
||||
mouseX = -1;
|
||||
mouseY = -1;
|
||||
mouseEventReceived = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void mouseReleased(final MouseEvent var1) {
|
||||
if (instance != null) {
|
||||
ticksSinceLastMouseEvent = 0;
|
||||
mouseButtonDown = Button.NONE;
|
||||
mouseEventReceived = true;
|
||||
|
||||
}
|
||||
|
||||
if (var1.isPopupTrigger()) {
|
||||
var1.consume();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void mousePressed(final MouseEvent var1) {
|
||||
if (instance != null) {
|
||||
ticksSinceLastMouseEvent = 0;
|
||||
final Point point = transform(var1);
|
||||
pressX = point.x;
|
||||
pressY = point.y;
|
||||
PseudoMonotonicClock.currentTimeMillis();
|
||||
if (SwingUtilities.isRightMouseButton(var1)) {
|
||||
mouseButtonJustClicked = Button.RIGHT;
|
||||
mouseButtonDown = Button.RIGHT;
|
||||
} else {
|
||||
mouseButtonJustClicked = Button.LEFT;
|
||||
mouseButtonDown = Button.LEFT;
|
||||
}
|
||||
|
||||
mouseEventReceived = true;
|
||||
|
||||
}
|
||||
|
||||
if (var1.isPopupTrigger()) {
|
||||
var1.consume();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void focusLost(final FocusEvent var1) {
|
||||
if (instance != null) {
|
||||
mouseButtonDown = Button.NONE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static final class Button {
|
||||
public static final int NONE = 0;
|
||||
public static final int LEFT = 1;
|
||||
public static final int RIGHT = 2;
|
||||
}
|
||||
}
|
30
src/main/java/funorb/awt/MouseWheelState.java
Normal file
30
src/main/java/funorb/awt/MouseWheelState.java
Normal file
@ -0,0 +1,30 @@
|
||||
package funorb.awt;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.event.MouseWheelEvent;
|
||||
import java.awt.event.MouseWheelListener;
|
||||
|
||||
public final class MouseWheelState implements MouseWheelListener {
|
||||
public static final MouseWheelState instance = new MouseWheelState();
|
||||
private int rotation = 0;
|
||||
|
||||
public void attach(final Component c) {
|
||||
c.addMouseWheelListener(this);
|
||||
}
|
||||
|
||||
public void detach(final Component c) {
|
||||
c.removeMouseWheelListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void mouseWheelMoved(final MouseWheelEvent e) {
|
||||
this.rotation += e.getWheelRotation();
|
||||
e.consume();
|
||||
}
|
||||
|
||||
public synchronized int poll() {
|
||||
final int rotation = this.rotation;
|
||||
this.rotation = 0;
|
||||
return rotation;
|
||||
}
|
||||
}
|
22
src/main/java/funorb/awt/ScreenBuffer.java
Normal file
22
src/main/java/funorb/awt/ScreenBuffer.java
Normal file
@ -0,0 +1,22 @@
|
||||
package funorb.awt;
|
||||
|
||||
import funorb.graphics.Drawing;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Image;
|
||||
|
||||
public abstract class ScreenBuffer {
|
||||
protected int[] screenBuffer;
|
||||
public int width;
|
||||
protected Image screenBufferImage;
|
||||
public int height;
|
||||
|
||||
public abstract void initialize(Component canvas, int width, int height);
|
||||
|
||||
protected final void makeGlobal() {
|
||||
Drawing.initialize(this.screenBuffer, this.width, this.height);
|
||||
}
|
||||
|
||||
public abstract void paint(Graphics var1);
|
||||
}
|
158
src/main/java/funorb/cache/BufferedCacheFile.java
vendored
Normal file
158
src/main/java/funorb/cache/BufferedCacheFile.java
vendored
Normal file
@ -0,0 +1,158 @@
|
||||
package funorb.cache;
|
||||
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
|
||||
public final class BufferedCacheFile {
|
||||
private final CacheFile cacheFile;
|
||||
private final byte[] buffer;
|
||||
private int _a;
|
||||
private long physicalPos = 0L;
|
||||
private long _h;
|
||||
private long logicalPos = 0L;
|
||||
private long _l;
|
||||
private long _i = -1L;
|
||||
|
||||
public BufferedCacheFile(final CacheFile cacheFile, final int bufferSize) throws IOException {
|
||||
this.cacheFile = cacheFile;
|
||||
this._h = this._l = cacheFile.length();
|
||||
this.buffer = new byte[bufferSize];
|
||||
}
|
||||
|
||||
public void write(final byte[] data, final int offset, final int len) throws IOException {
|
||||
try {
|
||||
if ((long) len + this.logicalPos > this._h) {
|
||||
this._h = this.logicalPos + (long) len;
|
||||
}
|
||||
|
||||
if (len > 0) {
|
||||
if (this.physicalPos != this.logicalPos) {
|
||||
this.cacheFile.seek(this.logicalPos);
|
||||
this.physicalPos = this.logicalPos;
|
||||
}
|
||||
|
||||
this.cacheFile.write(data, offset, len);
|
||||
this.physicalPos += len;
|
||||
if (this.physicalPos > this._l) {
|
||||
this._l = this.physicalPos;
|
||||
}
|
||||
|
||||
final long var6;
|
||||
if (this.logicalPos >= this._i && this.logicalPos < this._i + (long) this._a) {
|
||||
var6 = this.logicalPos;
|
||||
} else if (this._i >= this.logicalPos && this._i < this.logicalPos + (long) len) {
|
||||
var6 = this._i;
|
||||
} else {
|
||||
var6 = -1;
|
||||
}
|
||||
|
||||
final long var8;
|
||||
if (this.logicalPos + (long) len > this._i && (long) this._a + this._i >= this.logicalPos + (long) len) {
|
||||
var8 = (long) len + this.logicalPos;
|
||||
} else if (this._i + (long) this._a > this.logicalPos && this.logicalPos + (long) len >= (long) this._a + this._i) {
|
||||
var8 = (long) this._a + this._i;
|
||||
} else {
|
||||
var8 = -1;
|
||||
}
|
||||
|
||||
if (var6 > -1L && var6 < var8) {
|
||||
final int var10 = (int) (var8 - var6);
|
||||
System.arraycopy(data, (int) (var6 + (long) offset - this.logicalPos), this.buffer, (int) (var6 - this._i), var10);
|
||||
}
|
||||
|
||||
this.logicalPos += len;
|
||||
}
|
||||
} catch (final IOException e) {
|
||||
this.physicalPos = -1L;
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
private void pageIn() throws IOException {
|
||||
if (this.logicalPos != this.physicalPos) {
|
||||
this.cacheFile.seek(this.logicalPos);
|
||||
this.physicalPos = this.logicalPos;
|
||||
}
|
||||
this._i = this.logicalPos;
|
||||
|
||||
for (this._a = 0; this._a < this.buffer.length;) {
|
||||
final int len = Math.min(this.buffer.length - this._a, 200000000);
|
||||
final int bytesRead = this.cacheFile.read(this.buffer, this._a, len);
|
||||
if (bytesRead == -1) {
|
||||
break;
|
||||
}
|
||||
|
||||
this._a += bytesRead;
|
||||
this.physicalPos += bytesRead;
|
||||
}
|
||||
}
|
||||
|
||||
public void read(final byte[] dest, final int len) throws IOException {
|
||||
int lenLeft = len;
|
||||
try {
|
||||
if (dest.length < len) {
|
||||
throw new ArrayIndexOutOfBoundsException(len - 1);
|
||||
}
|
||||
|
||||
int var4 = 0;
|
||||
if (this._i <= this.logicalPos && (long) this._a + this._i > this.logicalPos) {
|
||||
final int var9 = Math.min((int) ((long) this._a - this.logicalPos + this._i), lenLeft);
|
||||
System.arraycopy(this.buffer, (int) (this.logicalPos - this._i), dest, var4, var9);
|
||||
this.logicalPos += var9;
|
||||
lenLeft -= var9;
|
||||
var4 += var9;
|
||||
}
|
||||
|
||||
if (lenLeft <= this.buffer.length) {
|
||||
if (lenLeft > 0) {
|
||||
this.pageIn();
|
||||
final int var10 = Math.min(lenLeft, this._a);
|
||||
System.arraycopy(this.buffer, 0, dest, var4, var10);
|
||||
this.logicalPos += var10;
|
||||
lenLeft -= var10;
|
||||
}
|
||||
} else {
|
||||
this.cacheFile.seek(this.logicalPos);
|
||||
int var10;
|
||||
for (this.physicalPos = this.logicalPos; lenLeft > 0; var4 += var10) {
|
||||
var10 = this.cacheFile.read(dest, var4, lenLeft);
|
||||
if (var10 == -1) {
|
||||
break;
|
||||
}
|
||||
|
||||
lenLeft -= var10;
|
||||
this.physicalPos += var10;
|
||||
this.logicalPos += var10;
|
||||
}
|
||||
}
|
||||
|
||||
} catch (final IOException e) {
|
||||
this.physicalPos = -1L;
|
||||
throw e;
|
||||
}
|
||||
|
||||
if (lenLeft > 0) {
|
||||
throw new EOFException();
|
||||
}
|
||||
}
|
||||
|
||||
public void read(final byte[] dest) throws IOException {
|
||||
this.read(dest, dest.length);
|
||||
}
|
||||
|
||||
public long length() {
|
||||
return this._h;
|
||||
}
|
||||
|
||||
public void seek(final long pos) throws IOException {
|
||||
if (pos >= 0L) {
|
||||
this.logicalPos = pos;
|
||||
} else {
|
||||
throw new IOException();
|
||||
}
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
this.cacheFile.close();
|
||||
}
|
||||
}
|
250
src/main/java/funorb/cache/BufferedPageCache.java
vendored
Normal file
250
src/main/java/funorb/cache/BufferedPageCache.java
vendored
Normal file
@ -0,0 +1,250 @@
|
||||
package funorb.cache;
|
||||
|
||||
import org.intellij.lang.annotations.MagicConstant;
|
||||
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
|
||||
public final class BufferedPageCache {
|
||||
private static final int INDEX_ENTRY_SIZE = 6;
|
||||
private static final int MAX_DATA_ENTRY_SIZE = 0x200000;
|
||||
// an 8-byte header + 512 bytes of data, or a 10-byte header + 510 bytes of data for high indexes
|
||||
private static final int DATA_ENTRY_BLOCK_SIZE = 520;
|
||||
|
||||
private static final byte[] buffer = new byte[DATA_ENTRY_BLOCK_SIZE];
|
||||
private final BufferedCacheFile indexFile;
|
||||
private final BufferedCacheFile dataFile;
|
||||
@MagicConstant(valuesFromClass = ResourceLoader.PageId.class)
|
||||
private final int pageId;
|
||||
|
||||
public BufferedPageCache(@MagicConstant(valuesFromClass = ResourceLoader.PageId.class) final int pageId, final BufferedCacheFile dataFile, final BufferedCacheFile indexFile) {
|
||||
this.pageId = pageId;
|
||||
this.dataFile = dataFile;
|
||||
this.indexFile = indexFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "" + this.pageId;
|
||||
}
|
||||
|
||||
public byte[] read(final int groupId) {
|
||||
synchronized (this.dataFile) {
|
||||
try {
|
||||
if ((groupId + 1) * (long) INDEX_ENTRY_SIZE > this.indexFile.length()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
this.indexFile.seek(groupId * (long) INDEX_ENTRY_SIZE);
|
||||
this.indexFile.read(buffer, 6);
|
||||
final int len = ((buffer[0] & 0xff) << 16) + ((buffer[1] & 0xff) << 8) + (buffer[2] & 0xff);
|
||||
if (len > MAX_DATA_ENTRY_SIZE) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int slot = ((buffer[3] & 0xff) << 16) + ((buffer[4] & 0xff) << 8) + (buffer[5] & 0xff);
|
||||
if (slot <= 0 || (long) slot > this.dataFile.length() / DATA_ENTRY_BLOCK_SIZE) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final byte[] data = new byte[len];
|
||||
int bytesRead = 0;
|
||||
int part = 0;
|
||||
while (bytesRead < len) {
|
||||
if (slot == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final int bytesLeft = len - bytesRead;
|
||||
final boolean isSmallIndex = groupId <= 0xffff;
|
||||
final int blockHeaderLen = isSmallIndex ? 8 : 10;
|
||||
final int blockDataLen = Math.min(bytesLeft, DATA_ENTRY_BLOCK_SIZE - blockHeaderLen);
|
||||
final int blockLen = blockHeaderLen + blockDataLen;
|
||||
|
||||
this.dataFile.seek(slot * (long) DATA_ENTRY_BLOCK_SIZE);
|
||||
this.dataFile.read(buffer, blockLen);
|
||||
final int entryIndex;
|
||||
final int entryPart;
|
||||
final int nextSlot;
|
||||
final int indexId;
|
||||
if (isSmallIndex) {
|
||||
entryIndex = ((buffer[0] & 0xff) << 8) + (buffer[1] & 0xff);
|
||||
entryPart = ((buffer[2] & 0xff) << 8) + (buffer[3] & 0xff);
|
||||
nextSlot = ((buffer[4] & 0xff) << 16) + ((buffer[5] & 0xff) << 8) + (buffer[6] & 0xff);
|
||||
indexId = buffer[7] & 0xff;
|
||||
} else {
|
||||
entryIndex = ((buffer[0] & 0xff) << 24) + ((buffer[1] & 0xff) << 16) + ((buffer[2] & 0xff) << 8) + (buffer[3] & 0xff);
|
||||
entryPart = ((buffer[4] & 0xff) << 8) + (buffer[5] & 0xff);
|
||||
nextSlot = ((buffer[6] & 0xff) << 16) + ((buffer[7] & 0xff) << 8) + (buffer[8] & 0xff);
|
||||
indexId = buffer[9] & 0xff;
|
||||
}
|
||||
|
||||
//noinspection MagicConstant
|
||||
if (entryIndex != groupId || entryPart != part || this.pageId != indexId) {
|
||||
return null;
|
||||
}
|
||||
if ((long) nextSlot > this.dataFile.length() / DATA_ENTRY_BLOCK_SIZE) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (int i = blockHeaderLen; i < blockLen; ++i) {
|
||||
data[bytesRead++] = buffer[i];
|
||||
}
|
||||
|
||||
slot = nextSlot;
|
||||
++part;
|
||||
}
|
||||
|
||||
return data;
|
||||
} catch (final IOException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void write(final int groupId, final byte[] data, final int len) {
|
||||
synchronized (this.dataFile) {
|
||||
if (len >= 0 && len <= MAX_DATA_ENTRY_SIZE) {
|
||||
final boolean var6 = this.write(groupId, data, len, true);
|
||||
if (!var6) {
|
||||
this.write(groupId, data, len, false);
|
||||
}
|
||||
} else {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean write(final int groupId, final byte[] data, final int len, boolean replaceExisting) {
|
||||
synchronized (this.dataFile) {
|
||||
try {
|
||||
int slot;
|
||||
if (replaceExisting) {
|
||||
if (this.indexFile.length() < (groupId + 1) * 6L) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.indexFile.seek(groupId * (long) INDEX_ENTRY_SIZE);
|
||||
this.indexFile.read(buffer, INDEX_ENTRY_SIZE);
|
||||
slot = ((buffer[3] & 255) << 16)
|
||||
+ ((buffer[4] & 255) << 8)
|
||||
+ (buffer[5] & 255);
|
||||
if (slot <= 0 || (long) slot > this.dataFile.length() / DATA_ENTRY_BLOCK_SIZE) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
slot = (int) ((this.dataFile.length() + (DATA_ENTRY_BLOCK_SIZE - 1L)) / DATA_ENTRY_BLOCK_SIZE);
|
||||
if (slot == 0) {
|
||||
slot = 1;
|
||||
}
|
||||
}
|
||||
|
||||
buffer[0] = (byte) (len >> 16);
|
||||
buffer[1] = (byte) (len >> 8);
|
||||
buffer[2] = (byte) len;
|
||||
buffer[3] = (byte) (slot >> 16);
|
||||
buffer[4] = (byte) (slot >> 8);
|
||||
buffer[5] = (byte) slot;
|
||||
this.indexFile.seek(groupId * (long) INDEX_ENTRY_SIZE);
|
||||
this.indexFile.write(buffer, 0, 6);
|
||||
|
||||
int bytesWritten = 0;
|
||||
int part = 0;
|
||||
while (len > bytesWritten) {
|
||||
int nextSlot = 0;
|
||||
if (replaceExisting) {
|
||||
final int entryIndex;
|
||||
this.dataFile.seek(slot * (long) DATA_ENTRY_BLOCK_SIZE);
|
||||
final int entryPart;
|
||||
final int indexId;
|
||||
if (groupId <= 0xffff) {
|
||||
try {
|
||||
this.dataFile.read(buffer, 8);
|
||||
} catch (final EOFException e) {
|
||||
return true;
|
||||
}
|
||||
|
||||
entryIndex = ((buffer[0] & 0xff) << 8) + (buffer[1] & 0xff);
|
||||
entryPart = ((buffer[2] & 0xff) << 8) + (buffer[3] & 0xff);
|
||||
nextSlot = ((buffer[4] & 0xff) << 16) + ((buffer[5] & 0xff) << 8) + (buffer[6] & 0xff);
|
||||
indexId = buffer[7] & 0xff;
|
||||
} else {
|
||||
try {
|
||||
this.dataFile.read(buffer, 10);
|
||||
} catch (final EOFException e) {
|
||||
return true;
|
||||
}
|
||||
|
||||
entryIndex = ((buffer[0] & 0xff) << 24) + ((buffer[1] & 0xff) << 16) + ((buffer[2] & 0xff) << 8) + (buffer[3] & 0xff);
|
||||
entryPart = ((buffer[4] & 0xff) << 8) + (buffer[5] & 0xff);
|
||||
nextSlot = ((buffer[6] & 0xff) << 16) + ((buffer[7] & 0xff) << 8) + (buffer[8] & 0xff);
|
||||
indexId = buffer[9] & 0xff;
|
||||
}
|
||||
|
||||
//noinspection MagicConstant
|
||||
if (entryIndex != groupId || entryPart != part || indexId != this.pageId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((long) nextSlot > this.dataFile.length() / DATA_ENTRY_BLOCK_SIZE) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (nextSlot == 0) {
|
||||
replaceExisting = false;
|
||||
nextSlot = (int) ((this.dataFile.length() + (DATA_ENTRY_BLOCK_SIZE - 1L)) / DATA_ENTRY_BLOCK_SIZE);
|
||||
if (nextSlot == 0) {
|
||||
++nextSlot;
|
||||
}
|
||||
|
||||
if (nextSlot == slot) {
|
||||
++nextSlot;
|
||||
}
|
||||
}
|
||||
|
||||
if (len - bytesWritten <= 512) {
|
||||
nextSlot = 0; // no next part, so no next slot
|
||||
}
|
||||
|
||||
final int entryLen;
|
||||
if (groupId <= 0xffff) {
|
||||
buffer[0] = (byte) (groupId >> 8);
|
||||
buffer[1] = (byte) groupId;
|
||||
buffer[2] = (byte) (part >> 8);
|
||||
buffer[3] = (byte) part;
|
||||
buffer[4] = (byte) (nextSlot >> 16);
|
||||
buffer[5] = (byte) (nextSlot >> 8);
|
||||
buffer[6] = (byte) nextSlot;
|
||||
buffer[7] = (byte) this.pageId;
|
||||
this.dataFile.seek(slot * (long) DATA_ENTRY_BLOCK_SIZE);
|
||||
this.dataFile.write(buffer, 0, 8);
|
||||
entryLen = Math.min(len - bytesWritten, 512);
|
||||
} else {
|
||||
buffer[0] = (byte) (groupId >> 24);
|
||||
buffer[1] = (byte) (groupId >> 16);
|
||||
buffer[2] = (byte) (groupId >> 8);
|
||||
buffer[3] = (byte) groupId;
|
||||
buffer[4] = (byte) (part >> 8);
|
||||
buffer[5] = (byte) part;
|
||||
buffer[6] = (byte) (nextSlot >> 16);
|
||||
buffer[7] = (byte) (nextSlot >> 8);
|
||||
buffer[8] = (byte) nextSlot;
|
||||
buffer[9] = (byte) this.pageId;
|
||||
this.dataFile.seek(slot * (long) DATA_ENTRY_BLOCK_SIZE);
|
||||
this.dataFile.write(buffer, 0, 10);
|
||||
entryLen = Math.min(len - bytesWritten, 510);
|
||||
}
|
||||
this.dataFile.write(data, bytesWritten, entryLen);
|
||||
bytesWritten += entryLen;
|
||||
|
||||
++part;
|
||||
slot = nextSlot;
|
||||
}
|
||||
return true;
|
||||
} catch (final IOException var18) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
110
src/main/java/funorb/cache/CacheFile.java
vendored
Normal file
110
src/main/java/funorb/cache/CacheFile.java
vendored
Normal file
@ -0,0 +1,110 @@
|
||||
package funorb.cache;
|
||||
|
||||
import funorb.shatteredplans.client.MessagePumpThread;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.EOFException;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
public final class CacheFile implements Closeable {
|
||||
private static final Path BASE_DIRECTORY = Paths.get(System.getProperty("user.home"), ".alterorb");
|
||||
private static final Path CACHES_DIRECTORY = BASE_DIRECTORY.resolve("caches");
|
||||
|
||||
private final long maxSize;
|
||||
private long pos;
|
||||
private RandomAccessFile file;
|
||||
|
||||
public CacheFile(final File file, long maxSize) throws IOException {
|
||||
if (maxSize == -1L) {
|
||||
maxSize = Long.MAX_VALUE;
|
||||
}
|
||||
|
||||
if (maxSize < file.length()) {
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
file.delete();
|
||||
}
|
||||
|
||||
this.file = new RandomAccessFile(file, "rw");
|
||||
this.maxSize = maxSize;
|
||||
this.pos = 0L;
|
||||
final int var5 = this.file.read();
|
||||
if (var5 != -1) {
|
||||
this.file.seek(0L);
|
||||
this.file.write(var5);
|
||||
}
|
||||
|
||||
this.file.seek(0L);
|
||||
}
|
||||
|
||||
public static File path(final String var0, final String var2) {
|
||||
try {
|
||||
final var path = cacheFilePath(var2, var0);
|
||||
if (!Files.exists(path)) {
|
||||
Files.createDirectories(path.getParent());
|
||||
}
|
||||
return path.toFile();
|
||||
} catch (final IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static File path(final String var0) {
|
||||
return path(var0, MessagePumpThread.GAME_ID);
|
||||
}
|
||||
|
||||
private static Path cacheFilePath(final String subDirectory, final String file) {
|
||||
if (subDirectory != null) {
|
||||
return CACHES_DIRECTORY.resolve(subDirectory).resolve(file);
|
||||
}
|
||||
return CACHES_DIRECTORY.resolve(file);
|
||||
}
|
||||
|
||||
public int read(final byte[] buffer, final int offset, final int len) throws IOException {
|
||||
final int bytesRead = this.file.read(buffer, offset, len);
|
||||
if (bytesRead > 0) {
|
||||
this.pos += bytesRead;
|
||||
}
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
public long length() throws IOException {
|
||||
return this.file.length();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
if (this.file != null) {
|
||||
this.file.close();
|
||||
this.file = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
if (this.file != null) {
|
||||
System.out.println();
|
||||
this.close();
|
||||
}
|
||||
}
|
||||
|
||||
public void seek(final long pos) throws IOException {
|
||||
this.file.seek(pos);
|
||||
this.pos = pos;
|
||||
}
|
||||
|
||||
public void write(final byte[] data, final int offset, final int len) throws IOException {
|
||||
if (this.pos + (long) len <= this.maxSize) {
|
||||
this.file.write(data, offset, len);
|
||||
this.pos += len;
|
||||
} else {
|
||||
this.file.seek(this.maxSize);
|
||||
this.file.write(1);
|
||||
throw new EOFException();
|
||||
}
|
||||
}
|
||||
}
|
159
src/main/java/funorb/cache/CacheWorker.java
vendored
Normal file
159
src/main/java/funorb/cache/CacheWorker.java
vendored
Normal file
@ -0,0 +1,159 @@
|
||||
package funorb.cache;
|
||||
|
||||
import funorb.shatteredplans.client.MailboxMessage;
|
||||
import funorb.shatteredplans.client.MessagePumpThread;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Queue;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* A {@link CacheWorker} mediates reads and writes to the local resource cache.
|
||||
* It maintains a queue of {@link WorkItem}s and processes them in the
|
||||
* background, ensuring all reads and writes to the cache are serialized.
|
||||
*/
|
||||
public final class CacheWorker implements Runnable, Closeable {
|
||||
public static CacheWorker instance;
|
||||
|
||||
private final Queue<WorkItem> pending = new ArrayDeque<>();
|
||||
public int pendingCount = 0;
|
||||
private Thread thread;
|
||||
private boolean shutdownRequested = false;
|
||||
|
||||
public CacheWorker(final Function<Runnable, Thread> createThread) {
|
||||
this.thread = createThread.apply(this);
|
||||
}
|
||||
|
||||
public static CacheWorker create(final MessagePumpThread messagePumpThread) {
|
||||
return new CacheWorker(self -> {
|
||||
final MailboxMessage message = messagePumpThread.sendSpawnThreadMessage(self, 5);
|
||||
if (message.busyAwait() == MailboxMessage.Status.FAILURE) {
|
||||
throw new RuntimeException();
|
||||
} else {
|
||||
return (Thread) message.response;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
while (!this.shutdownRequested) {
|
||||
final WorkItem req;
|
||||
synchronized (this.pending) {
|
||||
req = this.pending.poll();
|
||||
if (req == null) {
|
||||
try {
|
||||
this.pending.wait();
|
||||
} catch (final InterruptedException var5) {}
|
||||
continue;
|
||||
}
|
||||
|
||||
--this.pendingCount;
|
||||
}
|
||||
|
||||
if (req.type == WorkItem.Type.WRITE) {
|
||||
req.cacheFile.write(req.groupId, req.data, req.data.length);
|
||||
} else if (req.type == WorkItem.Type.READ) {
|
||||
req.data = req.cacheFile.read(req.groupId);
|
||||
} else {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
req.setLoaded();
|
||||
}
|
||||
}
|
||||
|
||||
private void enqueue(final WorkItem req) {
|
||||
synchronized (this.pending) {
|
||||
this.pending.add(req);
|
||||
++this.pendingCount;
|
||||
this.pending.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
public void enqueueWrite(final BufferedPageCache cacheFile, final int groupId, final byte[] data) {
|
||||
final WorkItem req = new WorkItem(WorkItem.Type.WRITE, cacheFile, false);
|
||||
req.groupId = groupId;
|
||||
req.data = data;
|
||||
this.enqueue(req);
|
||||
}
|
||||
|
||||
public WorkItem enqueueRead(final BufferedPageCache cacheFile, final int groupId) {
|
||||
final WorkItem req = new WorkItem(WorkItem.Type.READ, cacheFile, false);
|
||||
req.groupId = groupId;
|
||||
this.enqueue(req);
|
||||
return req;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs an <i>immediate</i> read, blocking until the read has been
|
||||
* performed. If there are any pending writes to the cache for the given
|
||||
* group, the pending written data will be returned. Otherwise, the data is
|
||||
* fetched via a call to {@link BufferedPageCache#read(int)}. <b>Note that the
|
||||
* returned data may be {@code null} in the case of a cache miss.</b>
|
||||
*/
|
||||
public WorkItem tryRead(final BufferedPageCache cacheFile, final int groupId) {
|
||||
synchronized (this.pending) {
|
||||
for (final WorkItem next : this.pending) {
|
||||
if (next.groupId == groupId && next.cacheFile == cacheFile && next.type == WorkItem.Type.WRITE) {
|
||||
assert next.data != null;
|
||||
final WorkItem req = new WorkItem(WorkItem.Type.TRY_READ, null, false);
|
||||
req.data = next.data;
|
||||
req.setLoaded();
|
||||
return req;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final WorkItem req = new WorkItem(WorkItem.Type.TRY_READ, null, true);
|
||||
req.data = cacheFile.read(groupId);
|
||||
req.setLoaded();
|
||||
return req;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
this.shutdownRequested = true;
|
||||
synchronized (this.pending) {
|
||||
this.pending.notifyAll();
|
||||
}
|
||||
|
||||
try {
|
||||
this.thread.join();
|
||||
} catch (final InterruptedException var4) {}
|
||||
|
||||
this.thread = null;
|
||||
}
|
||||
|
||||
public static final class WorkItem extends PageLoader.WorkItem {
|
||||
private enum Type {
|
||||
TRY_READ, WRITE, READ
|
||||
}
|
||||
|
||||
private final Type type;
|
||||
private final BufferedPageCache cacheFile;
|
||||
private byte[] data;
|
||||
private int groupId;
|
||||
public final boolean isTryWithoutWrite;
|
||||
|
||||
private WorkItem(final Type type, final BufferedPageCache cacheFile, final boolean isTryWithoutWrite) {
|
||||
this.type = type;
|
||||
this.cacheFile = cacheFile;
|
||||
this.isTryWithoutWrite = isTryWithoutWrite;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int percentLoaded() {
|
||||
return this.isLoaded() ? 100 : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getData() {
|
||||
if (!this.isLoaded()) {
|
||||
throw new IllegalStateException("not yet loaded");
|
||||
}
|
||||
return this.data;
|
||||
}
|
||||
}
|
||||
}
|
33
src/main/java/funorb/cache/LocalPageSource.java
vendored
Normal file
33
src/main/java/funorb/cache/LocalPageSource.java
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
package funorb.cache;
|
||||
|
||||
import funorb.io.Buffer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
public final class LocalPageSource extends PageSource {
|
||||
private final BiFunction<Integer, Integer, InputStream> open;
|
||||
|
||||
public LocalPageSource(final BiFunction<Integer, Integer, InputStream> open) {
|
||||
this.open = open;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void enqueue(final @NotNull WorkItem item) {
|
||||
final int pageId = (int) (item.partId >> 32);
|
||||
final int part = (int) item.partId;
|
||||
try (final InputStream in = this.open.apply(pageId, part)) {
|
||||
final byte[] data = in.readAllBytes();
|
||||
item.buffer = new Buffer(data.length + item.extraBytes);
|
||||
item.buffer.writeBytes(data);
|
||||
} catch (final IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
item.setLoaded();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeDueToError() {}
|
||||
}
|
85
src/main/java/funorb/cache/MasterIndexLoader.java
vendored
Normal file
85
src/main/java/funorb/cache/MasterIndexLoader.java
vendored
Normal file
@ -0,0 +1,85 @@
|
||||
package funorb.cache;
|
||||
|
||||
import funorb.io.Buffer;
|
||||
import funorb.util.Whirlpool;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public final class MasterIndexLoader {
|
||||
private final @NotNull PageSource pageSource;
|
||||
private final @NotNull CacheWorker cacheWorker;
|
||||
|
||||
private PageSource.WorkItem loadRequest;
|
||||
private Buffer buffer;
|
||||
private PageLoader[] pageLoaders;
|
||||
|
||||
public MasterIndexLoader(final @NotNull PageSource pageSource, final @NotNull CacheWorker cacheWorker) {
|
||||
this.pageSource = pageSource;
|
||||
this.cacheWorker = cacheWorker;
|
||||
this.loadRequest = this.pageSource.enqueueLoad(ResourceLoader.PageId.INDEX, 255, (byte) 0);
|
||||
}
|
||||
|
||||
public boolean loadIndex() {
|
||||
if (this.buffer != null) {
|
||||
return true;
|
||||
}
|
||||
if (this.loadRequest == null) {
|
||||
this.loadRequest = this.pageSource.enqueueLoad(ResourceLoader.PageId.INDEX, 255, (byte) 0);
|
||||
}
|
||||
if (!this.loadRequest.isLoaded()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final Buffer buffer = new Buffer(this.loadRequest.getData());
|
||||
buffer.pos = 5;
|
||||
final int partCount = buffer.readUByte();
|
||||
buffer.pos += partCount * 72;
|
||||
final byte[] remoteHash = new byte[buffer.data.length - buffer.pos];
|
||||
buffer.readBytes(remoteHash, remoteHash.length);
|
||||
|
||||
if (remoteHash.length != 65) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
Whirlpool.checkHash(buffer.data, 5, buffer.pos - remoteHash.length - 5, remoteHash, 1);
|
||||
|
||||
this.pageLoaders = new PageLoader[partCount];
|
||||
this.buffer = buffer;
|
||||
return true;
|
||||
}
|
||||
|
||||
public PageLoader getPageLoader(final int pageId, final @Nullable BufferedPageCache masterIndexCache, final @NotNull BufferedPageCache pageCache) {
|
||||
if (this.buffer == null) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
if (pageId < 0 || this.pageLoaders.length <= pageId) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
if (this.pageLoaders[pageId] == null) {
|
||||
this.buffer.pos = 6 + pageId * 72;
|
||||
final int crc = this.buffer.readInt();
|
||||
final int version = this.buffer.readInt();
|
||||
final byte[] whirlpoolHash = new byte[Whirlpool.HASH_BYTES];
|
||||
this.buffer.readBytes(whirlpoolHash);
|
||||
final PageLoader entry = new PageLoader(pageId, pageCache, masterIndexCache, this.pageSource, this.cacheWorker, crc, whirlpoolHash, version);
|
||||
this.pageLoaders[pageId] = entry;
|
||||
return entry;
|
||||
} else {
|
||||
return this.pageLoaders[pageId];
|
||||
}
|
||||
}
|
||||
|
||||
public void tick() {
|
||||
if (this.pageLoaders != null) {
|
||||
for (final PageLoader pageLoader : this.pageLoaders) {
|
||||
if (pageLoader != null) {
|
||||
pageLoader.tryGetOrCreateIndex();
|
||||
}
|
||||
}
|
||||
for (final PageLoader pageLoader : this.pageLoaders) {
|
||||
if (pageLoader != null) {
|
||||
pageLoader.tick();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
209
src/main/java/funorb/cache/PageIndex.java
vendored
Normal file
209
src/main/java/funorb/cache/PageIndex.java
vendored
Normal file
@ -0,0 +1,209 @@
|
||||
package funorb.cache;
|
||||
|
||||
import funorb.io.Buffer;
|
||||
import funorb.io.Bzip2;
|
||||
import funorb.io.Inflater;
|
||||
import funorb.util.ArrayUtil;
|
||||
import funorb.util.Whirlpool;
|
||||
|
||||
public final class PageIndex {
|
||||
public ResourceDirectory groupDirectory;
|
||||
public ResourceDirectory[] itemDirectories;
|
||||
public final int pageVersion;
|
||||
public final int groupCount;
|
||||
public final int[] groupIndexes;
|
||||
public final int[] groupSizes;
|
||||
public final int[] itemCounts;
|
||||
public final int[][] itemIdMaps;
|
||||
public byte[][] groupWhirlpoolHashes;
|
||||
public final int[] _v;
|
||||
public final int[] groupCrcs;
|
||||
|
||||
public PageIndex(final byte[] data, final int expectedCrc, final byte[] expectedWhirlpool) {
|
||||
final int crc = Buffer.computeCrc(data, data.length);
|
||||
if (crc != expectedCrc) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
if (expectedWhirlpool != null) {
|
||||
if (expectedWhirlpool.length != 64) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
Whirlpool.checkHash(data, 0, data.length, expectedWhirlpool);
|
||||
}
|
||||
|
||||
final Buffer buffer = new Buffer(decompress(data));
|
||||
final int var4 = buffer.readUByte();
|
||||
if (var4 < 5 || var4 > 7) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
|
||||
if (var4 >= 6) {
|
||||
this.pageVersion = buffer.readInt();
|
||||
} else {
|
||||
this.pageVersion = 0;
|
||||
}
|
||||
|
||||
final int flags = buffer.readUByte();
|
||||
final boolean var6 = (flags & 1) != 0;
|
||||
final boolean hasWhirlpool = (flags & 2) != 0;
|
||||
|
||||
final int len = var4 == 7 ? buffer.readVariable16_32() : buffer.readUShort();
|
||||
int var8 = 0;
|
||||
this.groupIndexes = new int[len];
|
||||
int highestEntryIndex = -1;
|
||||
if (var4 == 7) {
|
||||
for (int i = 0; i < len; ++i) {
|
||||
this.groupIndexes[i] = var8 += buffer.readVariable16_32();
|
||||
if (highestEntryIndex < this.groupIndexes[i]) {
|
||||
highestEntryIndex = this.groupIndexes[i];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < len; ++i) {
|
||||
this.groupIndexes[i] = var8 += buffer.readUShort();
|
||||
if (highestEntryIndex < this.groupIndexes[i]) {
|
||||
highestEntryIndex = this.groupIndexes[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.groupCount = highestEntryIndex + 1;
|
||||
this.itemIdMaps = new int[this.groupCount][];
|
||||
this.itemCounts = new int[this.groupCount];
|
||||
this.groupSizes = new int[this.groupCount];
|
||||
this.groupCrcs = new int[this.groupCount];
|
||||
if (hasWhirlpool) {
|
||||
this.groupWhirlpoolHashes = new byte[this.groupCount][];
|
||||
}
|
||||
|
||||
this._v = new int[this.groupCount];
|
||||
if (var6) {
|
||||
final int[] _s = ArrayUtil.create(this.groupCount, -1);
|
||||
for (int i = 0; i < len; ++i) {
|
||||
_s[this.groupIndexes[i]] = buffer.readInt();
|
||||
}
|
||||
this.groupDirectory = new ResourceDirectory(_s);
|
||||
}
|
||||
|
||||
for (int i = 0; i < len; ++i) {
|
||||
this.groupCrcs[this.groupIndexes[i]] = buffer.readInt();
|
||||
}
|
||||
|
||||
if (hasWhirlpool) {
|
||||
for (int i = 0; len > i; ++i) {
|
||||
final byte[] var11 = new byte[64];
|
||||
buffer.readBytes(var11, 64);
|
||||
this.groupWhirlpoolHashes[this.groupIndexes[i]] = var11;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < len; ++i) {
|
||||
this._v[this.groupIndexes[i]] = buffer.readInt();
|
||||
}
|
||||
|
||||
if (var4 == 7) {
|
||||
for (int i = 0; len > i; ++i) {
|
||||
this.itemCounts[this.groupIndexes[i]] = buffer.readVariable16_32();
|
||||
}
|
||||
|
||||
for (int i = 0; i < len; ++i) {
|
||||
final int var16 = this.groupIndexes[i];
|
||||
final int var12 = this.itemCounts[var16];
|
||||
var8 = 0;
|
||||
this.itemIdMaps[var16] = new int[var12];
|
||||
int var13 = -1;
|
||||
|
||||
for (int j = 0; var12 > j; ++j) {
|
||||
final int var15 = this.itemIdMaps[var16][j] = var8 += buffer.readVariable16_32();
|
||||
if (var15 > var13) {
|
||||
var13 = var15;
|
||||
}
|
||||
}
|
||||
|
||||
this.groupSizes[var16] = var13 + 1;
|
||||
if (var12 == var13 + 1) {
|
||||
this.itemIdMaps[var16] = null;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < len; ++i) {
|
||||
this.itemCounts[this.groupIndexes[i]] = buffer.readUShort();
|
||||
}
|
||||
|
||||
for (int i = 0; i < len; ++i) {
|
||||
final int var16 = this.groupIndexes[i];
|
||||
var8 = 0;
|
||||
final int var12 = this.itemCounts[var16];
|
||||
int var13 = -1;
|
||||
this.itemIdMaps[var16] = new int[var12];
|
||||
|
||||
for (int var14 = 0; var12 > var14; ++var14) {
|
||||
final int var15 = this.itemIdMaps[var16][var14] = var8 += buffer.readUShort();
|
||||
if (var13 < var15) {
|
||||
var13 = var15;
|
||||
}
|
||||
}
|
||||
|
||||
this.groupSizes[var16] = 1 + var13;
|
||||
if (var13 + 1 == var12) {
|
||||
this.itemIdMaps[var16] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (var6) {
|
||||
final int[][] _t = new int[1 + highestEntryIndex][];
|
||||
this.itemDirectories = new ResourceDirectory[highestEntryIndex + 1];
|
||||
|
||||
for (int i = 0; len > i; ++i) {
|
||||
final int var16 = this.groupIndexes[i];
|
||||
final int var12 = this.itemCounts[var16];
|
||||
_t[var16] = new int[this.groupSizes[var16]];
|
||||
|
||||
for (int var13 = 0; this.groupSizes[var16] > var13; ++var13) {
|
||||
_t[var16][var13] = -1;
|
||||
}
|
||||
|
||||
for (int var13 = 0; var13 < var12; ++var13) {
|
||||
final int var14;
|
||||
if (this.itemIdMaps[var16] == null) {
|
||||
var14 = var13;
|
||||
} else {
|
||||
var14 = this.itemIdMaps[var16][var13];
|
||||
}
|
||||
|
||||
_t[var16][var14] = buffer.readInt();
|
||||
}
|
||||
|
||||
this.itemDirectories[var16] = new ResourceDirectory(_t[var16]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] decompress(final byte[] data) {
|
||||
final Buffer buffer = new Buffer(data);
|
||||
final int compressionFormat = buffer.readUByte();
|
||||
final int dataLen = buffer.readInt();
|
||||
if (dataLen < 0) {
|
||||
throw new RuntimeException("negative data length");
|
||||
}
|
||||
|
||||
if (compressionFormat == 0) {
|
||||
final byte[] result = new byte[dataLen];
|
||||
buffer.readBytes(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
final int compressedLen = buffer.readInt();
|
||||
if (compressedLen < 0) {
|
||||
throw new RuntimeException("negative compressed data length");
|
||||
}
|
||||
final byte[] result = new byte[compressedLen];
|
||||
if (compressionFormat == 1) {
|
||||
Bzip2.decompress(data, result);
|
||||
} else {
|
||||
Inflater.inflate(buffer, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
272
src/main/java/funorb/cache/PageLoader.java
vendored
Normal file
272
src/main/java/funorb/cache/PageLoader.java
vendored
Normal file
@ -0,0 +1,272 @@
|
||||
package funorb.cache;
|
||||
|
||||
import funorb.util.Whirlpool;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.zip.CRC32;
|
||||
|
||||
public final class PageLoader {
|
||||
private static final CRC32 CRC_32 = new CRC32();
|
||||
|
||||
private final int pageId;
|
||||
private final @NotNull BufferedPageCache pageCache;
|
||||
private final @Nullable BufferedPageCache masterIndexCache;
|
||||
private final @NotNull PageSource pageSource;
|
||||
private final @NotNull CacheWorker cacheWorker;
|
||||
private final int pageCrc;
|
||||
private final byte@NotNull[] pageExpectedWhirlpool;
|
||||
private final int pageVersion;
|
||||
|
||||
private PageIndex index;
|
||||
private WorkItem indexItem;
|
||||
private final Map<Integer, WorkItem> dataItems = new HashMap<>();
|
||||
private Collection<Integer> pendingGroups = new ArrayList<>();
|
||||
private @Nullable GroupStatus[] groupStatuses;
|
||||
private int nextGroupId = 0;
|
||||
|
||||
public PageLoader(final int pageId,
|
||||
final @NotNull BufferedPageCache pageCache,
|
||||
final @Nullable BufferedPageCache masterIndexCache,
|
||||
final @NotNull PageSource pageSource,
|
||||
final @NotNull CacheWorker cacheWorker,
|
||||
final int pageCrc,
|
||||
final byte@NotNull[] pageExpectedWhirlpool,
|
||||
final int pageVersion) {
|
||||
this.pageId = pageId;
|
||||
this.pageCache = pageCache;
|
||||
this.masterIndexCache = masterIndexCache;
|
||||
this.pageSource = pageSource;
|
||||
this.cacheWorker = cacheWorker;
|
||||
this.pageCrc = pageCrc;
|
||||
this.pageExpectedWhirlpool = pageExpectedWhirlpool;
|
||||
this.pageVersion = pageVersion;
|
||||
if (this.masterIndexCache != null) {
|
||||
this.indexItem = this.cacheWorker.tryRead(this.masterIndexCache, this.pageId);
|
||||
}
|
||||
}
|
||||
|
||||
public void tick() {
|
||||
if (this.pendingGroups != null) {
|
||||
if (this.tryGetOrCreateIndex() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean isLoaded = true;
|
||||
for (final Iterator<Integer> it = this.pendingGroups.iterator(); it.hasNext(); ) {
|
||||
final Integer groupId = it.next();
|
||||
if (this.groupStatuses[groupId] == null) {
|
||||
this.tryLoadGroup(LoadMethod.READ_FROM_CACHE, groupId);
|
||||
}
|
||||
if (this.groupStatuses[groupId] == null) {
|
||||
isLoaded = false;
|
||||
} else {
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
|
||||
while (this.nextGroupId < this.index.itemCounts.length) {
|
||||
if (this.index.itemCounts[this.nextGroupId] != 0) {
|
||||
if (this.cacheWorker.pendingCount >= 250) {
|
||||
isLoaded = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (this.groupStatuses[this.nextGroupId] == null) {
|
||||
this.tryLoadGroup(LoadMethod.READ_FROM_CACHE, this.nextGroupId);
|
||||
}
|
||||
|
||||
if (this.groupStatuses[this.nextGroupId] == null) {
|
||||
isLoaded = false;
|
||||
this.pendingGroups.add(this.nextGroupId);
|
||||
}
|
||||
}
|
||||
++this.nextGroupId;
|
||||
}
|
||||
|
||||
if (isLoaded) {
|
||||
this.nextGroupId = 0;
|
||||
this.pendingGroups = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public @Nullable PageIndex tryGetOrCreateIndex() {
|
||||
if (this.index != null) {
|
||||
return this.index;
|
||||
}
|
||||
if (this.indexItem == null) {
|
||||
this.indexItem = this.pageSource.enqueueLoad(ResourceLoader.PageId.INDEX, this.pageId, (byte) 0);
|
||||
}
|
||||
if (!this.indexItem.isLoaded()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final byte[] data = this.indexItem.getData();
|
||||
if (this.indexItem instanceof CacheWorker.WorkItem) {
|
||||
try {
|
||||
if (data == null) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
this.index = new PageIndex(data, this.pageCrc, this.pageExpectedWhirlpool);
|
||||
if (this.pageVersion != this.index.pageVersion) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
} catch (final RuntimeException e) {
|
||||
this.index = null;
|
||||
this.indexItem = this.pageSource.enqueueLoad(ResourceLoader.PageId.INDEX, this.pageId, (byte) 0);
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
if (data == null) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
this.index = new PageIndex(data, this.pageCrc, this.pageExpectedWhirlpool);
|
||||
} catch (final RuntimeException e) {
|
||||
this.pageSource.closeDueToError();
|
||||
this.index = null;
|
||||
this.indexItem = this.pageSource.enqueueLoad(ResourceLoader.PageId.INDEX, this.pageId, (byte) 0);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (this.masterIndexCache != null) {
|
||||
this.cacheWorker.enqueueWrite(this.masterIndexCache, this.pageId, data);
|
||||
}
|
||||
}
|
||||
|
||||
this.indexItem = null;
|
||||
this.groupStatuses = new GroupStatus[this.index.groupCount];
|
||||
return this.index;
|
||||
}
|
||||
|
||||
public int percentLoaded(final int groupId) {
|
||||
final WorkItem item = this.dataItems.get(groupId);
|
||||
return item != null ? item.percentLoaded() : 0;
|
||||
}
|
||||
|
||||
public byte@Nullable[] tryGetLoadedData(final int groupId) {
|
||||
final WorkItem item = this.tryLoadGroup(LoadMethod.TRY_CACHE_ELSE_FETCH, groupId);
|
||||
if (item == null) {
|
||||
return null;
|
||||
}
|
||||
this.dataItems.remove(groupId);
|
||||
return item.getData();
|
||||
}
|
||||
|
||||
private @Nullable WorkItem tryLoadGroup(final @NotNull LoadMethod how, final int groupId) {
|
||||
WorkItem item = this.dataItems.get(groupId);
|
||||
if (how == LoadMethod.TRY_CACHE_ELSE_FETCH
|
||||
&& item instanceof CacheWorker.WorkItem cacheItem
|
||||
&& !cacheItem.isTryWithoutWrite
|
||||
&& !item.isLoaded()) {
|
||||
this.dataItems.remove(groupId);
|
||||
item = null;
|
||||
}
|
||||
|
||||
if (item == null) {
|
||||
item = switch (how) {
|
||||
case TRY_CACHE_ELSE_FETCH ->
|
||||
this.groupStatuses[groupId] == GroupStatus.NOT_IN_CACHE
|
||||
? this.pageSource.enqueueLoad(this.pageId, groupId, (byte) 2)
|
||||
: this.cacheWorker.tryRead(this.pageCache, groupId);
|
||||
case READ_FROM_CACHE ->
|
||||
this.cacheWorker.enqueueRead(this.pageCache, groupId);
|
||||
};
|
||||
this.dataItems.put(groupId, item);
|
||||
}
|
||||
|
||||
if (!item.isLoaded()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final byte[] data = item.getData();
|
||||
if (item instanceof CacheWorker.WorkItem cacheItem) {
|
||||
try {
|
||||
if (data == null || data.length <= 2) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
|
||||
CRC_32.reset();
|
||||
CRC_32.update(data, 0, data.length - 2);
|
||||
if ((int) CRC_32.getValue() != this.index.groupCrcs[groupId]) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
if (this.index.groupWhirlpoolHashes != null && this.index.groupWhirlpoolHashes[groupId] != null) {
|
||||
Whirlpool.checkHash(data, 0, data.length - 2, this.index.groupWhirlpoolHashes[groupId]);
|
||||
}
|
||||
final int var12 = ((data[data.length - 2] & 255) << 8) + (data[data.length - 1] & 255);
|
||||
if (var12 != (this.index._v[groupId] & 0xffff)) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
|
||||
if (this.groupStatuses[groupId] != GroupStatus.IN_CACHE) {
|
||||
this.groupStatuses[groupId] = GroupStatus.IN_CACHE;
|
||||
}
|
||||
if (!cacheItem.isTryWithoutWrite) {
|
||||
this.dataItems.remove(groupId);
|
||||
}
|
||||
return cacheItem;
|
||||
} catch (final Exception e) {
|
||||
this.groupStatuses[groupId] = GroupStatus.NOT_IN_CACHE;
|
||||
this.dataItems.remove(groupId);
|
||||
if (cacheItem.isTryWithoutWrite) {
|
||||
this.dataItems.put(groupId, this.pageSource.enqueueLoad(this.pageId, groupId, (byte) 2));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
if (data == null || data.length <= 2) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
|
||||
CRC_32.reset();
|
||||
CRC_32.update(data, 0, data.length - 2);
|
||||
if ((int) CRC_32.getValue() != this.index.groupCrcs[groupId]) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
if (this.index.groupWhirlpoolHashes != null && this.index.groupWhirlpoolHashes[groupId] != null) {
|
||||
Whirlpool.checkHash(data, 0, data.length - 2, this.index.groupWhirlpoolHashes[groupId]);
|
||||
}
|
||||
|
||||
this.pageSource.failureCount = 0;
|
||||
this.pageSource.errorCode = null;
|
||||
data[data.length - 2] = (byte) (this.index._v[groupId] >>> 8);
|
||||
data[data.length - 1] = (byte) this.index._v[groupId];
|
||||
this.cacheWorker.enqueueWrite(this.pageCache, groupId, data);
|
||||
if (this.groupStatuses[groupId] != GroupStatus.IN_CACHE) {
|
||||
this.groupStatuses[groupId] = GroupStatus.IN_CACHE;
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
||||
private enum GroupStatus {
|
||||
IN_CACHE, NOT_IN_CACHE
|
||||
}
|
||||
|
||||
private enum LoadMethod {
|
||||
TRY_CACHE_ELSE_FETCH, READ_FROM_CACHE
|
||||
}
|
||||
|
||||
public abstract static sealed class WorkItem permits PageSource.WorkItem, CacheWorker.WorkItem {
|
||||
private volatile boolean isLoaded = false;
|
||||
|
||||
public abstract byte[] getData();
|
||||
public abstract int percentLoaded();
|
||||
|
||||
public final boolean isLoaded() {
|
||||
return this.isLoaded;
|
||||
}
|
||||
|
||||
public final void setLoaded() {
|
||||
this.isLoaded = true;
|
||||
}
|
||||
}
|
||||
}
|
55
src/main/java/funorb/cache/PageSource.java
vendored
Normal file
55
src/main/java/funorb/cache/PageSource.java
vendored
Normal file
@ -0,0 +1,55 @@
|
||||
package funorb.cache;
|
||||
|
||||
import funorb.io.Buffer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* A {@link PageSource} manages loading resource pages that aren’t yet in the cache.
|
||||
*/
|
||||
public abstract class PageSource {
|
||||
public volatile int failureCount = 0;
|
||||
public volatile ErrorCode errorCode = null;
|
||||
|
||||
protected abstract void enqueue(@NotNull WorkItem item);
|
||||
public abstract void closeDueToError();
|
||||
|
||||
public final WorkItem enqueueLoad(final int pageId, final int part, final byte extraBytes) {
|
||||
final WorkItem item = new WorkItem(((long) pageId << 32) + (long) part);
|
||||
item.extraBytes = extraBytes;
|
||||
|
||||
this.enqueue(item);
|
||||
return item;
|
||||
}
|
||||
|
||||
public static final class WorkItem extends PageLoader.WorkItem {
|
||||
final long partId;
|
||||
byte extraBytes;
|
||||
int bytesReadSoFar;
|
||||
Buffer buffer;
|
||||
|
||||
private WorkItem(final long partId) {
|
||||
this.partId = partId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int percentLoaded() {
|
||||
if (this.buffer == null) {
|
||||
return 0;
|
||||
} else {
|
||||
return 100 * this.buffer.pos / (this.buffer.data.length - this.extraBytes);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getData() {
|
||||
if (!this.isLoaded() || this.buffer.pos < this.buffer.data.length - this.extraBytes) {
|
||||
throw new IllegalStateException("not yet loaded");
|
||||
}
|
||||
return this.buffer.data;
|
||||
}
|
||||
}
|
||||
|
||||
public enum ErrorCode {
|
||||
PROTOCOL_ERROR, INTEGRITY_CHECK_FAILURE, UNKNOWN_CONNECTION_FAILURE, SERVER_CODE_51, SERVER_CODE_50
|
||||
}
|
||||
}
|
252
src/main/java/funorb/cache/RemotePageSource.java
vendored
Normal file
252
src/main/java/funorb/cache/RemotePageSource.java
vendored
Normal file
@ -0,0 +1,252 @@
|
||||
package funorb.cache;
|
||||
|
||||
import funorb.io.Buffer;
|
||||
import funorb.io.DuplexStream;
|
||||
import funorb.shatteredplans.client.JagexApplet;
|
||||
import funorb.util.PseudoMonotonicClock;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Queue;
|
||||
|
||||
public final class RemotePageSource extends PageSource {
|
||||
private static final int QUEUE_CAPACITY = 20;
|
||||
|
||||
private final Queue<WorkItem> unsentItems = new ArrayDeque<>(QUEUE_CAPACITY);
|
||||
private final Queue<WorkItem> pendingItems = new ArrayDeque<>(QUEUE_CAPACITY);
|
||||
private WorkItem current;
|
||||
|
||||
private final Buffer c2sPacket = new Buffer(6);
|
||||
private final Buffer s2cPacket = new Buffer(10);
|
||||
|
||||
private DuplexStream serverConnection;
|
||||
private int millisSinceLastReceivedData;
|
||||
private long lastLoadTime;
|
||||
|
||||
@Override
|
||||
protected void enqueue(final @NotNull WorkItem item) {
|
||||
if (this.isQueueFull()) {
|
||||
throw new IllegalStateException("queue overflow");
|
||||
}
|
||||
this.unsentItems.add(item);
|
||||
}
|
||||
|
||||
private boolean isQueueFull() {
|
||||
return this.queueSize() >= QUEUE_CAPACITY;
|
||||
}
|
||||
|
||||
private int queueSize() {
|
||||
return this.unsentItems.size() + this.pendingItems.size();
|
||||
}
|
||||
|
||||
public void initializeServerConnection(final DuplexStream serverConnection) {
|
||||
if (this.serverConnection != null) {
|
||||
try {
|
||||
this.serverConnection.close();
|
||||
} catch (final Exception e) {}
|
||||
}
|
||||
|
||||
this.serverConnection = serverConnection;
|
||||
this.handshake1();
|
||||
this.handshake2();
|
||||
this.current = null;
|
||||
this.s2cPacket.pos = 0;
|
||||
|
||||
WorkItem item;
|
||||
while ((item = this.pendingItems.poll()) != null) {
|
||||
this.unsentItems.add(item);
|
||||
}
|
||||
|
||||
this.millisSinceLastReceivedData = 0;
|
||||
this.lastLoadTime = PseudoMonotonicClock.currentTimeMillis();
|
||||
}
|
||||
|
||||
public void close() {
|
||||
if (this.serverConnection != null) {
|
||||
this.serverConnection.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeDueToError() {
|
||||
try {
|
||||
this.serverConnection.close();
|
||||
} catch (final Exception e) {}
|
||||
|
||||
this.serverConnection = null;
|
||||
this.errorCode = ErrorCode.INTEGRITY_CHECK_FAILURE;
|
||||
//noinspection NonAtomicOperationOnVolatileField
|
||||
++this.failureCount;
|
||||
}
|
||||
|
||||
public boolean processWork() {
|
||||
if (this.serverConnection != null) {
|
||||
final long now = PseudoMonotonicClock.currentTimeMillis();
|
||||
int millisSinceLast = (int) (now - this.lastLoadTime);
|
||||
this.lastLoadTime = now;
|
||||
if (millisSinceLast > 200) {
|
||||
millisSinceLast = 200;
|
||||
}
|
||||
|
||||
this.millisSinceLastReceivedData += millisSinceLast;
|
||||
if (this.millisSinceLastReceivedData > JagexApplet.SERVER_TIMEOUT_MILLIS) {
|
||||
this.serverConnection.close();
|
||||
this.serverConnection = null;
|
||||
}
|
||||
}
|
||||
if (this.serverConnection == null) {
|
||||
return this.queueSize() == 0;
|
||||
}
|
||||
|
||||
try {
|
||||
this.serverConnection.pollForException();
|
||||
|
||||
WorkItem item;
|
||||
while ((item = this.unsentItems.poll()) != null) {
|
||||
this.c2sPacket.pos = 0;
|
||||
this.c2sPacket.writeByte(0);
|
||||
this.c2sPacket.writeI40(item.partId);
|
||||
this.serverConnection.write(this.c2sPacket.data, this.c2sPacket.data.length);
|
||||
this.pendingItems.add(item);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
final int available = this.serverConnection.inputAvailable();
|
||||
if (available == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
this.millisSinceLastReceivedData = 0;
|
||||
final byte bytesNeeded;
|
||||
if (this.current == null) {
|
||||
bytesNeeded = 10;
|
||||
} else if (this.current.bytesReadSoFar == 0) {
|
||||
bytesNeeded = 1;
|
||||
} else {
|
||||
bytesNeeded = 0;
|
||||
}
|
||||
|
||||
if (bytesNeeded > 0) {
|
||||
int bytesToRead = bytesNeeded - this.s2cPacket.pos;
|
||||
if (available < bytesToRead) {
|
||||
bytesToRead = available;
|
||||
}
|
||||
|
||||
this.serverConnection.read(this.s2cPacket.data, this.s2cPacket.pos, bytesToRead);
|
||||
this.s2cPacket.pos += bytesToRead;
|
||||
|
||||
if (this.s2cPacket.pos >= bytesNeeded) {
|
||||
if (this.current == null) {
|
||||
this.s2cPacket.pos = 0;
|
||||
final int group = this.s2cPacket.readUByte();
|
||||
final int index = this.s2cPacket.readInt();
|
||||
final int var8 = this.s2cPacket.readUByte();
|
||||
final int var9 = this.s2cPacket.readInt();
|
||||
final int isHigh = var8 & 127;
|
||||
final boolean priority = (var8 & 128) != 0;
|
||||
final long groupAndIndex = ((long) group << 32) + (long) index;
|
||||
if (!priority) {
|
||||
throw new IOException();
|
||||
}
|
||||
|
||||
final WorkItem var14 = this.pendingItems.stream()
|
||||
.filter(entry -> entry.partId == groupAndIndex).findFirst()
|
||||
.orElseThrow(IOException::new);
|
||||
|
||||
final int headerSize = isHigh != 0 ? 9 : 5;
|
||||
this.current = var14;
|
||||
this.current.buffer = new Buffer(this.current.extraBytes + var9 + headerSize);
|
||||
this.current.buffer.writeByte(isHigh);
|
||||
this.current.buffer.writeInt(var9);
|
||||
this.s2cPacket.pos = 0;
|
||||
this.current.bytesReadSoFar = 10;
|
||||
} else {
|
||||
if (this.current.bytesReadSoFar != 0) {
|
||||
throw new IOException();
|
||||
}
|
||||
|
||||
if (this.s2cPacket.data[0] == -1) {
|
||||
this.s2cPacket.pos = 0;
|
||||
this.current.bytesReadSoFar = 1;
|
||||
} else {
|
||||
this.current = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
final int bytesWanted = this.current.buffer.data.length - this.current.extraBytes;
|
||||
int bytesToRead = 512 - this.current.bytesReadSoFar;
|
||||
if (bytesToRead > bytesWanted - this.current.buffer.pos) {
|
||||
bytesToRead = bytesWanted - this.current.buffer.pos;
|
||||
}
|
||||
|
||||
if (bytesToRead > available) {
|
||||
bytesToRead = available;
|
||||
}
|
||||
|
||||
this.serverConnection.read(this.current.buffer.data, this.current.buffer.pos, bytesToRead);
|
||||
|
||||
this.current.bytesReadSoFar += bytesToRead;
|
||||
this.current.buffer.pos += bytesToRead;
|
||||
if (this.current.buffer.pos == bytesWanted) {
|
||||
this.pendingItems.remove(this.current);
|
||||
this.current.setLoaded();
|
||||
this.current = null;
|
||||
} else if (this.current.bytesReadSoFar == 512) {
|
||||
this.current.bytesReadSoFar = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} catch (final IOException e) {
|
||||
this.serverConnection.close();
|
||||
this.serverConnection = null;
|
||||
//noinspection NonAtomicOperationOnVolatileField
|
||||
++this.failureCount;
|
||||
this.errorCode = ErrorCode.PROTOCOL_ERROR;
|
||||
return this.queueSize() == 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void handshake1() {
|
||||
if (this.serverConnection != null) {
|
||||
try {
|
||||
this.c2sPacket.pos = 0;
|
||||
this.c2sPacket.writeByte(6);
|
||||
this.c2sPacket.writeI24(3);
|
||||
this.c2sPacket.writeShort(0);
|
||||
this.serverConnection.write(this.c2sPacket.data, this.c2sPacket.data.length);
|
||||
} catch (final IOException var5) {
|
||||
try {
|
||||
this.serverConnection.close();
|
||||
} catch (final Exception e) {}
|
||||
|
||||
//noinspection NonAtomicOperationOnVolatileField
|
||||
++this.failureCount;
|
||||
this.serverConnection = null;
|
||||
this.errorCode = ErrorCode.PROTOCOL_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handshake2() {
|
||||
if (this.serverConnection != null) {
|
||||
try {
|
||||
this.c2sPacket.pos = 0;
|
||||
this.c2sPacket.writeByte(3);
|
||||
this.c2sPacket.writeI40(0L);
|
||||
this.serverConnection.write(this.c2sPacket.data, this.c2sPacket.data.length);
|
||||
} catch (final IOException var6) {
|
||||
try {
|
||||
this.serverConnection.close();
|
||||
} catch (final Exception e) {}
|
||||
|
||||
//noinspection NonAtomicOperationOnVolatileField
|
||||
++this.failureCount;
|
||||
this.errorCode = ErrorCode.PROTOCOL_ERROR;
|
||||
this.serverConnection = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
57
src/main/java/funorb/cache/ResourceDirectory.java
vendored
Normal file
57
src/main/java/funorb/cache/ResourceDirectory.java
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
package funorb.cache;
|
||||
|
||||
import funorb.Strings;
|
||||
|
||||
public final class ResourceDirectory {
|
||||
private final int[] data;
|
||||
|
||||
public ResourceDirectory(final int[] var1) {
|
||||
int var2 = 1;
|
||||
while (var2 <= var1.length + (var1.length >> 1)) {
|
||||
var2 <<= 1;
|
||||
}
|
||||
|
||||
this.data = new int[var2 + var2];
|
||||
|
||||
for (int var3 = 0; var3 < var2 + var2; ++var3) {
|
||||
this.data[var3] = -1;
|
||||
}
|
||||
|
||||
for (int var3 = 0; var1.length > var3; var3++) {
|
||||
int var4 = var1[var3] & (var2 - 1);
|
||||
while (this.data[1 + var4 + var4] != -1) {
|
||||
var4 = (var2 - 1) & (var4 + 1);
|
||||
}
|
||||
|
||||
this.data[var4 + var4] = var1[var3];
|
||||
this.data[1 + var4 + var4] = var3;
|
||||
}
|
||||
}
|
||||
|
||||
private static int resourceKeyHash(final CharSequence key) {
|
||||
int hash = 0;
|
||||
for (int var4 = 0; var4 < key.length(); ++var4) {
|
||||
hash = Strings.encode1252Char(key.charAt(var4)) + (hash << 5) - hash;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
public int lookup(final String key) {
|
||||
final int hash = resourceKeyHash(key.toLowerCase());
|
||||
final int var3 = (this.data.length / 2) - 1;
|
||||
|
||||
int var4 = var3 & hash;
|
||||
while (true) {
|
||||
final int var5 = this.data[1 + var4 + var4];
|
||||
if (var5 == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (this.data[var4 + var4] == hash) {
|
||||
return var5;
|
||||
}
|
||||
|
||||
var4 = var4 + 1 & var3;
|
||||
}
|
||||
}
|
||||
}
|
472
src/main/java/funorb/cache/ResourceLoader.java
vendored
Normal file
472
src/main/java/funorb/cache/ResourceLoader.java
vendored
Normal file
@ -0,0 +1,472 @@
|
||||
package funorb.cache;
|
||||
|
||||
import funorb.io.Buffer;
|
||||
import funorb.io.ByteContainer;
|
||||
import funorb.io.DirectByteContainer;
|
||||
import funorb.shatteredplans.CacheFiles;
|
||||
import org.intellij.lang.annotations.MagicConstant;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public final class ResourceLoader {
|
||||
public static ResourceLoader COMMON_STRINGS;
|
||||
public static ResourceLoader COMMON_SPRITES;
|
||||
public static ResourceLoader COMMON_FONTS;
|
||||
public static ResourceLoader HUFFMAN_CODES;
|
||||
public static ResourceLoader SHATTERED_PLANS_STRINGS_1;
|
||||
public static ResourceLoader SHATTERED_PLANS_SPRITES;
|
||||
public static ResourceLoader SHATTERED_PLANS_JPEGS;
|
||||
public static ResourceLoader SHATTERED_PLANS_FONTS;
|
||||
public static ResourceLoader SHATTERED_PLANS_SFX_1;
|
||||
public static ResourceLoader SHATTERED_PLANS_SFX_2;
|
||||
public static ResourceLoader SHATTERED_PLANS_MUSIC_1;
|
||||
public static ResourceLoader SHATTERED_PLANS_MUSIC_2;
|
||||
public static ResourceLoader SHATTERED_PLANS_STRINGS_2;
|
||||
public static ResourceLoader QUICK_CHAT_DATA;
|
||||
public static ResourceLoader JAGEX_LOGO_ANIMATION;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public static final class PageId {
|
||||
public static final int COMMON_STRINGS = 0;
|
||||
public static final int COMMON_SPRITES = 1;
|
||||
public static final int COMMON_FONTS = 2;
|
||||
public static final int HUFFMAN_CODES = 3;
|
||||
public static final int SHATTERED_PLANS_STRINGS_1 = 4;
|
||||
public static final int SHATTERED_PLANS_SPRITES = 5;
|
||||
public static final int SHATTERED_PLANS_JPEGS = 6;
|
||||
public static final int SHATTERED_PLANS_FONTS = 7;
|
||||
public static final int SHATTERED_PLANS_SFX_1 = 8;
|
||||
public static final int SHATTERED_PLANS_SFX_2 = 9;
|
||||
public static final int SHATTERED_PLANS_MUSIC_1 = 10;
|
||||
public static final int SHATTERED_PLANS_MUSIC_2 = 11;
|
||||
public static final int SHATTERED_PLANS_STRINGS_2 = 12;
|
||||
public static final int QUICK_CHAT_DATA = 13;
|
||||
public static final int JAGEX_LOGO_ANIMATION = 14;
|
||||
public static final int INDEX = 255;
|
||||
}
|
||||
|
||||
public static BufferedCacheFile bufferedCacheDat2;
|
||||
public static BufferedCacheFile[] bufferedCacheFiles;
|
||||
|
||||
private final PageLoader pageLoader;
|
||||
public boolean releaseGroupsOnGet;
|
||||
public boolean releaseItemsOnGet;
|
||||
private Object[] loadedGroupData;
|
||||
private Object[][] loadedItems;
|
||||
private PageIndex index;
|
||||
|
||||
private ResourceLoader(final PageLoader pageLoader, final boolean releaseItemsOnGet) {
|
||||
this.releaseItemsOnGet = releaseItemsOnGet;
|
||||
this.releaseGroupsOnGet = true;
|
||||
this.pageLoader = pageLoader;
|
||||
}
|
||||
|
||||
public static ResourceLoader create(final MasterIndexLoader masterIndexLoader,
|
||||
final CacheFiles cacheFiles,
|
||||
@MagicConstant(valuesFromClass = PageId.class) final int pageId) {
|
||||
return create(cacheFiles, masterIndexLoader, pageId, true);
|
||||
}
|
||||
|
||||
public static ResourceLoader create(final CacheFiles cacheFiles,
|
||||
final MasterIndexLoader masterIndexLoader,
|
||||
@MagicConstant(valuesFromClass = PageId.class) final int pageId,
|
||||
final boolean releaseItemsOnGet) {
|
||||
try {
|
||||
BufferedPageCache masterIndexCache = null;
|
||||
if (bufferedCacheDat2 == null) {
|
||||
bufferedCacheDat2 = new BufferedCacheFile(cacheFiles.data, 5200);
|
||||
masterIndexCache = new BufferedPageCache(PageId.INDEX, bufferedCacheDat2, new BufferedCacheFile(cacheFiles.masterIndex, 12000));
|
||||
}
|
||||
|
||||
if (bufferedCacheFiles == null) {
|
||||
bufferedCacheFiles = new BufferedCacheFile[cacheFiles.indexes.length];
|
||||
}
|
||||
if (bufferedCacheFiles[pageId] == null) {
|
||||
bufferedCacheFiles[pageId] = new BufferedCacheFile(cacheFiles.indexes[pageId], 12000);
|
||||
}
|
||||
final BufferedPageCache pageCache = new BufferedPageCache(pageId, bufferedCacheDat2, bufferedCacheFiles[pageId]);
|
||||
|
||||
final PageLoader entry = masterIndexLoader.getPageLoader(pageId, masterIndexCache, pageCache);
|
||||
return new ResourceLoader(entry, releaseItemsOnGet);
|
||||
} catch (final IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
//<editor-fold desc="Byte containers">
|
||||
private static byte[] asBytes(final Object o) {
|
||||
if (o == null) {
|
||||
return null;
|
||||
} else if (o instanceof byte[] bs) {
|
||||
return bs;
|
||||
} else if (o instanceof ByteContainer bc) {
|
||||
return bc.toByteArray();
|
||||
} else {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
|
||||
private static Object questionablyOptimizeBytes(final byte[] bs) {
|
||||
if (bs == null) {
|
||||
return null;
|
||||
} else if (bs.length <= 136) {
|
||||
return bs;
|
||||
} else {
|
||||
final DirectByteContainer bc = new DirectByteContainer();
|
||||
bc.put(bs);
|
||||
return bc;
|
||||
}
|
||||
}
|
||||
//</editor-fold>
|
||||
|
||||
//<editor-fold desc="Load progress">
|
||||
public synchronized boolean isIndexLoaded() {
|
||||
if (this.index == null) {
|
||||
this.index = this.pageLoader.tryGetOrCreateIndex();
|
||||
if (this.index == null) {
|
||||
return false;
|
||||
}
|
||||
this.loadedGroupData = new Object[this.index.groupCount];
|
||||
this.loadedItems = new Object[this.index.groupCount][];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public synchronized int percentLoaded() {
|
||||
if (!this.isIndexLoaded()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int loadedSoFar = 0;
|
||||
int totalNeeded = 0;
|
||||
for (int i = 0; i < this.loadedGroupData.length; ++i) {
|
||||
if (this.index.itemCounts[i] > 0) {
|
||||
loadedSoFar += this.percentLoaded(i);
|
||||
totalNeeded += 100;
|
||||
}
|
||||
}
|
||||
|
||||
if (totalNeeded == 0) {
|
||||
return 100;
|
||||
} else {
|
||||
return loadedSoFar * 100 / totalNeeded;
|
||||
}
|
||||
}
|
||||
public int percentLoaded(final String group) {
|
||||
if (this.isIndexLoaded()) {
|
||||
return this.percentLoaded(this.index.groupDirectory.lookup(group));
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized int percentLoaded(final int groupId) {
|
||||
if (!this.hasGroup(groupId)) {
|
||||
return 0;
|
||||
} else if (this.loadedGroupData[groupId] == null) {
|
||||
return this.pageLoader.percentLoaded(groupId);
|
||||
} else {
|
||||
return 100;
|
||||
}
|
||||
}
|
||||
//</editor-fold>
|
||||
|
||||
//<editor-fold desc="Querying the directory">
|
||||
public int groupCount() {
|
||||
return this.isIndexLoaded() ? this.index.groupSizes.length : -1;
|
||||
}
|
||||
|
||||
public int itemCount(final int groupId) {
|
||||
if (this.hasGroup(groupId)) {
|
||||
return this.index.groupSizes[groupId];
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
public int lookupGroup(final String group) {
|
||||
if (this.isIndexLoaded()) {
|
||||
final int var3 = this.index.groupDirectory.lookup(group);
|
||||
return this.hasGroup(var3) ? var3 : -1;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public int lookupItem(final int groupId, final String item) {
|
||||
if (!this.hasGroup(groupId)) {
|
||||
return -1;
|
||||
}
|
||||
final int itemId = this.index.itemDirectories[groupId].lookup(item);
|
||||
if (!this.hasResource(groupId, itemId)) {
|
||||
return -1;
|
||||
}
|
||||
return itemId;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"BooleanMethodIsAlwaysInverted", "SameParameterValue"})
|
||||
public boolean hasGroup(final String groupName) {
|
||||
return this.isIndexLoaded() && this.index.groupDirectory.lookup(groupName) >= 0;
|
||||
}
|
||||
|
||||
private synchronized boolean hasGroup(final int groupId) {
|
||||
return this.isIndexLoaded() && groupId >= 0 && groupId < this.index.groupSizes.length && this.index.groupSizes[groupId] != 0;
|
||||
}
|
||||
|
||||
private synchronized boolean hasResource(final int groupId, final int itemId) {
|
||||
return this.isIndexLoaded() && groupId >= 0 && itemId >= 0 && groupId < this.index.groupSizes.length && itemId < this.index.groupSizes[groupId];
|
||||
}
|
||||
|
||||
@SuppressWarnings({"BooleanMethodIsAlwaysInverted", "SameParameterValue"})
|
||||
public boolean hasResource(final String group, final String item) {
|
||||
if (this.isIndexLoaded()) {
|
||||
final int groupId = this.index.groupDirectory.lookup(group);
|
||||
if (groupId < 0) {
|
||||
return false;
|
||||
} else {
|
||||
final int itemId = this.index.itemDirectories[groupId].lookup(item);
|
||||
return itemId >= 0;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
//</editor-fold>
|
||||
|
||||
//<editor-fold desc="Loading resources">
|
||||
public synchronized boolean loadAllGroups() {
|
||||
if (!this.isIndexLoaded()) {
|
||||
return false;
|
||||
}
|
||||
boolean allLoaded = true;
|
||||
for (int i = 0; i < this.index.groupIndexes.length; ++i) {
|
||||
final int j = this.index.groupIndexes[i];
|
||||
if (this.loadedGroupData[j] == null) {
|
||||
this.doLoadGroupData(j);
|
||||
if (this.loadedGroupData[j] == null) {
|
||||
allLoaded = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return allLoaded;
|
||||
}
|
||||
|
||||
public boolean loadGroupData(final String group) {
|
||||
if (this.isIndexLoaded()) {
|
||||
return this.loadGroupData(this.index.groupDirectory.lookup(group));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized boolean loadGroupData(final int groupId) {
|
||||
if (!this.hasGroup(groupId)) {
|
||||
return false;
|
||||
} else if (this.loadedGroupData[groupId] == null) {
|
||||
this.doLoadGroupData(groupId);
|
||||
return this.loadedGroupData[groupId] != null;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
public void loadGroupDataForItem(final String group, final String item) {
|
||||
if (this.isIndexLoaded()) {
|
||||
final int groupId = this.index.groupDirectory.lookup(group);
|
||||
if (this.hasGroup(groupId)) {
|
||||
final int itemId = this.index.itemDirectories[groupId].lookup(item);
|
||||
this.loadGroupDataForItem(groupId, itemId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void loadGroupDataForItem(final int groupId, final int itemId) {
|
||||
if (this.hasResource(groupId, itemId) &&
|
||||
(this.loadedItems[groupId] == null || this.loadedItems[groupId][itemId] == null) &&
|
||||
this.loadedGroupData[groupId] == null) {
|
||||
this.doLoadGroupData(groupId);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized byte[] getResource(final String group, final String item) {
|
||||
if (!this.isIndexLoaded()) {
|
||||
return null;
|
||||
}
|
||||
final int groupId = this.index.groupDirectory.lookup(group);
|
||||
if (!this.hasGroup(groupId)) {
|
||||
return null;
|
||||
}
|
||||
final int itemId = this.index.itemDirectories[groupId].lookup(item);
|
||||
return this.getResource(groupId, itemId);
|
||||
}
|
||||
|
||||
public byte[] getResource(final int groupId, final int itemId) {
|
||||
synchronized (this) {
|
||||
if (!this.hasResource(groupId, itemId)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
byte[] data = null;
|
||||
if (this.loadedItems[groupId] == null || this.loadedItems[groupId][itemId] == null) {
|
||||
if (!this.tryLoadGroupItems(groupId)) {
|
||||
this.doLoadGroupData(groupId);
|
||||
if (!this.tryLoadGroupItems(groupId)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.loadedItems[groupId] == null) {
|
||||
throw new RuntimeException("");
|
||||
}
|
||||
|
||||
if (this.loadedItems[groupId][itemId] != null) {
|
||||
data = asBytes(this.loadedItems[groupId][itemId]);
|
||||
if (data == null) {
|
||||
throw new RuntimeException("");
|
||||
}
|
||||
}
|
||||
|
||||
if (data != null) {
|
||||
if (this.releaseItemsOnGet) {
|
||||
this.loadedItems[groupId][itemId] = null;
|
||||
if (this.index.groupSizes[groupId] == 1) {
|
||||
this.loadedItems[groupId] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized byte[] getSingletonResource(final int id) {
|
||||
if (!this.isIndexLoaded()) {
|
||||
return null;
|
||||
} else if (this.index.groupSizes.length == 1) {
|
||||
return this.getResource(0, id);
|
||||
} else if (this.hasGroup(id)) {
|
||||
if (this.index.groupSizes[id] == 1) {
|
||||
return this.getResource(id, 0);
|
||||
} else {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void doLoadGroupData(final int groupId) {
|
||||
if (this.releaseGroupsOnGet) {
|
||||
this.loadedGroupData[groupId] = this.pageLoader.tryGetLoadedData(groupId);
|
||||
} else {
|
||||
this.loadedGroupData[groupId] = questionablyOptimizeBytes(this.pageLoader.tryGetLoadedData(groupId));
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
|
||||
private synchronized boolean tryLoadGroupItems(final int groupId) {
|
||||
if (!this.hasGroup(groupId)) {
|
||||
return false;
|
||||
}
|
||||
if (this.loadedGroupData[groupId] == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final int itemCount = this.index.itemCounts[groupId];
|
||||
final int[] itemIdMap = this.index.itemIdMaps[groupId];
|
||||
if (this.loadedItems[groupId] == null) {
|
||||
this.loadedItems[groupId] = new Object[this.index.groupSizes[groupId]];
|
||||
}
|
||||
|
||||
final Object[] loadedItems = this.loadedItems[groupId];
|
||||
boolean alreadyLoaded = true;
|
||||
for (int i = 0; i < itemCount; ++i) {
|
||||
final int itemId;
|
||||
if (itemIdMap == null) {
|
||||
itemId = i;
|
||||
} else {
|
||||
itemId = itemIdMap[i];
|
||||
}
|
||||
if (loadedItems[itemId] == null) {
|
||||
alreadyLoaded = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!alreadyLoaded) {
|
||||
final byte[] groupData = PageIndex.decompress(asBytes(this.loadedGroupData[groupId]));
|
||||
if (this.releaseGroupsOnGet) {
|
||||
this.loadedGroupData[groupId] = null;
|
||||
}
|
||||
|
||||
if (itemCount > 1) {
|
||||
final int lastPos = groupData.length - 1;
|
||||
final int itemBlocks = groupData[lastPos] & 255;
|
||||
final int lengthsStartPos = lastPos - (4 * itemBlocks * itemCount);
|
||||
final Buffer groupBuffer = new Buffer(groupData);
|
||||
groupBuffer.pos = lengthsStartPos;
|
||||
final int[] itemPosns = new int[itemCount];
|
||||
|
||||
for (int i = 0; i < itemBlocks; ++i) {
|
||||
int var16 = 0;
|
||||
for (int j = 0; j < itemCount; ++j) {
|
||||
var16 += groupBuffer.readInt();
|
||||
itemPosns[j] += var16;
|
||||
}
|
||||
}
|
||||
|
||||
final byte[][] itemData = new byte[itemCount][];
|
||||
|
||||
for (int i = 0; i < itemCount; ++i) {
|
||||
itemData[i] = new byte[itemPosns[i]];
|
||||
itemPosns[i] = 0;
|
||||
}
|
||||
|
||||
groupBuffer.pos = lengthsStartPos;
|
||||
int groupPos = 0;
|
||||
for (int i = 0; i < itemBlocks; ++i) {
|
||||
int len = 0;
|
||||
for (int j = 0; j < itemCount; ++j) {
|
||||
len += groupBuffer.readInt();
|
||||
System.arraycopy(groupData, groupPos, itemData[j], itemPosns[j], len);
|
||||
itemPosns[j] += len;
|
||||
groupPos += len;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < itemCount; ++i) {
|
||||
final int itemId;
|
||||
if (itemIdMap == null) {
|
||||
itemId = i;
|
||||
} else {
|
||||
itemId = itemIdMap[i];
|
||||
}
|
||||
|
||||
if (this.releaseItemsOnGet) {
|
||||
loadedItems[itemId] = itemData[i];
|
||||
} else {
|
||||
loadedItems[itemId] = questionablyOptimizeBytes(itemData[i]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
final int itemId;
|
||||
if (itemIdMap == null) {
|
||||
itemId = 0;
|
||||
} else {
|
||||
itemId = itemIdMap[0];
|
||||
}
|
||||
|
||||
if (this.releaseItemsOnGet) {
|
||||
loadedItems[itemId] = groupData;
|
||||
} else {
|
||||
loadedItems[itemId] = questionablyOptimizeBytes(groupData);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//</editor-fold>
|
||||
}
|
7
src/main/java/funorb/client/AchievementRequest.java
Normal file
7
src/main/java/funorb/client/AchievementRequest.java
Normal file
@ -0,0 +1,7 @@
|
||||
package funorb.client;
|
||||
|
||||
public final class AchievementRequest {
|
||||
public boolean areAchievementsOffline = true;
|
||||
public boolean completed = false;
|
||||
public int unlockedAchievementsBitmap;
|
||||
}
|
7
src/main/java/funorb/client/DisplayMode.java
Normal file
7
src/main/java/funorb/client/DisplayMode.java
Normal file
@ -0,0 +1,7 @@
|
||||
package funorb.client;
|
||||
|
||||
public final class DisplayMode {
|
||||
public int height;
|
||||
public int width;
|
||||
public int bitDepth;
|
||||
}
|
36
src/main/java/funorb/client/EmailLoginCredentials.java
Normal file
36
src/main/java/funorb/client/EmailLoginCredentials.java
Normal file
@ -0,0 +1,36 @@
|
||||
package funorb.client;
|
||||
|
||||
import funorb.client.LoginCredentials;
|
||||
import funorb.io.Buffer;
|
||||
import funorb.shatteredplans.client.AuthMode;
|
||||
import funorb.shatteredplans.client.JagexApplet;
|
||||
|
||||
public final class EmailLoginCredentials extends LoginCredentials {
|
||||
private static final AuthMode emailAuthMode = new AuthMode(AuthMode.EMAIL);
|
||||
private final String email;
|
||||
private final String password;
|
||||
|
||||
public EmailLoginCredentials(final String email, final String password) {
|
||||
this.email = email;
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public static boolean containsPassword(final String message) {
|
||||
if (JagexApplet.lastLoginPassword == null) {
|
||||
return false;
|
||||
} else {
|
||||
return message.toLowerCase().contains(JagexApplet.lastLoginPassword.toLowerCase());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToPacket(final Buffer packet) {
|
||||
JagexApplet.loginPacket.writeNullBracketedString(this.email);
|
||||
JagexApplet.loginPacket.writePasswordHash(this.password);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthMode getAuthMode() {
|
||||
return emailAuthMode;
|
||||
}
|
||||
}
|
6
src/main/java/funorb/client/GetProfileRequest.java
Normal file
6
src/main/java/funorb/client/GetProfileRequest.java
Normal file
@ -0,0 +1,6 @@
|
||||
package funorb.client;
|
||||
|
||||
public final class GetProfileRequest {
|
||||
public byte[] data;
|
||||
public boolean completed;
|
||||
}
|
328
src/main/java/funorb/client/JagexBaseApplet.java
Normal file
328
src/main/java/funorb/client/JagexBaseApplet.java
Normal file
@ -0,0 +1,328 @@
|
||||
package funorb.client;
|
||||
|
||||
import funorb.awt.CanvasScreenBuffer;
|
||||
import funorb.awt.ImageProducerScreenBuffer;
|
||||
import funorb.awt.ScreenBuffer;
|
||||
import funorb.awt.ComponentCanvas;
|
||||
import funorb.shatteredplans.client.FrameClock;
|
||||
import funorb.shatteredplans.client.JagexApplet;
|
||||
import funorb.shatteredplans.client.MessagePumpThread;
|
||||
import funorb.util.PseudoMonotonicClock;
|
||||
|
||||
import java.applet.Applet;
|
||||
import java.awt.Canvas;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.GridLayout;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.FocusListener;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.awt.event.WindowListener;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.net.URL;
|
||||
|
||||
public abstract class JagexBaseApplet extends Applet implements Runnable, FocusListener, WindowListener {
|
||||
protected static final long[] recentFrameTimes = new long[32];
|
||||
protected static JagexBaseApplet instance; // we are a singleton
|
||||
public static Canvas canvas;
|
||||
protected static volatile boolean _ncc = false;
|
||||
protected static boolean hadFocus; // honestly not quite sure how this differs from hasFocus
|
||||
protected static FrameClock frameClock;
|
||||
protected static int framesToAdvance;
|
||||
public static int lastFrameScore = 0; // not entirely sure how the absolute value of this is supposed to be interpreted
|
||||
protected static int[] _f;
|
||||
public static volatile boolean _oqe = true;
|
||||
private static volatile long _pvcm = 0L;
|
||||
public static ScreenBuffer screenBuffer;
|
||||
private static boolean isShutdown = false;
|
||||
private static long shutdownTimestamp = 0L;
|
||||
private static int recentFrameIndex = 0;
|
||||
public int gameCrc;
|
||||
public boolean didHandleError = false;
|
||||
private volatile boolean hasFocus = true;
|
||||
private int canvasSyncTimer = 0;
|
||||
|
||||
protected JagexBaseApplet() {}
|
||||
|
||||
public static JagexBaseApplet getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public static int[] a612(final int[] var0) {
|
||||
final int var1 = var0.length;
|
||||
final int[] var2 = new int[var1];
|
||||
|
||||
int var3 = 0;
|
||||
while (var3 < var1) {
|
||||
var2[var0[var3]] = var3++;
|
||||
}
|
||||
|
||||
return var2;
|
||||
}
|
||||
|
||||
public static void maybeSleep(final long var0) {
|
||||
if (var0 > 0L) {
|
||||
try {
|
||||
Thread.sleep(var0);
|
||||
} catch (final InterruptedException var3) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static ScreenBuffer initializeScreenBuffer(final Component canvas, final int width, final int height) {
|
||||
try {
|
||||
final ScreenBuffer sb = new CanvasScreenBuffer();
|
||||
sb.initialize(canvas, width, height);
|
||||
return sb;
|
||||
} catch (final Throwable e) {
|
||||
final ImageProducerScreenBuffer sb = new ImageProducerScreenBuffer();
|
||||
sb.initialize(canvas, width, height);
|
||||
return sb;
|
||||
}
|
||||
}
|
||||
|
||||
public static AffineTransform getTransform(final Component canvas) {
|
||||
final double scaleX = (double) canvas.getWidth() / JagexApplet.gameWidth;
|
||||
final double scaleY = (double) canvas.getHeight() / JagexApplet.gameHeight;
|
||||
final double scale = Math.min(scaleX, scaleY);
|
||||
|
||||
final double offsetX = (canvas.getWidth() - (JagexApplet.gameWidth * scale)) / 2;
|
||||
final double offsetY = (canvas.getHeight() - (JagexApplet.gameHeight * scale)) / 2;
|
||||
|
||||
final AffineTransform transform = new AffineTransform();
|
||||
transform.translate(offsetX, offsetY);
|
||||
transform.scale(scale, scale);
|
||||
return transform;
|
||||
}
|
||||
|
||||
public static void paint(final Canvas canvas) {
|
||||
try {
|
||||
final Graphics2D graphics = (Graphics2D) canvas.getGraphics();
|
||||
graphics.transform(getTransform(canvas));
|
||||
screenBuffer.paint(graphics);
|
||||
graphics.dispose();
|
||||
} catch (final Exception e) {
|
||||
canvas.repaint();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void start() {
|
||||
if (instance == this && !isShutdown) {
|
||||
shutdownTimestamp = 0L;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void windowActivated(final WindowEvent var1) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void stop() {
|
||||
if (instance == this && !isShutdown) {
|
||||
shutdownTimestamp = PseudoMonotonicClock.currentTimeMillis() + 4000L;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void windowIconified(final WindowEvent var1) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void windowDeiconified(final WindowEvent var1) {
|
||||
}
|
||||
|
||||
protected abstract void tick();
|
||||
|
||||
protected abstract void render();
|
||||
|
||||
@Override
|
||||
public final void update(final Graphics var1) {
|
||||
this.paint(var1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void windowClosing(final WindowEvent var1) {
|
||||
this.destroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void run() {
|
||||
instance.setFocusCycleRoot(true);
|
||||
|
||||
this.initializeCanvas();
|
||||
screenBuffer = initializeScreenBuffer(canvas, JagexApplet.gameWidth, JagexApplet.gameHeight);
|
||||
this.initialize();
|
||||
frameClock = new FrameClock();
|
||||
|
||||
while (shutdownTimestamp == 0L || shutdownTimestamp > PseudoMonotonicClock.currentTimeMillis()) {
|
||||
maybeSleep(frameClock.finishFrame());
|
||||
framesToAdvance = frameClock.advanceFrame();
|
||||
|
||||
for (int i = 0; i < framesToAdvance; ++i) {
|
||||
synchronized (this) {
|
||||
hadFocus = this.hasFocus;
|
||||
}
|
||||
this.tick();
|
||||
}
|
||||
|
||||
this.syncAndRender();
|
||||
MessagePumpThread.instance.postEvent(canvas);
|
||||
}
|
||||
|
||||
this.performShutdown(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void windowOpened(final WindowEvent var1) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String getParameter(final String var1) {
|
||||
return super.getParameter(var1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void focusLost(final FocusEvent var1) {
|
||||
this.hasFocus = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void windowClosed(final WindowEvent var1) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public final synchronized void paint(final Graphics var1) {
|
||||
if (instance == this && !isShutdown) {
|
||||
_oqe = true;
|
||||
if (PseudoMonotonicClock.currentTimeMillis() - _pvcm > 1000L) {
|
||||
final Rectangle var2 = var1.getClipBounds();
|
||||
if (var2 == null || var2.width >= JagexApplet.gameWidth && var2.height >= JagexApplet.gameHeight) {
|
||||
_ncc = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract void init();
|
||||
|
||||
public final void redirectToErrorPage(final String which) {
|
||||
if (!this.didHandleError) {
|
||||
this.didHandleError = true;
|
||||
System.out.println("error_game_" + which);
|
||||
|
||||
try {
|
||||
throw new NullPointerException("no Applet#getWindow anymore");
|
||||
} catch (final Throwable var5) {
|
||||
}
|
||||
try {
|
||||
this.getAppletContext().showDocument(new URL(this.getCodeBase(), "error_game_" + which + ".ws"), "_top");
|
||||
} catch (final Exception var4) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void initialize();
|
||||
|
||||
private void syncAndRender() {
|
||||
final long now = PseudoMonotonicClock.currentTimeMillis();
|
||||
final long lastFrameTime = recentFrameTimes[recentFrameIndex];
|
||||
recentFrameTimes[recentFrameIndex] = now;
|
||||
recentFrameIndex = (recentFrameIndex + 1) % recentFrameTimes.length;
|
||||
if (lastFrameTime != 0L && lastFrameTime < now) {
|
||||
final int lastFrameDuration = (int) (now - lastFrameTime);
|
||||
lastFrameScore = ((lastFrameDuration / 2) + 32000) / lastFrameDuration;
|
||||
}
|
||||
|
||||
if (--this.canvasSyncTimer <= 0) {
|
||||
this.canvasSyncTimer = 50;
|
||||
_oqe = true;
|
||||
canvas.setSize(instance.getSize());
|
||||
canvas.setVisible(true);
|
||||
canvas.setLocation(0, 0);
|
||||
}
|
||||
|
||||
this.render();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void destroy() {
|
||||
if (this == instance && !isShutdown) {
|
||||
shutdownTimestamp = PseudoMonotonicClock.currentTimeMillis();
|
||||
maybeSleep(5000L);
|
||||
MessagePumpThread.instance = null;
|
||||
this.performShutdown(false);
|
||||
}
|
||||
}
|
||||
|
||||
private void performShutdown(final boolean isClean) {
|
||||
synchronized (this) {
|
||||
if (isShutdown) {
|
||||
return;
|
||||
}
|
||||
|
||||
isShutdown = true;
|
||||
}
|
||||
|
||||
try {
|
||||
this.shutdown();
|
||||
} catch (final Exception var8) {
|
||||
}
|
||||
|
||||
if (canvas != null) {
|
||||
try {
|
||||
canvas.removeFocusListener(this);
|
||||
canvas.getParent().remove(canvas);
|
||||
} catch (final Exception var7) {
|
||||
}
|
||||
}
|
||||
|
||||
if (MessagePumpThread.instance != null) {
|
||||
try {
|
||||
MessagePumpThread.instance.shutdown();
|
||||
} catch (final Exception var6) {
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("Shutdown complete - clean:" + isClean);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void windowDeactivated(final WindowEvent var1) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void focusGained(final FocusEvent var1) {
|
||||
this.hasFocus = true;
|
||||
_oqe = true;
|
||||
}
|
||||
|
||||
protected abstract void shutdown();
|
||||
|
||||
protected final synchronized void initializeCanvas() {
|
||||
if (canvas != null) {
|
||||
canvas.removeFocusListener(this);
|
||||
canvas.getParent().setBackground(Color.black);
|
||||
canvas.getParent().remove(canvas);
|
||||
}
|
||||
|
||||
instance.setLayout(new GridLayout());
|
||||
canvas = new ComponentCanvas(this);
|
||||
instance.add(canvas);
|
||||
canvas.setVisible(true);
|
||||
canvas.setLocation(0, 0);
|
||||
canvas.addFocusListener(this);
|
||||
canvas.requestFocus();
|
||||
|
||||
hadFocus = true;
|
||||
this.hasFocus = true;
|
||||
|
||||
_oqe = true;
|
||||
_ncc = false;
|
||||
_pvcm = PseudoMonotonicClock.currentTimeMillis();
|
||||
}
|
||||
}
|
13
src/main/java/funorb/client/LoginCredentials.java
Normal file
13
src/main/java/funorb/client/LoginCredentials.java
Normal file
@ -0,0 +1,13 @@
|
||||
package funorb.client;
|
||||
|
||||
import funorb.io.Buffer;
|
||||
import funorb.shatteredplans.client.AuthMode;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
|
||||
public abstract class LoginCredentials {
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
public abstract void writeToPacket(Buffer packet);
|
||||
|
||||
@Contract(pure = true)
|
||||
public abstract AuthMode getAuthMode();
|
||||
}
|
15
src/main/java/funorb/client/LoginState.java
Normal file
15
src/main/java/funorb/client/LoginState.java
Normal file
@ -0,0 +1,15 @@
|
||||
package funorb.client;
|
||||
|
||||
public enum LoginState {
|
||||
C1,
|
||||
LOGGED_IN,
|
||||
C3,
|
||||
C4,
|
||||
SERVER_HANDSHAKE_FAILED,
|
||||
C6,
|
||||
READY_TO_LOG_IN,
|
||||
LOGIN_REQUEST_SUCCESSFUL,
|
||||
LOGIN_REQUEST_SENT,
|
||||
C10,
|
||||
SERVER_HANDSHAKE_SUCCESS
|
||||
}
|
129
src/main/java/funorb/client/MenuInputState.java
Normal file
129
src/main/java/funorb/client/MenuInputState.java
Normal file
@ -0,0 +1,129 @@
|
||||
package funorb.client;
|
||||
|
||||
import funorb.awt.KeyState;
|
||||
import funorb.awt.MouseState;
|
||||
import funorb.shatteredplans.client.JagexApplet;
|
||||
|
||||
public final class MenuInputState {
|
||||
public int itemCount;
|
||||
public int selectedItem = 0;
|
||||
|
||||
private boolean isMouseSelection = false;
|
||||
private int lastTypedKeyCode;
|
||||
private int mouseButtonDown;
|
||||
private int mouseButtonJustClicked;
|
||||
private int mouseButtonJustClickedOrRepeated;
|
||||
private int mouseClickRepeatCounter;
|
||||
|
||||
public MenuInputState(final int itemCount) {
|
||||
this.itemCount = itemCount;
|
||||
}
|
||||
|
||||
public void setSelectedItem(final int mouseItem, final int keyboardItem, final boolean isMouseSelection) {
|
||||
this.mouseButtonDown = 0;
|
||||
this.isMouseSelection = isMouseSelection;
|
||||
if (this.isMouseSelection) {
|
||||
this.selectedItem = mouseItem;
|
||||
} else {
|
||||
this.selectedItem = keyboardItem;
|
||||
}
|
||||
}
|
||||
|
||||
public void processKeyInputVertical() {
|
||||
this.processKeyInput(KeyState.Code.UP, KeyState.Code.DOWN);
|
||||
}
|
||||
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
private void processKeyInput(final int prevCode, final int nextCode) {
|
||||
this.lastTypedKeyCode = 0;
|
||||
this.mouseButtonJustClickedOrRepeated = 0;
|
||||
this.mouseButtonJustClicked = 0;
|
||||
|
||||
if (this.mouseButtonDown == 0) {
|
||||
this.lastTypedKeyCode = JagexApplet.lastTypedKeyCode;
|
||||
if (this.lastTypedKeyCode == prevCode) {
|
||||
this.isMouseSelection = false;
|
||||
if (this.selectedItem <= 0) {
|
||||
this.selectedItem = this.itemCount;
|
||||
}
|
||||
--this.selectedItem;
|
||||
} else if (this.lastTypedKeyCode == nextCode) {
|
||||
this.isMouseSelection = false;
|
||||
++this.selectedItem;
|
||||
if (this.selectedItem >= this.itemCount) {
|
||||
this.selectedItem = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isHomeTyped() {
|
||||
return this.lastTypedKeyCode == KeyState.Code.HOME;
|
||||
}
|
||||
|
||||
public boolean isEndTyped() {
|
||||
return this.lastTypedKeyCode == KeyState.Code.END;
|
||||
}
|
||||
|
||||
public boolean isLeftTyped() {
|
||||
return this.lastTypedKeyCode == KeyState.Code.LEFT;
|
||||
}
|
||||
|
||||
public boolean isRightTyped() {
|
||||
return this.lastTypedKeyCode == KeyState.Code.RIGHT;
|
||||
}
|
||||
|
||||
public void processMouseInput(final int hoveredItem, final int clickedItem) {
|
||||
if (hoveredItem >= this.itemCount) {
|
||||
throw new IndexOutOfBoundsException("hovered item is not in range [0," + this.itemCount + "): " + hoveredItem);
|
||||
}
|
||||
if (clickedItem >= this.itemCount) {
|
||||
throw new IndexOutOfBoundsException("clicked item is not in range [0," + this.itemCount + "): " + clickedItem);
|
||||
}
|
||||
|
||||
this.lastTypedKeyCode = 0;
|
||||
this.mouseButtonJustClickedOrRepeated = 0;
|
||||
this.mouseButtonJustClicked = 0;
|
||||
if (JagexApplet.mouseButtonJustClicked != MouseState.Button.NONE) {
|
||||
this.mouseClickRepeatCounter = 20;
|
||||
this.selectedItem = clickedItem;
|
||||
this.mouseButtonJustClicked = this.mouseButtonJustClickedOrRepeated = JagexApplet.mouseButtonJustClicked;
|
||||
this.mouseButtonDown = JagexApplet.mouseButtonJustClicked;
|
||||
this.isMouseSelection = true;
|
||||
}
|
||||
|
||||
if (this.mouseButtonDown != 0 && JagexApplet.mouseButtonDown != MouseState.Button.NONE) {
|
||||
if (this.mouseClickRepeatCounter <= 0) {
|
||||
this.mouseClickRepeatCounter = 4;
|
||||
this.mouseButtonJustClickedOrRepeated = this.mouseButtonDown;
|
||||
}
|
||||
--this.mouseClickRepeatCounter;
|
||||
}
|
||||
|
||||
if (JagexApplet.mouseButtonJustClicked == MouseState.Button.NONE
|
||||
&& JagexApplet.mouseButtonDown == MouseState.Button.NONE) {
|
||||
this.mouseButtonDown = 0;
|
||||
}
|
||||
|
||||
if (this.mouseButtonDown == 0 && (this.isMouseSelection || JagexApplet.mouseEventReceived)) {
|
||||
if (hoveredItem >= 0) {
|
||||
this.selectedItem = hoveredItem;
|
||||
this.isMouseSelection = true;
|
||||
} else if (this.isMouseSelection) {
|
||||
this.selectedItem = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isMouseButtonDown() {
|
||||
return this.mouseButtonDown != 0;
|
||||
}
|
||||
|
||||
public boolean isItemActive() {
|
||||
return this.mouseButtonJustClicked != 0 || this.lastTypedKeyCode == KeyState.Code.ENTER || this.lastTypedKeyCode == KeyState.Code.SPACE;
|
||||
}
|
||||
|
||||
public boolean isItemActiveAllowRepeat() {
|
||||
return this.mouseButtonJustClickedOrRepeated != 0 || this.lastTypedKeyCode == KeyState.Code.ENTER || this.lastTypedKeyCode == KeyState.Code.SPACE;
|
||||
}
|
||||
}
|
13
src/main/java/funorb/client/RankingsRequest.java
Normal file
13
src/main/java/funorb/client/RankingsRequest.java
Normal file
@ -0,0 +1,13 @@
|
||||
package funorb.client;
|
||||
|
||||
public final class RankingsRequest {
|
||||
public int[][] _m;
|
||||
public String[][] _n;
|
||||
public int _r;
|
||||
public int _h;
|
||||
public boolean _q;
|
||||
public int _k;
|
||||
public int _i;
|
||||
public int _j;
|
||||
public int _l;
|
||||
}
|
125
src/main/java/funorb/client/ReflectionRequest.java
Normal file
125
src/main/java/funorb/client/ReflectionRequest.java
Normal file
@ -0,0 +1,125 @@
|
||||
package funorb.client;
|
||||
|
||||
import funorb.io.CipheredBuffer;
|
||||
import funorb.shatteredplans.client.MailboxMessage;
|
||||
import funorb.shatteredplans.client.MessagePumpThread;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Queue;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public final class ReflectionRequest {
|
||||
public static Queue<ReflectionRequest> pending = new ArrayDeque<>();
|
||||
|
||||
public final int id;
|
||||
public final int messageCount;
|
||||
public final int[] types;
|
||||
public final int[] statusCodes;
|
||||
public final MailboxMessage[] fieldMessages;
|
||||
public final int[] fieldValues;
|
||||
public final MailboxMessage[] methodMessages;
|
||||
public final byte[][][] serializedParams;
|
||||
|
||||
private ReflectionRequest(final int id, final int messageCount) {
|
||||
this.id = id;
|
||||
this.messageCount = messageCount;
|
||||
this.types = new int[this.messageCount];
|
||||
this.statusCodes = new int[this.messageCount];
|
||||
this.fieldMessages = new MailboxMessage[this.messageCount];
|
||||
this.fieldValues = new int[this.messageCount];
|
||||
this.methodMessages = new MailboxMessage[this.messageCount];
|
||||
this.serializedParams = new byte[this.messageCount][][];
|
||||
}
|
||||
|
||||
public static void recieve(final MessagePumpThread messagePumpThread, @SuppressWarnings("SameParameterValue") final CipheredBuffer packet) {
|
||||
final int messageCount = packet.readUByte();
|
||||
final int id = packet.readInt();
|
||||
final ReflectionRequest req = new ReflectionRequest(id, messageCount);
|
||||
|
||||
for (int i = 0; i < req.messageCount; ++i) {
|
||||
try {
|
||||
final int type = packet.readUByte();
|
||||
if (type == 0 || type == 1 || type == 2) {
|
||||
final String className = packet.readNullTerminatedString();
|
||||
final String fieldName = packet.readNullTerminatedString();
|
||||
final int fieldValue = type == 1 ? packet.readInt() : 0;
|
||||
|
||||
req.types[i] = type;
|
||||
req.fieldValues[i] = fieldValue;
|
||||
req.fieldMessages[i] = messagePumpThread.sendGetDeclaredFieldMessage(classForName(className), fieldName);
|
||||
} else if (type == 3 || type == 4) {
|
||||
final String className = packet.readNullTerminatedString();
|
||||
final String methodName = packet.readNullTerminatedString();
|
||||
|
||||
final int var9 = packet.readUByte();
|
||||
final String[] paramTypeNames = IntStream.range(0, var9)
|
||||
.mapToObj(j -> packet.readNullTerminatedString())
|
||||
.toArray(String[]::new);
|
||||
|
||||
final byte[][] serializedObjects = new byte[var9][];
|
||||
if (type == 3) {
|
||||
for (int j = 0; j < var9; ++j) {
|
||||
final int objectLen = packet.readInt();
|
||||
serializedObjects[j] = new byte[objectLen];
|
||||
packet.readBytes(serializedObjects[j], objectLen);
|
||||
}
|
||||
}
|
||||
|
||||
req.types[i] = type;
|
||||
final Class<?>[] paramTypes = new Class[var9];
|
||||
for (int var13 = 0; var13 < var9; ++var13) {
|
||||
paramTypes[var13] = classForName(paramTypeNames[var13]);
|
||||
}
|
||||
|
||||
req.methodMessages[i] = messagePumpThread.sendGetDeclaredMethodMessage(classForName(className), methodName, paramTypes);
|
||||
req.serializedParams[i] = serializedObjects;
|
||||
}
|
||||
} catch (final ClassNotFoundException e) {
|
||||
req.statusCodes[i] = Status.CLASS_NOT_FOUND;
|
||||
} catch (final SecurityException e) {
|
||||
req.statusCodes[i] = Status.SECURITY_EXCEPTION;
|
||||
} catch (final NullPointerException e) {
|
||||
req.statusCodes[i] = Status.NULL_POINTER_EXCEPTION;
|
||||
} catch (final Exception e) {
|
||||
req.statusCodes[i] = Status.OTHER_EXCEPTION;
|
||||
} catch (final Throwable e) {
|
||||
req.statusCodes[i] = Status.OTHER_THROWABLE;
|
||||
}
|
||||
}
|
||||
|
||||
pending.add(req);
|
||||
}
|
||||
|
||||
private static Class<?> classForName(final String name) throws ClassNotFoundException {
|
||||
return switch (name) {
|
||||
case "B" -> Byte.TYPE;
|
||||
case "C" -> Character.TYPE;
|
||||
case "D" -> Double.TYPE;
|
||||
case "F" -> Float.TYPE;
|
||||
case "I" -> Integer.TYPE;
|
||||
case "J" -> Long.TYPE;
|
||||
case "S" -> Short.TYPE;
|
||||
case "Z" -> Boolean.TYPE;
|
||||
default -> Class.forName(name);
|
||||
};
|
||||
}
|
||||
|
||||
public static final class Type {
|
||||
public static final int STATIC_FIELD_GET = 0;
|
||||
public static final int STATIC_FIELD_SET = 1;
|
||||
public static final int FIELD_GET_MODIFIERS = 2;
|
||||
public static final int METHOD_INVOKE = 3;
|
||||
public static final int METHOD_GET_MODIFIERS = 4;
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public static final class Status {
|
||||
public static final int OK = 0;
|
||||
public static final int CLASS_NOT_FOUND = -1;
|
||||
public static final int SECURITY_EXCEPTION = -2;
|
||||
public static final int NULL_POINTER_EXCEPTION = -3;
|
||||
public static final int OTHER_EXCEPTION = -4;
|
||||
public static final int OTHER_THROWABLE = -5;
|
||||
}
|
||||
}
|
10
src/main/java/funorb/client/SetProfileRequest.java
Normal file
10
src/main/java/funorb/client/SetProfileRequest.java
Normal file
@ -0,0 +1,10 @@
|
||||
package funorb.client;
|
||||
|
||||
public final class SetProfileRequest {
|
||||
public final byte[] data;
|
||||
public int digest;
|
||||
|
||||
public SetProfileRequest(final byte[] data) {
|
||||
this.data = data;
|
||||
}
|
||||
}
|
84
src/main/java/funorb/client/TemplateDictionary.java
Normal file
84
src/main/java/funorb/client/TemplateDictionary.java
Normal file
@ -0,0 +1,84 @@
|
||||
package funorb.client;
|
||||
|
||||
public final class TemplateDictionary {
|
||||
private final TemplateDictionary next;
|
||||
private Entry entry;
|
||||
|
||||
public TemplateDictionary() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
public TemplateDictionary(final TemplateDictionary var1) {
|
||||
this.next = var1;
|
||||
}
|
||||
|
||||
private String get(final String key) {
|
||||
for (Entry entry = this.entry; entry != null; entry = entry.next) {
|
||||
if (key.equals(entry.key)) {
|
||||
return entry.value;
|
||||
}
|
||||
}
|
||||
if (this.next == null) {
|
||||
return null;
|
||||
} else {
|
||||
return this.next.get(key);
|
||||
}
|
||||
}
|
||||
|
||||
public void put(final String key, final String value) {
|
||||
for (Entry entry = this.entry; entry != null; entry = entry.next) {
|
||||
if (key.equals(entry.key)) {
|
||||
entry.value = value;
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.entry = new Entry(key, value, this.entry);
|
||||
}
|
||||
|
||||
public String expand(final String template) {
|
||||
final StringBuilder var3 = new StringBuilder(template.length());
|
||||
int var4 = 0;
|
||||
|
||||
final int var5 = template.length();
|
||||
|
||||
while (var4 < var5) {
|
||||
int var6 = template.indexOf("<%", var4);
|
||||
if (var6 >= 0) {
|
||||
var3.append(template, var4, var6);
|
||||
var4 = var6;
|
||||
var6 = template.indexOf(">", var6 + 2);
|
||||
if (var6 >= 0) {
|
||||
final String var7 = template.substring(var4 + 2, var6);
|
||||
final String var8 = this.get(var7);
|
||||
if (var8 != null) {
|
||||
var3.append(var8);
|
||||
}
|
||||
|
||||
var4 = 1 + var6;
|
||||
continue;
|
||||
}
|
||||
|
||||
var3.append(template, var4, var5);
|
||||
break;
|
||||
}
|
||||
|
||||
var3.append(template, var4, var5);
|
||||
break;
|
||||
}
|
||||
|
||||
return var3.toString();
|
||||
}
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
private static final class Entry {
|
||||
public final Entry next;
|
||||
public final String key;
|
||||
public String value;
|
||||
|
||||
public Entry(final String key, final String value, final Entry next) {
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
this.next = next;
|
||||
}
|
||||
}
|
||||
}
|
74
src/main/java/funorb/client/UserIdLoginCredentials.java
Normal file
74
src/main/java/funorb/client/UserIdLoginCredentials.java
Normal file
@ -0,0 +1,74 @@
|
||||
package funorb.client;
|
||||
|
||||
import funorb.io.Buffer;
|
||||
import funorb.shatteredplans.client.AuthMode;
|
||||
|
||||
public final class UserIdLoginCredentials extends LoginCredentials {
|
||||
private static final long USER_ID_LIMIT = 6582952005840035281L;
|
||||
private static final AuthMode userIdAuthMode = new AuthMode(AuthMode.USER_ID);
|
||||
|
||||
private final long userId;
|
||||
private final String password;
|
||||
|
||||
public UserIdLoginCredentials(final long userId, final String password) {
|
||||
this.userId = userId;
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public static long encodeUsername(final CharSequence username) {
|
||||
long userId = 0L;
|
||||
for (int i = 0; i < username.length(); ++i) {
|
||||
userId *= 37L;
|
||||
final char c = username.charAt(i);
|
||||
if (c >= 'A' && c <= 'Z') {
|
||||
userId += 1 - (65 - c);
|
||||
} else if (c >= 'a' && c <= 'z') {
|
||||
userId += 1 + c - 97;
|
||||
} else if (c >= '0' && c <= '9') {
|
||||
userId += c + 27 - 48;
|
||||
}
|
||||
|
||||
if (userId >= USER_ID_LIMIT / 37L) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while (userId != 0L && userId % 37L == 0L) {
|
||||
userId /= 37L;
|
||||
}
|
||||
|
||||
return userId;
|
||||
}
|
||||
|
||||
public static String decodeUsername(long userId) {
|
||||
assert userId >= 0 && userId < USER_ID_LIMIT;
|
||||
final StringBuilder sb = new StringBuilder(12);
|
||||
while (userId != 0) {
|
||||
final int x = (int) (userId % 37);
|
||||
if (x == 0) {
|
||||
sb.append(' ');
|
||||
} else if (x < 27) {
|
||||
if (userId / 37 % 37 == 0) {
|
||||
sb.append((char) ('A' + (x - 1)));
|
||||
} else {
|
||||
sb.append((char) ('a' + (x - 1)));
|
||||
}
|
||||
} else {
|
||||
sb.append((char) ('0' + (x - 27)));
|
||||
}
|
||||
userId /= 37;
|
||||
}
|
||||
return sb.reverse().toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthMode getAuthMode() {
|
||||
return userIdAuthMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToPacket(final Buffer packet) {
|
||||
packet.writeLong(this.userId);
|
||||
packet.writePasswordHash(this.password);
|
||||
}
|
||||
}
|
31
src/main/java/funorb/client/e_.java
Normal file
31
src/main/java/funorb/client/e_.java
Normal file
@ -0,0 +1,31 @@
|
||||
package funorb.client;
|
||||
|
||||
public final class e_ {
|
||||
private String _c;
|
||||
private boolean _a;
|
||||
|
||||
public e_(final String var1) {
|
||||
this(var1, false);
|
||||
}
|
||||
|
||||
public e_(final String var1, final boolean var2) {
|
||||
this._c = var1;
|
||||
this._a = var2;
|
||||
if (this._c == null) {
|
||||
this._c = "";
|
||||
}
|
||||
|
||||
if (this._c.length() == 0) {
|
||||
this._a = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public String a983() {
|
||||
return this._c;
|
||||
}
|
||||
|
||||
public boolean a154() {
|
||||
return this._a;
|
||||
}
|
||||
}
|
1325
src/main/java/funorb/client/intro/JagexLogoIntroAnimation.java
Normal file
1325
src/main/java/funorb/client/intro/JagexLogoIntroAnimation.java
Normal file
File diff suppressed because it is too large
Load Diff
5
src/main/java/funorb/client/intro/hc_.java
Normal file
5
src/main/java/funorb/client/intro/hc_.java
Normal file
@ -0,0 +1,5 @@
|
||||
package funorb.client.intro;
|
||||
|
||||
public final class hc_ {
|
||||
public int _a;
|
||||
}
|
110
src/main/java/funorb/client/intro/sr_.java
Normal file
110
src/main/java/funorb/client/intro/sr_.java
Normal file
@ -0,0 +1,110 @@
|
||||
package funorb.client.intro;
|
||||
|
||||
public final class sr_ {
|
||||
public byte _o = 0;
|
||||
public short[] _P;
|
||||
public short[] _g;
|
||||
public short[] _M;
|
||||
public short[] _b;
|
||||
public short[] _C;
|
||||
public short[] _w;
|
||||
public short[] _s;
|
||||
public short[] _v;
|
||||
public short[] _y;
|
||||
public short _x;
|
||||
public short[] _I;
|
||||
public short[] _z;
|
||||
public byte[] _p;
|
||||
public short[] _B;
|
||||
public short _u;
|
||||
public short[] _i;
|
||||
public int _k;
|
||||
public int _E;
|
||||
public short[] _f;
|
||||
public int _t;
|
||||
public int _j;
|
||||
public int _r;
|
||||
public short _e;
|
||||
public short[] _L;
|
||||
public short[] _J;
|
||||
public short[] _n;
|
||||
public short[] _G;
|
||||
public int _O;
|
||||
private boolean _d = false;
|
||||
|
||||
private void a150() {
|
||||
this._d = false;
|
||||
}
|
||||
|
||||
public void a115(final int var1, final int var2, final int var3) {
|
||||
for (int var5 = 0; this._x > var5; ++var5) {
|
||||
final short[] var10000 = this._w;
|
||||
var10000[var5] = (short) (var10000[var5] + var2);
|
||||
final short[] z = this._z;
|
||||
z[var5] = (short) (z[var5] + var3);
|
||||
final short[] f = this._f;
|
||||
f[var5] = (short) (f[var5] + var1);
|
||||
}
|
||||
|
||||
this.a150();
|
||||
}
|
||||
|
||||
public void a487() {
|
||||
if (!this._d) {
|
||||
this._d = true;
|
||||
short var2 = 32767;
|
||||
short var3 = 32767;
|
||||
short var4 = 32767;
|
||||
short var5 = -32768;
|
||||
short var6 = -32768;
|
||||
short var7 = -32768;
|
||||
|
||||
for (int var8 = 0; var8 < this._x; ++var8) {
|
||||
final short var9 = this._w[var8];
|
||||
final short var10 = this._z[var8];
|
||||
if (var2 > var9) {
|
||||
var2 = var9;
|
||||
}
|
||||
|
||||
if (var9 > var5) {
|
||||
var5 = var9;
|
||||
}
|
||||
|
||||
if (var6 < var10) {
|
||||
var6 = var10;
|
||||
}
|
||||
|
||||
if (var10 < var3) {
|
||||
var3 = var10;
|
||||
}
|
||||
|
||||
final short var11 = this._f[var8];
|
||||
if (var4 > var11) {
|
||||
var4 = var11;
|
||||
}
|
||||
|
||||
if (var7 < var11) {
|
||||
var7 = var11;
|
||||
}
|
||||
}
|
||||
|
||||
this._k = var2;
|
||||
this._t = var6;
|
||||
this._j = var3;
|
||||
this._E = var4;
|
||||
this._O = var5;
|
||||
this._r = var7;
|
||||
}
|
||||
}
|
||||
|
||||
public void a050() {
|
||||
for (int var6 = 0; var6 < this._x; ++var6) {
|
||||
this._w[var6] = (short) (6 * this._w[var6]);
|
||||
this._z[var6] = (short) (this._z[var6] * 6);
|
||||
this._f[var6] = (short) (this._f[var6] * 6);
|
||||
}
|
||||
|
||||
this.a150();
|
||||
|
||||
}
|
||||
}
|
15
src/main/java/funorb/client/li_.java
Normal file
15
src/main/java/funorb/client/li_.java
Normal file
@ -0,0 +1,15 @@
|
||||
package funorb.client;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.Socket;
|
||||
|
||||
public abstract class li_ {
|
||||
protected int _a;
|
||||
protected String _f;
|
||||
|
||||
protected final Socket a693() throws IOException {
|
||||
return new Socket(this._f, this._a);
|
||||
}
|
||||
|
||||
public abstract Socket b693() throws IOException;
|
||||
}
|
88
src/main/java/funorb/client/lobby/ActionButton.java
Normal file
88
src/main/java/funorb/client/lobby/ActionButton.java
Normal file
@ -0,0 +1,88 @@
|
||||
package funorb.client.lobby;
|
||||
|
||||
import funorb.graphics.Font;
|
||||
import funorb.graphics.Sprite;
|
||||
|
||||
public final class ActionButton extends Component<Component<?>> {
|
||||
public Component<?> _Bb;
|
||||
private Component<?> _Db;
|
||||
|
||||
public ActionButton(final Component<?> attrsSrc, final Component<?> tooltipAttrsSrc, final Sprite var6, final String tooltipLabel) {
|
||||
super(attrsSrc);
|
||||
if (var6 != null) {
|
||||
this._Db = new Component<>(null);
|
||||
this._Db.sprite = var6;
|
||||
this.addChild(this._Db);
|
||||
}
|
||||
|
||||
if (tooltipLabel != null) {
|
||||
this._Bb = new Component<>(tooltipAttrsSrc, tooltipLabel);
|
||||
this.addChild(this._Bb);
|
||||
}
|
||||
|
||||
this.recursivelySet_H();
|
||||
}
|
||||
|
||||
private void a326(final int var2, int var3) {
|
||||
int var4 = -var2;
|
||||
|
||||
if (this._Db != null) {
|
||||
var4 = this._Db.e474();
|
||||
}
|
||||
|
||||
int var5 = -var2;
|
||||
if (this._Bb != null) {
|
||||
var5 = this._Bb.a353(-var3 + (-var2 - var3) + (this.width - var4));
|
||||
}
|
||||
|
||||
int var6 = var3 + var4 + var3 - (-var2 - var5);
|
||||
if (this.width < var6) {
|
||||
var5 += this.width - var6;
|
||||
var6 = this.width;
|
||||
}
|
||||
|
||||
if (this.textAlignment == Font.HorizontalAlignment.CENTER) {
|
||||
var3 += (this.width - var6) / 2;
|
||||
}
|
||||
|
||||
if (this.textAlignment == Font.HorizontalAlignment.RIGHT) {
|
||||
var3 += this.width - var6;
|
||||
}
|
||||
|
||||
if (this._Db != null) {
|
||||
this._Db.setBounds(var3, 0, var4, this.height);
|
||||
this._Db.verticalAlignment = this.verticalAlignment;
|
||||
}
|
||||
|
||||
if (this._Bb != null) {
|
||||
this._Bb.setBounds(var3 + var4 + var2, 0, var5, this.height);
|
||||
if (this._Db == null) {
|
||||
this._Bb.textAlignment = this.textAlignment;
|
||||
} else {
|
||||
this._Bb.textAlignment = Font.HorizontalAlignment.LEFT;
|
||||
}
|
||||
|
||||
this._Bb.verticalAlignment = this.verticalAlignment;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void a370(final int var2, final int var3, final int var4, final int var5, final int var6, final int var7) {
|
||||
this.setBounds(var7, var3, var6, var2);
|
||||
this.a326(var5, var4);
|
||||
}
|
||||
|
||||
public int a776(final int var1, final int var3) {
|
||||
int var4 = -var1;
|
||||
int var5 = -var1;
|
||||
if (this._Db != null) {
|
||||
var4 = this._Db.e474();
|
||||
}
|
||||
|
||||
if (this._Bb != null) {
|
||||
var5 = this._Bb.e474();
|
||||
}
|
||||
|
||||
return var5 + var4 + var3 + var1 + var3;
|
||||
}
|
||||
}
|
190
src/main/java/funorb/client/lobby/AddOrRemovePlayerPopup.java
Normal file
190
src/main/java/funorb/client/lobby/AddOrRemovePlayerPopup.java
Normal file
@ -0,0 +1,190 @@
|
||||
package funorb.client.lobby;
|
||||
|
||||
import funorb.Strings;
|
||||
import funorb.awt.KeyState;
|
||||
import funorb.awt.MouseState;
|
||||
import funorb.shatteredplans.client.JagexApplet;
|
||||
import org.intellij.lang.annotations.MagicConstant;
|
||||
|
||||
public final class AddOrRemovePlayerPopup extends Component<Component<?>> {
|
||||
public static AddOrRemovePlayerPopup openInstance;
|
||||
@MagicConstant(valuesFromClass = Action.class)
|
||||
public static int action = Action.NONE;
|
||||
private final Component<?> _zb;
|
||||
private final StringBuilder _Db;
|
||||
private int _Ab = 0;
|
||||
|
||||
public AddOrRemovePlayerPopup(final int x, final int y, final int var3, final int var4, final String labelText, final Component<?> attrsSrc, final Component<?> labelAttrsSrc, final Component<?> var8) {
|
||||
super(attrsSrc);
|
||||
final Component<?> label = new Component<>(labelAttrsSrc, labelText);
|
||||
this.addChild(label);
|
||||
this._zb = new Component<>(var8);
|
||||
this._zb.textColor = 16764006;
|
||||
this.addChild(this._zb);
|
||||
this._zb._u = "|";
|
||||
this._Db = new StringBuilder(12);
|
||||
final int var9 = label.e474();
|
||||
label.setBounds(5, 3, var9, Component.LABEL_HEIGHT);
|
||||
this._zb.setBounds(5, Component.LABEL_HEIGHT + 3, var9, Component.LABEL_HEIGHT);
|
||||
final int var10 = 5 + var9 + 5;
|
||||
final int var11 = 3 + Component.LABEL_HEIGHT * 2 + 3;
|
||||
final int var12 = PopupMenu.positionPopupX(x, var3, var10);
|
||||
final int var13 = PopupMenu.positionPopupY(y, var4, var11);
|
||||
this.setBounds(var12, var13, var10, var11);
|
||||
}
|
||||
|
||||
private static void setStringBuilderLengthAndFillWithSpaces(final StringBuilder sb, final int newLen) {
|
||||
final int oldLen = sb.length();
|
||||
sb.setLength(newLen);
|
||||
|
||||
for (int i = oldLen; i < newLen; ++i) {
|
||||
sb.setCharAt(i, ' ');
|
||||
}
|
||||
}
|
||||
|
||||
public static void removeLastCharacterFromStringBuilder(final StringBuilder sb) {
|
||||
setStringBuilderLengthAndFillWithSpaces(sb, sb.length() - 1);
|
||||
}
|
||||
|
||||
private static boolean a412tmg(final char var0, final CharSequence var1) {
|
||||
if (Strings.isNormalizable(var0)) {
|
||||
|
||||
if (var1 == null) {
|
||||
return false;
|
||||
} else {
|
||||
final int var3 = var1.length();
|
||||
if (var3 >= 12) {
|
||||
return false;
|
||||
} else {
|
||||
return !Strings.isSpaceLikeUsernameChar(var0) || var3 != 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static void tick(final boolean mouseNotYetHandled) {
|
||||
if (openInstance != null) {
|
||||
final int var3 = openInstance.getAction(mouseNotYetHandled);
|
||||
if (var3 != 0) {
|
||||
if (var3 == 2 && openInstance.label != null && !openInstance.label.equals("")) {
|
||||
final String var4;
|
||||
if (openInstance.label.charAt(0) == '[') {
|
||||
var4 = openInstance.label;
|
||||
} else {
|
||||
var4 = Strings.normalize(openInstance.label);
|
||||
}
|
||||
|
||||
String var5 = null;
|
||||
if (action == Action.ADD_FRIEND) {
|
||||
var5 = ContextMenu.addFriend(var4);
|
||||
}
|
||||
|
||||
if (action == Action.REMOVE_FRIEND) {
|
||||
var5 = PlayerListEntry.removeFriend(var4);
|
||||
}
|
||||
|
||||
if (action == Action.ADD_IGNORE) {
|
||||
var5 = ContextMenu.addIgnore(var4);
|
||||
}
|
||||
|
||||
if (action == Action.REMOVE_IGNORE) {
|
||||
var5 = PlayerListEntry.removeIgnore(var4, var4);
|
||||
}
|
||||
|
||||
if (var5 != null) {
|
||||
ContextMenu.showChatMessage(ChatMessage.Channel.PRIVATE, var5, 0, var4, null);
|
||||
}
|
||||
}
|
||||
|
||||
action = Action.NONE;
|
||||
openInstance = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean f427() {
|
||||
if (this._Ab == 0) {
|
||||
if (JagexApplet.lastTypedKeyCode == KeyState.Code.BACKSPACE && this._Db.length() > 0) {
|
||||
removeLastCharacterFromStringBuilder(this._Db);
|
||||
}
|
||||
|
||||
if (this._Db.length() < 12) {
|
||||
char var2 = Character.toLowerCase(JagexApplet.lastTypedKeyChar);
|
||||
if (var2 == ' ') {
|
||||
var2 = '_';
|
||||
}
|
||||
|
||||
if (var2 == '_' && this._Db.length() > 0) {
|
||||
this._Db.append('_');
|
||||
}
|
||||
|
||||
if (Strings.isAlpha(var2) || Strings.isDigit(var2)) {
|
||||
this._Db.append(var2);
|
||||
}
|
||||
}
|
||||
|
||||
if (JagexApplet.lastTypedKeyCode == KeyState.Code.ENTER) {
|
||||
if (this._Db.length() <= 0) {
|
||||
this._Ab = 1;
|
||||
} else {
|
||||
this.label = this._Db.toString();
|
||||
this._Ab = 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (JagexApplet.lastTypedKeyCode == KeyState.Code.ESCAPE) {
|
||||
this._Ab = 1;
|
||||
}
|
||||
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private int getAction(final boolean mouseNotYetHandled) {
|
||||
this.rootProcessMouseEvents(mouseNotYetHandled);
|
||||
if (mouseNotYetHandled) {
|
||||
while (JagexApplet.nextTypedKey()) {
|
||||
if (JagexApplet.lastTypedKeyCode == KeyState.Code.BACKSPACE && this._Db.length() > 0) {
|
||||
removeLastCharacterFromStringBuilder(this._Db);
|
||||
}
|
||||
|
||||
if (a412tmg(JagexApplet.lastTypedKeyChar, this._Db) || this._Db.length() == 0 && JagexApplet.lastTypedKeyChar == '[' || this._Db.length() == 1 && JagexApplet.lastTypedKeyChar == '#' || JagexApplet.lastTypedKeyChar == ']') {
|
||||
this._Db.append(JagexApplet.lastTypedKeyChar);
|
||||
}
|
||||
|
||||
if (JagexApplet.lastTypedKeyCode == KeyState.Code.ENTER) {
|
||||
if (this._Db.length() <= 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
this.label = this._Db.toString();
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (JagexApplet.lastTypedKeyCode == KeyState.Code.ESCAPE) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this._zb.label = this._Db.toString();
|
||||
if (mouseNotYetHandled && JagexApplet.mouseButtonJustClicked != MouseState.Button.NONE && this.clickButton == MouseState.Button.NONE) {
|
||||
this._Ab = 1;
|
||||
}
|
||||
|
||||
return this._Ab;
|
||||
}
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public static final class Action {
|
||||
public static final int NONE = -1;
|
||||
public static final int ADD_FRIEND = 0;
|
||||
public static final int REMOVE_FRIEND = 1;
|
||||
public static final int ADD_IGNORE = 2;
|
||||
public static final int REMOVE_IGNORE = 3;
|
||||
}
|
||||
}
|
119
src/main/java/funorb/client/lobby/ChatMessage.java
Normal file
119
src/main/java/funorb/client/lobby/ChatMessage.java
Normal file
@ -0,0 +1,119 @@
|
||||
package funorb.client.lobby;
|
||||
|
||||
import funorb.shatteredplans.client.ShatteredPlansClient;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public final class ChatMessage {
|
||||
public final long senderId;
|
||||
public final boolean _h;
|
||||
public final int _g;
|
||||
public final String _o;
|
||||
public final @NotNull String message;
|
||||
public final int _c;
|
||||
public final String senderDisplayName;
|
||||
public final int _l;
|
||||
public final int[] _f;
|
||||
public final String senderName;
|
||||
public final @NotNull Channel channel;
|
||||
public final int _e;
|
||||
public Component<?> component;
|
||||
|
||||
public ChatMessage(final boolean isQuick,
|
||||
final int c,
|
||||
final long senderId,
|
||||
final int l,
|
||||
final @NotNull Channel channel,
|
||||
final int e,
|
||||
final String senderDisplayName,
|
||||
final int[] f,
|
||||
final String senderName,
|
||||
final @NotNull String message,
|
||||
final boolean h,
|
||||
final String o,
|
||||
final int g) {
|
||||
this._e = e;
|
||||
this._f = isQuick ? f : null;
|
||||
this.senderName = senderName;
|
||||
this.message = message;
|
||||
this._c = c;
|
||||
this._h = h;
|
||||
this._o = o;
|
||||
this.senderId = senderId;
|
||||
this._l = l;
|
||||
this._g = g;
|
||||
this.channel = channel;
|
||||
this.senderDisplayName = senderDisplayName;
|
||||
}
|
||||
|
||||
public ChatMessage(final @NotNull Channel channel,
|
||||
final String var2,
|
||||
final int var3,
|
||||
final String var4,
|
||||
final @NotNull String message) {
|
||||
this._h = true;
|
||||
this.message = message;
|
||||
this._g = var3;
|
||||
this._o = var4;
|
||||
this.senderDisplayName = var2;
|
||||
this._c = 0;
|
||||
this.channel = channel;
|
||||
this.senderId = 0L;
|
||||
this._e = 0;
|
||||
this._f = null;
|
||||
this.senderName = var2;
|
||||
this._l = 0;
|
||||
}
|
||||
|
||||
public static String a651(final String var0, String var1, final String var2) {
|
||||
for (int var3 = var1.indexOf(var0); var3 != -1; var3 = var1.indexOf(var0, var3 + var2.length())) {
|
||||
var1 = var1.substring(0, var3) + var2 + var1.substring(var3 + var0.length());
|
||||
}
|
||||
|
||||
return var1;
|
||||
}
|
||||
|
||||
public Channel a410() {
|
||||
if (this._h || (this.channel == Channel.PRIVATE && this._c > 0)) {
|
||||
return Channel.PRIVATE;
|
||||
} else if (this.senderId == ShatteredPlansClient.localPlayerId || (PlayerListEntry.serverStatus == PlayerListEntry.ServerStatus.LOADED && ShatteredPlansClient.a988da(this.senderName))) {
|
||||
return Channel.ROOM;
|
||||
} else {
|
||||
return Channel.LOBBY;
|
||||
}
|
||||
}
|
||||
|
||||
public enum Channel {
|
||||
LOBBY,
|
||||
ROOM,
|
||||
PRIVATE,
|
||||
// not sure what these are for!
|
||||
CHANNEL_4,
|
||||
CHANNEL_5;
|
||||
|
||||
public int encode() {
|
||||
return this.ordinal();
|
||||
}
|
||||
|
||||
public static Channel decode(final int val) {
|
||||
return values()[val];
|
||||
}
|
||||
}
|
||||
|
||||
public enum FilterLevel {
|
||||
ALL,
|
||||
FRIENDS,
|
||||
NONE;
|
||||
|
||||
public boolean lessThanOrEqual(final Channel other) {
|
||||
return this.ordinal() <= other.ordinal();
|
||||
}
|
||||
|
||||
public int encode() {
|
||||
return this.ordinal();
|
||||
}
|
||||
|
||||
public static FilterLevel decode(final int val) {
|
||||
return values()[val];
|
||||
}
|
||||
}
|
||||
}
|
45
src/main/java/funorb/client/lobby/Checkbox.java
Normal file
45
src/main/java/funorb/client/lobby/Checkbox.java
Normal file
@ -0,0 +1,45 @@
|
||||
package funorb.client.lobby;
|
||||
|
||||
import funorb.graphics.Font;
|
||||
import funorb.graphics.Sprite;
|
||||
|
||||
public final class Checkbox extends Component<Component<?>> {
|
||||
private final Component<?> _Ab;
|
||||
private final Component<?> _xb;
|
||||
|
||||
private Checkbox(final Component<?> var3, final Component<?> var4, final String var5) {
|
||||
super(null);
|
||||
this._xb = new Component<>(var3);
|
||||
this._Ab = new Component<>(var4);
|
||||
this._Ab.label = var5;
|
||||
this.addChild(this._xb);
|
||||
this.addChild(this._Ab);
|
||||
this.recursivelySet_H();
|
||||
}
|
||||
|
||||
public Checkbox(final Checkbox var3, final String var4) {
|
||||
this(var3._xb, var3._Ab, var4);
|
||||
}
|
||||
|
||||
public Checkbox(final Sprite var3, final Sprite var4, final Component<?> var6) {
|
||||
this(null, var6, null);
|
||||
this._xb.sprite = var4;
|
||||
this._xb.verticalAlignment = Font.VerticalAlignment.MIDDLE;
|
||||
this._xb._Z = var3;
|
||||
}
|
||||
|
||||
private void b366() {
|
||||
this._xb.setBounds(0, 0, this._xb.e474(), this.height);
|
||||
final int var3 = this._xb.width + 4;
|
||||
this._Ab.setBounds(var3, 0, -var3 + this.width, this.height);
|
||||
}
|
||||
|
||||
public int c080() {
|
||||
return this._xb.e474() + 4 + this._Ab.e474();
|
||||
}
|
||||
|
||||
public void a669(final int var1, final int var2, final int var6) {
|
||||
this.setBounds(var2, var6, var1, Component.LABEL_HEIGHT);
|
||||
this.b366();
|
||||
}
|
||||
}
|
568
src/main/java/funorb/client/lobby/ClientLobbyRoom.java
Normal file
568
src/main/java/funorb/client/lobby/ClientLobbyRoom.java
Normal file
@ -0,0 +1,568 @@
|
||||
package funorb.client.lobby;
|
||||
|
||||
import funorb.Strings;
|
||||
import funorb.awt.MouseState;
|
||||
import funorb.graphics.Drawing;
|
||||
import funorb.graphics.Font;
|
||||
import funorb.graphics.Sprite;
|
||||
import funorb.io.Buffer;
|
||||
import funorb.shatteredplans.C2SPacket;
|
||||
import funorb.shatteredplans.StringConstants;
|
||||
import funorb.shatteredplans.client.JagexApplet;
|
||||
import funorb.shatteredplans.client.ShatteredPlansClient;
|
||||
import funorb.util.CollectionUtil;
|
||||
import funorb.util.PseudoMonotonicClock;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public final class ClientLobbyRoom extends Component<Component<?>> {
|
||||
private static final int _mlj = 4;
|
||||
|
||||
public static List<ClientLobbyRoom> rooms;
|
||||
public static Map<Integer, ClientLobbyRoom> roomsMap;
|
||||
|
||||
public final int roomId;
|
||||
public static Sprite[][] GAMEOPT_SPRITES;
|
||||
public static String currentTooltip;
|
||||
public static int _qob;
|
||||
public static Sprite[] ALLOW_SPECTATORS_SPRITES;
|
||||
public static Sprite[] RATED_GAME_SPRITES;
|
||||
public static Sprite[] OPEN_TO_ME_SPRITES;
|
||||
public static Sprite[] WHO_CAN_JOIN_OPTION_SPRITES;
|
||||
public static String[] WHO_CAN_JOIN_OPTION_TOOLTIPS;
|
||||
public final byte[] gameSpecificOptions;
|
||||
private Component<?> askingToJoinLabel;
|
||||
public boolean notInProgress;
|
||||
private Component<?> _Wb;
|
||||
private Component<?> _Ib;
|
||||
private Component<?> _Db;
|
||||
private int averageRating;
|
||||
private Component<?> _Ub;
|
||||
private boolean youAreAllowedToJoin;
|
||||
public String[] joinedPlayerNames;
|
||||
private Component<?> isRatedIcon;
|
||||
private Component<Component<?>> _Mb;
|
||||
private long startedAt;
|
||||
public int status;
|
||||
private Component<?>[] gameOptionIcons;
|
||||
private Component<?> _Rb;
|
||||
public boolean youCanJoin;
|
||||
public int allowSpectate;
|
||||
private Component<?> canJoinIcon;
|
||||
public int finalElapsedTime;
|
||||
public boolean hasStarted;
|
||||
private Component<?> _Pb;
|
||||
public long ownerId;
|
||||
public int whoCanJoin;
|
||||
private Component<?> youAreInvitedLabel;
|
||||
public int maxPlayerCount;
|
||||
private Component<?> cannotJoinReasonLabel;
|
||||
private Component<?> playersInGameLabel;
|
||||
private boolean isRated;
|
||||
public boolean submittedJoinRequest;
|
||||
private Component<?> whoCanJoinIcon;
|
||||
public int statusTimer;
|
||||
public String ownerName;
|
||||
public boolean youAreInvited;
|
||||
public int joinedPlayerCount;
|
||||
private Component<?> ageLabel;
|
||||
private Component<?> allowSpectateIcon;
|
||||
|
||||
public ClientLobbyRoom(final int roomId) {
|
||||
super(null);
|
||||
this.roomId = roomId;
|
||||
this.gameSpecificOptions = new byte[ShatteredPlansClient.GAMEOPT_CHOICES_COUNTS.length];
|
||||
}
|
||||
|
||||
private static String removalReasonMessage(final int status, final String ownerName) {
|
||||
if (status == Status.ENTERED_OTHER_GAME) {
|
||||
return StringConstants.MU_ENTERED_OTHER_GAME;
|
||||
} else if (status == Status.ROOM_FULL) {
|
||||
return StringConstants.MU_GAME_IS_FULL;
|
||||
} else if (status == Status.GAME_HAS_STARTED) {
|
||||
return StringConstants.MU_GAME_HAS_STARTED;
|
||||
} else if (status == Status.YOU_DECLINED_INVITE) {
|
||||
return StringConstants.MU_YOU_DECLINED_INVITE;
|
||||
} else if (status == Status.INVITE_WITHDRAWN) {
|
||||
return StringConstants.MU_INVITE_WITHDRAWN;
|
||||
} else if (status == Status.REQUEST_DECLINED) {
|
||||
return StringConstants.MU_REQUEST_DECLINED;
|
||||
} else if (status == Status.REQUEST_WITHDRAWN) {
|
||||
return StringConstants.MU_REQUEST_WITHDRAWN;
|
||||
} else if (status == Status.ALL_PLAYERS_HAVE_LEFT) {
|
||||
return Strings.format(StringConstants.MU_ALL_PLAYERS_HAVE_LEFT, ownerName);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static void tick(final boolean var0, final int var4) {
|
||||
final boolean var6 = Component.GAME_LIST_SCROLL_PANE.processScrollInput(var0, ShatteredPlansClient.currentContextMenuParent == Component.GAME_LIST_SCROLL_PANE, (2 + Component.LABEL_HEIGHT) * 2, (Component.LABEL_HEIGHT * 4 + 8) * var4);
|
||||
final List<ClientLobbyRoom> rooms = Component.GAME_LIST_SCROLL_PANE.content.children;
|
||||
final long now = PseudoMonotonicClock.currentTimeMillis();
|
||||
|
||||
for (final ClientLobbyRoom room : rooms) {
|
||||
boolean var12 = false;
|
||||
if (room.children == null) {
|
||||
room._Ub = new Component<>(Component.UNSELECTED_LABEL_DARK_1);
|
||||
room.addChild(room._Ub);
|
||||
room._Ub.textAlignment = Font.HorizontalAlignment.CENTER;
|
||||
room._Pb = new Component<>(Component.UNSELECTED_LABEL_DARK_2);
|
||||
room.addChild(room._Pb);
|
||||
room._Rb = new Component<>(Component.UNSELECTED_LABEL_DARK_1);
|
||||
room.addChild(room._Rb);
|
||||
room._Rb._kb = 0;
|
||||
room._Wb = new Component<>(Component.UNSELECTED_LABEL_DARK_1);
|
||||
room.addChild(room._Wb);
|
||||
room._Wb._kb = 0;
|
||||
room._Ib = new Component<>(Component.UNSELECTED_LABEL_DARK_2);
|
||||
room.addChild(room._Ib);
|
||||
room._Ib.textAlignment = Font.HorizontalAlignment.RIGHT;
|
||||
room._Mb = new Component<>(Component.UNSELECTED_LABEL_DARK_1);
|
||||
room.addChild(room._Mb);
|
||||
room.gameOptionIcons = new Component[ShatteredPlansClient.GAMEOPT_CHOICES_COUNTS.length];
|
||||
room.whoCanJoinIcon = new Component<>(null);
|
||||
room._Mb.addChild(room.whoCanJoinIcon);
|
||||
|
||||
room.canJoinIcon = new Component<>(null);
|
||||
room._Mb.addChild(room.canJoinIcon);
|
||||
|
||||
room.allowSpectateIcon = new Component<>(null);
|
||||
room._Mb.addChild(room.allowSpectateIcon);
|
||||
|
||||
room.isRatedIcon = new Component<>(null);
|
||||
room._Mb.addChild(room.isRatedIcon);
|
||||
|
||||
final Component<?> var14 = room.whoCanJoinIcon;
|
||||
final Component<?> var15 = room.isRatedIcon;
|
||||
room.allowSpectateIcon.verticalAlignment = Font.VerticalAlignment.MIDDLE;
|
||||
final Component<?> var16 = room.canJoinIcon;
|
||||
var16.verticalAlignment = Font.VerticalAlignment.MIDDLE;
|
||||
var15.verticalAlignment = Font.VerticalAlignment.MIDDLE;
|
||||
var14.verticalAlignment = Font.VerticalAlignment.MIDDLE;
|
||||
|
||||
for (int i = 0; i < ShatteredPlansClient.GAMEOPT_CHOICES_COUNTS.length; ++i) {
|
||||
room.gameOptionIcons[i] = new Component<>(null);
|
||||
if (((1 << (_mlj + i)) & Drawing.WHITE) != 0) {
|
||||
room._Mb.addChild(room.gameOptionIcons[i]);
|
||||
}
|
||||
room.gameOptionIcons[i].verticalAlignment = Font.VerticalAlignment.MIDDLE;
|
||||
}
|
||||
|
||||
room.ageLabel = new Component<>(Component.UNSELECTED_LABEL_DARK_2);
|
||||
room.addChild(room.ageLabel);
|
||||
room.ageLabel.textAlignment = Font.HorizontalAlignment.RIGHT;
|
||||
room.playersInGameLabel = new Component<>(Component.UNSELECTED_LABEL_DARK_2);
|
||||
room.addChild(room.playersInGameLabel);
|
||||
room.youAreInvitedLabel = new Component<>(Component.UNSELECTED_LABEL);
|
||||
room.addChild(room.youAreInvitedLabel);
|
||||
room.askingToJoinLabel = new Component<>(Component.UNSELECTED_LABEL);
|
||||
room.addChild(room.askingToJoinLabel);
|
||||
room.cannotJoinReasonLabel = new Component<>(Component.LABEL);
|
||||
room.addChild(room.cannotJoinReasonLabel);
|
||||
room.recursivelySet_H();
|
||||
room._Db = new Component<>(Component.GREEN_BUTTON);
|
||||
var12 = true;
|
||||
room.addChild(room._Db);
|
||||
}
|
||||
|
||||
room._Ub.label = null;
|
||||
room._Ub.height = 0;
|
||||
final Component<?> var14 = room._Ub;
|
||||
var14.width = 0;
|
||||
room._Db.label = null;
|
||||
room._Db.height = 0;
|
||||
final Component<?> var15 = room._Db;
|
||||
var15.width = 0;
|
||||
room._Pb.label = null;
|
||||
final Component<?> var16 = room._Pb;
|
||||
room._Pb.height = 0;
|
||||
room._Rb.label = null;
|
||||
var16.width = 0;
|
||||
room._Rb.height = 0;
|
||||
final Component<?> var40 = room._Rb;
|
||||
var40.width = 0;
|
||||
room._Wb.label = null;
|
||||
room._Wb.height = 0;
|
||||
final Component<?> var18 = room._Wb;
|
||||
var18.width = 0;
|
||||
room._Ib.label = null;
|
||||
final Component<?> var19 = room._Ib;
|
||||
room._Ib.height = 0;
|
||||
var19.width = 0;
|
||||
room._Mb.label = null;
|
||||
final Component<?> var20 = room._Mb;
|
||||
room._Mb.height = 0;
|
||||
var20.width = 0;
|
||||
|
||||
for (int i = 0; i < ShatteredPlansClient.GAMEOPT_CHOICES_COUNTS.length; ++i) {
|
||||
room.gameOptionIcons[i].sprite = null;
|
||||
room.gameOptionIcons[i].height = 0;
|
||||
room.gameOptionIcons[i].width = 0;
|
||||
}
|
||||
|
||||
room.whoCanJoinIcon.sprite = null;
|
||||
room.whoCanJoinIcon.height = 0;
|
||||
final Component<?> var41 = room.whoCanJoinIcon;
|
||||
room.isRatedIcon.sprite = null;
|
||||
var41.width = 0;
|
||||
room.isRatedIcon.height = 0;
|
||||
final Component<?> var22 = room.isRatedIcon;
|
||||
room.canJoinIcon.sprite = null;
|
||||
var22.width = 0;
|
||||
final Component<?> var23 = room.canJoinIcon;
|
||||
room.canJoinIcon.height = 0;
|
||||
room.allowSpectateIcon.sprite = null;
|
||||
var23.width = 0;
|
||||
final Component<?> var24 = room.allowSpectateIcon;
|
||||
room.allowSpectateIcon.height = 0;
|
||||
var24.width = 0;
|
||||
room.ageLabel.label = null;
|
||||
final Component<?> var25 = room.ageLabel;
|
||||
room.ageLabel.height = 0;
|
||||
room.playersInGameLabel.label = null;
|
||||
var25.width = 0;
|
||||
room.playersInGameLabel.height = 0;
|
||||
final Component<?> var26 = room.playersInGameLabel;
|
||||
room.youAreInvitedLabel.label = null;
|
||||
var26.width = 0;
|
||||
room.youAreInvitedLabel.height = 0;
|
||||
final Component<?> var27 = room.youAreInvitedLabel;
|
||||
room.askingToJoinLabel.label = null;
|
||||
var27.width = 0;
|
||||
room.askingToJoinLabel.height = 0;
|
||||
final Component<?> var28 = room.askingToJoinLabel;
|
||||
var28.width = 0;
|
||||
room.cannotJoinReasonLabel.label = null;
|
||||
room.cannotJoinReasonLabel.height = 0;
|
||||
final Component<?> var29 = room.cannotJoinReasonLabel;
|
||||
var29.width = 0;
|
||||
room.width = Component.GAME_LIST_SCROLL_PANE.content.width;
|
||||
|
||||
int var30 = 0;
|
||||
if (room.isInMap()) {
|
||||
if (room.hasStarted) {
|
||||
if (room.finalElapsedTime >= 0) {
|
||||
room._Ub.label = StringConstants.STATUS_CONCLUDED;
|
||||
} else if (room.notInProgress && (room.youCanJoin || room.youAreInvited)) {
|
||||
room._Db.label = StringConstants.STATUS_JOIN;
|
||||
} else if (room.allowSpectate == 2) {
|
||||
room._Db.label = StringConstants.STATUS_SPECTATE;
|
||||
} else {
|
||||
room._Ub.label = StringConstants.STATUS_PLAYING;
|
||||
}
|
||||
} else if (room.youCanJoin || room.youAreInvited) {
|
||||
room._Db.label = StringConstants.STATUS_JOIN;
|
||||
} else if (room.youAreAllowedToJoin) {
|
||||
room._Ub.label = StringConstants.STATUS_FULL;
|
||||
} else {
|
||||
room._Ub.label = StringConstants.STATUS_PRIVATE;
|
||||
}
|
||||
|
||||
if (room._Db.label == null) {
|
||||
room._Ub.setBounds(0, var30, 68, Component.LABEL_HEIGHT);
|
||||
} else {
|
||||
room._Db.setBounds(0, var30, 68, Component.LABEL_HEIGHT);
|
||||
}
|
||||
|
||||
room._Pb.label = room._Pb.font.truncateWithEllipsisToFit(room.ownerName, 78);
|
||||
room._Pb.setBounds(70, var30, 78, Component.LABEL_HEIGHT);
|
||||
if (room._Pb.isMouseOverTarget && !room._Pb.label.equals(room.ownerName)) {
|
||||
currentTooltip = room.ownerName;
|
||||
}
|
||||
|
||||
room._Rb.label = Integer.toString(room.joinedPlayerCount);
|
||||
int var32;
|
||||
if (room.notInProgress) {
|
||||
room._Wb.label = "/" + room.maxPlayerCount;
|
||||
room._Rb.textAlignment = Font.HorizontalAlignment.RIGHT;
|
||||
var32 = (348 - room._Wb.font.measureLineWidth("/")) / 2;
|
||||
room._Rb.setBounds(150, var30, var32 - 150, Component.LABEL_HEIGHT);
|
||||
room._Wb.setBounds(var32, var30, -var32 + 198, Component.LABEL_HEIGHT);
|
||||
} else {
|
||||
room._Rb.textAlignment = Font.HorizontalAlignment.CENTER;
|
||||
room._Rb.setBounds(150, var30, 48, Component.LABEL_HEIGHT);
|
||||
}
|
||||
|
||||
room._Ib.label = Integer.toString(room.averageRating);
|
||||
room._Ib.setBounds(200, var30, 48, Component.LABEL_HEIGHT);
|
||||
var32 = 250;
|
||||
room._Mb.setBounds(var32, var30, 365 - var32 - 2, Component.LABEL_HEIGHT);
|
||||
int var33 = _qob;
|
||||
Sprite var34;
|
||||
var34 = WHO_CAN_JOIN_OPTION_SPRITES[room.whoCanJoin];
|
||||
room.whoCanJoinIcon.sprite = var34;
|
||||
room.whoCanJoinIcon.setBounds(var33, 0, var34.offsetX, room._Mb.height);
|
||||
var33 += var34.offsetX + _qob;
|
||||
|
||||
final boolean var35 = room.youCanJoin || room.youAreInvited;
|
||||
var34 = OPEN_TO_ME_SPRITES[var35 ? 1 : 0];
|
||||
room.canJoinIcon.sprite = var34;
|
||||
room.canJoinIcon.setBounds(var33, 0, var34.offsetX, room._Mb.height);
|
||||
var33 += _qob + var34.offsetX;
|
||||
|
||||
var34 = ALLOW_SPECTATORS_SPRITES[room.allowSpectate - 1];
|
||||
room.allowSpectateIcon.sprite = var34;
|
||||
room.allowSpectateIcon.setBounds(var33, 0, var34.offsetX, room._Mb.height);
|
||||
var33 += _qob + var34.offsetX;
|
||||
|
||||
var34 = RATED_GAME_SPRITES[!room.isRated ? 0 : 1];
|
||||
room.isRatedIcon.sprite = var34;
|
||||
room.isRatedIcon.setBounds(var33, 0, var34.offsetX, room._Mb.height);
|
||||
var33 += _qob + var34.offsetX;
|
||||
|
||||
if (GAMEOPT_SPRITES != null) {
|
||||
for (int i = 0; i < ShatteredPlansClient.GAMEOPT_CHOICES_COUNTS.length; ++i) {
|
||||
if (GAMEOPT_SPRITES[i] != null && (((1 << (i + _mlj)) & Drawing.WHITE) != 0)) {
|
||||
var34 = GAMEOPT_SPRITES[i][room.gameSpecificOptions[i] & 255];
|
||||
room.gameOptionIcons[i].sprite = var34;
|
||||
room.gameOptionIcons[i].setBounds(var33, 0, var34.offsetX, room._Mb.height);
|
||||
var33 += _qob + var34.offsetX;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final int var43 = (room._Mb.width - var33) / 2;
|
||||
if (var43 > 0) {
|
||||
room.whoCanJoinIcon.x += var43;
|
||||
final Component<?> oc = room.canJoinIcon;
|
||||
oc.x += var43;
|
||||
final Component<?> ac = room.allowSpectateIcon;
|
||||
ac.x += var43;
|
||||
Component<?> kb = room.isRatedIcon;
|
||||
kb.x += var43;
|
||||
|
||||
for (int var36 = 0; ShatteredPlansClient.GAMEOPT_CHOICES_COUNTS.length > var36; ++var36) {
|
||||
kb = room.gameOptionIcons[var36];
|
||||
kb.x += var43;
|
||||
}
|
||||
}
|
||||
|
||||
if (room.hasStarted) {
|
||||
int millis = room.finalElapsedTime;
|
||||
if (millis < 0) {
|
||||
millis = (int) (now - room.startedAt);
|
||||
}
|
||||
|
||||
int seconds = millis / 1000;
|
||||
int minutes = seconds / 60;
|
||||
seconds %= 60;
|
||||
if (minutes >= 60) {
|
||||
final int hours = minutes / 60;
|
||||
minutes %= 60;
|
||||
room.ageLabel.label = hours + ":" + minutes / 10 + minutes % 10 + ":" + seconds / 10 + seconds % 10;
|
||||
} else {
|
||||
room.ageLabel.label = minutes + ":" + seconds / 10 + seconds % 10;
|
||||
}
|
||||
}
|
||||
|
||||
room.ageLabel.setBounds(365, var30, room.width - 365, Component.LABEL_HEIGHT);
|
||||
var30 += Component.LABEL_HEIGHT;
|
||||
if (room.joinedPlayerNames != null) {
|
||||
var30 += 2;
|
||||
|
||||
final String playersInGame = Arrays.stream(room.joinedPlayerNames, 0, room.joinedPlayerCount)
|
||||
.collect(Collectors.joining(", ", StringConstants.PLAYERS_IN_GAME, ""));
|
||||
room.playersInGameLabel.label = playersInGame;
|
||||
final int lineCount = room.playersInGameLabel.font.breakLines(playersInGame, room.width - 2 * room.playersInGameLabel._kb);
|
||||
room.playersInGameLabel.setBounds(0, var30, room.width, Component.LABEL_HEIGHT * lineCount);
|
||||
var30 += lineCount * Component.LABEL_HEIGHT;
|
||||
}
|
||||
|
||||
if (room.youAreInvited) {
|
||||
room.youAreInvitedLabel.label = Strings.format(StringConstants.YOU_ARE_INVITED_TO_XS_GAME, room.ownerName);
|
||||
room.youAreInvitedLabel.setBounds(ShatteredPlansClient._tga, var30, room.width - ShatteredPlansClient._tga * 2, Component.LABEL_HEIGHT);
|
||||
var30 += Component.LABEL_HEIGHT;
|
||||
}
|
||||
|
||||
if (room.submittedJoinRequest) {
|
||||
room.askingToJoinLabel.label = Strings.format(StringConstants.ASKING_TO_JOIN_XS_GAME, room.ownerName);
|
||||
room.askingToJoinLabel.setBounds(ShatteredPlansClient._tga, var30, -(2 * ShatteredPlansClient._tga) + room.width, Component.LABEL_HEIGHT);
|
||||
var30 += Component.LABEL_HEIGHT;
|
||||
}
|
||||
}
|
||||
|
||||
final String message = removalReasonMessage(room.status, room.ownerName);
|
||||
if (message != null) {
|
||||
final int var33 = room.cannotJoinReasonLabel.font.breakLines(message, -ShatteredPlansClient._tga - ShatteredPlansClient._tga + room.width);
|
||||
room.cannotJoinReasonLabel.label = message;
|
||||
room.cannotJoinReasonLabel._I = 256 * room.statusTimer / ShatteredPlansClient.STATUS_MESSAGE_TIMEOUT_DURATION;
|
||||
room.cannotJoinReasonLabel.setBounds(ShatteredPlansClient._tga, var30, room.width - ShatteredPlansClient._tga * 2, Component.LABEL_HEIGHT * var33);
|
||||
var30 += var33 * Component.LABEL_HEIGHT;
|
||||
}
|
||||
|
||||
if (!var6) {
|
||||
room._gb = var30 - room.height;
|
||||
}
|
||||
|
||||
if (var12) {
|
||||
Component.GAME_LIST_SCROLL_PANE.content.placeAfter(null, room);
|
||||
}
|
||||
|
||||
for (int i = 0; i < ShatteredPlansClient.GAMEOPT_CHOICES_COUNTS.length; ++i) {
|
||||
if (room.gameOptionIcons[i].isMouseOverTarget) {
|
||||
final String tooltip = ShatteredPlansClient.GAMEOPT_TOOLTIPS == null ? null
|
||||
: ShatteredPlansClient.GAMEOPT_TOOLTIPS[i] == null ? null
|
||||
: ShatteredPlansClient.GAMEOPT_TOOLTIPS[i][room.gameSpecificOptions[i] & 255];
|
||||
if (tooltip == null) {
|
||||
currentTooltip = StringConstants.GAMEOPT_LABELS[i];
|
||||
} else {
|
||||
currentTooltip = StringConstants.GAMEOPT_LABELS[i] + " - " + tooltip;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (room.whoCanJoinIcon.isMouseOverTarget) {
|
||||
final String tooltip;
|
||||
if (room.whoCanJoin == 1) {
|
||||
tooltip = StringConstants.RUNESCAPE_CLAN;
|
||||
} else {
|
||||
tooltip = WHO_CAN_JOIN_OPTION_TOOLTIPS[room.whoCanJoin];
|
||||
}
|
||||
|
||||
currentTooltip = StringConstants.WHO_CAN_JOIN + " - " + tooltip;
|
||||
}
|
||||
|
||||
if (room.isRatedIcon.isMouseOverTarget) {
|
||||
currentTooltip = room.isRated ? StringConstants.RATED_GAME : StringConstants.UNRATED_GAME;
|
||||
}
|
||||
|
||||
if (room.canJoinIcon.isMouseOverTarget) {
|
||||
currentTooltip = room.youCanJoin || room.youAreInvited ? StringConstants.YOU_CAN_JOIN
|
||||
: room.notInProgress ? StringConstants.YOU_CAN_ASK_TO_JOIN
|
||||
: StringConstants.YOU_CANNOT_JOIN_IN_PROGRESS;
|
||||
}
|
||||
|
||||
if (room.allowSpectateIcon.isMouseOverTarget) {
|
||||
currentTooltip = room.allowSpectate != 2 ? StringConstants.YOU_CAN_NOT_SPECTATE : StringConstants.YOU_CAN_SPECTATE;
|
||||
}
|
||||
|
||||
if (room.clickButton != MouseState.Button.NONE && room.isInMap()) {
|
||||
if (room._Db.clickButton == MouseState.Button.NONE) {
|
||||
a458aj(room, room.ownerName);
|
||||
} else if (!room.hasStarted || (room.notInProgress && (room.youCanJoin || room.youAreInvited))) {
|
||||
C2SPacket.requestToJoinRoom(room.roomId);
|
||||
} else {
|
||||
C2SPacket.spectateGame(room.roomId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void a458aj(final ClientLobbyRoom var1, final String var2) {
|
||||
ShatteredPlansClient.showContextMenu(Component.GAME_LIST_SCROLL_PANE, var1, 0L, null, null, var1.roomId, null);
|
||||
if (var1.hasStarted && (var1.allowSpectate == 2 || JagexApplet.adminLevel >= 2)) {
|
||||
ContextMenu.openInstance.view.addItem(Strings.format(StringConstants.SPECTATE_XS_GAME, var2), ContextMenu.ClickAction.SPECTATE_GAME);
|
||||
}
|
||||
|
||||
ContextMenu.openInstance.a487();
|
||||
if (ContextMenu.openInstance.roomId == ContextMenu.roomShowingPlayers) {
|
||||
ContextMenu.openInstance.view.addItem(Strings.format(StringConstants.HIDE_PLAYERS_IN_XS_GAME, var2), ContextMenu.ClickAction.HIDE_PLAYERS_IN_GAME);
|
||||
} else {
|
||||
ContextMenu.openInstance.view.addItem(Strings.format(StringConstants.SHOW_PLAYERS_IN_XS_GAME, var2), ContextMenu.ClickAction.SHOW_PLAYERS_IN_GAME);
|
||||
}
|
||||
|
||||
ContextMenu.openInstance.view.positionRelativeToTarget(JagexApplet.mousePressX, JagexApplet.mousePressY);
|
||||
}
|
||||
|
||||
public static ClientLobbyRoom lookup(final int roomId) {
|
||||
return roomsMap == null ? null : roomsMap.get(roomId);
|
||||
}
|
||||
|
||||
public static void add(final ClientLobbyRoom room) {
|
||||
rooms.remove(room);
|
||||
CollectionUtil.insertSorted(rooms, room, ClientLobbyRoom::lessThan);
|
||||
}
|
||||
|
||||
public boolean isInMap() {
|
||||
return roomsMap.containsKey(this.roomId);
|
||||
}
|
||||
|
||||
public void initializeFromServer(@SuppressWarnings("SameParameterValue") final Buffer packet, final boolean includesJoinedPlayerCount) {
|
||||
if (includesJoinedPlayerCount) {
|
||||
this.joinedPlayerCount = packet.readUByte();
|
||||
}
|
||||
this.maxPlayerCount = packet.readUByte();
|
||||
this.whoCanJoin = packet.readUByte();
|
||||
final int var4 = packet.readUByte();
|
||||
final boolean includesJoinedPlayerNames = (var4 & 2) != 0;
|
||||
final boolean concluded = (var4 & 4) != 0;
|
||||
this.notInProgress = (var4 & 8) != 0;
|
||||
this.allowSpectate = (var4 & 16) == 0 ? 1 : 2;
|
||||
this.isRated = (var4 & 32) != 0;
|
||||
this.hasStarted = (var4 & 64) != 0;
|
||||
this.youAreAllowedToJoin = (var4 & 128) != 0;
|
||||
this.youCanJoin = this.youAreAllowedToJoin && this.joinedPlayerCount < this.maxPlayerCount;
|
||||
packet.readBytes(this.gameSpecificOptions, this.gameSpecificOptions.length);
|
||||
this.averageRating = packet.readUShort();
|
||||
this.startedAt = PseudoMonotonicClock.currentTimeMillis() - (long) packet.readInt();
|
||||
if (concluded) {
|
||||
this.finalElapsedTime = packet.readInt();
|
||||
} else {
|
||||
this.finalElapsedTime = -1;
|
||||
}
|
||||
|
||||
this.ownerId = packet.readLong();
|
||||
final int var7 = packet.pos;
|
||||
this.ownerName = packet.readNullTerminatedString();
|
||||
if (includesJoinedPlayerNames) {
|
||||
packet.pos = var7;
|
||||
this.joinedPlayerNames = new String[this.joinedPlayerCount];
|
||||
for (int i = 0; i < this.joinedPlayerCount; ++i) {
|
||||
this.joinedPlayerNames[i] = packet.readNullTerminatedString();
|
||||
}
|
||||
} else {
|
||||
this.joinedPlayerNames = null;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean lessThan(final ClientLobbyRoom var1) {
|
||||
final boolean var3 = this.youAreInvited || this.status == Status.ROOM_FULL;
|
||||
final boolean var4 = var1.youAreInvited || var1.status == Status.ROOM_FULL;
|
||||
if (var3 == var4) {
|
||||
if (!var3) {
|
||||
if (this.youCanJoin != var1.youCanJoin) {
|
||||
return this.youCanJoin;
|
||||
}
|
||||
|
||||
if (this.youCanJoin && this.whoCanJoin != var1.whoCanJoin) {
|
||||
return this.whoCanJoin < var1.whoCanJoin;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.hasStarted == var1.hasStarted) {
|
||||
if (this.hasStarted) {
|
||||
final boolean var5 = this.notInProgress || this.allowSpectate == 2;
|
||||
final boolean var6 = var1.notInProgress || var1.allowSpectate == 2;
|
||||
if (var5 == var6) {
|
||||
return this.startedAt > var1.startedAt;
|
||||
} else {
|
||||
return var5;
|
||||
}
|
||||
} else {
|
||||
return this.startedAt < var1.startedAt;
|
||||
}
|
||||
} else {
|
||||
return !this.hasStarted;
|
||||
}
|
||||
} else {
|
||||
return var3;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public static final class Status {
|
||||
public static final int NONE = 0;
|
||||
public static final int ENTERED_OTHER_GAME = 3;
|
||||
public static final int ROOM_FULL = 6;
|
||||
public static final int GAME_HAS_STARTED = 7;
|
||||
public static final int YOU_DECLINED_INVITE = 8;
|
||||
public static final int INVITE_WITHDRAWN = 9;
|
||||
public static final int REQUEST_DECLINED = 10;
|
||||
public static final int REQUEST_WITHDRAWN = 11;
|
||||
public static final int ALL_PLAYERS_HAVE_LEFT = 14;
|
||||
}
|
||||
}
|
1530
src/main/java/funorb/client/lobby/Component.java
Normal file
1530
src/main/java/funorb/client/lobby/Component.java
Normal file
File diff suppressed because it is too large
Load Diff
446
src/main/java/funorb/client/lobby/ContextMenu.java
Normal file
446
src/main/java/funorb/client/lobby/ContextMenu.java
Normal file
@ -0,0 +1,446 @@
|
||||
package funorb.client.lobby;
|
||||
|
||||
import funorb.Strings;
|
||||
import funorb.client.lobby.ChatMessage.Channel;
|
||||
import funorb.client.lobby.ChatMessage.FilterLevel;
|
||||
import funorb.shatteredplans.C2SPacket;
|
||||
import funorb.shatteredplans.StringConstants;
|
||||
import funorb.shatteredplans.client.JagexApplet;
|
||||
import funorb.shatteredplans.client.ShatteredPlansClient;
|
||||
import funorb.shatteredplans.game.ai.TutorialAI2;
|
||||
import org.intellij.lang.annotations.MagicConstant;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import static funorb.client.lobby.ContextMenu.ClickAction.*;
|
||||
|
||||
public final class ContextMenu {
|
||||
public static String recipientPlayerName;
|
||||
public static boolean _fpv = true;
|
||||
public static long recipientPlayerId;
|
||||
public static int roomShowingPlayers;
|
||||
public static String normalizedRecipientPlayerName;
|
||||
public static ContextMenu openInstance;
|
||||
private static @NotNull FilterLevel chatFilterLobby = FilterLevel.ALL;
|
||||
private static @NotNull FilterLevel chatFilterRoom = FilterLevel.ALL;
|
||||
private static @NotNull FilterLevel chatFilterPrivate = FilterLevel.NONE;
|
||||
public final Component<?> target;
|
||||
public final int roomId;
|
||||
public final PopupMenu view;
|
||||
public final String playerName;
|
||||
private final String playerDisplayName;
|
||||
private int[] _i;
|
||||
private @Nullable Channel selectedChannel;
|
||||
private final long playerId;
|
||||
|
||||
public ContextMenu(final Component<?> target, final long playerId, final String playerName, final String playerDisplayName, final int roomId, final @Nullable Channel selectedChannel) {
|
||||
this.target = target;
|
||||
target.selected = true;
|
||||
this.view = new PopupMenu(Component._hdt);
|
||||
this._i = null;
|
||||
this.playerId = playerId;
|
||||
this.playerName = playerName;
|
||||
this.playerDisplayName = playerDisplayName;
|
||||
this.roomId = roomId;
|
||||
this.selectedChannel = selectedChannel;
|
||||
}
|
||||
|
||||
private static void sendChannelMessage() {
|
||||
ShatteredPlansClient.currentChatChannel = Channel.LOBBY;
|
||||
ShatteredPlansClient.isChatboxSelected = true;
|
||||
}
|
||||
|
||||
private static void sendPrivateMessage(final long playerId, final String playerName) {
|
||||
ShatteredPlansClient.currentChatChannel = Channel.PRIVATE;
|
||||
recipientPlayerId = playerId;
|
||||
recipientPlayerName = playerName;
|
||||
normalizedRecipientPlayerName = Strings.normalize(playerName);
|
||||
ShatteredPlansClient.isChatboxSelected = true;
|
||||
}
|
||||
|
||||
public static void setChatFilter(final @NotNull Channel channel,
|
||||
final @NotNull FilterLevel value) {
|
||||
if (channel == Channel.LOBBY && chatFilterLobby != value) {
|
||||
_fpv = true;
|
||||
chatFilterLobby = value;
|
||||
C2SPacket.setChatFilters(getChatFilters());
|
||||
}
|
||||
if (channel == Channel.ROOM && chatFilterRoom != value) {
|
||||
_fpv = true;
|
||||
chatFilterRoom = value;
|
||||
C2SPacket.setChatFilters(getChatFilters());
|
||||
}
|
||||
if (channel == Channel.PRIVATE && chatFilterPrivate != value) {
|
||||
_fpv = true;
|
||||
chatFilterPrivate = value;
|
||||
C2SPacket.setChatFilters(getChatFilters());
|
||||
}
|
||||
}
|
||||
|
||||
private static void sendPrivateMessageQC(final String recipientName, final long var1) {
|
||||
recipientPlayerName = recipientName;
|
||||
ShatteredPlansClient.currentChatChannel = Channel.PRIVATE;
|
||||
normalizedRecipientPlayerName = Strings.normalize(recipientName);
|
||||
recipientPlayerId = var1;
|
||||
r150bo();
|
||||
}
|
||||
|
||||
public static void sendChannelMessageQC() {
|
||||
ShatteredPlansClient.currentChatChannel = Channel.LOBBY;
|
||||
r150bo();
|
||||
}
|
||||
|
||||
private static void r150bo() {
|
||||
a130bp(Component._ofb);
|
||||
}
|
||||
|
||||
public static boolean autoRespond(final long var0, final String var2, final int[] var4, @NotNull Channel channel) {
|
||||
if (TutorialAI2.a051(var4, var2, channel, var0)) {
|
||||
if (channel == Channel.ROOM) {
|
||||
channel = Channel.LOBBY;
|
||||
}
|
||||
|
||||
ShatteredPlansClient.currentChatChannel = channel;
|
||||
recipientPlayerName = var2;
|
||||
normalizedRecipientPlayerName = Strings.normalize(var2);
|
||||
recipientPlayerId = var0;
|
||||
final vm_ var6 = a925bo(var4, Component._nld, Component._hlI, ReportAbuseDialog._Nb);
|
||||
a130bp(var6);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static vm_ a925bo(final int[] var0, final Component<?> var2, final Component<?> var3, final Component<?> var4) {
|
||||
final int var5 = var0.length;
|
||||
final String[] var6 = new String[var5];
|
||||
final char[] var7 = new char[var5];
|
||||
final vm_[] var8 = new vm_[var5];
|
||||
char var9 = '1';
|
||||
|
||||
try {
|
||||
|
||||
for (int var10 = 0; var5 > var10; ++var10) {
|
||||
final QuickChatResponse var11 = JagexApplet._dhc.get(var0[var10]);
|
||||
var6[var10] = var11.joinStrings();
|
||||
var7[var10] = var9++;
|
||||
var8[var10] = null;
|
||||
}
|
||||
} catch (final Exception var12) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new vm_(var3, var4, var2, var8, var0, var6, var7);
|
||||
}
|
||||
|
||||
private static void a130bp(final vm_ var1) {
|
||||
if (var1 != null) {
|
||||
ShatteredPlansClient._dmrh = var1;
|
||||
Component._uaf.children.clear();
|
||||
Component._uaf.addChild(ShatteredPlansClient._dmrh);
|
||||
ShatteredPlansClient.isQuickChatOpen = true;
|
||||
}
|
||||
}
|
||||
|
||||
public static String addFriend(final String playerName) {
|
||||
if (!PlayerListEntry.isValidPlayerName(playerName)) {
|
||||
return StringConstants.INVALID_NAME;
|
||||
} else if (PlayerListEntry.serverStatus != PlayerListEntry.ServerStatus.LOADED) {
|
||||
return StringConstants.UNABLE_TO_ADD_FRIEND;
|
||||
} else if (JagexApplet.a623jp(playerName)) {
|
||||
return StringConstants.CANNOT_ADD_YOURSELF;
|
||||
} else if (ShatteredPlansClient.a988da(playerName)) {
|
||||
return Strings.format(StringConstants.FRIEND_LIST_DUPE, playerName);
|
||||
} else if (PlayerListEntry.friendCount >= 100 && JagexApplet.membershipLevel <= 0) {
|
||||
return StringConstants.FRIEND_LIST_FULL;
|
||||
} else if (PlayerListEntry.friendCount >= 200) {
|
||||
return StringConstants.FRIEND_LIST_FULL;
|
||||
} else if (PlayerListEntry.isIgnored(playerName)) {
|
||||
return Strings.format(StringConstants.REMOVE_FROM_IGNORE_FIRST, playerName);
|
||||
} else {
|
||||
C2SPacket.friendIgnore(0, playerName);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static String addIgnore(final String var1) {
|
||||
if (PlayerListEntry.isValidPlayerName(var1)) {
|
||||
if (JagexApplet.a623jp(var1)) {
|
||||
return StringConstants.CANNOT_ADD_YOURSELF;
|
||||
} else if (PlayerListEntry.serverStatus != PlayerListEntry.ServerStatus.LOADED) {
|
||||
return StringConstants.UNABLE_TO_ADD_IGNORE;
|
||||
} else if (PlayerListEntry.isIgnored(var1)) {
|
||||
return Strings.format(StringConstants.IGNORE_LIST_DUPE, var1);
|
||||
} else if (PlayerListEntry.ignoreCount < 100) {
|
||||
if (ShatteredPlansClient.a988da(var1)) {
|
||||
return Strings.format(StringConstants.REMOVE_FRIEND_FIRST, var1);
|
||||
} else {
|
||||
C2SPacket.friendIgnore(2, var1);
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
return StringConstants.IGNORE_LIST_FULL;
|
||||
}
|
||||
} else {
|
||||
return StringConstants.INVALID_NAME;
|
||||
}
|
||||
}
|
||||
|
||||
public static void showChatMessage(final @NotNull Channel channel, final @NotNull String message, final int var2, final String var3, final String var4) {
|
||||
showChatMessage(new ChatMessage(channel, var3, var2, var4, message));
|
||||
}
|
||||
|
||||
private static void showPlayersInRoom(final int roomId) {
|
||||
if (roomShowingPlayers != roomId) {
|
||||
final ClientLobbyRoom prevRoomShowingPlayers = ClientLobbyRoom.roomsMap.get(roomShowingPlayers);
|
||||
roomShowingPlayers = roomId;
|
||||
if (prevRoomShowingPlayers != null) {
|
||||
prevRoomShowingPlayers.joinedPlayerNames = null;
|
||||
}
|
||||
C2SPacket.showPlayersInGame(roomId);
|
||||
}
|
||||
}
|
||||
|
||||
private static int getChatFilters() {
|
||||
return chatFilterPrivate.encode() + (chatFilterRoom.encode() << 2) + (chatFilterLobby.encode() << 4);
|
||||
}
|
||||
|
||||
public static void setChatFilters(final int packed) {
|
||||
chatFilterLobby = FilterLevel.decode(Math.min((packed >> 4) & 0b11, 2));
|
||||
chatFilterRoom = FilterLevel.decode(Math.min((packed >> 2) & 0b11, 2));
|
||||
chatFilterPrivate = FilterLevel.decode(Math.min(packed & 0b11, 2));
|
||||
}
|
||||
|
||||
public static @NotNull FilterLevel getChatChannelFilter(final @NotNull Channel channel) {
|
||||
return switch (channel) {
|
||||
case LOBBY -> chatFilterLobby;
|
||||
case ROOM -> chatFilterRoom;
|
||||
case PRIVATE -> chatFilterPrivate;
|
||||
default -> FilterLevel.ALL;
|
||||
};
|
||||
}
|
||||
|
||||
public static void showChatMessage(final ChatMessage message) {
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
ShatteredPlansClient._imb[i] = 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < ShatteredPlansClient.chatMessageCount; ++i) {
|
||||
if (ShatteredPlansClient.chatMessages[i].channel == message.channel) {
|
||||
ShatteredPlansClient._imb[ShatteredPlansClient.chatMessages[i].a410().ordinal()]++;
|
||||
}
|
||||
}
|
||||
ShatteredPlansClient._imb[message.a410().ordinal()]++;
|
||||
|
||||
int var1 = 0;
|
||||
for (int i = 0; i < ShatteredPlansClient.chatMessageCount; ++i) {
|
||||
if (ShatteredPlansClient.chatMessages[i].channel == message.channel) {
|
||||
final Channel var3 = ShatteredPlansClient.chatMessages[i].a410();
|
||||
if (ShatteredPlansClient._kpi < ShatteredPlansClient._imb[var3.ordinal()]) {
|
||||
ShatteredPlansClient._imb[var3.ordinal()]--;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
ShatteredPlansClient.chatMessages[var1++] = ShatteredPlansClient.chatMessages[i];
|
||||
}
|
||||
|
||||
ShatteredPlansClient.chatMessageCount = var1;
|
||||
ShatteredPlansClient.chatMessages[ShatteredPlansClient.chatMessageCount++] = message;
|
||||
}
|
||||
|
||||
public void addPlayerItems(final boolean var1) {
|
||||
if (this.playerName != null && this.playerId != ShatteredPlansClient.localPlayerId && ShatteredPlansClient.unratedLobbyRoom != null && ShatteredPlansClient.isCurrentRoomOwner()) {
|
||||
final LobbyPlayer var3 = LobbyPlayer.getOnline(this.playerId);
|
||||
final LobbyPlayer var4 = LobbyPlayer.getJoined(this.playerId);
|
||||
final String var5 = this.a738();
|
||||
if (var4 != null) {
|
||||
if (!ShatteredPlansClient.unratedLobbyRoom.hasStarted || ShatteredPlansClient.unratedLobbyRoom.finalElapsedTime >= 0) {
|
||||
this.view.addItem(Strings.format(StringConstants.MU_GAMEOPT_KICK_X_FROM_THIS_GAME, var5), KICK_FROM_GAME);
|
||||
}
|
||||
} else if (var3 != null && ShatteredPlansClient.unratedLobbyRoom.notInProgress && ShatteredPlansClient.unratedLobbyRoom.joinedPlayerCount < ShatteredPlansClient.unratedLobbyRoom.maxPlayerCount) {
|
||||
if (var3.inviteSent) {
|
||||
this.view.addItem(Strings.format(StringConstants.MU_GAMEOPT_WITHDRAW_INVITE_TO_X, var5), KICK_FROM_GAME);
|
||||
} else if (var1 && var3.joinRequestReceived) {
|
||||
this.view.addItem(Strings.format(StringConstants.MU_GAMEOPT_ACCEPT_X_INTO_GAME, var5), INVITE_TO_GAME);
|
||||
this.view.addItem(Strings.format(StringConstants.MU_GAMEOPT_REJECT_X_FROM_GAME, var5), KICK_FROM_GAME);
|
||||
} else {
|
||||
this.view.addItem(Strings.format(StringConstants.MU_GAMEOPT_INVITE_X_TO_GAME, var5), INVITE_TO_GAME);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean tick(final boolean mouseNotYetHandled) {
|
||||
@MagicConstant(valuesFromClass = ClickAction.class)
|
||||
final int which = this.view.getClickAction(mouseNotYetHandled);
|
||||
if (which == PASS) {
|
||||
return false;
|
||||
} else {
|
||||
switch (which) {
|
||||
case INVITE_TO_GAME -> C2SPacket.inviteToGame(this.playerId);
|
||||
case KICK_FROM_GAME -> C2SPacket.kickFromGame(this.playerId);
|
||||
|
||||
case SUBMIT_JOIN_ROOM_REQUEST -> C2SPacket.requestToJoinRoom(this.roomId);
|
||||
case WITHDRAW_JOIN_ROOM_REQUEST -> C2SPacket.requestToLeaveRoom(this.roomId);
|
||||
case SPECTATE_GAME -> C2SPacket.spectateGame(this.roomId);
|
||||
case SHOW_PLAYERS_IN_GAME -> showPlayersInRoom(this.roomId);
|
||||
case HIDE_PLAYERS_IN_GAME -> showPlayersInRoom(0);
|
||||
|
||||
case ADD_FRIEND -> this.maybeShowSocialActionError(addFriend(this.playerName));
|
||||
case REMOVE_FRIEND -> this.maybeShowSocialActionError(PlayerListEntry.removeFriend(this.playerName));
|
||||
case ADD_IGNORE -> this.maybeShowSocialActionError(addIgnore(this.playerName));
|
||||
case REMOVE_IGNORE -> this.maybeShowSocialActionError(PlayerListEntry.removeIgnore(this.playerName, this.playerDisplayName));
|
||||
|
||||
case CHAT_SHOW_ALL -> setChatFilter(Objects.requireNonNull(this.selectedChannel), FilterLevel.ALL);
|
||||
case CHAT_SHOW_FRIENDS -> setChatFilter(Objects.requireNonNull(this.selectedChannel), FilterLevel.FRIENDS);
|
||||
case CHAT_SHOW_NONE -> setChatFilter(Objects.requireNonNull(this.selectedChannel), FilterLevel.NONE);
|
||||
|
||||
case SEND_PRIVATE_MESSAGE -> sendPrivateMessage(this.playerId, this.playerName);
|
||||
case SEND_CHANNEL_MESSAGE -> sendChannelMessage();
|
||||
case SEND_PRIVATE_MESSAGE_QC -> sendPrivateMessageQC(this.playerName, this.playerId);
|
||||
case SEND_CHANNEL_MESSAGE_QC -> sendChannelMessageQC();
|
||||
case AUTO_RESPOND -> autoRespond(this.playerId, this.playerName, this._i, Objects.requireNonNull(this.selectedChannel));
|
||||
case REPORT_ABUSE -> this.openReportAbuseDialog();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private void maybeShowSocialActionError(final String message) {
|
||||
if (message != null) {
|
||||
showChatMessage(Channel.PRIVATE, message, 0, this.playerName, null);
|
||||
}
|
||||
}
|
||||
|
||||
private void openReportAbuseDialog() {
|
||||
ReportAbuseDialog.openInstance = new ReportAbuseDialog(this.target.x2, this.target.y2, this.target.width, this.target.height, Component.TAB_ACTIVE, Component.CLOSE_BUTTON, Component.LABEL, Component.CHECKBOX, Component.UNSELECTED_LABEL, this.playerName, this.playerId);
|
||||
}
|
||||
|
||||
public void a124(final int[] var1, final @NotNull Channel var2) {
|
||||
if (this.playerName != null && (this.playerId != ShatteredPlansClient.localPlayerId || var2 == Channel.PRIVATE) && PlayerListEntry.serverStatus == PlayerListEntry.ServerStatus.LOADED) {
|
||||
final String var4 = this.a738();
|
||||
final PlayerListEntry var5 = PlayerListEntry.lookupFriend(this.playerName);
|
||||
final boolean var6 = PlayerListEntry.isIgnored(this.playerName);
|
||||
if (var5 == null && !var6) {
|
||||
this.view.addItem(Strings.format(StringConstants.ADD_X_TO_FRIENDS, var4), ADD_FRIEND);
|
||||
this.view.addItem(Strings.format(StringConstants.ADD_X_TO_IGNORE, var4), ADD_IGNORE);
|
||||
if (var1 != null && var2 != Channel.PRIVATE && !JagexApplet.cannotChat) {
|
||||
this._i = var1;
|
||||
this.view.addItem(Strings.format(StringConstants.AUTO_RESPOND, var4), AUTO_RESPOND);
|
||||
}
|
||||
}
|
||||
|
||||
if (var5 != null) {
|
||||
if (!ShatteredPlansClient.isComposingChatMessageTo(this.playerName) && !JagexApplet.cannotChat) {
|
||||
if (!JagexApplet.canOnlyQuickChat) {
|
||||
this.view.addItem(Strings.format(StringConstants.SEND_PM_TO_X, var4), SEND_PRIVATE_MESSAGE);
|
||||
}
|
||||
|
||||
this.view.addItem(Strings.format(StringConstants.SEND_QC_TO_X, var4), SEND_PRIVATE_MESSAGE_QC);
|
||||
if (var1 != null) {
|
||||
this._i = var1;
|
||||
this.view.addItem(Strings.format(StringConstants.AUTO_RESPOND, var4), AUTO_RESPOND);
|
||||
}
|
||||
}
|
||||
|
||||
this.view.addItem(Strings.format(StringConstants.RM_X_FROM_FRIENDS, var4), REMOVE_FRIEND);
|
||||
}
|
||||
|
||||
if (var6) {
|
||||
this.view.addItem(Strings.format(StringConstants.RM_X_FROM_IGNORE, var4), REMOVE_IGNORE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String a738() {
|
||||
return this.playerDisplayName == null ? this.playerName : this.playerDisplayName;
|
||||
}
|
||||
|
||||
public void b150() {
|
||||
|
||||
if (this.playerName != null && ShatteredPlansClient.localPlayerId != this.playerId) {
|
||||
final String var2 = this.a738();
|
||||
this.view.addItem(Strings.format(StringConstants.REPORT_X_FOR_ABUSE, var2), REPORT_ABUSE);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void a430(final boolean var2) {
|
||||
|
||||
this.view.b540(var2);
|
||||
}
|
||||
|
||||
public void a408(final ChatMessage message) {
|
||||
if (!message._h) {
|
||||
this.selectedChannel = message.channel;
|
||||
if (message.channel == Channel.LOBBY) {
|
||||
if (chatFilterLobby == FilterLevel.ALL) {
|
||||
this.view.addItem(StringConstants.MU_CHAT_LOBBY_FRIENDS_ONLY, CHAT_SHOW_FRIENDS);
|
||||
}
|
||||
this.view.addItem(StringConstants.MU_CHAT_LOBBY_HIDE, CHAT_SHOW_NONE);
|
||||
} else if (message.channel == Channel.ROOM) {
|
||||
if (chatFilterRoom == FilterLevel.ALL) {
|
||||
this.view.addItem(StringConstants.MU_CHAT_GAME_FRIENDS_ONLY, CHAT_SHOW_FRIENDS);
|
||||
}
|
||||
this.view.addItem(StringConstants.MU_CHAT_GAME_HIDE, CHAT_SHOW_NONE);
|
||||
} else if (message.channel == Channel.PRIVATE) {
|
||||
if (chatFilterPrivate == FilterLevel.ALL) {
|
||||
this.view.addItem(StringConstants.MU_CHAT_PM_FRIENDS_ONLY, CHAT_SHOW_FRIENDS);
|
||||
}
|
||||
this.view.addItem(StringConstants.MU_CHAT_INVISIBLE_AND_SILENT_MODE, CHAT_SHOW_NONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void a487() {
|
||||
if (ShatteredPlansClient.unratedLobbyRoom == null) {
|
||||
final ClientLobbyRoom room = ClientLobbyRoom.lookup(this.roomId);
|
||||
if (room != null) {
|
||||
if (room.youAreInvited) {
|
||||
this.view.addItem(Strings.format(StringConstants.ACCEPT_PLAYER_INVITATION, room.ownerName), SUBMIT_JOIN_ROOM_REQUEST);
|
||||
this.view.addItem(Strings.format(StringConstants.INVITE_DECLINE_XS_GAME, room.ownerName), WITHDRAW_JOIN_ROOM_REQUEST);
|
||||
} else {
|
||||
if (room.youCanJoin) {
|
||||
this.view.addItem(Strings.format(StringConstants.JOIN_XS_GAME, room.ownerName), SUBMIT_JOIN_ROOM_REQUEST);
|
||||
} else if (!room.submittedJoinRequest && room.notInProgress && !room.hasStarted) {
|
||||
this.view.addItem(Strings.format(StringConstants.JOIN_REQUEST_XS_GAME, room.ownerName), SUBMIT_JOIN_ROOM_REQUEST);
|
||||
}
|
||||
|
||||
if (room.submittedJoinRequest) {
|
||||
this.view.addItem(Strings.format(StringConstants.JOIN_WITHDRAW_REQUEST_XS_GAME, room.ownerName), WITHDRAW_JOIN_ROOM_REQUEST);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public static final class ClickAction {
|
||||
public static final int NONE = -1;
|
||||
public static final int PASS = -2;
|
||||
public static final int INVITE_TO_GAME = 0;
|
||||
public static final int KICK_FROM_GAME = 1;
|
||||
public static final int SUBMIT_JOIN_ROOM_REQUEST = 2;
|
||||
public static final int WITHDRAW_JOIN_ROOM_REQUEST = 3;
|
||||
public static final int ADD_FRIEND = 4;
|
||||
public static final int REMOVE_FRIEND = 5;
|
||||
public static final int ADD_IGNORE = 6;
|
||||
public static final int REMOVE_IGNORE = 7;
|
||||
public static final int SEND_PRIVATE_MESSAGE = 8;
|
||||
public static final int SPECTATE_GAME = 10;
|
||||
public static final int CHAT_SHOW_ALL = 11;
|
||||
public static final int CHAT_SHOW_FRIENDS = 12;
|
||||
public static final int CHAT_SHOW_NONE = 13;
|
||||
public static final int SEND_CHANNEL_MESSAGE = 14;
|
||||
public static final int SHOW_PLAYERS_IN_GAME = 15;
|
||||
public static final int HIDE_PLAYERS_IN_GAME = 16;
|
||||
public static final int REPORT_ABUSE = 17;
|
||||
public static final int SEND_PRIVATE_MESSAGE_QC = 18;
|
||||
public static final int AUTO_RESPOND = 19;
|
||||
public static final int SEND_CHANNEL_MESSAGE_QC = 20;
|
||||
}
|
||||
}
|
86
src/main/java/funorb/client/lobby/LobbyPlayer.java
Normal file
86
src/main/java/funorb/client/lobby/LobbyPlayer.java
Normal file
@ -0,0 +1,86 @@
|
||||
package funorb.client.lobby;
|
||||
|
||||
import funorb.util.CollectionUtil;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public final class LobbyPlayer extends Component<Component<?>> {
|
||||
public static List<LobbyPlayer> online;
|
||||
public static Map<Long, LobbyPlayer> onlineMap;
|
||||
public static List<LobbyPlayer> joinedPlayers;
|
||||
public static Map<Long, LobbyPlayer> joinedPlayersMap;
|
||||
|
||||
public final long playerId;
|
||||
public int rating;
|
||||
public long joinedAt;
|
||||
public int ratedGameCount;
|
||||
public Component<?> _xb;
|
||||
public int unlockedOptionsBitmap;
|
||||
public boolean joinRequestReceived;
|
||||
public int statusTimer;
|
||||
public Component<?> _Ob;
|
||||
public Component<?> _Mb;
|
||||
public int status;
|
||||
public int crown;
|
||||
public String playerDisplayName;
|
||||
public boolean inviteSent;
|
||||
public Component<?> _Jb;
|
||||
public String playerName;
|
||||
public Component<?> _Ab;
|
||||
|
||||
public LobbyPlayer(final long playerId, final String playerName, final String playerDisplayName) {
|
||||
super(null);
|
||||
this.playerName = playerName;
|
||||
this.playerDisplayName = playerDisplayName;
|
||||
this.playerId = playerId;
|
||||
}
|
||||
|
||||
public static LobbyPlayer getOnline(final long playerId) {
|
||||
return onlineMap.get(playerId);
|
||||
}
|
||||
|
||||
public static LobbyPlayer getJoined(final long playerId) {
|
||||
return joinedPlayersMap.get(playerId);
|
||||
}
|
||||
|
||||
public static void addOnline(final LobbyPlayer player) {
|
||||
online.remove(player);
|
||||
CollectionUtil.insertSorted(online, player, LobbyPlayer::lessThan);
|
||||
}
|
||||
|
||||
@SuppressWarnings("InverseElseComparator")
|
||||
private boolean lessThan(final LobbyPlayer other) {
|
||||
if (this.joinRequestReceived != other.joinRequestReceived) {
|
||||
return this.joinRequestReceived;
|
||||
} else if (this.inviteSent != other.inviteSent) {
|
||||
return this.inviteSent;
|
||||
} else {
|
||||
return this.joinedAt < other.joinedAt;
|
||||
}
|
||||
}
|
||||
|
||||
public void setName(final String name, final String displayName) {
|
||||
this.playerName = name;
|
||||
this.playerDisplayName = displayName;
|
||||
}
|
||||
|
||||
public boolean isInMap() {
|
||||
return onlineMap.containsKey(this.playerId) || joinedPlayersMap.containsKey(this.playerId);
|
||||
}
|
||||
|
||||
public static final class Status {
|
||||
public static final int NONE = 0;
|
||||
public static final int ENTERED_GAME = 1;
|
||||
public static final int JOINED_YOUR_GAME = 2;
|
||||
public static final int ENTERED_OTHER_GAME = 3;
|
||||
public static final int LEFT_LOBBY = 4;
|
||||
public static final int LOST_CON = 5;
|
||||
public static final int CANNOT_JOIN_FULL = 6;
|
||||
public static final int CANNOT_JOIN_IN_PROGRESS = 7;
|
||||
public static final int DECLINED_INVITE = 8;
|
||||
public static final int WITHDREW_REQUEST = 11;
|
||||
public static final int KICKED = 12;
|
||||
public static final int DROPPED_OUT = 13;
|
||||
}
|
||||
}
|
49
src/main/java/funorb/client/lobby/PlayerList.java
Normal file
49
src/main/java/funorb/client/lobby/PlayerList.java
Normal file
@ -0,0 +1,49 @@
|
||||
package funorb.client.lobby;
|
||||
|
||||
public final class PlayerList extends Component<Component<?>> {
|
||||
public final Component<PlayerListEntry> entries;
|
||||
public final ScrollPane<?> scrollPane;
|
||||
public final Component<?> addButton;
|
||||
public final Component<?> removeButton;
|
||||
|
||||
public PlayerList(final PlayerList other, final String addLabel, final String removeLabel) {
|
||||
this(other, other.scrollPane.viewport, other.scrollPane.scrollBar, other.addButton, addLabel, removeLabel);
|
||||
}
|
||||
|
||||
public PlayerList(final Component<?> attrsSrc, final Component<?> viewportAttrsSrc, final ScrollBar scrollBar, final Component<?> buttonAttrsSrc, final String addLabel, final String removeLabel) {
|
||||
super(attrsSrc);
|
||||
this.entries = new Component<>(null);
|
||||
this.scrollPane = new ScrollPane<>(this.entries, viewportAttrsSrc, scrollBar);
|
||||
this.addButton = new Component<>(buttonAttrsSrc);
|
||||
this.removeButton = new Component<>(buttonAttrsSrc);
|
||||
this.addButton.label = addLabel;
|
||||
this.removeButton.label = removeLabel;
|
||||
this.addChild(this.scrollPane);
|
||||
this.addChild(this.addButton);
|
||||
this.addChild(this.removeButton);
|
||||
}
|
||||
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
public void updateBounds(final int x, final int y, final int width, final int height) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.updateChildBounds();
|
||||
}
|
||||
|
||||
public void updateChildBounds() {
|
||||
final int buttonWidth = (this.width + 2) / 2;
|
||||
final int paneHeight = this.height - 20;
|
||||
//noinspection SuspiciousNameCombination
|
||||
this.scrollPane.setBounds(0, 0, this.width, paneHeight - 2, LABEL_HEIGHT);
|
||||
this.addButton.height = 20;
|
||||
this.addButton.x = 0;
|
||||
this.addButton.width = buttonWidth - 2;
|
||||
this.addButton.y = paneHeight;
|
||||
this.removeButton.width = this.width - buttonWidth;
|
||||
this.removeButton.x = buttonWidth;
|
||||
this.removeButton.y = paneHeight;
|
||||
this.removeButton.height = 20;
|
||||
}
|
||||
}
|
256
src/main/java/funorb/client/lobby/PlayerListEntry.java
Normal file
256
src/main/java/funorb/client/lobby/PlayerListEntry.java
Normal file
@ -0,0 +1,256 @@
|
||||
package funorb.client.lobby;
|
||||
|
||||
import funorb.Strings;
|
||||
import funorb.commonui.form.validator.UsernameValidator;
|
||||
import funorb.io.CipheredBuffer;
|
||||
import funorb.shatteredplans.C2SPacket;
|
||||
import funorb.shatteredplans.S2CPacket;
|
||||
import funorb.shatteredplans.StringConstants;
|
||||
import funorb.shatteredplans.client.JagexApplet;
|
||||
import funorb.shatteredplans.client.ShatteredPlansClient;
|
||||
import funorb.util.CollectionUtil;
|
||||
import org.intellij.lang.annotations.MagicConstant;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public final class PlayerListEntry extends Component<Component<?>> {
|
||||
@MagicConstant(valuesFromClass = ServerStatus.class)
|
||||
public static int serverStatus = ServerStatus.UNINITIALIZED;
|
||||
public static int ignoreCount;
|
||||
private static List<PlayerListEntry> ignores;
|
||||
private static Map<String, PlayerListEntry> ignoreMap;
|
||||
public static int friendCount;
|
||||
private static List<PlayerListEntry> friends;
|
||||
private static Map<String, PlayerListEntry> friendMap;
|
||||
|
||||
public String playerDisplayName;
|
||||
public String playerName;
|
||||
public Component<?> serverNameLabel;
|
||||
public Component<?> displayNameChangedIcon;
|
||||
private int index;
|
||||
public String serverName;
|
||||
public String previousDisplayName;
|
||||
public Component<?> playerNameLabel;
|
||||
|
||||
private PlayerListEntry() {
|
||||
super(null);
|
||||
}
|
||||
|
||||
public static String removeFriend(final String playerName) {
|
||||
if (!isValidPlayerName(playerName)) {
|
||||
return StringConstants.INVALID_NAME;
|
||||
}
|
||||
if (serverStatus != ServerStatus.LOADED) {
|
||||
return StringConstants.UNABLE_TO_DELETE_FRIEND;
|
||||
}
|
||||
|
||||
final PlayerListEntry entry = lookupFriend(playerName);
|
||||
if (entry == null) {
|
||||
return Strings.format(StringConstants.FRIEND_NOT_FOUND, playerName);
|
||||
}
|
||||
|
||||
final int entryIndex = friends.indexOf(entry);
|
||||
friends.remove(entryIndex);
|
||||
friends.stream().skip(entryIndex).forEach(entry1 -> entry1.index--);
|
||||
friendMap.remove(Strings.normalize(playerName));
|
||||
friendCount--;
|
||||
C2SPacket.friendIgnore(1, playerName);
|
||||
return null;
|
||||
}
|
||||
|
||||
static boolean isValidPlayerName(final CharSequence playerName) {
|
||||
return UsernameValidator.isValidUsername(playerName, true)
|
||||
&& IntStream.range(0, playerName.length()).allMatch(i -> Strings.isNormalizable(playerName.charAt(i)));
|
||||
}
|
||||
|
||||
public static String removeIgnore(final String playerName, final String playerDisplayName) {
|
||||
if (!isValidPlayerName(playerName)) {
|
||||
return StringConstants.INVALID_NAME;
|
||||
} else if (serverStatus == ServerStatus.LOADED) {
|
||||
final PlayerListEntry var4 = lookupIgnore(playerDisplayName);
|
||||
if (var4 == null) {
|
||||
return Strings.format(StringConstants.IGNORE_NOT_FOUND, playerDisplayName);
|
||||
} else {
|
||||
ignores.remove(var4);
|
||||
ignoreMap.remove(Strings.normalizeIfPossible(playerDisplayName));
|
||||
--ignoreCount;
|
||||
|
||||
C2SPacket.friendIgnore(3, playerName);
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
return StringConstants.UNABLE_TO_DELETE_IGNORE;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean lessThan(final PlayerListEntry other) {
|
||||
int delta = other.index - this.index;
|
||||
|
||||
if (Objects.equals(other.serverName, ShatteredPlansClient.currentServerName)) {
|
||||
delta -= 200;
|
||||
} else if (other.serverName == null) {
|
||||
delta += 200;
|
||||
}
|
||||
if (Objects.equals(this.serverName, ShatteredPlansClient.currentServerName)) {
|
||||
delta += 200;
|
||||
} else if (this.serverName == null) {
|
||||
delta -= 200;
|
||||
}
|
||||
|
||||
return delta > 0;
|
||||
}
|
||||
|
||||
public static boolean isIgnored(final String displayName) {
|
||||
return lookupIgnore(displayName) != null;
|
||||
}
|
||||
|
||||
private static PlayerListEntry lookupIgnore(final String displayName) {
|
||||
return ignoreMap == null ? null : ignoreMap.get(Strings.normalizeIfPossible(displayName));
|
||||
}
|
||||
|
||||
public static PlayerListEntry lookupFriend(final String displayName) {
|
||||
return (friendMap == null || displayName == null || displayName.isEmpty())
|
||||
? null
|
||||
: friendMap.get(Strings.normalize(displayName));
|
||||
}
|
||||
|
||||
public static void initialize(final @NotNull Component<PlayerListEntry> friendList, final @NotNull Component<PlayerListEntry> ignoreList) {
|
||||
if (friendList.children == null) {
|
||||
friendList.children = new ArrayList<>();
|
||||
}
|
||||
if (ignoreList.children == null) {
|
||||
ignoreList.children = new ArrayList<>();
|
||||
}
|
||||
if (friendMap == null) {
|
||||
friendMap = new HashMap<>();
|
||||
}
|
||||
if (ignoreMap == null) {
|
||||
ignoreMap = new HashMap<>();
|
||||
}
|
||||
|
||||
friends = friendList.children;
|
||||
ignores = ignoreList.children;
|
||||
reset();
|
||||
}
|
||||
|
||||
public static void reset() {
|
||||
ShatteredPlansClient.currentServerName = null;
|
||||
friendCount = 0;
|
||||
ignoreCount = 0;
|
||||
friends.clear();
|
||||
ignores.clear();
|
||||
friendMap.clear();
|
||||
ignoreMap.clear();
|
||||
serverStatus = ServerStatus.UNINITIALIZED;
|
||||
}
|
||||
|
||||
public static void handleSocialPacket(@SuppressWarnings("SameParameterValue") final CipheredBuffer packet) {
|
||||
final int type = packet.readUByte();
|
||||
if (type == S2CPacket.SocialAction.IGNORE) {
|
||||
handleIgnorePacket(packet);
|
||||
} else if (type == S2CPacket.SocialAction.FRIEND) {
|
||||
handleFriendPacket(packet);
|
||||
} else if (type == S2CPacket.SocialAction.LOADED) {
|
||||
if (serverStatus == ServerStatus.LOADING) {
|
||||
serverStatus = ServerStatus.LOADED;
|
||||
}
|
||||
} else if (type == S2CPacket.SocialAction.LOADING) {
|
||||
if (serverStatus == ServerStatus.LOADED) {
|
||||
serverStatus = ServerStatus.LOADING;
|
||||
}
|
||||
} else if (type == S2CPacket.SocialAction.INITIALIZE) {
|
||||
serverStatus = ServerStatus.LOADING;
|
||||
ShatteredPlansClient.currentServerName = packet.readNullTerminatedString().intern();
|
||||
ContextMenu.setChatFilters(packet.readUByte());
|
||||
} else {
|
||||
JagexApplet.clientError(null, "F1: " + JagexApplet.a738w());
|
||||
JagexApplet.shutdownServerConnection();
|
||||
}
|
||||
}
|
||||
|
||||
private static void handleIgnorePacket(final CipheredBuffer packet) {
|
||||
if (ignoreMap == null) {
|
||||
ignoreMap = new HashMap<>();
|
||||
ignoreCount = 0;
|
||||
}
|
||||
|
||||
final boolean hasNonDisplayName = packet.readUByte() == 1;
|
||||
final String displayName = packet.readNullTerminatedString();
|
||||
final String playerName;
|
||||
if (hasNonDisplayName) {
|
||||
playerName = packet.readNullTerminatedString();
|
||||
} else {
|
||||
playerName = displayName;
|
||||
}
|
||||
|
||||
PlayerListEntry entry = lookupIgnore(displayName);
|
||||
final String previousName = packet.readNullTerminatedString();
|
||||
final String normalizedDisplayName = Strings.normalizeIfPossible(displayName);
|
||||
|
||||
if (entry == null) {
|
||||
entry = lookupIgnore(previousName);
|
||||
if (entry != null) {
|
||||
ignoreMap.put(normalizedDisplayName, entry);
|
||||
}
|
||||
}
|
||||
|
||||
if (entry == null) {
|
||||
entry = new PlayerListEntry();
|
||||
ignoreMap.put(normalizedDisplayName, entry);
|
||||
entry.index = ignoreCount++;
|
||||
ignores.add(entry);
|
||||
}
|
||||
|
||||
entry.playerName = playerName;
|
||||
entry.playerDisplayName = displayName;
|
||||
entry.previousDisplayName = previousName;
|
||||
}
|
||||
|
||||
private static void handleFriendPacket(final CipheredBuffer packet) {
|
||||
if (friendMap == null) {
|
||||
friendMap = new HashMap<>();
|
||||
friendCount = 0;
|
||||
}
|
||||
|
||||
String serverName = packet.readNullableNullTerminatedString();
|
||||
if (serverName != null) {
|
||||
serverName = serverName.intern();
|
||||
}
|
||||
|
||||
final String displayName = packet.readNullTerminatedString();
|
||||
final String previousDisplayName = packet.readNullTerminatedString();
|
||||
PlayerListEntry entry = lookupFriend(displayName);
|
||||
if (entry == null) {
|
||||
entry = lookupFriend(previousDisplayName);
|
||||
if (entry != null) {
|
||||
friendMap.put(Strings.normalize(displayName), entry);
|
||||
}
|
||||
}
|
||||
|
||||
if (entry == null) {
|
||||
entry = new PlayerListEntry();
|
||||
friendMap.put(Strings.normalize(displayName), entry);
|
||||
entry.index = friendCount++;
|
||||
}
|
||||
|
||||
entry.playerDisplayName = displayName;
|
||||
entry.serverName = serverName;
|
||||
entry.previousDisplayName = previousDisplayName;
|
||||
|
||||
friends.remove(entry);
|
||||
CollectionUtil.insertSorted(friends, entry, PlayerListEntry::lessThan);
|
||||
}
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public static final class ServerStatus {
|
||||
public static final int UNINITIALIZED = 0;
|
||||
public static final int LOADING = 1;
|
||||
public static final int LOADED = 2;
|
||||
}
|
||||
}
|
143
src/main/java/funorb/client/lobby/PopupMenu.java
Normal file
143
src/main/java/funorb/client/lobby/PopupMenu.java
Normal file
@ -0,0 +1,143 @@
|
||||
package funorb.client.lobby;
|
||||
|
||||
import funorb.awt.KeyState;
|
||||
import funorb.awt.MouseState;
|
||||
import funorb.graphics.Drawing;
|
||||
import funorb.graphics.Font;
|
||||
import funorb.graphics.Sprite;
|
||||
import funorb.shatteredplans.StringConstants;
|
||||
import funorb.shatteredplans.client.JagexApplet;
|
||||
import org.intellij.lang.annotations.MagicConstant;
|
||||
|
||||
public final class PopupMenu extends Component<Component<?>> {
|
||||
private final int _yb;
|
||||
private final Component<?> _Nb;
|
||||
private final Sprite[] _Lb;
|
||||
private final Component<?> _Mb;
|
||||
private final int _Eb;
|
||||
private final int _Kb;
|
||||
private final int _zb;
|
||||
private final int _Jb;
|
||||
private final ActionButton[] items;
|
||||
@MagicConstant(valuesFromClass = ContextMenu.ClickAction.class)
|
||||
private final int[] actions;
|
||||
private int _Bb;
|
||||
private int clickTargetCount;
|
||||
|
||||
public PopupMenu(final PopupMenu attrsSrc) {
|
||||
this(attrsSrc, attrsSrc._Lb, attrsSrc._Nb, attrsSrc._Mb, attrsSrc._Kb, attrsSrc._Eb, attrsSrc._Jb, attrsSrc._yb, attrsSrc._zb);
|
||||
}
|
||||
|
||||
public PopupMenu(final Component<?> attrsSrc, final Sprite[] var2, final Component<?> var3, final Component<?> var4, final int var5, final int var6, final int var7, final int var8, final int var9) {
|
||||
super(attrsSrc);
|
||||
this.actions = new int[256];
|
||||
this.items = new ActionButton[256];
|
||||
this._Bb = -2;
|
||||
this._Kb = var5;
|
||||
this._Lb = var2;
|
||||
this._zb = var9;
|
||||
this._Mb = var4;
|
||||
this._Jb = var7;
|
||||
this._Nb = var3;
|
||||
this._Eb = var6;
|
||||
this._yb = var8;
|
||||
}
|
||||
|
||||
public static int positionPopupX(final int targetX, final int targetWidth, final int popupWidth) {
|
||||
if (targetX + popupWidth <= Drawing.width) {
|
||||
return targetX;
|
||||
} else if (targetX + targetWidth - popupWidth >= 0) {
|
||||
return targetX + targetWidth - popupWidth;
|
||||
} else {
|
||||
return Drawing.width - popupWidth;
|
||||
}
|
||||
}
|
||||
|
||||
public static int positionPopupY(final int targetY, final int targetHeight, final int popupHeight) {
|
||||
if (popupHeight + targetHeight + targetY <= Drawing.height) {
|
||||
return targetY + targetHeight;
|
||||
} else if (targetY - popupHeight >= 0) {
|
||||
return targetY - popupHeight;
|
||||
} else {
|
||||
return Drawing.height - popupHeight;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean f427() {
|
||||
if (this._Bb == -2) {
|
||||
if (JagexApplet.lastTypedKeyCode == KeyState.Code.ESCAPE) {
|
||||
this._Bb = -1;
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void addItem(final Sprite sprite, final String tooltip, @MagicConstant(valuesFromClass = ContextMenu.ClickAction.class) final int action) {
|
||||
this.items[this.clickTargetCount] = new ActionButton(null, this._Mb, sprite, tooltip);
|
||||
this.items[this.clickTargetCount].mouseOverNineSliceSprites = this._Lb;
|
||||
this.items[this.clickTargetCount]._r = true;
|
||||
this.items[this.clickTargetCount].verticalAlignment = Font.VerticalAlignment.MIDDLE;
|
||||
this.addChild(this.items[this.clickTargetCount]);
|
||||
this.actions[this.clickTargetCount] = action;
|
||||
++this.clickTargetCount;
|
||||
}
|
||||
|
||||
public void addItem(final String tooltip, @MagicConstant(valuesFromClass = ContextMenu.ClickAction.class) final int action) {
|
||||
this.addItem(null, tooltip, action);
|
||||
}
|
||||
|
||||
public void positionRelativeToTarget(final int targetX, final int targetY) {
|
||||
this.positionRelativeToTarget(targetX, targetY, 0, 0);
|
||||
}
|
||||
|
||||
public void positionRelativeToTarget(final int targetX, final int targetY, final int targetWidth, final int targetHeight) {
|
||||
if (this.clickTargetCount == 0) {
|
||||
this.items[this.clickTargetCount] = new ActionButton(null, this._Nb, null, StringConstants.NO_OPTIONS_AVAILABLE);
|
||||
this.items[this.clickTargetCount].verticalAlignment = Font.VerticalAlignment.MIDDLE;
|
||||
this.addChild(this.items[this.clickTargetCount]);
|
||||
this.actions[this.clickTargetCount] = -1;
|
||||
++this.clickTargetCount;
|
||||
}
|
||||
|
||||
int width = 0;
|
||||
for (int i = 0; i < this.clickTargetCount; ++i) {
|
||||
final int var8 = this.items[i].a776(this._Jb, this._Eb);
|
||||
if (width < var8) {
|
||||
width = var8;
|
||||
}
|
||||
}
|
||||
|
||||
width += this._Kb * 2;
|
||||
final int height = this._yb + this._yb + this.clickTargetCount * this._zb;
|
||||
final int x = positionPopupX(targetX, targetWidth, width);
|
||||
final int y = positionPopupY(targetY, targetHeight, height);
|
||||
this.setBounds(x, y, width, height);
|
||||
|
||||
for (int i = 0; i < this.clickTargetCount; ++i) {
|
||||
this.items[i].a370(this._zb, this._yb + i * this._zb, this._Eb, this._Jb, width - (2 * this._Kb), this._Kb);
|
||||
}
|
||||
}
|
||||
|
||||
@MagicConstant(valuesFromClass = ContextMenu.ClickAction.class)
|
||||
public int getClickAction(final boolean mouseNotYetHandled) {
|
||||
this.rootProcessMouseEvents(mouseNotYetHandled);
|
||||
if (mouseNotYetHandled) {
|
||||
for (int i = 0; i < this.clickTargetCount; ++i) {
|
||||
if (this.items[i].clickButton != MouseState.Button.NONE) {
|
||||
//noinspection MagicConstant
|
||||
return this.actions[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (JagexApplet.mouseButtonJustClicked == MouseState.Button.NONE) {
|
||||
return this._Bb;
|
||||
} else {
|
||||
return ContextMenu.ClickAction.NONE;
|
||||
}
|
||||
} else {
|
||||
return ContextMenu.ClickAction.PASS;
|
||||
}
|
||||
}
|
||||
}
|
36
src/main/java/funorb/client/lobby/QuickChatCategories.java
Normal file
36
src/main/java/funorb/client/lobby/QuickChatCategories.java
Normal file
@ -0,0 +1,36 @@
|
||||
package funorb.client.lobby;
|
||||
|
||||
import funorb.cache.ResourceLoader;
|
||||
import funorb.data.LRUCache;
|
||||
import funorb.io.Buffer;
|
||||
|
||||
public final class QuickChatCategories {
|
||||
private final ResourceLoader loader;
|
||||
private final LRUCache<Integer, QuickChatCategory> _b = new LRUCache<>();
|
||||
|
||||
public QuickChatCategories(final ResourceLoader loader) {
|
||||
this.loader = loader;
|
||||
if (this.loader != null) {
|
||||
this.loader.itemCount(0);
|
||||
}
|
||||
}
|
||||
|
||||
public QuickChatCategory get(final int id) {
|
||||
final QuickChatCategory loadedCategory = this._b.get(id);
|
||||
if (loadedCategory != null) {
|
||||
return loadedCategory;
|
||||
}
|
||||
|
||||
final byte[] data = this.loader.getResource(0, id & 0x7fff);
|
||||
final QuickChatCategory category = new QuickChatCategory();
|
||||
if (data != null) {
|
||||
category.load(new Buffer(data));
|
||||
}
|
||||
if (id >= 0x8000) {
|
||||
category.markHigh();
|
||||
}
|
||||
|
||||
this._b.put(id, category);
|
||||
return category;
|
||||
}
|
||||
}
|
63
src/main/java/funorb/client/lobby/QuickChatCategory.java
Normal file
63
src/main/java/funorb/client/lobby/QuickChatCategory.java
Normal file
@ -0,0 +1,63 @@
|
||||
package funorb.client.lobby;
|
||||
|
||||
import funorb.Strings;
|
||||
import funorb.io.Buffer;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public final class QuickChatCategory {
|
||||
public boolean _y = false;
|
||||
public String name;
|
||||
public char[] _s;
|
||||
public char[] _p;
|
||||
public int[] _x;
|
||||
public int[] _r;
|
||||
|
||||
public void markHigh() {
|
||||
if (this._x != null) {
|
||||
Arrays.setAll(this._x, i -> this._x[i] | 0x8000);
|
||||
}
|
||||
if (this._r != null) {
|
||||
Arrays.setAll(this._r, i -> this._r[i] | 0x8000);
|
||||
}
|
||||
}
|
||||
|
||||
public void load(final Buffer buffer) {
|
||||
while (true) {
|
||||
final int type = buffer.readUByte();
|
||||
if (type == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.loadEntry(buffer, type);
|
||||
}
|
||||
}
|
||||
|
||||
private void loadEntry(final Buffer buffer, final int type) {
|
||||
if (type == 1) {
|
||||
this.name = buffer.readNullTerminatedString();
|
||||
} else if (type == 2) {
|
||||
final int len = buffer.readUByte();
|
||||
this._p = new char[len];
|
||||
this._r = new int[len];
|
||||
|
||||
for (int i = 0; i < len; ++i) {
|
||||
this._r[i] = buffer.readUShort();
|
||||
final byte var6 = buffer.readByte();
|
||||
this._p[i] = var6 == 0 ? 0 : Strings.decode1252Char(var6);
|
||||
}
|
||||
} else if (type == 3) {
|
||||
final int var4 = buffer.readUByte();
|
||||
this._s = new char[var4];
|
||||
this._x = new int[var4];
|
||||
|
||||
for (int i = 0; i < var4; ++i) {
|
||||
this._x[i] = buffer.readUShort();
|
||||
final byte var6 = buffer.readByte();
|
||||
this._s[i] = var6 == 0 ? 0 : Strings.decode1252Char(var6);
|
||||
}
|
||||
} else if (type == 4) {
|
||||
this._y = true;
|
||||
}
|
||||
}
|
||||
}
|
63
src/main/java/funorb/client/lobby/QuickChatHelpPanel.java
Normal file
63
src/main/java/funorb/client/lobby/QuickChatHelpPanel.java
Normal file
@ -0,0 +1,63 @@
|
||||
package funorb.client.lobby;
|
||||
|
||||
import funorb.awt.MouseState;
|
||||
import funorb.graphics.Font;
|
||||
import funorb.shatteredplans.StringConstants;
|
||||
import funorb.shatteredplans.client.JagexApplet;
|
||||
import funorb.shatteredplans.client.ShatteredPlansClient;
|
||||
|
||||
public final class QuickChatHelpPanel extends Component<Component<?>> {
|
||||
public static QuickChatHelpPanel openInstance;
|
||||
private final Component<?> closeButton;
|
||||
|
||||
public QuickChatHelpPanel(final Component<?> var2, final Component<?> var3, final Component<?> var4) {
|
||||
final Component<Component<?>> var7 = new Component<>(var2, StringConstants.QUICK_CHAT_HELP.toUpperCase());
|
||||
var7.textAlignment = Font.HorizontalAlignment.CENTER;
|
||||
this.closeButton = new Component<>(var3);
|
||||
final Component<Component<?>> var8 = new Component<>(var4);
|
||||
final Component<Component<?>> var9 = new Component<>(var4, StringConstants.QUICK_CHAT_HELP_TITLE);
|
||||
var9.textAlignment = Font.HorizontalAlignment.CENTER;
|
||||
int var10 = 50;
|
||||
int var11 = 0;
|
||||
|
||||
for (int var12 = 0; var12 < StringConstants.QUICK_CHAT_SHORTCUT_HELP.length; ++var12) {
|
||||
final Component<?> var13 = new Component<>(var4, StringConstants.QUICK_CHAT_SHORTCUT_KEYS[var12]);
|
||||
final Component<?> var14 = new Component<>(var4, StringConstants.QUICK_CHAT_SHORTCUT_HELP[var12]);
|
||||
final int var15 = var4.font.measureLineWidth(StringConstants.QUICK_CHAT_SHORTCUT_HELP[var12]);
|
||||
var13.setBounds(20, var10, 65, 15);
|
||||
if (var15 > var11) {
|
||||
var11 = var15;
|
||||
}
|
||||
|
||||
var14.setBounds(90, var10, ShatteredPlansClient.SCREEN_WIDTH, 15);
|
||||
var8.addChild(var13);
|
||||
var8.addChild(var14);
|
||||
var10 += 30;
|
||||
}
|
||||
|
||||
var10 += 15;
|
||||
var7.setBounds(0, 0, 20 + var11 + 90, 24);
|
||||
this.setBounds(100, 100, var7.width, var10 + var7.height);
|
||||
this.closeButton.setBounds(var7.width - 20, 5, 15, 15);
|
||||
var8.setBounds(0, var7.height, this.width, -var7.height + this.height);
|
||||
var9.setBounds(0, 20, this.width, 15);
|
||||
var8.nineSliceSprites = Component.createGradientOutlineSprites(var8.height, 11579568, 8421504, 2105376);
|
||||
var7.addChild(this.closeButton);
|
||||
var8.addChild(var9);
|
||||
this.addChild(var7);
|
||||
this.addChild(var8);
|
||||
this.x = 320 - (this.width >> 1);
|
||||
}
|
||||
|
||||
public static void tick() {
|
||||
if (openInstance != null && openInstance.isCloseRequested()) {
|
||||
openInstance = null;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isCloseRequested() {
|
||||
this.rootProcessMouseEvents(true);
|
||||
return (JagexApplet.mouseButtonJustClicked != MouseState.Button.NONE && this.clickButton == MouseState.Button.NONE)
|
||||
|| this.closeButton.clickButton != MouseState.Button.NONE;
|
||||
}
|
||||
}
|
59
src/main/java/funorb/client/lobby/QuickChatResponse.java
Normal file
59
src/main/java/funorb/client/lobby/QuickChatResponse.java
Normal file
@ -0,0 +1,59 @@
|
||||
package funorb.client.lobby;
|
||||
|
||||
import funorb.io.Buffer;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public final class QuickChatResponse {
|
||||
private static final int[] SHORTS_TO_SKIP = {1, 0, 0, 0, 1, 0, 2, 1, 1, 1, 0, 2, 0, 0, 1, 0};
|
||||
|
||||
public int[] ids;
|
||||
private String[] strings;
|
||||
|
||||
public void load(final Buffer buffer) {
|
||||
while (true) {
|
||||
final int type = buffer.readUByte();
|
||||
if (type == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.loadEntry(buffer, type);
|
||||
}
|
||||
}
|
||||
|
||||
private void loadEntry(final Buffer buffer, final int type) {
|
||||
if (type == 1) {
|
||||
this.strings = buffer.readNullTerminatedString().split("<");
|
||||
} else if (type == 2) {
|
||||
final int len = buffer.readUByte();
|
||||
this.ids = new int[len];
|
||||
for (int i = 0; i < len; ++i) {
|
||||
this.ids[i] = buffer.readUShort();
|
||||
}
|
||||
} else if (type == 3) {
|
||||
final int len = buffer.readUByte();
|
||||
for (int i = 0; i < len; ++i) {
|
||||
final int shortsToSkip = SHORTS_TO_SKIP[buffer.readUShort()];
|
||||
for (int j = 0; j < shortsToSkip; ++j) {
|
||||
buffer.readUShort();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void markHigh() {
|
||||
if (this.ids != null) {
|
||||
Arrays.setAll(this.ids, i -> this.ids[i] | 0x8000);
|
||||
}
|
||||
}
|
||||
|
||||
public String joinStrings() {
|
||||
if (this.strings == null) {
|
||||
return "";
|
||||
} else {
|
||||
return Arrays.stream(this.strings, 1, this.strings.length)
|
||||
.collect(Collectors.joining("...", this.strings[0], ""));
|
||||
}
|
||||
}
|
||||
}
|
36
src/main/java/funorb/client/lobby/QuickChatResponses.java
Normal file
36
src/main/java/funorb/client/lobby/QuickChatResponses.java
Normal file
@ -0,0 +1,36 @@
|
||||
package funorb.client.lobby;
|
||||
|
||||
import funorb.cache.ResourceLoader;
|
||||
import funorb.data.LRUCache;
|
||||
import funorb.io.Buffer;
|
||||
|
||||
public final class QuickChatResponses {
|
||||
private final ResourceLoader loader;
|
||||
private final LRUCache<Integer, QuickChatResponse> _f = new LRUCache<>();
|
||||
|
||||
public QuickChatResponses(final ResourceLoader loader) {
|
||||
this.loader = loader;
|
||||
if (this.loader != null) {
|
||||
this.loader.itemCount(1);
|
||||
}
|
||||
}
|
||||
|
||||
public QuickChatResponse get(final int id) {
|
||||
final QuickChatResponse loadedResponse = this._f.get(id);
|
||||
if (loadedResponse != null) {
|
||||
return loadedResponse;
|
||||
}
|
||||
|
||||
final byte[] data = this.loader.getResource(1, id & 0x7fff);
|
||||
final QuickChatResponse response = new QuickChatResponse();
|
||||
if (data != null) {
|
||||
response.load(new Buffer(data));
|
||||
}
|
||||
if (id >= 0x8000) {
|
||||
response.markHigh();
|
||||
}
|
||||
|
||||
this._f.put(id, response);
|
||||
return response;
|
||||
}
|
||||
}
|
273
src/main/java/funorb/client/lobby/ReportAbuseDialog.java
Normal file
273
src/main/java/funorb/client/lobby/ReportAbuseDialog.java
Normal file
@ -0,0 +1,273 @@
|
||||
package funorb.client.lobby;
|
||||
|
||||
import funorb.awt.KeyState;
|
||||
import funorb.awt.MouseState;
|
||||
import funorb.graphics.Font;
|
||||
import funorb.shatteredplans.C2SPacket;
|
||||
import funorb.shatteredplans.StringConstants;
|
||||
import funorb.shatteredplans.client.JagexApplet;
|
||||
import funorb.shatteredplans.client.ShatteredPlansClient;
|
||||
|
||||
public final class ReportAbuseDialog extends Component<Component<?>> {
|
||||
public static Component<?> _Nb;
|
||||
public static String _Kb = "ESC - cancel private message";
|
||||
public static ReportAbuseDialog openInstance;
|
||||
public static String[] RULE_STRINGS;
|
||||
private final long _Gb;
|
||||
private final Component<?> _Ob;
|
||||
private Component<?> _Bb;
|
||||
private Component<?>[] _Hb;
|
||||
private int _yb = -2;
|
||||
private Checkbox _zb;
|
||||
private StringBuilder _xb;
|
||||
|
||||
public ReportAbuseDialog(final int var1, final int var2, final int var3, final int var4, final Component<?> var7, final Component<?> var8, final Component<?> var9, final Checkbox var10, final Component<?> var11, final String var12, final long var13) {
|
||||
super(null);
|
||||
this._Gb = var13;
|
||||
final Component<Component<?>> _Jb = new Component<>(var7, StringConstants.RA_TITLE.toUpperCase());
|
||||
_Jb.textAlignment = Font.HorizontalAlignment.CENTER;
|
||||
this.addChild(_Jb);
|
||||
this._Ob = new Component<>(var8);
|
||||
_Jb.addChild(this._Ob);
|
||||
final Component<Component<?>> _Cb = new Component<>(null);
|
||||
this.addChild(_Cb);
|
||||
int var16;
|
||||
int var17;
|
||||
int var18;
|
||||
int var19;
|
||||
int var20;
|
||||
int var31;
|
||||
final Component<?> _Ab;
|
||||
if (var12 == null) {
|
||||
_Ab = new Component<>(var9, StringConstants.RA_INTRO_NO_NAME);
|
||||
_Ab.textAlignment = Font.HorizontalAlignment.CENTER;
|
||||
_Ab.textColor = 11184810;
|
||||
_Cb.addChild(_Ab);
|
||||
final short var27 = 226;
|
||||
final byte var30 = 10;
|
||||
var17 = _Ab.font.breakLines(_Ab.label, var27);
|
||||
_Ab.setBounds(13, var30, var27, Component.LABEL_HEIGHT * var17);
|
||||
var16 = var30 + Component.LABEL_HEIGHT * var17;
|
||||
_Cb.setBounds(0, 24, 252, var16 + 10);
|
||||
_Cb.nineSliceSprites = createGradientOutlineSprites(_Cb.height, 11579568, 8421504, 2105376);
|
||||
var18 = 252;
|
||||
var19 = 34 + var16;
|
||||
var20 = PopupMenu.positionPopupX(var1, var3, var18);
|
||||
var31 = PopupMenu.positionPopupY(var2, var4, var19);
|
||||
this.setBounds(var20, var31, var18, var19);
|
||||
} else {
|
||||
_Ab = new Component<>(var9, StringConstants.RA_INTRO);
|
||||
_Ab.textAlignment = Font.HorizontalAlignment.CENTER;
|
||||
_Ab.textColor = 11184810;
|
||||
_Cb.addChild(_Ab);
|
||||
final Component<?> _Fb = new Component<>(var9, StringConstants.RA_EXPLANATION);
|
||||
_Fb.textAlignment = Font.HorizontalAlignment.CENTER;
|
||||
_Fb.textColor = 11184810;
|
||||
_Cb.addChild(_Fb);
|
||||
this._Bb = new Component<>(var9);
|
||||
this._Bb.textColor = 16764006;
|
||||
_Cb.addChild(this._Bb);
|
||||
this._Bb._u = "|";
|
||||
if (JagexApplet.modLevel >= 5 || JagexApplet.adminLevel >= 2) {
|
||||
this._zb = new Checkbox(var10, JagexApplet.modLevel < 7 && JagexApplet.adminLevel < 2 ? StringConstants.RA_SUGGEST_MUTE : StringConstants.RA_MUTE_THIS_PLAYER);
|
||||
_Cb.addChild(this._zb);
|
||||
}
|
||||
|
||||
final Component<Component<?>> qr1 = new Component<>(null);
|
||||
final Component<Component<?>> qr2 = new Component<>(null);
|
||||
final Component<Component<?>> qr3 = new Component<>(null);
|
||||
_Cb.addChild(qr1);
|
||||
_Cb.addChild(qr2);
|
||||
_Cb.addChild(qr3);
|
||||
this._Hb = new Component[RULE_STRINGS.length];
|
||||
|
||||
for (var16 = 0; var16 < RULE_STRINGS.length; ++var16) {
|
||||
if (RULE_STRINGS[var16] != null) {
|
||||
this._Hb[var16] = new Component<>(var11, RULE_STRINGS[var16]);
|
||||
this._Hb[var16].textAlignment = Font.HorizontalAlignment.LEFT;
|
||||
this._Hb[var16].enabled = true;
|
||||
_Cb.addChild(this._Hb[var16]);
|
||||
}
|
||||
}
|
||||
|
||||
this._xb = new StringBuilder(12);
|
||||
this._xb.append(var12);
|
||||
|
||||
var16 = 0;
|
||||
var17 = var7.font.measureLineWidth(StringConstants.RULE_PILLAR_0);
|
||||
if (var17 > var16) {
|
||||
var16 = var17;
|
||||
}
|
||||
|
||||
var17 = var7.font.measureLineWidth(StringConstants.RULE_PILLAR_1);
|
||||
if (var17 > var16) {
|
||||
var16 = var17;
|
||||
}
|
||||
|
||||
var17 = var7.font.measureLineWidth(StringConstants.RULE_PILLAR_2);
|
||||
if (var17 > var16) {
|
||||
var16 = var17;
|
||||
}
|
||||
|
||||
for (var17 = 0; var17 < RULE_STRINGS.length; ++var17) {
|
||||
if (this._Hb[var17] != null) {
|
||||
var18 = this._Hb[var17].e474();
|
||||
if (var16 < var18) {
|
||||
var16 = var18;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (var16 > 140) {
|
||||
var16 = 140;
|
||||
}
|
||||
|
||||
var17 = 0;
|
||||
this.a315(var7, qr1, StringConstants.RULE_PILLAR_0, var16);
|
||||
var18 = this.a082(qr1, this._Hb[6], 32, var16);
|
||||
var18 = this.a082(qr1, this._Hb[9], var18, var16);
|
||||
var18 = this.a082(qr1, this._Hb[5], var18, var16);
|
||||
var18 = this.a082(qr1, this._Hb[7], var18, var16);
|
||||
var18 = this.a082(qr1, this._Hb[15], var18, var16);
|
||||
var18 = this.a082(qr1, this._Hb[4], var18, var16);
|
||||
if (var17 < var18) {
|
||||
var17 = var18;
|
||||
}
|
||||
|
||||
this.a315(var7, qr2, StringConstants.RULE_PILLAR_1, var16);
|
||||
var18 = this.a082(qr2, this._Hb[16], 32, var16);
|
||||
var18 = this.a082(qr2, this._Hb[17], var18, var16);
|
||||
var18 = this.a082(qr2, this._Hb[18], var18, var16);
|
||||
var18 = this.a082(qr2, this._Hb[19], var18, var16);
|
||||
var18 = this.a082(qr2, this._Hb[20], var18, var16);
|
||||
if (var18 > var17) {
|
||||
var17 = var18;
|
||||
}
|
||||
|
||||
this.a315(var7, qr3, StringConstants.RULE_PILLAR_2, var16);
|
||||
var18 = this.a082(qr3, this._Hb[13], 32, var16);
|
||||
var18 = this.a082(qr3, this._Hb[21], var18, var16);
|
||||
var18 = this.a082(qr3, this._Hb[11], var18, var16);
|
||||
if (var18 > var17) {
|
||||
var17 = var18;
|
||||
}
|
||||
|
||||
var19 = 3 * var16 + 26;
|
||||
var20 = _Jb.e474();
|
||||
if (var20 > var19) {
|
||||
var19 = var20;
|
||||
}
|
||||
|
||||
if (this._zb != null) {
|
||||
var20 = this._zb.c080();
|
||||
if (var19 < var20) {
|
||||
var19 = var20;
|
||||
}
|
||||
}
|
||||
|
||||
_Jb.setBounds(0, 0, var19 + 26, 24);
|
||||
this._Ob.setBounds(_Jb.width - 20, 5, 15, 15);
|
||||
final byte var21 = 10;
|
||||
_Ab.setBounds(13, var21, var19, Component.LABEL_HEIGHT * 2);
|
||||
var31 = var21 + Component.LABEL_HEIGHT * 2;
|
||||
_Fb.setBounds(13, var31, var19, Component.LABEL_HEIGHT * 2);
|
||||
var31 += Component.LABEL_HEIGHT * 2 + 10;
|
||||
this._Bb.setBounds(0, var31, 0, Component.LABEL_HEIGHT);
|
||||
var31 += Component.LABEL_HEIGHT + 10;
|
||||
if (this._zb != null) {
|
||||
var20 = this._zb.c080();
|
||||
this._zb.a669(var20, 13 + (var19 - var20) / 2, var31);
|
||||
var31 += Component.LABEL_HEIGHT + 10;
|
||||
}
|
||||
|
||||
qr1.setBounds(13, var31, var16, var17);
|
||||
qr2.setBounds(13 + var16 + 13, var31, var16, var17);
|
||||
qr3.setBounds(39 + var16 * 2, var31, var16, var17);
|
||||
_Cb.setBounds(0, 24, 13 + var19 + 13, var17 + var31 + 10);
|
||||
_Cb.nineSliceSprites = createGradientOutlineSprites(_Cb.height, 11579568, 8421504, 2105376);
|
||||
final int var23 = 13 + 13 + var19;
|
||||
final int var24 = var17 + 24 + var31 + 10;
|
||||
final int var25 = PopupMenu.positionPopupX(var1, var3, var23);
|
||||
final int var26 = PopupMenu.positionPopupY(var2, var4, var24);
|
||||
this.setBounds(var25, var26, var23, var24);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void tick(final boolean mouseNotYetHandled) {
|
||||
final int var3;
|
||||
if (openInstance != null) {
|
||||
var3 = openInstance.getAction(mouseNotYetHandled);
|
||||
if (var3 != -2) {
|
||||
if (var3 != -1) {
|
||||
final boolean var4 = openInstance.i154();
|
||||
C2SPacket.reportAbuse(openInstance._Gb, var4, openInstance.g983(), var3);
|
||||
}
|
||||
|
||||
openInstance = null;
|
||||
ShatteredPlansClient.dismissContextMenu();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void a315(final Component<?> var1, final Component<Component<?>> var2, final String var3, final int var4) {
|
||||
var2.addChild(new Component<>(var1, var4, 24, var3));
|
||||
}
|
||||
|
||||
private int a082(final Component<Component<?>> var2, final Component<?> var3, int var4, final int var5) {
|
||||
var4 += 8;
|
||||
final int var6 = var3.font.measureParagraphHeight(var3.label, var5 - 2 * var3._kb, var3._Y);
|
||||
var3.setBounds(0, var4, var5, var6);
|
||||
var4 += var6;
|
||||
var2.addChild(var3);
|
||||
return var4;
|
||||
}
|
||||
|
||||
public boolean h154() {
|
||||
if (this._yb == -2) {
|
||||
if (JagexApplet.lastTypedKeyCode == KeyState.Code.ESCAPE) {
|
||||
this._yb = -1;
|
||||
}
|
||||
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private String g983() {
|
||||
return this._xb.toString();
|
||||
}
|
||||
|
||||
private int getAction(final boolean var1) {
|
||||
this.rootProcessMouseEvents(var1);
|
||||
if (this._Bb != null) {
|
||||
this._Bb.label = this._xb.toString();
|
||||
this._Bb.x = (this.width - this._Bb.font.measureLineWidth(this._Bb.label)) / 2;
|
||||
if (this._zb != null && this._zb.clickButton != MouseState.Button.NONE) {
|
||||
this._zb.selected = !this._zb.selected;
|
||||
}
|
||||
|
||||
this._Bb.width = this.width - this._Bb.x;
|
||||
|
||||
for (int var3 = 0; var3 < RULE_STRINGS.length; ++var3) {
|
||||
if (this._Hb[var3] != null) {
|
||||
this._Hb[var3].enabled = this._xb.length() > 0;
|
||||
if (this._Hb[var3].enabled && this._Hb[var3].clickButton != MouseState.Button.NONE) {
|
||||
return var3;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this._Ob.clickButton == MouseState.Button.NONE) {
|
||||
return var1 && JagexApplet.mouseButtonJustClicked != MouseState.Button.NONE && this.clickButton == MouseState.Button.NONE ? -1 : this._yb;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean i154() {
|
||||
return this._zb != null && this._zb.selected;
|
||||
}
|
||||
}
|
211
src/main/java/funorb/client/lobby/ScrollBar.java
Normal file
211
src/main/java/funorb/client/lobby/ScrollBar.java
Normal file
@ -0,0 +1,211 @@
|
||||
package funorb.client.lobby;
|
||||
|
||||
import funorb.awt.MouseState;
|
||||
import funorb.shatteredplans.client.JagexApplet;
|
||||
|
||||
public final class ScrollBar extends Component<Component<?>> {
|
||||
private final Component<Component<?>> track;
|
||||
private final Component<?> upButton;
|
||||
private final Component<?> upperSlideRegion;
|
||||
private final Component<?> lowerSlideRegion;
|
||||
private final Component<?> dragBar;
|
||||
private final Component<?> downButton;
|
||||
private int repeatDelayTimer;
|
||||
|
||||
public ScrollBar(final Component<?> upButton, final Component<?> downButton, final Component<?> slideRegion, final Component<?> dragBar) {
|
||||
super(null);
|
||||
this.upButton = new Component<>(upButton);
|
||||
this.downButton = new Component<>(downButton);
|
||||
this.addChild(this.upButton);
|
||||
this.addChild(this.downButton);
|
||||
this.track = new Component<>(null);
|
||||
this.addChild(this.track);
|
||||
this.upperSlideRegion = new Component<>(slideRegion);
|
||||
this.lowerSlideRegion = new Component<>(slideRegion);
|
||||
this.lowerSlideRegion._r = true;
|
||||
this.upperSlideRegion._r = true;
|
||||
this.track.addChild(this.upperSlideRegion);
|
||||
this.track.addChild(this.lowerSlideRegion);
|
||||
this.dragBar = new Component<>(dragBar);
|
||||
this.dragBar.isDraggable = true;
|
||||
this.track.addChild(this.dragBar);
|
||||
}
|
||||
|
||||
@SuppressWarnings("CopyConstructorMissesField")
|
||||
public ScrollBar(final ScrollBar other) {
|
||||
this(other.upButton, other.downButton, other.upperSlideRegion, other.dragBar);
|
||||
}
|
||||
|
||||
public boolean isUpperSlideRegionClicked() {
|
||||
if (this.upperSlideRegion.clickButton == MouseState.Button.NONE) {
|
||||
if (this.upperSlideRegion.dragButton != MouseState.Button.NONE) {
|
||||
if (this.repeatDelayTimer > 0) {
|
||||
--this.repeatDelayTimer;
|
||||
}
|
||||
|
||||
if (this.repeatDelayTimer == 0 && this.dragBar.y2 + this.dragBar._w > JagexApplet.mouseY) {
|
||||
this.repeatDelayTimer = 3;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
} else {
|
||||
this.repeatDelayTimer = 20;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public int a791(final int var2, final int var3, final boolean var4) {
|
||||
int var5 = 0;
|
||||
final int var6 = this.track.height - this.dragBar.height;
|
||||
if (var6 > 0) {
|
||||
final int var7 = this.dragBar.y;
|
||||
final int var8 = -var3 + var2;
|
||||
var5 = (var6 / 2 + var8 * var7) / var6;
|
||||
}
|
||||
|
||||
if (var4) {
|
||||
if (var5 < 0) {
|
||||
var5 = 0;
|
||||
}
|
||||
|
||||
if (var5 > var2 - var3) {
|
||||
var5 = var2 - var3;
|
||||
}
|
||||
} else {
|
||||
if (-var3 + var2 < var5) {
|
||||
var5 = -var3 + var2;
|
||||
}
|
||||
|
||||
if (var5 < 0) {
|
||||
var5 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return var5;
|
||||
}
|
||||
|
||||
public boolean isUpButtonClicked() {
|
||||
if (this.upButton.clickButton == MouseState.Button.NONE) {
|
||||
if (this.upButton.dragButton != MouseState.Button.NONE) {
|
||||
if (this.repeatDelayTimer > 0) {
|
||||
--this.repeatDelayTimer;
|
||||
}
|
||||
|
||||
if (this.repeatDelayTimer == 0) {
|
||||
this.repeatDelayTimer = 3;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
this.repeatDelayTimer = 20;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isLowerSlideRegionClicked() {
|
||||
if (this.lowerSlideRegion.clickButton == MouseState.Button.NONE) {
|
||||
if (this.lowerSlideRegion.dragButton != MouseState.Button.NONE) {
|
||||
if (this.repeatDelayTimer > 0) {
|
||||
--this.repeatDelayTimer;
|
||||
}
|
||||
|
||||
if (this.repeatDelayTimer == 0 && JagexApplet.mouseY >= this.dragBar.y2 + this.dragBar._w + this.dragBar.height + this.dragBar._gb) {
|
||||
this.repeatDelayTimer = 3;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
} else {
|
||||
this.repeatDelayTimer = 20;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
public void setBounds(final int x, final int y, final int width, final int height, final int viewportHeight, final int contentHeight, final int scrollPosition) {
|
||||
this.x = x;
|
||||
this.height = height;
|
||||
this.y = y;
|
||||
this.width = width;
|
||||
this.updateScrollBounds(viewportHeight, contentHeight, scrollPosition);
|
||||
}
|
||||
|
||||
public boolean isDragBarBeingDragged() {
|
||||
return this.dragBar.dragButton != MouseState.Button.NONE;
|
||||
}
|
||||
|
||||
public boolean isDownButtonClicked() {
|
||||
if (this.downButton.clickButton == MouseState.Button.NONE) {
|
||||
if (this.downButton.dragButton != MouseState.Button.NONE) {
|
||||
if (this.repeatDelayTimer > 0) {
|
||||
--this.repeatDelayTimer;
|
||||
}
|
||||
|
||||
if (this.repeatDelayTimer == 0) {
|
||||
this.repeatDelayTimer = 3;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
} else {
|
||||
this.repeatDelayTimer = 20;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public void updateScrollBounds(final int viewportHeight, final int contentHeight, final int scrollPosition) {
|
||||
final int trackStart;
|
||||
final int trackEnd;
|
||||
if (this.width * 2 <= this.height) {
|
||||
trackStart = this.width;
|
||||
trackEnd = this.height - this.width;
|
||||
} else {
|
||||
trackStart = trackEnd = this.height / 2;
|
||||
}
|
||||
|
||||
final int trackHeight = trackEnd - trackStart;
|
||||
int dragBarHeight = trackHeight;
|
||||
if (contentHeight > 0) {
|
||||
dragBarHeight = Math.min(Math.max(this.width, trackHeight * viewportHeight / contentHeight), trackHeight);
|
||||
}
|
||||
|
||||
final int overflowHeight = contentHeight - viewportHeight;
|
||||
final int visibleTrackHeight = trackHeight - dragBarHeight;
|
||||
int dragBarStart = 0;
|
||||
if (overflowHeight > 0) {
|
||||
dragBarStart = (scrollPosition * visibleTrackHeight + overflowHeight / 2) / overflowHeight;
|
||||
}
|
||||
|
||||
final int upperRegionHeight = dragBarStart + dragBarHeight / 2;
|
||||
this.upButton.height = trackStart;
|
||||
this.upButton.x = 0;
|
||||
this.upButton.y = 0;
|
||||
this.upButton.width = this.width;
|
||||
this.downButton.x = 0;
|
||||
this.downButton.y = trackEnd;
|
||||
this.downButton.width = this.width;
|
||||
this.downButton.height = this.height - trackEnd;
|
||||
this.track.x = 0;
|
||||
this.track.y = trackStart;
|
||||
this.track.width = this.width;
|
||||
this.track.height = trackHeight;
|
||||
this.upperSlideRegion.height = upperRegionHeight;
|
||||
this.upperSlideRegion.width = this.width;
|
||||
this.upperSlideRegion.x = 0;
|
||||
this.upperSlideRegion.y = 0;
|
||||
this.lowerSlideRegion.height = trackHeight - upperRegionHeight;
|
||||
this.lowerSlideRegion.y = upperRegionHeight;
|
||||
this.lowerSlideRegion.x = 0;
|
||||
this.lowerSlideRegion.width = this.width;
|
||||
this.upButton.enabled = this.downButton.enabled = this.track.enabled = contentHeight > viewportHeight;
|
||||
this.dragBar.x = 0;
|
||||
this.dragBar.y = dragBarStart;
|
||||
this.dragBar.width = this.width;
|
||||
this.dragBar.height = dragBarHeight;
|
||||
}
|
||||
}
|
95
src/main/java/funorb/client/lobby/ScrollPane.java
Normal file
95
src/main/java/funorb/client/lobby/ScrollPane.java
Normal file
@ -0,0 +1,95 @@
|
||||
package funorb.client.lobby;
|
||||
|
||||
import funorb.commonui.kj_;
|
||||
|
||||
public final class ScrollPane<T extends Component<?>> extends Component<Component<?>> {
|
||||
public final Component<T> content;
|
||||
public final Component<Component<?>> viewport;
|
||||
public final ScrollBar scrollBar;
|
||||
|
||||
public ScrollPane(final Component<T> content, final Component<?> viewportAttrsSrc, final ScrollBar scrollBar) {
|
||||
super(null);
|
||||
this.viewport = new Component<>(viewportAttrsSrc);
|
||||
this.scrollBar = new ScrollBar(scrollBar);
|
||||
this.addChild(this.viewport);
|
||||
this.addChild(this.scrollBar);
|
||||
this.content = content;
|
||||
this.viewport.addChild(content);
|
||||
}
|
||||
|
||||
public static kj_ a705(final boolean var0) {
|
||||
final kj_ var1 = new kj_(true);
|
||||
var1._b = var0;
|
||||
return var1;
|
||||
}
|
||||
|
||||
private void processScrollBar(final int mouseWheelRotation, final int buttonScrollAmount, final int slideRegionScrollAmount, final boolean var2) {
|
||||
if (this.scrollBar.isUpButtonClicked()) {
|
||||
this.content._w += buttonScrollAmount;
|
||||
}
|
||||
if (this.scrollBar.isDownButtonClicked()) {
|
||||
this.content._w -= buttonScrollAmount;
|
||||
}
|
||||
if (this.scrollBar.isUpperSlideRegionClicked()) {
|
||||
this.content._w += slideRegionScrollAmount;
|
||||
}
|
||||
if (this.scrollBar.isLowerSlideRegionClicked()) {
|
||||
this.content._w -= slideRegionScrollAmount;
|
||||
}
|
||||
if (this.isMouseOverTarget) {
|
||||
this.content._w -= mouseWheelRotation;
|
||||
}
|
||||
|
||||
if (var2) {
|
||||
if (this.content._w + this.content.y > 0) {
|
||||
this.content._w = -this.content.y;
|
||||
}
|
||||
|
||||
if (-this.viewport.height + this.content._gb + this.content.height < -(this.content.y + this.content._w)) {
|
||||
this.content._w = -(this.content.height + this.content._gb - this.viewport.height) - this.content.y;
|
||||
}
|
||||
} else {
|
||||
if (-(this.content._w + this.content.y) > this.content.height + this.content._gb - this.viewport.height) {
|
||||
this.content._w = -this.content.y - (-this.viewport.height + this.content._gb + this.content.height);
|
||||
}
|
||||
|
||||
if (this.content.y + this.content._w > 0) {
|
||||
this.content._w = -this.content.y;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.scrollBar.isDragBarBeingDragged()) {
|
||||
this.content.y = -this.scrollBar.a791(this.content.height, this.viewport.height, var2);
|
||||
this.content._w = 0;
|
||||
}
|
||||
|
||||
this.scrollBar.updateScrollBounds(this.viewport.height, this.content.height, -this.content.y);
|
||||
}
|
||||
|
||||
public void a795(final int mouseWheelRotationAmount, final int buttonScrollAmount) {
|
||||
this.processScrollBar(mouseWheelRotationAmount, buttonScrollAmount, this.viewport.height, true);
|
||||
}
|
||||
|
||||
public void setBounds(final int x, final int y, final int width, final int height, final int scrollBarWidth) {
|
||||
this.x = x;
|
||||
this.width = width;
|
||||
this.y = y;
|
||||
this.height = height;
|
||||
this.updateChildBounds(scrollBarWidth);
|
||||
}
|
||||
|
||||
public boolean processScrollInput(final boolean mouseStill, final boolean isContextMenuParent, final int buttonScrollAmount, final int mouseWheelRotationAmount) {
|
||||
final boolean var8 = isContextMenuParent || (this.isMouseOverTarget && !mouseStill);
|
||||
this.content.a811(this.viewport.height, var8);
|
||||
this.processScrollBar(mouseWheelRotationAmount, buttonScrollAmount, this.viewport.height, false);
|
||||
return var8;
|
||||
}
|
||||
|
||||
private void updateChildBounds(final int scrollBarWidth) {
|
||||
this.viewport.height = this.height;
|
||||
this.viewport.width = (this.width - scrollBarWidth) - 2;
|
||||
this.content.x = 0;
|
||||
this.content.width = this.width - scrollBarWidth - 2;
|
||||
this.scrollBar.setBounds(this.width - scrollBarWidth, 0, scrollBarWidth, this.height, this.viewport.height, this.content.height, -this.content.y);
|
||||
}
|
||||
}
|
75
src/main/java/funorb/client/lobby/TabbedPlayerList.java
Normal file
75
src/main/java/funorb/client/lobby/TabbedPlayerList.java
Normal file
@ -0,0 +1,75 @@
|
||||
package funorb.client.lobby;
|
||||
|
||||
import funorb.awt.MouseState;
|
||||
|
||||
public final class TabbedPlayerList extends Component<Component<?>> {
|
||||
private final Component<?>[] _xb;
|
||||
private final Component<?>[] _Db;
|
||||
private final Component<Component<?>> _yb;
|
||||
private int _zb;
|
||||
|
||||
public TabbedPlayerList(final Component<?> var3, final String[] var4, final Component<?> var5, final Component<?>[] var6) {
|
||||
super(null);
|
||||
this._Db = new Component[var4.length];
|
||||
this._yb = new Component<>(var5);
|
||||
this._xb = var6;
|
||||
|
||||
int var8;
|
||||
for (var8 = 0; var4.length > var8; ++var8) {
|
||||
final Component<?> var9 = new Component<>(var3);
|
||||
var9.label = var4[var8];
|
||||
this._Db[var8] = var9;
|
||||
this.addChild(var9);
|
||||
}
|
||||
|
||||
this.addChild(this._yb);
|
||||
|
||||
for (var8 = 0; var8 < var6.length; ++var8) {
|
||||
this._yb.addChild(var6[var8]);
|
||||
}
|
||||
|
||||
this._zb = 0;
|
||||
this._Db[0].selected = true;
|
||||
}
|
||||
|
||||
public void updateBounds(final int var1, final int var3) {
|
||||
this.height = var3;
|
||||
this.x = 0;
|
||||
this.width = var1;
|
||||
this.y = 0;
|
||||
this.updateChildBounds();
|
||||
}
|
||||
|
||||
public void f487() {
|
||||
for (int i = 0; i < this._Db.length; ++i) {
|
||||
if (this._zb != i && this._Db[i].clickButton != MouseState.Button.NONE) {
|
||||
this._Db[this._zb].selected = false;
|
||||
this._xb[this._zb].x += 10000;
|
||||
this._zb = i;
|
||||
this._Db[i].selected = true;
|
||||
this._xb[i].x -= 10000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateChildBounds() {
|
||||
for (int var4 = 0; var4 < this._Db.length; ++var4) {
|
||||
final int var5 = this.width * var4 / this._Db.length;
|
||||
final int var6 = (1 + var4) * this.width / this._Db.length;
|
||||
this._Db[var4].x = var5;
|
||||
this._Db[var4].y = 0;
|
||||
this._Db[var4].width = var6 - var5;
|
||||
this._Db[var4].height = 24;
|
||||
}
|
||||
|
||||
this._yb.setBounds(0, 24, this.width, this.height - 24);
|
||||
|
||||
for (int var4 = 0; var4 < this._xb.length; ++var4) {
|
||||
this._xb[var4].setBounds(5, 5, -10 + this._yb.width, this._yb.height - 10);
|
||||
if (this._zb != var4) {
|
||||
final Component<?> var10000 = this._xb[var4];
|
||||
var10000.x += 10000;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package funorb.client.lobby;
|
||||
|
||||
import funorb.shatteredplans.StringConstants;
|
||||
|
||||
public final class TabbedPlayerListWrapper {
|
||||
public final TabbedPlayerList view;
|
||||
|
||||
public TabbedPlayerListWrapper(final String firstTabLabel, final Component<?> var2) {
|
||||
final String[] labels = new String[]{firstTabLabel, StringConstants.MU_CHAT_FRIENDS, StringConstants.MU_CHAT_IGNORE};
|
||||
final Component<?>[] views = new Component[]{var2, Component.FRIEND_LIST_PANEL, Component.IGNORE_LIST};
|
||||
this.view = new TabbedPlayerList(Component.TAB_INACTIVE, labels, Component._tmt, views);
|
||||
}
|
||||
|
||||
public void updateBounds(final int width, final int height) {
|
||||
this.view.updateBounds(width, height);
|
||||
Component.SERVER_INFO_LABEL.setBounds(0, 0, Component.FRIEND_LIST_PANEL.width, Component.LABEL_HEIGHT);
|
||||
Component.NAME_LABEL_2.setBounds(0, 2 + Component.LABEL_HEIGHT, -15 + (Component.FRIEND_LIST_PANEL.width - 2 - 82), 18);
|
||||
Component.LOCATION_LABEL.setBounds(-95 + (Component.FRIEND_LIST_PANEL.width - 2), 2 + Component.LABEL_HEIGHT, 97, 18);
|
||||
Component.FRIEND_LIST.updateBounds(0, 20 + Component.LABEL_HEIGHT + 2, Component.FRIEND_LIST_PANEL.width, Component.FRIEND_LIST_PANEL.height - Component.LABEL_HEIGHT - 22);
|
||||
Component.IGNORE_LIST.updateChildBounds();
|
||||
}
|
||||
}
|
239
src/main/java/funorb/client/lobby/vm_.java
Normal file
239
src/main/java/funorb/client/lobby/vm_.java
Normal file
@ -0,0 +1,239 @@
|
||||
package funorb.client.lobby;
|
||||
|
||||
import funorb.awt.KeyState;
|
||||
import funorb.awt.MouseState;
|
||||
import funorb.graphics.Font;
|
||||
import funorb.graphics.Sprite;
|
||||
import funorb.shatteredplans.C2SPacket;
|
||||
import funorb.shatteredplans.StringConstants;
|
||||
import funorb.shatteredplans.client.JagexApplet;
|
||||
import funorb.shatteredplans.client.Menu;
|
||||
import funorb.shatteredplans.client.ShatteredPlansClient;
|
||||
import funorb.util.PseudoMonotonicClock;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public final class vm_ extends Component<Component<?>> {
|
||||
public static String _ahS;
|
||||
public static long _aco;
|
||||
public static Sprite _kflc;
|
||||
private final int _xb;
|
||||
private final int _Qb;
|
||||
private final ActionButton[] _Kb;
|
||||
private final int _Pb;
|
||||
private final char[] _zb;
|
||||
private final int[] _Hb;
|
||||
private final vm_[] _yb;
|
||||
private int _Eb;
|
||||
private vm_ _Ob;
|
||||
private int _Mb;
|
||||
private int _Ib;
|
||||
private int _Db;
|
||||
private int _Gb = -1;
|
||||
|
||||
public vm_(final Component<?> var3, final Component<?> var4, final Component<?> var5, final vm_[] var6, final int[] var7, final String[] var8, final char[] var9) {
|
||||
super(var3);
|
||||
this._Hb = var7;
|
||||
this._zb = var9;
|
||||
this._yb = var6;
|
||||
this._Pb = this._Hb.length;
|
||||
final Font var10 = var5.font;
|
||||
this._Qb = var10.descent + 2 + var10.ascent;
|
||||
this._xb = this._Qb * this._Pb;
|
||||
this._Kb = new ActionButton[this._Pb];
|
||||
this._Ib = 0;
|
||||
final String var11 = "<col=999999>";
|
||||
final String var12 = "</col>";
|
||||
|
||||
for (int var13 = 0; this._Pb > var13; ++var13) {
|
||||
if (this._zb[var13] > 0) {
|
||||
var8[var13] = var11 + String.valueOf(this._zb[var13]).toUpperCase() + ": " + var12 + var8[var13];
|
||||
}
|
||||
|
||||
Sprite var14 = null;
|
||||
if (this._yb[var13] != null || this._Hb[var13] == -1) {
|
||||
var14 = _kflc;
|
||||
}
|
||||
|
||||
this._Kb[var13] = new ActionButton(var4, var5, var14, var8[var13]);
|
||||
this.addChild(this._Kb[var13]);
|
||||
final int var15 = var10.measureLineWidth(var8[var13]);
|
||||
if (this._Ib < var15) {
|
||||
this._Ib = var15;
|
||||
}
|
||||
}
|
||||
|
||||
this._Ib += _kflc.offsetX + 10;
|
||||
this.c540(12);
|
||||
}
|
||||
|
||||
public static int a827(final String var0) {
|
||||
return Menu.FONT.measureLineWidth(var0);
|
||||
}
|
||||
|
||||
private static void a345un(final String var0, final long var1, final @NotNull ChatMessage.Channel var3, final int var4) {
|
||||
ShatteredPlansClient._cvcn = true;
|
||||
ShatteredPlansClient._vsd = var4;
|
||||
_aco = var1;
|
||||
_ahS = var0;
|
||||
ShatteredPlansClient._tlr = var3;
|
||||
}
|
||||
|
||||
private static void a150gs() {
|
||||
ShatteredPlansClient._tkz = PseudoMonotonicClock.currentTimeMillis();
|
||||
ShatteredPlansClient._vjC = 0;
|
||||
}
|
||||
|
||||
public void close() {
|
||||
for (final ActionButton button : this._Kb) {
|
||||
button.clickButton = MouseState.Button.NONE;
|
||||
button.selected = false;
|
||||
}
|
||||
|
||||
if (this._Ob != null) {
|
||||
this._Ob.close();
|
||||
_uaf.children.remove(this._Ob);
|
||||
}
|
||||
|
||||
this._Ob = null;
|
||||
this._Gb = -1;
|
||||
this.c540(12);
|
||||
}
|
||||
|
||||
public void a669(final int var2, final int var3, final int var4, final int var5, final int var6) {
|
||||
this._Eb = this._Ib + var2 * 2;
|
||||
this.setBounds(var4, var6 - this._xb, this._Eb, this._xb);
|
||||
if (this._Mb != var3) {
|
||||
this._Mb = var3;
|
||||
this.c540(this._Db);
|
||||
}
|
||||
|
||||
int var7;
|
||||
for (var7 = 0; this._Pb > var7; ++var7) {
|
||||
this._Kb[var7].a370(this._Qb, this._Kb[var7].y, var2, var5, this._Eb, 0);
|
||||
}
|
||||
|
||||
if (this._Gb != -1 && this._yb[this._Gb] != null) {
|
||||
var7 = this._yb[this._Gb]._Pb;
|
||||
|
||||
int var8 = this._Qb * (var7 + this._Gb) + this.y;
|
||||
while (var6 < var8) {
|
||||
var8 -= this._Qb;
|
||||
}
|
||||
|
||||
this._yb[this._Gb].a669(var2, this._Kb[this._Gb].y2, var4 + this._Eb, var5, var8);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public int g474() {
|
||||
return this._Eb + (this._Ob != null ? this._Ob.g474() : 0);
|
||||
}
|
||||
|
||||
public void a599() {
|
||||
for (int var4 = 0; this._Kb.length > var4; ++var4) {
|
||||
final ActionButton var5 = this._Kb[var4];
|
||||
if (var5.clickButton == MouseState.Button.LEFT) {
|
||||
this.a115(var4);
|
||||
var5.selected = this._Gb == var4;
|
||||
}
|
||||
}
|
||||
|
||||
if (this._Gb != -1) {
|
||||
final vm_ var6 = this._yb[this._Gb];
|
||||
if (var6 != null) {
|
||||
var6.a599();
|
||||
}
|
||||
}
|
||||
|
||||
if (this._Db > 0) {
|
||||
this.c540(this._Db - 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void a115(final int var3) {
|
||||
if (this._Gb == var3) {
|
||||
this.close();
|
||||
this.c540(0);
|
||||
} else if (this._yb[var3] != null) {
|
||||
this.close();
|
||||
this.c540(0);
|
||||
this._Gb = var3;
|
||||
this._Ob = this._yb[this._Gb];
|
||||
_uaf.addChild(this._Ob);
|
||||
this._Ob.c540(12);
|
||||
} else if (this._Hb[var3] == -1) {
|
||||
QuickChatHelpPanel.openInstance = new QuickChatHelpPanel(Component.TAB_ACTIVE, CLOSE_BUTTON, Component.LABEL);
|
||||
ShatteredPlansClient.closeQuickChat();
|
||||
} else {
|
||||
final int var5 = this._Hb[var3] | 0x8000;
|
||||
ChatMessage.Channel var6 = ShatteredPlansClient.currentChatChannel;
|
||||
if (var6 == ChatMessage.Channel.LOBBY && ShatteredPlansClient.unratedLobbyRoom != null) {
|
||||
var6 = ChatMessage.Channel.ROOM;
|
||||
}
|
||||
|
||||
if (ContextMenu.getChatChannelFilter(var6) == ChatMessage.FilterLevel.NONE) {
|
||||
ContextMenu.setChatFilter(var6, ChatMessage.FilterLevel.FRIENDS);
|
||||
}
|
||||
|
||||
C2SPacket.sendQuickChatMessage(ShatteredPlansClient.currentChatChannel, ContextMenu.recipientPlayerName, var5);
|
||||
a345un(ContextMenu.recipientPlayerName, ContextMenu.recipientPlayerId, ShatteredPlansClient.currentChatChannel, var5);
|
||||
ShatteredPlansClient.closeQuickChat();
|
||||
a150gs();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void c540(final int var2) {
|
||||
this._Db = var2;
|
||||
for (int var5 = 0; this._Pb > var5; ++var5) {
|
||||
final int var3 = this._Qb * var5;
|
||||
final int var4 = this._Db * this._Db;
|
||||
this._Kb[var5].y = ((-this.y2 + this._Mb) * var4 + var3 * (144 - var4)) / 144;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean f491() {
|
||||
boolean var2 = Arrays.stream(this._Kb).anyMatch(var5 -> var5.clickButton != MouseState.Button.NONE);
|
||||
|
||||
if (!var2 && this._Gb != -1 && this._yb[this._Gb] != null) {
|
||||
var2 = this._yb[this._Gb].f491();
|
||||
}
|
||||
|
||||
return var2;
|
||||
}
|
||||
|
||||
public boolean a777() {
|
||||
final boolean var4 = JagexApplet.lastTypedKeyCode == KeyState.Code.BACKSPACE;
|
||||
if (this._Ob != null) {
|
||||
if (var4 && this._Ob._Gb == -1) {
|
||||
this.close();
|
||||
this.c540(0);
|
||||
return true;
|
||||
} else {
|
||||
return this._Ob.a777();
|
||||
}
|
||||
} else if (this == ShatteredPlansClient._dmrh && var4) {
|
||||
ShatteredPlansClient.closeQuickChat();
|
||||
return true;
|
||||
} else {
|
||||
char var5 = JagexApplet.lastTypedKeyChar;
|
||||
if (var5 > 0) {
|
||||
if (var5 == StringConstants.KEYCHAR_THE_CHARACTER_UNDER_QUESTION_MARK) {
|
||||
var5 = '?';
|
||||
}
|
||||
|
||||
for (int var6 = 0; var6 < this._zb.length; ++var6) {
|
||||
if (var5 == this._zb[var6]) {
|
||||
this.a115(var6);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
69
src/main/java/funorb/client/pa_.java
Normal file
69
src/main/java/funorb/client/pa_.java
Normal file
@ -0,0 +1,69 @@
|
||||
package funorb.client;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.Proxy;
|
||||
import java.net.Proxy.Type;
|
||||
import java.net.ProxySelector;
|
||||
import java.net.Socket;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.List;
|
||||
|
||||
public final class pa_ extends li_ {
|
||||
private final ProxySelector _g = ProxySelector.getDefault();
|
||||
|
||||
private pa_() {}
|
||||
|
||||
public static li_ a287ho(final int var0, final String var1) {
|
||||
final pa_ var2 = new pa_();
|
||||
var2._a = var0;
|
||||
var2._f = var1;
|
||||
return var2;
|
||||
}
|
||||
|
||||
private Socket a837(final Proxy var2) throws IOException {
|
||||
if (var2.type() == Type.DIRECT) {
|
||||
return this.a693();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket b693() throws IOException {
|
||||
final boolean var2 = Boolean.parseBoolean(System.getProperty("java.net.useSystemProxies"));
|
||||
if (!var2) {
|
||||
System.setProperty("java.net.useSystemProxies", "true");
|
||||
}
|
||||
|
||||
final boolean var5 = this._a == 443;
|
||||
|
||||
final List<Proxy> var3;
|
||||
final List<Proxy> var4;
|
||||
try {
|
||||
var3 = this._g.select(new URI((var5 ? "https" : "http") + "://" + this._f));
|
||||
var4 = this._g.select(new URI((!var5 ? "https" : "http") + "://" + this._f));
|
||||
} catch (final URISyntaxException var15) {
|
||||
return this.a693();
|
||||
}
|
||||
|
||||
var3.addAll(var4);
|
||||
final Object[] var6 = var3.toArray();
|
||||
int var9 = 0;
|
||||
|
||||
for (; var6.length > var9; ++var9) {
|
||||
final Object var10 = var6[var9];
|
||||
final Proxy var11 = (Proxy) var10;
|
||||
|
||||
try {
|
||||
final Socket var12 = this.a837(var11);
|
||||
if (var12 != null) {
|
||||
return var12;
|
||||
}
|
||||
} catch (final IOException var14) {
|
||||
}
|
||||
}
|
||||
|
||||
return this.a693();
|
||||
}
|
||||
}
|
174
src/main/java/funorb/client/r_.java
Normal file
174
src/main/java/funorb/client/r_.java
Normal file
@ -0,0 +1,174 @@
|
||||
package funorb.client;
|
||||
|
||||
import funorb.Strings;
|
||||
import funorb.io.Buffer;
|
||||
import funorb.shatteredplans.client.MailboxMessage;
|
||||
import funorb.shatteredplans.client.MessagePumpThread;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.net.Socket;
|
||||
import java.net.URL;
|
||||
|
||||
public final class r_ implements Runnable {
|
||||
private final Buffer _k;
|
||||
private final MessagePumpThread _l;
|
||||
private final URL _e;
|
||||
private MailboxMessage _b;
|
||||
private DataInputStream _g;
|
||||
private int _h;
|
||||
private MailboxMessage _a;
|
||||
private MailboxMessage _i;
|
||||
|
||||
public r_(final MessagePumpThread var1, final URL var2) {
|
||||
this._e = var2;
|
||||
this._l = var1;
|
||||
this._k = new Buffer(5000);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finalize() {
|
||||
if (this._b != null) {
|
||||
if (this._b.response != null) {
|
||||
try {
|
||||
((DataInputStream) this._b.response).close();
|
||||
} catch (final Exception var4) {
|
||||
}
|
||||
}
|
||||
|
||||
this._b = null;
|
||||
}
|
||||
|
||||
if (this._i != null) {
|
||||
if (this._i.response != null) {
|
||||
try {
|
||||
((Socket) this._i.response).close();
|
||||
} catch (final Exception var3) {
|
||||
}
|
||||
}
|
||||
|
||||
this._i = null;
|
||||
}
|
||||
|
||||
if (this._g != null) {
|
||||
try {
|
||||
this._g.close();
|
||||
} catch (final Exception var2) {
|
||||
}
|
||||
|
||||
this._g = null;
|
||||
}
|
||||
|
||||
this._a = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
while (true) {
|
||||
try {
|
||||
if (this._k.data.length > this._k.pos) {
|
||||
final int var1 = this._g.read(this._k.data, this._k.pos, this._k.data.length - this._k.pos);
|
||||
if (var1 >= 0) {
|
||||
this._k.pos += var1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (this._k.pos == this._k.data.length) {
|
||||
throw new Exception("HG1: " + this._k.data.length + " " + this._e);
|
||||
}
|
||||
|
||||
synchronized (this) {
|
||||
//noinspection FinalizeCalledExplicitly
|
||||
this.finalize();
|
||||
this._h = 3;
|
||||
}
|
||||
} catch (final Exception var6) {
|
||||
synchronized (this) {
|
||||
//noinspection FinalizeCalledExplicitly
|
||||
this.finalize();
|
||||
++this._h;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized boolean b154() {
|
||||
if (this._h < 2) {
|
||||
if (this._h == 0) {
|
||||
if (this._b == null) {
|
||||
this._b = this._l.sendOpenUrlStreamMessage(this._e);
|
||||
}
|
||||
|
||||
if (this._b.status == MailboxMessage.Status.PENDING) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this._b.status != MailboxMessage.Status.SUCCESS) {
|
||||
++this._h;
|
||||
this._b = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (this._h == 1) {
|
||||
if (this._i == null) {
|
||||
this._i = this._l.sendOpenSocketMessage(this._e.getHost(), 443);
|
||||
}
|
||||
|
||||
if (this._i.status == MailboxMessage.Status.PENDING) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this._i.status != MailboxMessage.Status.SUCCESS) {
|
||||
++this._h;
|
||||
this._i = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (this._g == null) {
|
||||
try {
|
||||
if (this._h == 0) {
|
||||
this._g = (DataInputStream) this._b.response;
|
||||
}
|
||||
|
||||
if (this._h == 1) {
|
||||
final Socket var2 = (Socket) this._i.response;
|
||||
var2.setSoTimeout(10000);
|
||||
final OutputStream var3 = var2.getOutputStream();
|
||||
var3.write(17);
|
||||
var3.write(Strings.encode1252String("JAGGRAB " + this._e.getFile() + "\n\n"));
|
||||
this._g = new DataInputStream(var2.getInputStream());
|
||||
}
|
||||
|
||||
this._k.pos = 0;
|
||||
} catch (final IOException var4) {
|
||||
//noinspection FinalizeCalledExplicitly
|
||||
this.finalize();
|
||||
++this._h;
|
||||
}
|
||||
}
|
||||
|
||||
if (this._a == null) {
|
||||
this._a = this._l.sendSpawnThreadMessage(this, 5);
|
||||
}
|
||||
|
||||
if (this._a.status != MailboxMessage.Status.PENDING) {
|
||||
if (this._a.status != MailboxMessage.Status.SUCCESS) {
|
||||
//noinspection FinalizeCalledExplicitly
|
||||
this.finalize();
|
||||
++this._h;
|
||||
}
|
||||
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
359
src/main/java/funorb/commonui/AbstractTextField.java
Normal file
359
src/main/java/funorb/commonui/AbstractTextField.java
Normal file
@ -0,0 +1,359 @@
|
||||
package funorb.commonui;
|
||||
|
||||
import funorb.awt.KeyState;
|
||||
import funorb.commonui.listener.ComponentListener;
|
||||
import funorb.commonui.listener.TextFieldListener;
|
||||
import funorb.commonui.renderer.ComponentRenderer;
|
||||
import funorb.commonui.renderer.ITextRenderer;
|
||||
import funorb.shatteredplans.client.JagexApplet;
|
||||
import funorb.util.PseudoMonotonicClock;
|
||||
import org.intellij.lang.annotations.MagicConstant;
|
||||
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.datatransfer.DataFlavor;
|
||||
import java.awt.datatransfer.StringSelection;
|
||||
|
||||
public class AbstractTextField extends Button {
|
||||
private final int _O;
|
||||
private final boolean _M;
|
||||
private int _H;
|
||||
private int _R = -1;
|
||||
private int _N;
|
||||
private long _F = 0L;
|
||||
private boolean _P = false;
|
||||
private long _Q;
|
||||
|
||||
protected AbstractTextField(final String text, final ComponentRenderer renderer, final ComponentListener listener, final int var3) {
|
||||
super(text, renderer, listener);
|
||||
this._O = var3;
|
||||
this.a676(text, true);
|
||||
this._M = true;
|
||||
this._Q = PseudoMonotonicClock.currentTimeMillis();
|
||||
}
|
||||
|
||||
private void k423() {
|
||||
final int var2;
|
||||
if (this._H != this._N) {
|
||||
var2 = Math.min(this._N, this._H);
|
||||
final int var3 = Math.max(this._H, this._N);
|
||||
this._N = var2;
|
||||
this._H = var2;
|
||||
this.text = this.text.substring(0, var2) + this.text.substring(var3);
|
||||
this.i150();
|
||||
}
|
||||
}
|
||||
|
||||
private void h423() {
|
||||
this.h150();
|
||||
this.k423();
|
||||
}
|
||||
|
||||
private void a407(final String var2) {
|
||||
if (this._O != -1) {
|
||||
assert this._O - this.text.length() >= 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._H == this.text.length()) {
|
||||
this.text = this.text + var2;
|
||||
} else {
|
||||
this.text = this.text.substring(0, this._H) + var2 + this.text.substring(this._H);
|
||||
}
|
||||
|
||||
this._H += var2.length();
|
||||
this._N = this._H;
|
||||
this.i150();
|
||||
}
|
||||
|
||||
public final void e487() {
|
||||
this._N = 0;
|
||||
this._H = 0;
|
||||
this.text = "";
|
||||
this.i150();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean a446(final int var1, final int var2, final int var4, final int var5, final int var6, final Component var7) {
|
||||
if (super.a446(var1, var2, var4, var5, var6, var7) && this.renderer instanceof ITextRenderer) {
|
||||
final int var8 = ((ITextRenderer) this.renderer).a242(var5, JagexApplet.mouseX, var6, this, JagexApplet.mouseY);
|
||||
this.a093(var8 != -1 ? var8 : 0);
|
||||
final long var10 = PseudoMonotonicClock.currentTimeMillis();
|
||||
this._P = -this._F + var10 < 250L;
|
||||
if (this._P) {
|
||||
this._N = this.g410();
|
||||
this._H = this.a137();
|
||||
if (this._H > 0 && this.text.charAt(this._H - 1) == ' ') {
|
||||
--this._H;
|
||||
}
|
||||
|
||||
this._R = this._H;
|
||||
}
|
||||
|
||||
this._F = var10;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void j423() {
|
||||
if (this._M) {
|
||||
if (this.renderer instanceof ITextRenderer var2) {
|
||||
final AbstractTextLayout var3 = var2.updateLayout(this);
|
||||
final int var4 = var3.getWidth();
|
||||
final int var5 = var2.getAvailableWidth(this);
|
||||
final int var6 = var2.a474() >> 1;
|
||||
if (var4 < -var6 + var5) {
|
||||
this._l = 0;
|
||||
this._h = 0;
|
||||
} else {
|
||||
final int var7 = this._h + var3.a527(this._H);
|
||||
if (-var6 + var5 >= var7) {
|
||||
if (var6 > var7) {
|
||||
this._h += -var7 + var6;
|
||||
}
|
||||
} else {
|
||||
this._h = this._h - var6 + (var5 - var7);
|
||||
}
|
||||
|
||||
if (this._h <= 0) {
|
||||
if (this._h < -var5 + var6) {
|
||||
this._h = -var5 + var6;
|
||||
}
|
||||
} else {
|
||||
this._h = 0;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this._l = 0;
|
||||
this._h = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void draw(final int x, final int y) {
|
||||
if (this.renderer != null) {
|
||||
this.renderer.draw(this, x, y, this.enabled);
|
||||
if (this.renderer instanceof ITextRenderer var5) {
|
||||
if (this._H != this._N) {
|
||||
var5.a132(this._N, y, x, this._H, this);
|
||||
}
|
||||
|
||||
final long var6 = PseudoMonotonicClock.currentTimeMillis();
|
||||
if ((var6 - this._Q) % 1000L < 500L) {
|
||||
var5.a403(this._H, x, y, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void a093(final int var2) {
|
||||
this._H = var2;
|
||||
if (!JagexApplet.keysDown[KeyState.Code.SHIFT]) {
|
||||
this._N = this._H;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean a686(@MagicConstant(valuesFromClass = KeyState.Code.class) final int keyCode, final char keyChar, final Component var4) {
|
||||
|
||||
this._Q = PseudoMonotonicClock.currentTimeMillis();
|
||||
if (keyChar == '<' || keyChar == '>') {
|
||||
return false;
|
||||
} else if (keyChar >= ' ' && keyChar <= '~') {
|
||||
if (this._H != this._N) {
|
||||
this.k423();
|
||||
}
|
||||
|
||||
if (this._O == -1 || this.text.length() < this._O) {
|
||||
if (this._H >= this.text.length()) {
|
||||
this.text = this.text + keyChar;
|
||||
this._N = this._H = this.text.length();
|
||||
} else {
|
||||
this.text = this.text.substring(0, this._H) + keyChar + this.text.substring(this._H);
|
||||
++this._H;
|
||||
this._N = this._H;
|
||||
}
|
||||
|
||||
this.i150();
|
||||
}
|
||||
|
||||
return true;
|
||||
} else {
|
||||
if (keyCode == KeyState.Code.BACKSPACE) {
|
||||
if (this._N != this._H) {
|
||||
this.k423();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this._H > 0) {
|
||||
this._N = this._H - 1;
|
||||
this.k423();
|
||||
return true;
|
||||
}
|
||||
} else if (keyCode == KeyState.Code.DELETE) {
|
||||
if (this._N != this._H) {
|
||||
this.k423();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this._H < this.text.length()) {
|
||||
this._N = 1 + this._H;
|
||||
this.k423();
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
if (keyCode == KeyState.Code.ESCAPE) {
|
||||
this.e487();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (keyCode != KeyState.Code.LEFT) {
|
||||
if (keyCode != KeyState.Code.RIGHT) {
|
||||
if (keyCode == KeyState.Code.HOME) {
|
||||
this.a093(0);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (keyCode == KeyState.Code.END) {
|
||||
this.a093(this.text.length());
|
||||
return true;
|
||||
}
|
||||
|
||||
if (keyCode == KeyState.Code.ENTER) {
|
||||
this.handleEnterKey();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (JagexApplet.keysDown[KeyState.Code.CONTROL] && keyCode == KeyState.Code.LETTER_X) {
|
||||
this.h423();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (JagexApplet.keysDown[KeyState.Code.CONTROL] && keyCode == KeyState.Code.LETTER_C) {
|
||||
this.h150();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (JagexApplet.keysDown[KeyState.Code.CONTROL] && keyCode == KeyState.Code.LETTER_V) {
|
||||
this.m423();
|
||||
return true;
|
||||
}
|
||||
} else if (this._H < this.text.length()) {
|
||||
this.a093(JagexApplet.keysDown[KeyState.Code.CONTROL] ? this.a137() : 1 + this._H);
|
||||
return true;
|
||||
}
|
||||
} else if (this._H > 0) {
|
||||
this.a093(!JagexApplet.keysDown[KeyState.Code.CONTROL] ? this._H - 1 : this.g410());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private int a137() {
|
||||
final int var2 = this.text.length();
|
||||
if (var2 == this._H) {
|
||||
return this._H;
|
||||
} else {
|
||||
int var3;
|
||||
var3 = 1 + this._H;
|
||||
while (var2 > var3 && this.text.charAt(var3 - 1) != ' ') {
|
||||
++var3;
|
||||
}
|
||||
return var3;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick(final int x, final int y, final Component root) {
|
||||
super.tick(x, y, root);
|
||||
this.j423();
|
||||
if (this._o == 1) {
|
||||
if (this.renderer instanceof ITextRenderer var5) {
|
||||
int var6 = var5.a242(x, JagexApplet.mouseX, y, this, JagexApplet.mouseY);
|
||||
if (var6 != -1) {
|
||||
if (this._P && this._R > var6 && var6 > this._N) {
|
||||
var6 = this._R;
|
||||
}
|
||||
|
||||
this._H = var6;
|
||||
}
|
||||
}
|
||||
|
||||
this._Q = PseudoMonotonicClock.currentTimeMillis();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected void i150() {
|
||||
if (this.listener instanceof TextFieldListener) {
|
||||
((TextFieldListener) this.listener).handleTextFieldChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public final void a676(String var2, final boolean var3) {
|
||||
if (var2 == null) {
|
||||
var2 = "";
|
||||
}
|
||||
|
||||
this.text = var2;
|
||||
final int var5 = var2.length();
|
||||
if (this._O != -1 && this._O < var5) {
|
||||
this.text = this.text.substring(0, this._O);
|
||||
}
|
||||
|
||||
this._H = this._N = this.text.length();
|
||||
if (!var3) {
|
||||
this.i150();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private String l983() {
|
||||
final int var2 = Math.min(this._H, this._N);
|
||||
final int var3 = Math.max(this._N, this._H);
|
||||
return this.text.substring(var2, var3);
|
||||
}
|
||||
|
||||
private void m423() {
|
||||
try {
|
||||
final String var2 = (String) Toolkit.getDefaultToolkit().getSystemClipboard().getContents(null).getTransferData(DataFlavor.stringFlavor);
|
||||
this.k423();
|
||||
this.a407(var2);
|
||||
} catch (final Exception var3) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void h150() {
|
||||
final String var2 = this.l983();
|
||||
if (var2.length() > 0) {
|
||||
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(this.l983()), null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private int g410() {
|
||||
if (this._H == 0) {
|
||||
return this._H;
|
||||
} else {
|
||||
int var2 = this._H - 1;
|
||||
while (var2 > 0 && this.text.charAt(var2 - 1) != ' ') {
|
||||
--var2;
|
||||
}
|
||||
|
||||
return var2;
|
||||
}
|
||||
}
|
||||
|
||||
private void handleEnterKey() {
|
||||
if (this.listener instanceof TextFieldListener l) {
|
||||
l.handleTextFieldEnterPressed(this);
|
||||
}
|
||||
}
|
||||
}
|
109
src/main/java/funorb/commonui/AbstractTextLayout.java
Normal file
109
src/main/java/funorb/commonui/AbstractTextLayout.java
Normal file
@ -0,0 +1,109 @@
|
||||
package funorb.commonui;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
public abstract class AbstractTextLayout {
|
||||
public TextLineMetrics[] lineMetrics;
|
||||
|
||||
public final int a543(int var2) {
|
||||
int var3 = 0;
|
||||
|
||||
while (this.lineMetrics.length > var3) {
|
||||
final TextLineMetrics var4 = this.lineMetrics[var3];
|
||||
if (var4._b.length > var2) {
|
||||
return var3;
|
||||
}
|
||||
|
||||
var2 -= var4.getCharCount();
|
||||
++var3;
|
||||
}
|
||||
|
||||
return this.lineMetrics.length;
|
||||
}
|
||||
|
||||
public final int b137() {
|
||||
return this.lineMetrics != null && this.lineMetrics.length > 0 ? this.lineMetrics[this.lineMetrics.length - 1].bottom - this.lineMetrics[0].top : 0;
|
||||
}
|
||||
|
||||
public final int getWidth() {
|
||||
if (this.lineMetrics == null) {
|
||||
return -1;
|
||||
} else {
|
||||
return Arrays.stream(this.lineMetrics).filter(Objects::nonNull)
|
||||
.mapToInt(TextLineMetrics::getWidth).max()
|
||||
.orElse(-1);
|
||||
}
|
||||
}
|
||||
|
||||
protected final int a947(final int var2, final int var3, final String var4) {
|
||||
int var5 = 0;
|
||||
boolean var6 = false;
|
||||
final int var7 = var4.length();
|
||||
|
||||
for (int var8 = 0; var7 > var8; ++var8) {
|
||||
final char var9 = var4.charAt(var8);
|
||||
if (var9 == '<') {
|
||||
var6 = true;
|
||||
} else if (var9 == '>') {
|
||||
var6 = false;
|
||||
} else if (!var6 && var9 == ' ') {
|
||||
++var5;
|
||||
}
|
||||
}
|
||||
|
||||
if (var5 <= 0) {
|
||||
return 0;
|
||||
} else {
|
||||
return (var2 - var3 << 8) / var5;
|
||||
}
|
||||
}
|
||||
|
||||
public final int a313(final int var1, final int var3) {
|
||||
if (this.lineMetrics != null && this.lineMetrics.length != 0 && this.lineMetrics[0].top <= var3) {
|
||||
if (this.lineMetrics[this.lineMetrics.length - 1].bottom >= var3) {
|
||||
if (this.lineMetrics.length == 1) {
|
||||
return this.lineMetrics[0].a527(var1);
|
||||
} else {
|
||||
int var4 = 0;
|
||||
|
||||
for (final TextLineMetrics var6 : this.lineMetrics) {
|
||||
if (var3 >= var6.top && var6.bottom >= var3) {
|
||||
final int var7 = var6.a527(var1);
|
||||
if (var7 != -1) {
|
||||
return var4 + var7;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
var4 += var6.getCharCount();
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public final int a527(int var2) {
|
||||
final TextLineMetrics[] var3 = this.lineMetrics;
|
||||
int var4 = 0;
|
||||
|
||||
while (var3.length > var4) {
|
||||
final TextLineMetrics var5 = var3[var4];
|
||||
if (var5._b.length > var2) {
|
||||
return var5._b[var2];
|
||||
}
|
||||
|
||||
var2 -= var5.getCharCount();
|
||||
++var4;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
133
src/main/java/funorb/commonui/AccountPage.java
Normal file
133
src/main/java/funorb/commonui/AccountPage.java
Normal file
@ -0,0 +1,133 @@
|
||||
package funorb.commonui;
|
||||
|
||||
import funorb.awt.KeyState;
|
||||
import funorb.commonui.form.LoginForm;
|
||||
import funorb.commonui.listener.ButtonListener;
|
||||
import funorb.graphics.Font;
|
||||
import funorb.shatteredplans.client.JagexApplet;
|
||||
import funorb.client.JagexBaseApplet;
|
||||
import funorb.shatteredplans.StringConstants;
|
||||
|
||||
public class AccountPage extends FormNavigationPage implements ButtonListener {
|
||||
private final boolean _vb;
|
||||
private final ProgressBar _yb;
|
||||
private final boolean _tb;
|
||||
private final Font _ub;
|
||||
private boolean _sb = false;
|
||||
private boolean _wb;
|
||||
|
||||
public AccountPage(final NavigationRoot var1, final Font var2, final String var3, final boolean var4, final boolean var5) {
|
||||
super(var1, new cf_(null, var2, var3), 77, 10, 10);
|
||||
this._tb = var4;
|
||||
this._vb = var5;
|
||||
this._wb = false;
|
||||
this._ub = var2;
|
||||
this._yb = new ProgressBar();
|
||||
this._yb.animateStripes = true;
|
||||
this.addChild(this._yb);
|
||||
}
|
||||
|
||||
private static void a150nb() {
|
||||
if (CommonUI._nlb) {
|
||||
if (CommonUI._jiG != null) {
|
||||
CommonUI._jiG.i423();
|
||||
}
|
||||
|
||||
final String var1 = l738w();
|
||||
LoginForm._noe = new LoginForm(var1, true, false, false);
|
||||
CommonUI.root.pushChild(CommonUI._aef);
|
||||
CommonUI._aef.b952(LoginForm._noe);
|
||||
CommonUI._aef.n150();
|
||||
} else {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
private static String l738w() {
|
||||
String var1 = "";
|
||||
if (LoginForm._noe != null) {
|
||||
var1 = LoginForm._noe.d791();
|
||||
}
|
||||
|
||||
if (var1.length() == 0) {
|
||||
var1 = a738id();
|
||||
}
|
||||
|
||||
if (var1.length() == 0) {
|
||||
var1 = StringConstants.DEFAULT_PLAYER_NAME;
|
||||
}
|
||||
|
||||
return var1;
|
||||
}
|
||||
|
||||
private static String a738id() {
|
||||
return JagexApplet.playerDisplayName == null ? "" : JagexApplet.playerDisplayName;
|
||||
}
|
||||
|
||||
public final void p150() {
|
||||
this._yb.setColor(ProgressBar.SUCCESS_COLOR);
|
||||
final cf_ var2 = new cf_(this, this._ub, StringConstants.CONNECTION_RESTORED);
|
||||
var2.a966(StringConstants.RETURN_TO_GAME, CommonUI.TickResult.RETURN_TO_GAME);
|
||||
this.b952(var2);
|
||||
}
|
||||
|
||||
public final void i423() {
|
||||
if (this.isAlive) {
|
||||
this.isAlive = false;
|
||||
if (this._tb) {
|
||||
a150nb();
|
||||
} else if (this._vb) {
|
||||
LoginForm.a667ce(JagexApplet._aeg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleButtonClicked(final Button button) {
|
||||
if (this._sb) {
|
||||
CommonUI._crb = CommonUI.TickResult.LOGGING_IN;
|
||||
this.i423();
|
||||
} else {
|
||||
JagexApplet.a808bp("tochangedisplayname.ws", JagexBaseApplet.getInstance());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean a686(final int keyCode, final char keyChar, final Component var4) {
|
||||
if (keyCode == KeyState.Code.ESCAPE) {
|
||||
this.i423();
|
||||
return true;
|
||||
} else {
|
||||
return super.a686(keyCode, keyChar, var4);
|
||||
}
|
||||
}
|
||||
|
||||
public final void a503(final String var1, final int var2) {
|
||||
if (!this._wb) {
|
||||
this._sb = var2 == 256;
|
||||
this._wb = true;
|
||||
this._yb.setColor(ProgressBar.FAILURE_COLOR);
|
||||
final cf_ var4 = new cf_(this, this._ub, var1);
|
||||
if (var2 == 5) {
|
||||
var4.a966(StringConstants.RELOAD_GAME, CommonUI.TickResult.RELOAD);
|
||||
var4.a966(StringConstants.QUIT_TO_WEBSITE, CommonUI.TickResult.QUIT_TO_WEBSITE);
|
||||
} else if (var2 == 256) {
|
||||
var4.a700(this, StringConstants.RETRY);
|
||||
} else {
|
||||
var4.a966(this._tb ? StringConstants.RETRY : StringConstants.BACK, null);
|
||||
}
|
||||
|
||||
if (var2 == 3) {
|
||||
var4.a966(StringConstants.TO_SERVER_LIST, CommonUI.TickResult.TO_SERVER_LIST);
|
||||
} else if (var2 == 4) {
|
||||
var4.a966(StringConstants.PLAY_FREE_VERSION, CommonUI.TickResult.PLAY_FREE_VERSION);
|
||||
} else if (var2 == 6) {
|
||||
var4.a966(StringConstants.TO_CUSTOMER_SUPPORT, CommonUI.TickResult.TO_CUSTOMER_SUPPORT);
|
||||
} else if (var2 == 9) {
|
||||
var4.a700(this, StringConstants.CHANGE_DISPLAY_NAME);
|
||||
}
|
||||
|
||||
this.b952(var4);
|
||||
}
|
||||
}
|
||||
}
|
195
src/main/java/funorb/commonui/Button.java
Normal file
195
src/main/java/funorb/commonui/Button.java
Normal file
@ -0,0 +1,195 @@
|
||||
package funorb.commonui;
|
||||
|
||||
import funorb.awt.KeyState;
|
||||
import funorb.awt.MouseState;
|
||||
import funorb.commonui.listener.ComponentListener;
|
||||
import funorb.commonui.listener.ButtonListener;
|
||||
import funorb.commonui.renderer.ButtonRenderer;
|
||||
import funorb.commonui.renderer.ComponentRenderer;
|
||||
import funorb.graphics.Drawing;
|
||||
import funorb.shatteredplans.client.JagexApplet;
|
||||
import org.intellij.lang.annotations.MagicConstant;
|
||||
|
||||
import java.util.Hashtable;
|
||||
|
||||
public class Button extends Component {
|
||||
private final boolean _B;
|
||||
public boolean active;
|
||||
public boolean enabled;
|
||||
private boolean focused;
|
||||
|
||||
public Button(final String text, final ComponentListener listener) {
|
||||
this(text, new ButtonRenderer(), listener);
|
||||
}
|
||||
|
||||
public Button(final String text, final ComponentRenderer renderer, final ComponentListener listener) {
|
||||
super(text, renderer, listener);
|
||||
this._B = true;
|
||||
this.focused = false;
|
||||
this.enabled = true;
|
||||
}
|
||||
|
||||
protected Button() {
|
||||
this._B = true;
|
||||
this.focused = false;
|
||||
this.enabled = true;
|
||||
this.renderer = null;
|
||||
}
|
||||
|
||||
public static void drawFocusRect(final int x, final int y, final int width, final int height) {
|
||||
final int var5 = x + width;
|
||||
final int var6 = height + y;
|
||||
final int var7 = Math.max(x, Drawing.left);
|
||||
final int var8 = Math.max(Drawing.top, y);
|
||||
final int var9 = Math.min(Drawing.right, var5);
|
||||
|
||||
final int var10 = Math.min(Drawing.bottom, var6);
|
||||
int var11;
|
||||
int var12;
|
||||
if (Drawing.left <= x && Drawing.right > x) {
|
||||
var11 = Drawing.width * var8 + x;
|
||||
var12 = var10 + 1 - var8 >> 1;
|
||||
|
||||
while (true) {
|
||||
--var12;
|
||||
if (var12 < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
Drawing.screenBuffer[var11] = Drawing.WHITE;
|
||||
var11 += Drawing.width * 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (y >= Drawing.top && Drawing.bottom > var6) {
|
||||
var11 = Drawing.pixelIndex(var7, y);
|
||||
var12 = -var7 + 1 + var9 >> 1;
|
||||
|
||||
while (true) {
|
||||
--var12;
|
||||
if (var12 < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
Drawing.screenBuffer[var11] = Drawing.WHITE;
|
||||
var11 += 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (Drawing.left <= var5 && var5 < Drawing.right) {
|
||||
var11 = Drawing.width * ((1 & var5 - x) + var8) + var5;
|
||||
var12 = 1 - (-var10 + var8) >> 1;
|
||||
|
||||
while (true) {
|
||||
--var12;
|
||||
if (var12 < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
Drawing.screenBuffer[var11] = Drawing.WHITE;
|
||||
var11 += Drawing.width * 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (y >= Drawing.top && Drawing.bottom > var6) {
|
||||
var11 = (1 & var6 - y) + var6 * Drawing.width + var7;
|
||||
var12 = -var7 + 1 + var9 >> 1;
|
||||
|
||||
while (true) {
|
||||
--var12;
|
||||
if (var12 < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
Drawing.screenBuffer[var11] = Drawing.WHITE;
|
||||
var11 += 2;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public final StringBuilder buildDebugString(final Hashtable<Component, Component> cycles, final int nestingLevel, final StringBuilder builder) {
|
||||
if (this.debugStringCycleCheck(cycles, builder)) {
|
||||
this.putDefaultDebugString(cycles, nestingLevel, builder);
|
||||
if (this.active) {
|
||||
builder.append(" active");
|
||||
}
|
||||
|
||||
if (!this.enabled) {
|
||||
builder.append(" disabled");
|
||||
}
|
||||
}
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean focus(final Component previouslyFocused) {
|
||||
if (this.enabled && this._B) {
|
||||
previouslyFocused.unfocus();
|
||||
this.focused = true;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isFocused() {
|
||||
return this.focused;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean a446(final int var1, final int var2, final int var4, final int var5, final int var6, final Component var7) {
|
||||
if (this.enabled && this.a046(var2, var4, var6, var5)) {
|
||||
this.focus(var7);
|
||||
this._o = var1;
|
||||
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void unfocus() {
|
||||
if (this.focused) {
|
||||
this.focused = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick(final int x, final int y, final Component root) {
|
||||
super.tick(x, y, root);
|
||||
if (this._o != 0 && JagexApplet.mouseButtonDown != this._o) {
|
||||
if (this.a046(JagexApplet.mouseX, JagexApplet.mouseY, y, x) && JagexApplet.mouseButtonDown == MouseState.Button.NONE) {
|
||||
this.handleClicked(this._o, JagexApplet.mouseX - x, -y + JagexApplet.mouseY);
|
||||
}
|
||||
|
||||
this.a132(JagexApplet.mouseX, y, x, JagexApplet.mouseY, root);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean a686(@MagicConstant(valuesFromClass = KeyState.Code.class) final int keyCode, final char keyChar, final Component var4) {
|
||||
if (!this.isFocused() || keyCode != KeyState.Code.ENTER && keyCode != KeyState.Code.SPACE) {
|
||||
return false;
|
||||
} else {
|
||||
this.handleClicked(1, -1, -1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
protected void handleClicked(final int var1, final int var2, final int var3) {
|
||||
if (this.listener != null && this.listener instanceof ButtonListener) {
|
||||
((ButtonListener) this.listener).handleButtonClicked(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void a132(final int var1, final int var2, final int var3, final int var4, final Component var6) {
|
||||
this._o = 0;
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user