connect to Twitch. Decreased retry interval from every 0.03 seconds to every 1 second.beta
commit
3d60722f68
@ -0,0 +1,19 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<classpath> |
||||
<classpathentry kind="src" path="src"/> |
||||
<classpathentry kind="src" path="lib"/> |
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/> |
||||
<classpathentry kind="lib" path="C:/Users/sigon/Downloads/sigIRCv2-master/sigIRCv2/lib/commons-io-2.5.jar"/> |
||||
<classpathentry kind="lib" path="C:/Users/sigon/Downloads/sigIRCv2-master/sigIRCv2/lib/jna-4.5.0.jar"/> |
||||
<classpathentry kind="lib" path="C:/Users/sigon/Downloads/sigIRCv2-master/sigIRCv2/lib/jna-platform-4.5.0.jar"/> |
||||
<classpathentry kind="lib" path="C:/Users/sigon/Downloads/sigIRCv2-master/sigIRCv2/lib/lwjgl.jar"/> |
||||
<classpathentry kind="lib" path="C:/Users/sigon/Downloads/sigIRCv2-master/sigIRCv2/lib/lwjgl-glfw.jar"/> |
||||
<classpathentry kind="lib" path="C:/Users/sigon/Downloads/sigIRCv2-master/sigIRCv2/lib/lwjgl-glfw-natives-linux.jar"/> |
||||
<classpathentry kind="lib" path="C:/Users/sigon/Downloads/sigIRCv2-master/sigIRCv2/lib/lwjgl-glfw-natives-macos.jar"/> |
||||
<classpathentry kind="lib" path="C:/Users/sigon/Downloads/sigIRCv2-master/sigIRCv2/lib/lwjgl-glfw-natives-windows.jar"/> |
||||
<classpathentry kind="lib" path="C:/Users/sigon/Downloads/sigIRCv2-master/sigIRCv2/lib/lwjgl-natives-linux.jar"/> |
||||
<classpathentry kind="lib" path="C:/Users/sigon/Downloads/sigIRCv2-master/sigIRCv2/lib/lwjgl-natives-macos.jar"/> |
||||
<classpathentry kind="lib" path="C:/Users/sigon/Downloads/sigIRCv2-master/sigIRCv2/lib/lwjgl-natives-windows.jar"/> |
||||
<classpathentry kind="lib" path="C:/Users/sigon/Downloads/sigIRCv2-master/sigIRCv2/lib/twitch-api-wrapper-0.3-jar-with-dependencies.jar"/> |
||||
<classpathentry kind="output" path="bin"/> |
||||
</classpath> |
@ -0,0 +1,20 @@ |
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
||||
<launchConfiguration type="org.eclipse.ant.AntBuilderLaunchConfigurationType"> |
||||
<booleanAttribute key="org.eclipse.ant.ui.ATTR_TARGETS_UPDATED" value="true"/> |
||||
<booleanAttribute key="org.eclipse.ant.ui.DEFAULT_VM_INSTALL" value="false"/> |
||||
<stringAttribute key="org.eclipse.debug.core.ATTR_REFRESH_SCOPE" value="${resource}"/> |
||||
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS"> |
||||
<listEntry value="/sigIRCv2"/> |
||||
</listAttribute> |
||||
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES"> |
||||
<listEntry value="4"/> |
||||
</listAttribute> |
||||
<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/> |
||||
<stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="org.eclipse.ant.ui.AntClasspathProvider"/> |
||||
<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="true"/> |
||||
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="sigIRCv2"/> |
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/sigIRCv2/projectBuilder.xml}"/> |
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_RUN_BUILD_KINDS" value="full,incremental,"/> |
||||
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED" value="true"/> |
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/sigIRCv2}"/> |
||||
</launchConfiguration> |
@ -0,0 +1,17 @@ |
||||
/bin/ |
||||
/sigIRC/ |
||||
/sigIRC/Emotes/ |
||||
/backcolor.png |
||||
/kill.png |
||||
/memory |
||||
/sigIRCv2.conf |
||||
/swap.png |
||||
/update.png |
||||
/WSplits |
||||
/drag_bar.png |
||||
/jinput-dx8.dll |
||||
/jinput-dx8_64.dll |
||||
/jinput-raw.dll |
||||
/jinput-raw_64.dll |
||||
/jinput-wintab.dll |
||||
/memoryDump.txt |
@ -0,0 +1,27 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<projectDescription> |
||||
<name>sigIRCv2</name> |
||||
<comment></comment> |
||||
<projects> |
||||
</projects> |
||||
<buildSpec> |
||||
<buildCommand> |
||||
<name>org.eclipse.jdt.core.javabuilder</name> |
||||
<arguments> |
||||
</arguments> |
||||
</buildCommand> |
||||
<buildCommand> |
||||
<name>org.eclipse.ui.externaltools.ExternalToolBuilder</name> |
||||
<triggers>full,incremental,</triggers> |
||||
<arguments> |
||||
<dictionary> |
||||
<key>LaunchConfigHandle</key> |
||||
<value><project>/.externalToolBuilders/Makejar.launch</value> |
||||
</dictionary> |
||||
</arguments> |
||||
</buildCommand> |
||||
</buildSpec> |
||||
<natures> |
||||
<nature>org.eclipse.jdt.core.javanature</nature> |
||||
</natures> |
||||
</projectDescription> |
@ -0,0 +1,11 @@ |
||||
eclipse.preferences.version=1 |
||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled |
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 |
||||
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve |
||||
org.eclipse.jdt.core.compiler.compliance=1.8 |
||||
org.eclipse.jdt.core.compiler.debug.lineNumber=generate |
||||
org.eclipse.jdt.core.compiler.debug.localVariable=generate |
||||
org.eclipse.jdt.core.compiler.debug.sourceFile=generate |
||||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error |
||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error |
||||
org.eclipse.jdt.core.compiler.source=1.8 |
@ -0,0 +1,7 @@ |
||||
#Dependencies |
||||
|
||||
You will need to download the commons-io library from the Apache Commons Library website. Download page found here: https://commons.apache.org/proper/commons-io/ |
||||
|
||||
You will also need the Java Twitch API Wrapper library if you are planning to use the Twitch module functionality. Download page found here: https://github.com/urgrue/Java-Twitch-Api-Wrapper/releases/tag/0.3 |
||||
|
||||
Include both as an External Jar and you should be good to go. |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,65 @@ |
||||
Could not find C:\Users\sigon\Downloads\sigIRCv2-master\sigIRCv2\.\sigIRC\oauthToken.txt, retrieving file online from http://45.33.13.215/sigIRCv2/oauthToken.txt. |
||||
Could not find C:\Users\sigon\Downloads\sigIRCv2-master\sigIRCv2\.\sigIRC\subscribers.txt, retrieving file online from http://45.33.13.215/sigIRCv2/subscribers.txt. |
||||
Could not find C:\Users\sigon\Downloads\sigIRCv2-master\sigIRCv2\.\sigIRC\follower_sounds\Glaceon_cry.wav, retrieving file online from http://45.33.13.215/sigIRCv2/Glaceon_cry.wav. |
||||
Could not find C:\Users\sigon\Downloads\sigIRCv2-master\sigIRCv2\.\sigIRC\follower_sounds\README.txt, retrieving file online from http://45.33.13.215/sigIRCv2/README.txt. |
||||
Could not find C:\Users\sigon\Downloads\sigIRCv2-master\sigIRCv2\.\sigIRC\record, retrieving file online from http://45.33.13.215/sigIRCv2/record. |
||||
Could not find C:\Users\sigon\Downloads\sigIRCv2-master\sigIRCv2\.\sigIRC\glaceon_follower.png, retrieving file online from http://45.33.13.215/sigIRCv2/glaceon_follower.png. |
||||
Could not find C:\Users\sigon\Downloads\sigIRCv2-master\sigIRCv2\.\sigIRC\sigIRCicon.png, retrieving file online from http://45.33.13.215/sigIRCv2/sigIRCicon.png. |
||||
Could not find C:\Users\sigon\Downloads\sigIRCv2-master\sigIRCv2\.\sigIRC\icon_down_arrow.png, retrieving file online from http://45.33.13.215/sigIRCv2/icon_down_arrow.png. |
||||
Could not find C:\Users\sigon\Downloads\sigIRCv2-master\sigIRCv2\.\sigIRC\icon_follower_count.png, retrieving file online from http://45.33.13.215/sigIRCv2/icon_follower_count.png. |
||||
Could not find C:\Users\sigon\Downloads\sigIRCv2-master\sigIRCv2\.\sigIRC\icon_up_arrow.png, retrieving file online from http://45.33.13.215/sigIRCv2/icon_up_arrow.png. |
||||
Could not find C:\Users\sigon\Downloads\sigIRCv2-master\sigIRCv2\.\sigIRC\icon_uptime.png, retrieving file online from http://45.33.13.215/sigIRCv2/icon_uptime.png. |
||||
Could not find C:\Users\sigon\Downloads\sigIRCv2-master\sigIRCv2\.\sigIRC\icon_viewers_count.png, retrieving file online from http://45.33.13.215/sigIRCv2/icon_viewers_count.png. |
||||
Could not find C:\Users\sigon\Downloads\sigIRCv2-master\sigIRCv2\.\sigIRC\icon_views_count.png, retrieving file online from http://45.33.13.215/sigIRCv2/icon_views_count.png. |
||||
Could not find C:\Users\sigon\Downloads\sigIRCv2-master\sigIRCv2\.\sigIRC\message_separator.png, retrieving file online from http://45.33.13.215/sigIRCv2/message_separator.png. |
||||
Could not find C:\Users\sigon\Downloads\sigIRCv2-master\sigIRCv2\.\sigIRC\controller\2-way_axis.png, retrieving file online from http://45.33.13.215/sigIRCv2/2-way_axis.png. |
||||
Could not find C:\Users\sigon\Downloads\sigIRCv2-master\sigIRCv2\.\sigIRC\controller\4-way_axis.png, retrieving file online from http://45.33.13.215/sigIRCv2/4-way_axis.png. |
||||
Could not find C:\Users\sigon\Downloads\sigIRCv2-master\sigIRCv2\.\sigIRC\controller\controller_overlay.png, retrieving file online from http://45.33.13.215/sigIRCv2/controller_overlay.png. |
||||
Could not find C:\Users\sigon\Downloads\sigIRCv2-master\sigIRCv2\.\sigIRC\controller\controller_template.png, retrieving file online from http://45.33.13.215/sigIRCv2/controller_template.png. |
||||
Could not find C:\Users\sigon\Downloads\sigIRCv2-master\sigIRCv2\.\sigIRC\CP_Font.ttf, retrieving file online from http://45.33.13.215/sigIRCv2/CP_Font.ttf. |
||||
Could not find C:\Users\sigon\Downloads\sigIRCv2-master\sigIRCv2\.\kill.png, retrieving file online from http://45.33.13.215/sigIRCv2/kill.png. |
||||
Could not find C:\Users\sigon\Downloads\sigIRCv2-master\sigIRCv2\.\memory, retrieving file online from http://45.33.13.215/sigIRCv2/memory. |
||||
Could not find C:\Users\sigon\Downloads\sigIRCv2-master\sigIRCv2\.\swap.png, retrieving file online from http://45.33.13.215/sigIRCv2/swap.png. |
||||
Could not find C:\Users\sigon\Downloads\sigIRCv2-master\sigIRCv2\.\update.png, retrieving file online from http://45.33.13.215/sigIRCv2/update.png. |
||||
Could not find C:\Users\sigon\Downloads\sigIRCv2-master\sigIRCv2\.\backcolor.png, retrieving file online from http://45.33.13.215/sigIRCv2/backcolor.png. |
||||
Could not find C:\Users\sigon\Downloads\sigIRCv2-master\sigIRCv2\.\drag_bar.png, retrieving file online from http://45.33.13.215/sigIRCv2/drag_bar.png. |
||||
File size is 10277104 |
||||
File size on Github is -1 |
||||
File size on Github varies from currently running program... Downloading new program. |
||||
Downloaded Dependencies. |
||||
!!!!!!!!!!!!!!!!!! |
||||
!!!!!WARNING!!!!!! |
||||
There is a space in the global file location sigIRC/sounds/Howler Monkeys Howling (Very Funny)-Pia8ku7jUNg.wav. This is going to cause huge errors! |
||||
!!!!!!!!!!!!!!!!!! |
||||
Trace:Mini stack tracer: |
||||
sig.utils.DebugUtils: **DebugUtils.java** getStackTrace():10 |
||||
sig.utils.DebugUtils: **DebugUtils.java** showStackTrace():6 |
||||
sig.FileManager: **FileManager.java** <init>():22 |
||||
sig.CustomSound: **CustomSound.java** <init>():24 |
||||
sig.sigIRC: **sigIRC.java** InitializeCustomSounds():406 |
||||
sig.sigIRC: **sigIRC.java** main():259 |
||||
!!!!!!!!!!!!!!!!!! |
||||
!!!!!WARNING!!!!!! |
||||
There is a space in the global file location sigIRC/sounds/Kuroyukihime Burst Link !-tv6wMw7KU9o.wav. This is going to cause huge errors! |
||||
!!!!!!!!!!!!!!!!!! |
||||
Trace:Mini stack tracer: |
||||
sig.utils.DebugUtils: **DebugUtils.java** getStackTrace():10 |
||||
sig.utils.DebugUtils: **DebugUtils.java** showStackTrace():6 |
||||
sig.FileManager: **FileManager.java** <init>():22 |
||||
sig.CustomSound: **CustomSound.java** <init>():24 |
||||
sig.sigIRC: **sigIRC.java** InitializeCustomSounds():407 |
||||
sig.sigIRC: **sigIRC.java** main():259 |
||||
!!!!!!!!!!!!!!!!!! |
||||
!!!!!WARNING!!!!!! |
||||
There is a space in the global file location sigIRC/sounds/Samus Appears - Metroid Prime [OST]-G8frLXCHtqM.wav. This is going to cause huge errors! |
||||
!!!!!!!!!!!!!!!!!! |
||||
Trace:Mini stack tracer: |
||||
sig.utils.DebugUtils: **DebugUtils.java** getStackTrace():10 |
||||
sig.utils.DebugUtils: **DebugUtils.java** showStackTrace():6 |
||||
sig.FileManager: **FileManager.java** <init>():22 |
||||
sig.CustomSound: **CustomSound.java** <init>():24 |
||||
sig.sigIRC: **sigIRC.java** InitializeCustomSounds():408 |
||||
sig.sigIRC: **sigIRC.java** main():259 |
||||
Local copy of Sub emotes not found. Downloading in background... |
||||
Properties successfully saved. |
||||
Properties successfully saved. |
@ -0,0 +1 @@ |
||||
sigonitori: This will go in the log file! |
@ -0,0 +1,30 @@ |
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
||||
<project default="create_run_jar" name="Create Runnable Jar for Project sigIRCv2"> |
||||
<!--this file was created by Eclipse Runnable JAR Export Wizard--> |
||||
<!--ANT 1.7 is required --> |
||||
<!--define folder properties--> |
||||
<property name="dir.buildfile" value="."/> |
||||
<property name="dir.workspace" value="${dir.buildfile}/.."/> |
||||
<property name="dir.jarfile" value="${dir.buildfile}"/> |
||||
<target name="create_run_jar"> |
||||
<jar destfile="${dir.jarfile}/sigIRCv2.jar" filesetmanifest="mergewithoutmain"> |
||||
<manifest> |
||||
<attribute name="Main-Class" value="sig.sigIRC"/> |
||||
<attribute name="Class-Path" value="."/> |
||||
</manifest> |
||||
<fileset dir="${dir.jarfile}/bin"/> |
||||
<zipfileset excludes="META-INF/*.SF" src="lib/commons-io-2.5.jar"/> |
||||
<zipfileset excludes="META-INF/*.SF" src="lib/twitch-api-wrapper-0.3-jar-with-dependencies.jar"/> |
||||
<zipfileset excludes="META-INF/*.SF" src="lib/lwjgl-glfw.jar"/> |
||||
<zipfileset excludes="META-INF/*.SF" src="lib/lwjgl-glfw-natives-linux.jar"/> |
||||
<zipfileset excludes="META-INF/*.SF" src="lib/lwjgl-glfw-natives-windows.jar"/> |
||||
<zipfileset excludes="META-INF/*.SF" src="lib/lwjgl-glfw-natives-macos.jar"/> |
||||
<zipfileset excludes="META-INF/*.SF" src="lib/lwjgl.jar"/> |
||||
<zipfileset excludes="META-INF/*.SF" src="lib/lwjgl-natives-linux.jar"/> |
||||
<zipfileset excludes="META-INF/*.SF" src="lib/lwjgl-natives-windows.jar"/> |
||||
<zipfileset excludes="META-INF/*.SF" src="lib/lwjgl-natives-macos.jar"/> |
||||
<zipfileset excludes="META-INF/*.SF" src="lib/jna-4.5.0.jar"/> |
||||
<zipfileset excludes="META-INF/*.SF" src="lib/jna-platform-4.5.0.jar"/> |
||||
</jar> |
||||
</target> |
||||
</project> |
@ -0,0 +1,2 @@ |
||||
cd "C:\Users\Joshua Sigona\git\sigIRCv2\" |
||||
java -jar sigIRCv2.jar > log |
Binary file not shown.
@ -0,0 +1,284 @@ |
||||
package org.json; |
||||
|
||||
/* |
||||
Copyright (c) 2002 JSON.org |
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
of this software and associated documentation files (the "Software"), to deal |
||||
in the Software without restriction, including without limitation the rights |
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
copies of the Software, and to permit persons to whom the Software is |
||||
furnished to do so, subject to the following conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be included in all |
||||
copies or substantial portions of the Software. |
||||
|
||||
The Software shall be used for Good, not Evil. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||
SOFTWARE. |
||||
*/ |
||||
|
||||
/** |
||||
* This provides static methods to convert comma delimited text into a |
||||
* JSONArray, and to convert a JSONArray into comma delimited text. Comma |
||||
* delimited text is a very popular format for data interchange. It is |
||||
* understood by most database, spreadsheet, and organizer programs. |
||||
* <p> |
||||
* Each row of text represents a row in a table or a data record. Each row |
||||
* ends with a NEWLINE character. Each row contains one or more values. |
||||
* Values are separated by commas. A value can contain any character except |
||||
* for comma, unless is is wrapped in single quotes or double quotes. |
||||
* <p> |
||||
* The first row usually contains the names of the columns. |
||||
* <p> |
||||
* A comma delimited list can be converted into a JSONArray of JSONObjects. |
||||
* The names for the elements in the JSONObjects can be taken from the names |
||||
* in the first row. |
||||
* @author JSON.org |
||||
* @version 2016-05-01 |
||||
*/ |
||||
public class CDL { |
||||
|
||||
/** |
||||
* Get the next value. The value can be wrapped in quotes. The value can |
||||
* be empty. |
||||
* @param x A JSONTokener of the source text. |
||||
* @return The value string, or null if empty. |
||||
* @throws JSONException if the quoted string is badly formed. |
||||
*/ |
||||
private static String getValue(JSONTokener x) throws JSONException { |
||||
char c; |
||||
char q; |
||||
StringBuffer sb; |
||||
do { |
||||
c = x.next(); |
||||
} while (c == ' ' || c == '\t'); |
||||
switch (c) { |
||||
case 0: |
||||
return null; |
||||
case '"': |
||||
case '\'': |
||||
q = c; |
||||
sb = new StringBuffer(); |
||||
for (;;) { |
||||
c = x.next(); |
||||
if (c == q) { |
||||
//Handle escaped double-quote
|
||||
if(x.next() != '\"') |
||||
{ |
||||
x.back(); |
||||
break; |
||||
} |
||||
} |
||||
if (c == 0 || c == '\n' || c == '\r') { |
||||
throw x.syntaxError("Missing close quote '" + q + "'."); |
||||
} |
||||
sb.append(c); |
||||
} |
||||
return sb.toString(); |
||||
case ',': |
||||
x.back(); |
||||
return ""; |
||||
default: |
||||
x.back(); |
||||
return x.nextTo(','); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Produce a JSONArray of strings from a row of comma delimited values. |
||||
* @param x A JSONTokener of the source text. |
||||
* @return A JSONArray of strings. |
||||
* @throws JSONException |
||||
*/ |
||||
public static JSONArray rowToJSONArray(JSONTokener x) throws JSONException { |
||||
JSONArray ja = new JSONArray(); |
||||
for (;;) { |
||||
String value = getValue(x); |
||||
char c = x.next(); |
||||
if (value == null || |
||||
(ja.length() == 0 && value.length() == 0 && c != ',')) { |
||||
return null; |
||||
} |
||||
ja.put(value); |
||||
for (;;) { |
||||
if (c == ',') { |
||||
break; |
||||
} |
||||
if (c != ' ') { |
||||
if (c == '\n' || c == '\r' || c == 0) { |
||||
return ja; |
||||
} |
||||
throw x.syntaxError("Bad character '" + c + "' (" + |
||||
(int)c + ")."); |
||||
} |
||||
c = x.next(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Produce a JSONObject from a row of comma delimited text, using a |
||||
* parallel JSONArray of strings to provides the names of the elements. |
||||
* @param names A JSONArray of names. This is commonly obtained from the |
||||
* first row of a comma delimited text file using the rowToJSONArray |
||||
* method. |
||||
* @param x A JSONTokener of the source text. |
||||
* @return A JSONObject combining the names and values. |
||||
* @throws JSONException |
||||
*/ |
||||
public static JSONObject rowToJSONObject(JSONArray names, JSONTokener x) |
||||
throws JSONException { |
||||
JSONArray ja = rowToJSONArray(x); |
||||
return ja != null ? ja.toJSONObject(names) : null; |
||||
} |
||||
|
||||
/** |
||||
* Produce a comma delimited text row from a JSONArray. Values containing |
||||
* the comma character will be quoted. Troublesome characters may be |
||||
* removed. |
||||
* @param ja A JSONArray of strings. |
||||
* @return A string ending in NEWLINE. |
||||
*/ |
||||
public static String rowToString(JSONArray ja) { |
||||
StringBuilder sb = new StringBuilder(); |
||||
for (int i = 0; i < ja.length(); i += 1) { |
||||
if (i > 0) { |
||||
sb.append(','); |
||||
} |
||||
Object object = ja.opt(i); |
||||
if (object != null) { |
||||
String string = object.toString(); |
||||
if (string.length() > 0 && (string.indexOf(',') >= 0 || |
||||
string.indexOf('\n') >= 0 || string.indexOf('\r') >= 0 || |
||||
string.indexOf(0) >= 0 || string.charAt(0) == '"')) { |
||||
sb.append('"'); |
||||
int length = string.length(); |
||||
for (int j = 0; j < length; j += 1) { |
||||
char c = string.charAt(j); |
||||
if (c >= ' ' && c != '"') { |
||||
sb.append(c); |
||||
} |
||||
} |
||||
sb.append('"'); |
||||
} else { |
||||
sb.append(string); |
||||
} |
||||
} |
||||
} |
||||
sb.append('\n'); |
||||
return sb.toString(); |
||||
} |
||||
|
||||
/** |
||||
* Produce a JSONArray of JSONObjects from a comma delimited text string, |
||||
* using the first row as a source of names. |
||||
* @param string The comma delimited text. |
||||
* @return A JSONArray of JSONObjects. |
||||
* @throws JSONException |
||||
*/ |
||||
public static JSONArray toJSONArray(String string) throws JSONException { |
||||
return toJSONArray(new JSONTokener(string)); |
||||
} |
||||
|
||||
/** |
||||
* Produce a JSONArray of JSONObjects from a comma delimited text string, |
||||
* using the first row as a source of names. |
||||
* @param x The JSONTokener containing the comma delimited text. |
||||
* @return A JSONArray of JSONObjects. |
||||
* @throws JSONException |
||||
*/ |
||||
public static JSONArray toJSONArray(JSONTokener x) throws JSONException { |
||||
return toJSONArray(rowToJSONArray(x), x); |
||||
} |
||||
|
||||
/** |
||||
* Produce a JSONArray of JSONObjects from a comma delimited text string |
||||
* using a supplied JSONArray as the source of element names. |
||||
* @param names A JSONArray of strings. |
||||
* @param string The comma delimited text. |
||||
* @return A JSONArray of JSONObjects. |
||||
* @throws JSONException |
||||
*/ |
||||
public static JSONArray toJSONArray(JSONArray names, String string) |
||||
throws JSONException { |
||||
return toJSONArray(names, new JSONTokener(string)); |
||||
} |
||||
|
||||
/** |
||||
* Produce a JSONArray of JSONObjects from a comma delimited text string |
||||
* using a supplied JSONArray as the source of element names. |
||||
* @param names A JSONArray of strings. |
||||
* @param x A JSONTokener of the source text. |
||||
* @return A JSONArray of JSONObjects. |
||||
* @throws JSONException |
||||
*/ |
||||
public static JSONArray toJSONArray(JSONArray names, JSONTokener x) |
||||
throws JSONException { |
||||
if (names == null || names.length() == 0) { |
||||
return null; |
||||
} |
||||
JSONArray ja = new JSONArray(); |
||||
for (;;) { |
||||
JSONObject jo = rowToJSONObject(names, x); |
||||
if (jo == null) { |
||||
break; |
||||
} |
||||
ja.put(jo); |
||||
} |
||||
if (ja.length() == 0) { |
||||
return null; |
||||
} |
||||
return ja; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Produce a comma delimited text from a JSONArray of JSONObjects. The |
||||
* first row will be a list of names obtained by inspecting the first |
||||
* JSONObject. |
||||
* @param ja A JSONArray of JSONObjects. |
||||
* @return A comma delimited text. |
||||
* @throws JSONException |
||||
*/ |
||||
public static String toString(JSONArray ja) throws JSONException { |
||||
JSONObject jo = ja.optJSONObject(0); |
||||
if (jo != null) { |
||||
JSONArray names = jo.names(); |
||||
if (names != null) { |
||||
return rowToString(names) + toString(names, ja); |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
/** |
||||
* Produce a comma delimited text from a JSONArray of JSONObjects using |
||||
* a provided list of names. The list of names is not included in the |
||||
* output. |
||||
* @param names A JSONArray of strings. |
||||
* @param ja A JSONArray of JSONObjects. |
||||
* @return A comma delimited text. |
||||
* @throws JSONException |
||||
*/ |
||||
public static String toString(JSONArray names, JSONArray ja) |
||||
throws JSONException { |
||||
if (names == null || names.length() == 0) { |
||||
return null; |
||||
} |
||||
StringBuffer sb = new StringBuffer(); |
||||
for (int i = 0; i < ja.length(); i += 1) { |
||||
JSONObject jo = ja.optJSONObject(i); |
||||
if (jo != null) { |
||||
sb.append(rowToString(jo.toJSONArray(names))); |
||||
} |
||||
} |
||||
return sb.toString(); |
||||
} |
||||
} |
@ -0,0 +1,169 @@ |
||||
package org.json; |
||||
|
||||
/* |
||||
Copyright (c) 2002 JSON.org |
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
of this software and associated documentation files (the "Software"), to deal |
||||
in the Software without restriction, including without limitation the rights |
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
copies of the Software, and to permit persons to whom the Software is |
||||
furnished to do so, subject to the following conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be included in all |
||||
copies or substantial portions of the Software. |
||||
|
||||
The Software shall be used for Good, not Evil. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||
SOFTWARE. |
||||
*/ |
||||
|
||||
/** |
||||
* Convert a web browser cookie specification to a JSONObject and back. |
||||
* JSON and Cookies are both notations for name/value pairs. |
||||
* @author JSON.org |
||||
* @version 2015-12-09 |
||||
*/ |
||||
public class Cookie { |
||||
|
||||
/** |
||||
* Produce a copy of a string in which the characters '+', '%', '=', ';' |
||||
* and control characters are replaced with "%hh". This is a gentle form |
||||
* of URL encoding, attempting to cause as little distortion to the |
||||
* string as possible. The characters '=' and ';' are meta characters in |
||||
* cookies. By convention, they are escaped using the URL-encoding. This is |
||||
* only a convention, not a standard. Often, cookies are expected to have |
||||
* encoded values. We encode '=' and ';' because we must. We encode '%' and |
||||
* '+' because they are meta characters in URL encoding. |
||||
* @param string The source string. |
||||
* @return The escaped result. |
||||
*/ |
||||
public static String escape(String string) { |
||||
char c; |
||||
String s = string.trim(); |
||||
int length = s.length(); |
||||
StringBuilder sb = new StringBuilder(length); |
||||
for (int i = 0; i < length; i += 1) { |
||||
c = s.charAt(i); |
||||
if (c < ' ' || c == '+' || c == '%' || c == '=' || c == ';') { |
||||
sb.append('%'); |
||||
sb.append(Character.forDigit((char)((c >>> 4) & 0x0f), 16)); |
||||
sb.append(Character.forDigit((char)(c & 0x0f), 16)); |
||||
} else { |
||||
sb.append(c); |
||||
} |
||||
} |
||||
return sb.toString(); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Convert a cookie specification string into a JSONObject. The string |
||||
* will contain a name value pair separated by '='. The name and the value |
||||
* will be unescaped, possibly converting '+' and '%' sequences. The |
||||
* cookie properties may follow, separated by ';', also represented as |
||||
* name=value (except the secure property, which does not have a value). |
||||
* The name will be stored under the key "name", and the value will be |
||||
* stored under the key "value". This method does not do checking or |
||||
* validation of the parameters. It only converts the cookie string into |
||||
* a JSONObject. |
||||
* @param string The cookie specification string. |
||||
* @return A JSONObject containing "name", "value", and possibly other |
||||
* members. |
||||
* @throws JSONException |
||||
*/ |
||||
public static JSONObject toJSONObject(String string) throws JSONException { |
||||
String name; |
||||
JSONObject jo = new JSONObject(); |
||||
Object value; |
||||
JSONTokener x = new JSONTokener(string); |
||||
jo.put("name", x.nextTo('=')); |
||||
x.next('='); |
||||
jo.put("value", x.nextTo(';')); |
||||
x.next(); |
||||
while (x.more()) { |
||||
name = unescape(x.nextTo("=;")); |
||||
if (x.next() != '=') { |
||||
if (name.equals("secure")) { |
||||
value = Boolean.TRUE; |
||||
} else { |
||||
throw x.syntaxError("Missing '=' in cookie parameter."); |
||||
} |
||||
} else { |
||||
value = unescape(x.nextTo(';')); |
||||
x.next(); |
||||
} |
||||
jo.put(name, value); |
||||
} |
||||
return jo; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Convert a JSONObject into a cookie specification string. The JSONObject |
||||
* must contain "name" and "value" members. |
||||
* If the JSONObject contains "expires", "domain", "path", or "secure" |
||||
* members, they will be appended to the cookie specification string. |
||||
* All other members are ignored. |
||||
* @param jo A JSONObject |
||||
* @return A cookie specification string |
||||
* @throws JSONException |
||||
*/ |
||||
public static String toString(JSONObject jo) throws JSONException { |
||||
StringBuilder sb = new StringBuilder(); |
||||
|
||||
sb.append(escape(jo.getString("name"))); |
||||
sb.append("="); |
||||
sb.append(escape(jo.getString("value"))); |
||||
if (jo.has("expires")) { |
||||
sb.append(";expires="); |
||||
sb.append(jo.getString("expires")); |
||||
} |
||||
if (jo.has("domain")) { |
||||
sb.append(";domain="); |
||||
sb.append(escape(jo.getString("domain"))); |
||||
} |
||||
if (jo.has("path")) { |
||||
sb.append(";path="); |
||||
sb.append(escape(jo.getString("path"))); |
||||
} |
||||
if (jo.optBoolean("secure")) { |
||||
sb.append(";secure"); |
||||
} |
||||
return sb.toString(); |
||||
} |
||||
|
||||
/** |
||||
* Convert <code>%</code><i>hh</i> sequences to single characters, and |
||||
* convert plus to space. |
||||
* @param string A string that may contain |
||||
* <code>+</code> <small>(plus)</small> and |
||||
* <code>%</code><i>hh</i> sequences. |
||||
* @return The unescaped string. |
||||
*/ |
||||
public static String unescape(String string) { |
||||
int length = string.length(); |
||||
StringBuilder sb = new StringBuilder(length); |
||||
for (int i = 0; i < length; ++i) { |
||||
char c = string.charAt(i); |
||||
if (c == '+') { |
||||
c = ' '; |
||||
} else if (c == '%' && i + 2 < length) { |
||||
int d = JSONTokener.dehexchar(string.charAt(i + 1)); |
||||
int e = JSONTokener.dehexchar(string.charAt(i + 2)); |
||||
if (d >= 0 && e >= 0) { |
||||
c = (char)(d * 16 + e); |
||||
i += 2; |
||||
} |
||||
} |
||||
sb.append(c); |
||||
} |
||||
return sb.toString(); |
||||
} |
||||
} |
@ -0,0 +1,89 @@ |
||||
package org.json; |
||||
|
||||
/* |
||||
Copyright (c) 2002 JSON.org |
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
of this software and associated documentation files (the "Software"), to deal |
||||
in the Software without restriction, including without limitation the rights |
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
copies of the Software, and to permit persons to whom the Software is |
||||
furnished to do so, subject to the following conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be included in all |
||||
copies or substantial portions of the Software. |
||||
|
||||
The Software shall be used for Good, not Evil. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||
SOFTWARE. |
||||
*/ |
||||
|
||||
import java.util.Iterator; |
||||
|
||||
/** |
||||
* Convert a web browser cookie list string to a JSONObject and back. |
||||
* @author JSON.org |
||||
* @version 2015-12-09 |
||||
*/ |
||||
public class CookieList { |
||||
|
||||
/** |
||||
* Convert a cookie list into a JSONObject. A cookie list is a sequence |
||||
* of name/value pairs. The names are separated from the values by '='. |
||||
* The pairs are separated by ';'. The names and the values |
||||
* will be unescaped, possibly converting '+' and '%' sequences. |
||||
* |
||||
* To add a cookie to a cooklist, |
||||
* cookielistJSONObject.put(cookieJSONObject.getString("name"), |
||||
* cookieJSONObject.getString("value")); |
||||
* @param string A cookie list string |
||||
* @return A JSONObject |
||||
* @throws JSONException |
||||
*/ |
||||
public static JSONObject toJSONObject(String string) throws JSONException { |
||||
JSONObject jo = new JSONObject(); |
||||
JSONTokener x = new JSONTokener(string); |
||||
while (x.more()) { |
||||
String name = Cookie.unescape(x.nextTo('=')); |
||||
x.next('='); |
||||
jo.put(name, Cookie.unescape(x.nextTo(';'))); |
||||
x.next(); |
||||
} |
||||
return jo; |
||||
} |
||||
|
||||
/** |
||||
* Convert a JSONObject into a cookie list. A cookie list is a sequence |
||||
* of name/value pairs. The names are separated from the values by '='. |
||||
* The pairs are separated by ';'. The characters '%', '+', '=', and ';' |
||||
* in the names and values are replaced by "%hh". |
||||
* @param jo A JSONObject |
||||
* @return A cookie list string |
||||
* @throws JSONException |
||||
*/ |
||||
public static String toString(JSONObject jo) throws JSONException { |
||||
boolean b = false; |
||||
Iterator<String> keys = jo.keys(); |
||||
String string; |
||||
StringBuilder sb = new StringBuilder(); |
||||
while (keys.hasNext()) { |
||||
string = keys.next(); |
||||
if (!jo.isNull(string)) { |
||||
if (b) { |
||||
sb.append(';'); |
||||
} |
||||
sb.append(Cookie.escape(string)); |
||||
sb.append("="); |
||||
sb.append(Cookie.escape(jo.getString(string))); |
||||
b = true; |
||||
} |
||||
} |
||||
return sb.toString(); |
||||
} |
||||
} |
@ -0,0 +1,164 @@ |
||||
package org.json; |
||||
|
||||
/* |
||||
Copyright (c) 2002 JSON.org |
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
of this software and associated documentation files (the "Software"), to deal |
||||
in the Software without restriction, including without limitation the rights |
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
copies of the Software, and to permit persons to whom the Software is |
||||
furnished to do so, subject to the following conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be included in all |
||||
copies or substantial portions of the Software. |
||||
|
||||
The Software shall be used for Good, not Evil. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||
SOFTWARE. |
||||
*/ |
||||
|
||||
import java.util.Iterator; |
||||
import java.util.Locale; |
||||
|
||||
/** |
||||
* Convert an HTTP header to a JSONObject and back. |
||||
* @author JSON.org |
||||
* @version 2015-12-09 |
||||
*/ |
||||
public class HTTP { |
||||
|
||||
/** Carriage return/line feed. */ |
||||
public static final String CRLF = "\r\n"; |
||||
|
||||
/** |
||||
* Convert an HTTP header string into a JSONObject. It can be a request |
||||
* header or a response header. A request header will contain |
||||
* <pre>{ |
||||
* Method: "POST" (for example), |
||||
* "Request-URI": "/" (for example), |
||||
* "HTTP-Version": "HTTP/1.1" (for example) |
||||
* }</pre> |
||||
* A response header will contain |
||||
* <pre>{ |
||||
* "HTTP-Version": "HTTP/1.1" (for example), |
||||
* "Status-Code": "200" (for example), |
||||
* "Reason-Phrase": "OK" (for example) |
||||
* }</pre> |
||||
* In addition, the other parameters in the header will be captured, using |
||||
* the HTTP field names as JSON names, so that <pre> |
||||
* Date: Sun, 26 May 2002 18:06:04 GMT |
||||
* Cookie: Q=q2=PPEAsg--; B=677gi6ouf29bn&b=2&f=s |
||||
* Cache-Control: no-cache</pre> |
||||
* become |
||||
* <pre>{... |
||||
* Date: "Sun, 26 May 2002 18:06:04 GMT", |
||||
* Cookie: "Q=q2=PPEAsg--; B=677gi6ouf29bn&b=2&f=s", |
||||
* "Cache-Control": "no-cache", |
||||
* ...}</pre> |
||||
* It does no further checking or conversion. It does not parse dates. |
||||
* It does not do '%' transforms on URLs. |
||||
* @param string An HTTP header string. |
||||
* @return A JSONObject containing the elements and attributes |
||||
* of the XML string. |
||||
* @throws JSONException |
||||
*/ |
||||
public static JSONObject toJSONObject(String string) throws JSONException { |
||||
JSONObject jo = new JSONObject(); |
||||
HTTPTokener x = new HTTPTokener(string); |
||||
String token; |
||||
|
||||
token = x.nextToken(); |
||||
if (token.toUpperCase(Locale.ROOT).startsWith("HTTP")) { |
||||
|
||||
// Response
|
||||
|
||||
jo.put("HTTP-Version", token); |
||||
jo.put("Status-Code", x.nextToken()); |
||||
jo.put("Reason-Phrase", x.nextTo('\0')); |
||||
x.next(); |
||||
|
||||
} else { |
||||
|
||||
// Request
|
||||
|
||||
jo.put("Method", token); |
||||
jo.put("Request-URI", x.nextToken()); |
||||
jo.put("HTTP-Version", x.nextToken()); |
||||
} |
||||
|
||||
// Fields
|
||||
|
||||
while (x.more()) { |
||||
String name = x.nextTo(':'); |
||||
x.next(':'); |
||||
jo.put(name, x.nextTo('\0')); |
||||
x.next(); |
||||
} |
||||
return jo; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Convert a JSONObject into an HTTP header. A request header must contain |
||||
* <pre>{ |
||||
* Method: "POST" (for example), |
||||
* "Request-URI": "/" (for example), |
||||
* "HTTP-Version": "HTTP/1.1" (for example) |
||||
* }</pre> |
||||
* A response header must contain |
||||
* <pre>{ |
||||
* "HTTP-Version": "HTTP/1.1" (for example), |
||||
* "Status-Code": "200" (for example), |
||||
* "Reason-Phrase": "OK" (for example) |
||||
* }</pre> |
||||
* Any other members of the JSONObject will be output as HTTP fields. |
||||
* The result will end with two CRLF pairs. |
||||
* @param jo A JSONObject |
||||
* @return An HTTP header string. |
||||
* @throws JSONException if the object does not contain enough |
||||
* information. |
||||
*/ |
||||
public static String toString(JSONObject jo) throws JSONException { |
||||
Iterator<String> keys = jo.keys(); |
||||
String string; |
||||
StringBuilder sb = new StringBuilder(); |
||||
if (jo.has("Status-Code") && jo.has("Reason-Phrase")) { |
||||
sb.append(jo.getString("HTTP-Version")); |
||||
sb.append(' '); |
||||
sb.append(jo.getString("Status-Code")); |
||||
sb.append(' '); |
||||
sb.append(jo.getString("Reason-Phrase")); |
||||
} else if (jo.has("Method") && jo.has("Request-URI")) { |
||||
sb.append(jo.getString("Method")); |
||||
sb.append(' '); |
||||
sb.append('"'); |
||||
sb.append(jo.getString("Request-URI")); |
||||
sb.append('"'); |
||||
sb.append(' '); |
||||
sb.append(jo.getString("HTTP-Version")); |
||||
} else { |
||||
throw new JSONException("Not enough material for an HTTP header."); |
||||
} |
||||
sb.append(CRLF); |
||||
while (keys.hasNext()) { |
||||
string = keys.next(); |
||||
if (!"HTTP-Version".equals(string) && !"Status-Code".equals(string) && |
||||
!"Reason-Phrase".equals(string) && !"Method".equals(string) && |
||||
!"Request-URI".equals(string) && !jo.isNull(string)) { |
||||
sb.append(string); |
||||
sb.append(": "); |
||||
sb.append(jo.getString(string)); |
||||
sb.append(CRLF); |
||||
} |
||||
} |
||||
sb.append(CRLF); |
||||
return sb.toString(); |
||||
} |
||||
} |
@ -0,0 +1,77 @@ |
||||
package org.json; |
||||
|
||||
/* |
||||
Copyright (c) 2002 JSON.org |
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
of this software and associated documentation files (the "Software"), to deal |
||||
in the Software without restriction, including without limitation the rights |
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
copies of the Software, and to permit persons to whom the Software is |
||||
furnished to do so, subject to the following conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be included in all |
||||
copies or substantial portions of the Software. |
||||
|
||||
The Software shall be used for Good, not Evil. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||
SOFTWARE. |
||||
*/ |
||||
|
||||
/** |
||||
* The HTTPTokener extends the JSONTokener to provide additional methods |
||||
* for the parsing of HTTP headers. |
||||
* @author JSON.org |
||||
* @version 2015-12-09 |
||||
*/ |
||||
public class HTTPTokener extends JSONTokener { |
||||
|
||||
/** |
||||
* Construct an HTTPTokener from a string. |
||||
* @param string A source string. |
||||
*/ |
||||
public HTTPTokener(String string) { |
||||
super(string); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Get the next token or string. This is used in parsing HTTP headers. |
||||
* @throws JSONException |
||||
* @return A String. |
||||
*/ |
||||
public String nextToken() throws JSONException { |
||||
char c; |
||||
char q; |
||||
StringBuilder sb = new StringBuilder(); |
||||
do { |
||||
c = next(); |
||||
} while (Character.isWhitespace(c)); |
||||
if (c == '"' || c == '\'') { |
||||
q = c; |
||||
for (;;) { |
||||
c = next(); |
||||
if (c < ' ') { |
||||
throw syntaxError("Unterminated string."); |
||||
} |
||||
if (c == q) { |
||||
return sb.toString(); |
||||
} |
||||
sb.append(c); |
||||
} |
||||
} |
||||
for (;;) { |
||||
if (c == 0 || Character.isWhitespace(c)) { |
||||
return sb.toString(); |
||||
} |
||||
sb.append(c); |
||||
c = next(); |
||||
} |
||||
} |
||||
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,45 @@ |
||||
package org.json; |
||||
|
||||
/** |
||||
* The JSONException is thrown by the JSON.org classes when things are amiss. |
||||
* |
||||
* @author JSON.org |
||||
* @version 2015-12-09 |
||||
*/ |
||||
public class JSONException extends RuntimeException { |
||||
/** Serialization ID */ |
||||
private static final long serialVersionUID = 0; |
||||
|
||||
/** |
||||
* Constructs a JSONException with an explanatory message. |
||||
* |
||||
* @param message |
||||
* Detail about the reason for the exception. |
||||
*/ |
||||
public JSONException(final String message) { |
||||
super(message); |
||||
} |
||||
|
||||
/** |
||||
* Constructs a JSONException with an explanatory message and cause. |
||||
* |
||||
* @param message |
||||
* Detail about the reason for the exception. |
||||
* @param cause |
||||
* The cause. |
||||
*/ |
||||
public JSONException(final String message, final Throwable cause) { |
||||
super(message, cause); |
||||
} |
||||
|
||||
/** |
||||
* Constructs a new JSONException with the specified cause. |
||||
* |
||||
* @param cause |
||||
* The cause. |
||||
*/ |
||||
public JSONException(final Throwable cause) { |
||||
super(cause.getMessage(), cause); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,552 @@ |
||||
package org.json; |
||||
|
||||
/* |
||||
Copyright (c) 2008 JSON.org |
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
of this software and associated documentation files (the "Software"), to deal |
||||
in the Software without restriction, including without limitation the rights |
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
copies of the Software, and to permit persons to whom the Software is |
||||
furnished to do so, subject to the following conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be included in all |
||||
copies or substantial portions of the Software. |
||||
|
||||
The Software shall be used for Good, not Evil. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||
SOFTWARE. |
||||
*/ |
||||
|
||||
import java.util.Iterator; |
||||
|
||||
|
||||
/** |
||||
* This provides static methods to convert an XML text into a JSONArray or |
||||
* JSONObject, and to covert a JSONArray or JSONObject into an XML text using |
||||
* the JsonML transform. |
||||
* |
||||
* @author JSON.org |
||||
* @version 2016-01-30 |
||||
*/ |
||||
public class JSONML { |
||||
/** |
||||
* Parse XML values and store them in a JSONArray. |
||||
* @param x The XMLTokener containing the source string. |
||||
* @param arrayForm true if array form, false if object form. |
||||
* @param ja The JSONArray that is containing the current tag or null |
||||
* if we are at the outermost level. |
||||
* @param keepStrings Don't type-convert text nodes and attibute values |
||||
* @return A JSONArray if the value is the outermost tag, otherwise null. |
||||
* @throws JSONException |
||||
*/ |
||||
private static Object parse( |
||||
XMLTokener x, |
||||
boolean arrayForm, |
||||
JSONArray ja, |
||||
boolean keepStrings |
||||
) throws JSONException { |
||||
String attribute; |
||||
char c; |
||||
String closeTag = null; |
||||
int i; |
||||
JSONArray newja = null; |
||||
JSONObject newjo = null; |
||||
Object token; |
||||
String tagName = null; |
||||
|
||||
// Test for and skip past these forms:
|
||||
// <!-- ... -->
|
||||
// <![ ... ]]>
|
||||
// <! ... >
|
||||
// <? ... ?>
|
||||
|
||||
while (true) { |
||||
if (!x.more()) { |
||||
throw x.syntaxError("Bad XML"); |
||||
} |
||||
token = x.nextContent(); |
||||
if (token == XML.LT) { |
||||
token = x.nextToken(); |
||||
if (token instanceof Character) { |
||||
if (token == XML.SLASH) { |
||||
|
||||
// Close tag </
|
||||
|
||||
token = x.nextToken(); |
||||
if (!(token instanceof String)) { |
||||
throw new JSONException( |
||||
"Expected a closing name instead of '" + |
||||
token + "'."); |
||||
} |
||||
if (x.nextToken() != XML.GT) { |
||||
throw x.syntaxError("Misshaped close tag"); |
||||
} |
||||
return token; |
||||
} else if (token == XML.BANG) { |
||||
|
||||
// <!
|
||||
|
||||
c = x.next(); |
||||
if (c == '-') { |
||||
if (x.next() == '-') { |
||||
x.skipPast("-->"); |
||||
} else { |
||||
x.back(); |
||||
} |
||||
} else if (c == '[') { |
||||
token = x.nextToken(); |
||||
if (token.equals("CDATA") && x.next() == '[') { |
||||
if (ja != null) { |
||||
ja.put(x.nextCDATA()); |
||||
} |
||||
} else { |
||||
throw x.syntaxError("Expected 'CDATA['"); |
||||
} |
||||
} else { |
||||
i = 1; |
||||
do { |
||||
token = x.nextMeta(); |
||||
if (token == null) { |
||||
throw x.syntaxError("Missing '>' after '<!'."); |
||||
} else if (token == XML.LT) { |
||||
i += 1; |
||||
} else if (token == XML.GT) { |
||||
i -= 1; |
||||
} |
||||
} while (i > 0); |
||||
} |
||||
} else if (token == XML.QUEST) { |
||||
|
||||
// <?
|
||||
|
||||
x.skipPast("?>"); |
||||
} else { |
||||
throw x.syntaxError("Misshaped tag"); |
||||
} |
||||
|
||||
// Open tag <
|
||||
|
||||
} else { |
||||
if (!(token instanceof String)) { |
||||
throw x.syntaxError("Bad tagName '" + token + "'."); |
||||
} |
||||
tagName = (String)token; |
||||
newja = new JSONArray(); |
||||
newjo = new JSONObject(); |
||||
if (arrayForm) { |
||||
newja.put(tagName); |
||||
if (ja != null) { |
||||
ja.put(newja); |
||||
} |
||||
} else { |
||||
newjo.put("tagName", tagName); |
||||
if (ja != null) { |
||||
ja.put(newjo); |
||||
} |
||||
} |
||||
token = null; |
||||
for (;;) { |
||||
if (token == null) { |
||||
token = x.nextToken(); |
||||
} |
||||
if (token == null) { |
||||
throw x.syntaxError("Misshaped tag"); |
||||
} |
||||
if (!(token instanceof String)) { |
||||
break; |
||||
} |
||||
|
||||
// attribute = value
|
||||
|
||||
attribute = (String)token; |
||||
if (!arrayForm && ("tagName".equals(attribute) || "childNode".equals(attribute))) { |
||||
throw x.syntaxError("Reserved attribute."); |
||||
} |
||||
token = x.nextToken(); |
||||
if (token == XML.EQ) { |
||||
token = x.nextToken(); |
||||
if (!(token instanceof String)) { |
||||
throw x.syntaxError("Missing value"); |
||||
} |
||||
newjo.accumulate(attribute, keepStrings ? XML.unescape((String)token) :XML.stringToValue((String)token)); |
||||
token = null; |
||||
} else { |
||||
newjo.accumulate(attribute, ""); |
||||
} |
||||
} |
||||
if (arrayForm && newjo.length() > 0) { |
||||
newja.put(newjo); |
||||
} |
||||
|
||||
// Empty tag <.../>
|
||||
|
||||
if (token == XML.SLASH) { |
||||
if (x.nextToken() != XML.GT) { |
||||
throw x.syntaxError("Misshaped tag"); |
||||
} |
||||
if (ja == null) { |
||||
if (arrayForm) { |
||||
return newja; |
||||
} |
||||
return newjo; |
||||
} |
||||
|
||||
// Content, between <...> and </...>
|
||||
|
||||
} else { |
||||
if (token != XML.GT) { |
||||
throw x.syntaxError("Misshaped tag"); |
||||
} |
||||
closeTag = (String)parse(x, arrayForm, newja, keepStrings); |
||||
if (closeTag != null) { |
||||
if (!closeTag.equals(tagName)) { |
||||
throw x.syntaxError("Mismatched '" + tagName + |
||||
"' and '" + closeTag + "'"); |
||||
} |
||||
tagName = null; |
||||
if (!arrayForm && newja.length() > 0) { |
||||
newjo.put("childNodes", newja); |
||||
} |
||||
if (ja == null) { |
||||
if (arrayForm) { |
||||
return newja; |
||||
} |
||||
return newjo; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} else { |
||||
if (ja != null) { |
||||
ja.put(token instanceof String |
||||
? keepStrings ? XML.unescape((String)token) :XML.stringToValue((String)token) |
||||
: token); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Convert a well-formed (but not necessarily valid) XML string into a |
||||
* JSONArray using the JsonML transform. Each XML tag is represented as |
||||
* a JSONArray in which the first element is the tag name. If the tag has |
||||
* attributes, then the second element will be JSONObject containing the |
||||
* name/value pairs. If the tag contains children, then strings and |
||||
* JSONArrays will represent the child tags. |
||||
* Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored. |
||||
* @param string The source string. |
||||
* @return A JSONArray containing the structured data from the XML string. |
||||
* @throws JSONException Thrown on error converting to a JSONArray |
||||
*/ |
||||
public static JSONArray toJSONArray(String string) throws JSONException { |
||||
return (JSONArray)parse(new XMLTokener(string), true, null, false); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Convert a well-formed (but not necessarily valid) XML string into a |
||||
* JSONArray using the JsonML transform. Each XML tag is represented as |
||||
* a JSONArray in which the first element is the tag name. If the tag has |
||||
* attributes, then the second element will be JSONObject containing the |
||||
* name/value pairs. If the tag contains children, then strings and |
||||
* JSONArrays will represent the child tags. |
||||
* As opposed to toJSONArray this method does not attempt to convert |
||||
* any text node or attribute value to any type |
||||
* but just leaves it as a string. |
||||
* Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored. |
||||
* @param string The source string. |
||||
* @param keepStrings If true, then values will not be coerced into boolean |
||||
* or numeric values and will instead be left as strings |
||||
* @return A JSONArray containing the structured data from the XML string. |
||||
* @throws JSONException Thrown on error converting to a JSONArray |
||||
*/ |
||||
public static JSONArray toJSONArray(String string, boolean keepStrings) throws JSONException { |
||||
return (JSONArray)parse(new XMLTokener(string), true, null, keepStrings); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Convert a well-formed (but not necessarily valid) XML string into a |
||||
* JSONArray using the JsonML transform. Each XML tag is represented as |
||||
* a JSONArray in which the first element is the tag name. If the tag has |
||||
* attributes, then the second element will be JSONObject containing the |
||||
* name/value pairs. If the tag contains children, then strings and |
||||
* JSONArrays will represent the child content and tags. |
||||
* As opposed to toJSONArray this method does not attempt to convert |
||||
* any text node or attribute value to any type |
||||
* but just leaves it as a string. |
||||
* Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored. |
||||
* @param x An XMLTokener. |
||||
* @param keepStrings If true, then values will not be coerced into boolean |
||||
* or numeric values and will instead be left as strings |
||||
* @return A JSONArray containing the structured data from the XML string. |
||||
* @throws JSONException Thrown on error converting to a JSONArray |
||||
*/ |
||||
public static JSONArray toJSONArray(XMLTokener x, boolean keepStrings) throws JSONException { |
||||
return (JSONArray)parse(x, true, null, keepStrings); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Convert a well-formed (but not necessarily valid) XML string into a |
||||
* JSONArray using the JsonML transform. Each XML tag is represented as |
||||
* a JSONArray in which the first element is the tag name. If the tag has |
||||
* attributes, then the second element will be JSONObject containing the |
||||
* name/value pairs. If the tag contains children, then strings and |
||||
* JSONArrays will represent the child content and tags. |
||||
* Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored. |
||||
* @param x An XMLTokener. |
||||
* @return A JSONArray containing the structured data from the XML string. |
||||
* @throws JSONException Thrown on error converting to a JSONArray |
||||
*/ |
||||
public static JSONArray toJSONArray(XMLTokener x) throws JSONException { |
||||
return (JSONArray)parse(x, true, null, false); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Convert a well-formed (but not necessarily valid) XML string into a |
||||
* JSONObject using the JsonML transform. Each XML tag is represented as |
||||
* a JSONObject with a "tagName" property. If the tag has attributes, then |
||||
* the attributes will be in the JSONObject as properties. If the tag |
||||
* contains children, the object will have a "childNodes" property which |
||||
* will be an array of strings and JsonML JSONObjects. |
||||
|
||||
* Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored. |
||||
* @param string The XML source text. |
||||
* @return A JSONObject containing the structured data from the XML string. |
||||
* @throws JSONException Thrown on error converting to a JSONObject |
||||
*/ |
||||
public static JSONObject toJSONObject(String string) throws JSONException { |
||||
return (JSONObject)parse(new XMLTokener(string), false, null, false); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Convert a well-formed (but not necessarily valid) XML string into a |
||||
* JSONObject using the JsonML transform. Each XML tag is represented as |
||||
* a JSONObject with a "tagName" property. If the tag has attributes, then |
||||
* the attributes will be in the JSONObject as properties. If the tag |
||||
* contains children, the object will have a "childNodes" property which |
||||
* will be an array of strings and JsonML JSONObjects. |
||||
|
||||
* Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored. |
||||
* @param string The XML source text. |
||||
* @param keepStrings If true, then values will not be coerced into boolean |
||||
* or numeric values and will instead be left as strings |
||||
* @return A JSONObject containing the structured data from the XML string. |
||||
* @throws JSONException Thrown on error converting to a JSONObject |
||||
*/ |
||||
public static JSONObject toJSONObject(String string, boolean keepStrings) throws JSONException { |
||||
return (JSONObject)parse(new XMLTokener(string), false, null, keepStrings); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Convert a well-formed (but not necessarily valid) XML string into a |
||||
* JSONObject using the JsonML transform. Each XML tag is represented as |
||||
* a JSONObject with a "tagName" property. If the tag has attributes, then |
||||
* the attributes will be in the JSONObject as properties. If the tag |
||||
* contains children, the object will have a "childNodes" property which |
||||
* will be an array of strings and JsonML JSONObjects. |
||||
|
||||
* Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored. |
||||
* @param x An XMLTokener of the XML source text. |
||||
* @return A JSONObject containing the structured data from the XML string. |
||||
* @throws JSONException Thrown on error converting to a JSONObject |
||||
*/ |
||||
public static JSONObject toJSONObject(XMLTokener x) throws JSONException { |
||||
return (JSONObject)parse(x, false, null, false); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Convert a well-formed (but not necessarily valid) XML string into a |
||||
* JSONObject using the JsonML transform. Each XML tag is represented as |
||||
* a JSONObject with a "tagName" property. If the tag has attributes, then |
||||
* the attributes will be in the JSONObject as properties. If the tag |
||||
* contains children, the object will have a "childNodes" property which |
||||
* will be an array of strings and JsonML JSONObjects. |
||||
|
||||
* Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored. |
||||
* @param x An XMLTokener of the XML source text. |
||||
* @param keepStrings If true, then values will not be coerced into boolean |
||||
* or numeric values and will instead be left as strings |
||||
* @return A JSONObject containing the structured data from the XML string. |
||||
* @throws JSONException Thrown on error converting to a JSONObject |
||||
*/ |
||||
public static JSONObject toJSONObject(XMLTokener x, boolean keepStrings) throws JSONException { |
||||
return (JSONObject)parse(x, false, null, keepStrings); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Reverse the JSONML transformation, making an XML text from a JSONArray. |
||||
* @param ja A JSONArray. |
||||
* @return An XML string. |
||||
* @throws JSONException Thrown on error converting to a string |
||||
*/ |
||||
public static String toString(JSONArray ja) throws JSONException { |
||||
int i; |
||||
JSONObject jo; |
||||
String key; |
||||
Iterator<String> keys; |
||||
int length; |
||||
Object object; |
||||
StringBuilder sb = new StringBuilder(); |
||||
String tagName; |
||||
String value; |
||||
|
||||
// Emit <tagName
|
||||
|
||||
tagName = ja.getString(0); |
||||
XML.noSpace(tagName); |
||||
tagName = XML.escape(tagName); |
||||
sb.append('<'); |
||||
sb.append(tagName); |
||||
|
||||
object = ja.opt(1); |
||||
if (object instanceof JSONObject) { |
||||
i = 2; |
||||
jo = (JSONObject)object; |
||||
|
||||
// Emit the attributes
|
||||
|
||||
keys = jo.keys(); |
||||
while (keys.hasNext()) { |
||||
key = keys.next(); |
||||
XML.noSpace(key); |
||||
value = jo.optString(key); |
||||
if (value != null) { |
||||
sb.append(' '); |
||||
sb.append(XML.escape(key)); |
||||
sb.append('='); |
||||
sb.append('"'); |
||||
sb.append(XML.escape(value)); |
||||
sb.append('"'); |
||||
} |
||||
} |
||||
} else { |
||||
i = 1; |
||||
} |
||||
|
||||
// Emit content in body
|
||||
|
||||
length = ja.length(); |
||||
if (i >= length) { |
||||
sb.append('/'); |
||||
sb.append('>'); |
||||
} else { |
||||
sb.append('>'); |
||||
do { |
||||
object = ja.get(i); |
||||
i += 1; |
||||
if (object != null) { |
||||
if (object instanceof String) { |
||||
sb.append(XML.escape(object.toString())); |
||||
} else if (object instanceof JSONObject) { |
||||
sb.append(toString((JSONObject)object)); |
||||
} else if (object instanceof JSONArray) { |
||||
sb.append(toString((JSONArray)object)); |
||||
} else { |
||||
sb.append(object.toString()); |
||||
} |
||||
} |
||||
} while (i < length); |
||||
sb.append('<'); |
||||
sb.append('/'); |
||||
sb.append(tagName); |
||||
sb.append('>'); |
||||
} |
||||
return sb.toString(); |
||||
} |
||||
|
||||
/** |
||||
* Reverse the JSONML transformation, making an XML text from a JSONObject. |
||||
* The JSONObject must contain a "tagName" property. If it has children, |
||||
* then it must have a "childNodes" property containing an array of objects. |
||||
* The other properties are attributes with string values. |
||||
* @param jo A JSONObject. |
||||
* @return An XML string. |
||||
* @throws JSONException Thrown on error converting to a string |
||||
*/ |
||||
public static String toString(JSONObject jo) throws JSONException { |
||||
StringBuilder sb = new StringBuilder(); |
||||
int i; |
||||
JSONArray ja; |
||||
String key; |
||||
Iterator<String> keys; |
||||
int length; |
||||
Object object; |
||||
String tagName; |
||||
String value; |
||||
|
||||
//Emit <tagName
|
||||
|
||||
tagName = jo.optString("tagName"); |
||||
if (tagName == null) { |
||||
return XML.escape(jo.toString()); |
||||
} |
||||
XML.noSpace(tagName); |
||||
tagName = XML.escape(tagName); |
||||
sb.append('<'); |
||||
sb.append(tagName); |
||||
|
||||
//Emit the attributes
|
||||
|
||||
keys = jo.keys(); |
||||
while (keys.hasNext()) { |
||||
key = keys.next(); |
||||
if (!"tagName".equals(key) && !"childNodes".equals(key)) { |
||||
XML.noSpace(key); |
||||
value = jo.optString(key); |
||||
if (value != null) { |
||||
sb.append(' '); |
||||
sb.append(XML.escape(key)); |
||||
sb.append('='); |
||||
sb.append('"'); |
||||
sb.append(XML.escape(value)); |
||||
sb.append('"'); |
||||
} |
||||
} |
||||
} |
||||
|
||||
//Emit content in body
|
||||
|
||||
ja = jo.optJSONArray("childNodes"); |
||||
if (ja == null) { |
||||
sb.append('/'); |
||||
sb.append('>'); |
||||
} else { |
||||
sb.append('>'); |
||||
length = ja.length(); |
||||
for (i = 0; i < length; i += 1) { |
||||
object = ja.get(i); |
||||
if (object != null) { |
||||
if (object instanceof String) { |
||||
sb.append(XML.escape(object.toString())); |
||||
} else if (object instanceof JSONObject) { |
||||
sb.append(toString((JSONObject)object)); |
||||
} else if (object instanceof JSONArray) { |
||||
sb.append(toString((JSONArray)object)); |
||||
} else { |
||||
sb.append(object.toString()); |
||||
} |
||||
} |
||||
} |
||||
sb.append('<'); |
||||
sb.append('/'); |
||||
sb.append(tagName); |
||||
sb.append('>'); |
||||
} |
||||
return sb.toString(); |
||||
} |
||||
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,267 @@ |
||||
package org.json; |
||||
|
||||
import static java.lang.String.format; |
||||
|
||||
import java.io.UnsupportedEncodingException; |
||||
import java.net.URLDecoder; |
||||
import java.net.URLEncoder; |
||||
import java.util.*; |
||||
|
||||
/* |
||||
Copyright (c) 2002 JSON.org |
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
of this software and associated documentation files (the "Software"), to deal |
||||
in the Software without restriction, including without limitation the rights |
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
copies of the Software, and to permit persons to whom the Software is |
||||
furnished to do so, subject to the following conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be included in all |
||||
copies or substantial portions of the Software. |
||||
|
||||
The Software shall be used for Good, not Evil. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||
SOFTWARE. |
||||
*/ |
||||
|
||||
/** |
||||
* A JSON Pointer is a simple query language defined for JSON documents by |
||||
* <a href="https://tools.ietf.org/html/rfc6901">RFC 6901</a>. |
||||
* |
||||
* In a nutshell, JSONPointer allows the user to navigate into a JSON document |
||||
* using strings, and retrieve targeted objects, like a simple form of XPATH. |
||||
* Path segments are separated by the '/' char, which signifies the root of |
||||
* the document when it appears as the first char of the string. Array |
||||
* elements are navigated using ordinals, counting from 0. JSONPointer strings |
||||
* may be extended to any arbitrary number of segments. If the navigation |
||||
* is successful, the matched item is returned. A matched item may be a |
||||
* JSONObject, a JSONArray, or a JSON value. If the JSONPointer string building |
||||
* fails, an appropriate exception is thrown. If the navigation fails to find |
||||
* a match, a JSONPointerException is thrown. |
||||
* |
||||
* @author JSON.org |
||||
* @version 2016-05-14 |
||||
*/ |
||||
public class JSONPointer { |
||||
|
||||
// used for URL encoding and decoding
|
||||
private static final String ENCODING = "utf-8"; |
||||
|
||||
/** |
||||
* This class allows the user to build a JSONPointer in steps, using |
||||
* exactly one segment in each step. |
||||
*/ |
||||
public static class Builder { |
||||
|
||||
// Segments for the eventual JSONPointer string
|
||||
private final List<String> refTokens = new ArrayList<String>(); |
||||
|
||||
/** |
||||
* Creates a {@code JSONPointer} instance using the tokens previously set using the |
||||
* {@link #append(String)} method calls. |
||||
*/ |
||||
public JSONPointer build() { |
||||
return new JSONPointer(refTokens); |
||||
} |
||||
|
||||
/** |
||||
* Adds an arbitary token to the list of reference tokens. It can be any non-null value. |
||||
* |
||||
* Unlike in the case of JSON string or URI fragment representation of JSON pointers, the |
||||
* argument of this method MUST NOT be escaped. If you want to query the property called |
||||
* {@code "a~b"} then you should simply pass the {@code "a~b"} string as-is, there is no |
||||
* need to escape it as {@code "a~0b"}. |
||||
* |
||||
* @param token the new token to be appended to the list |
||||
* @return {@code this} |
||||
* @throws NullPointerException if {@code token} is null |
||||
*/ |
||||
public Builder append(String token) { |
||||
if (token == null) { |
||||
throw new NullPointerException("token cannot be null"); |
||||
} |
||||
refTokens.add(token); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Adds an integer to the reference token list. Although not necessarily, mostly this token will |
||||
* denote an array index. |
||||
* |
||||
* @param arrayIndex the array index to be added to the token list |
||||
* @return {@code this} |
||||
*/ |
||||
public Builder append(int arrayIndex) { |
||||
refTokens.add(String.valueOf(arrayIndex)); |
||||
return this; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Static factory method for {@link Builder}. Example usage: |
||||
* |
||||
* <pre><code> |
||||
* JSONPointer pointer = JSONPointer.builder() |
||||
* .append("obj") |
||||
* .append("other~key").append("another/key") |
||||
* .append("\"") |
||||
* .append(0) |
||||
* .build(); |
||||
* </code></pre> |
||||
* |
||||
* @return a builder instance which can be used to construct a {@code JSONPointer} instance by chained |
||||
* {@link Builder#append(String)} calls. |
||||
*/ |
||||
public static Builder builder() { |
||||
return new Builder(); |
||||
} |
||||
|
||||
// Segments for the JSONPointer string
|
||||
private final List<String> refTokens; |
||||
|
||||
/** |
||||
* Pre-parses and initializes a new {@code JSONPointer} instance. If you want to |
||||
* evaluate the same JSON Pointer on different JSON documents then it is recommended |
||||
* to keep the {@code JSONPointer} instances due to performance considerations. |
||||
* |
||||
* @param pointer the JSON String or URI Fragment representation of the JSON pointer. |
||||
* @throws IllegalArgumentException if {@code pointer} is not a valid JSON pointer |
||||
*/ |
||||
public JSONPointer(String pointer) { |
||||
if (pointer == null) { |
||||
throw new NullPointerException("pointer cannot be null"); |
||||
} |
||||
if (pointer.isEmpty() || pointer.equals("#")) { |
||||
refTokens = Collections.emptyList(); |
||||
return; |
||||
} |
||||
if (pointer.startsWith("#/")) { |
||||
pointer = pointer.substring(2); |
||||
try { |
||||
pointer = URLDecoder.decode(pointer, ENCODING); |
||||
} catch (UnsupportedEncodingException e) { |
||||
throw new RuntimeException(e); |
||||
} |
||||
} else if (pointer.startsWith("/")) { |
||||
pointer = pointer.substring(1); |
||||
} else { |
||||
throw new IllegalArgumentException("a JSON pointer should start with '/' or '#/'"); |
||||
} |
||||
refTokens = new ArrayList<String>(); |
||||
for (String token : pointer.split("/")) { |
||||
refTokens.add(unescape(token)); |
||||
} |
||||
} |
||||
|
||||
public JSONPointer(List<String> refTokens) { |
||||
this.refTokens = new ArrayList<String>(refTokens); |
||||
} |
||||
|
||||
private String unescape(String token) { |
||||
return token.replace("~1", "/").replace("~0", "~") |
||||
.replace("\\\"", "\"") |
||||
.replace("\\\\", "\\"); |
||||
} |
||||
|
||||
/** |
||||
* Evaluates this JSON Pointer on the given {@code document}. The {@code document} |
||||
* is usually a {@link JSONObject} or a {@link JSONArray} instance, but the empty |
||||
* JSON Pointer ({@code ""}) can be evaluated on any JSON values and in such case the |
||||
* returned value will be {@code document} itself. |
||||
* |
||||
* @param document the JSON document which should be the subject of querying. |
||||
* @return the result of the evaluation |
||||
* @throws JSONPointerException if an error occurs during evaluation |
||||
*/ |
||||
public Object queryFrom(Object document) { |
||||
if (refTokens.isEmpty()) { |
||||
return document; |
||||
} |
||||
Object current = document; |
||||
for (String token : refTokens) { |
||||
if (current instanceof JSONObject) { |
||||
current = ((JSONObject) current).opt(unescape(token)); |
||||
} else if (current instanceof JSONArray) { |
||||
current = readByIndexToken(current, token); |
||||
} else { |
||||
throw new JSONPointerException(format( |
||||
"value [%s] is not an array or object therefore its key %s cannot be resolved", current, |
||||
token)); |
||||
} |
||||
} |
||||
return current; |
||||
} |
||||
|
||||
/** |
||||
* Matches a JSONArray element by ordinal position |
||||
* @param current the JSONArray to be evaluated |
||||
* @param indexToken the array index in string form |
||||
* @return the matched object. If no matching item is found a |
||||
* JSONPointerException is thrown |
||||
*/ |
||||
private Object readByIndexToken(Object current, String indexToken) { |
||||
try { |
||||
int index = Integer.parseInt(indexToken); |
||||
JSONArray currentArr = (JSONArray) current; |
||||
if (index >= currentArr.length()) { |
||||
throw new JSONPointerException(format("index %d is out of bounds - the array has %d elements", index, |
||||
currentArr.length())); |
||||
} |
||||
return currentArr.get(index); |
||||
} catch (NumberFormatException e) { |
||||
throw new JSONPointerException(format("%s is not an array index", indexToken), e); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Returns a string representing the JSONPointer path value using string |
||||
* representation |
||||
*/ |
||||
@Override |
||||
public String toString() { |
||||
StringBuilder rval = new StringBuilder(""); |
||||
for (String token: refTokens) { |
||||
rval.append('/').append(escape(token)); |
||||
} |
||||
return rval.toString(); |
||||
} |
||||
|
||||
/** |
||||
* Escapes path segment values to an unambiguous form. |
||||
* The escape char to be inserted is '~'. The chars to be escaped |
||||
* are ~, which maps to ~0, and /, which maps to ~1. Backslashes |
||||
* and double quote chars are also escaped. |
||||
* @param token the JSONPointer segment value to be escaped |
||||
* @return the escaped value for the token |
||||
*/ |
||||
private String escape(String token) { |
||||
return token.replace("~", "~0") |
||||
.replace("/", "~1") |
||||
.replace("\\", "\\\\") |
||||
.replace("\"", "\\\""); |
||||
} |
||||
|
||||
/** |
||||
* Returns a string representing the JSONPointer path value using URI |
||||
* fragment identifier representation |
||||
*/ |
||||
public String toURIFragment() { |
||||
try { |
||||
StringBuilder rval = new StringBuilder("#"); |
||||
for (String token : refTokens) { |
||||
rval.append('/').append(URLEncoder.encode(token, ENCODING)); |
||||
} |
||||
return rval.toString(); |
||||
} catch (UnsupportedEncodingException e) { |
||||
throw new RuntimeException(e); |
||||
} |
||||
} |
||||
|
||||
} |
@ -0,0 +1,45 @@ |
||||
package org.json; |
||||
|
||||
/* |
||||
Copyright (c) 2002 JSON.org |
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
of this software and associated documentation files (the "Software"), to deal |
||||
in the Software without restriction, including without limitation the rights |
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
copies of the Software, and to permit persons to whom the Software is |
||||
furnished to do so, subject to the following conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be included in all |
||||
copies or substantial portions of the Software. |
||||
|
||||
The Software shall be used for Good, not Evil. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||
SOFTWARE. |
||||
*/ |
||||
|
||||
/** |
||||
* The JSONPointerException is thrown by {@link JSONPointer} if an error occurs |
||||
* during evaluating a pointer. |
||||
* |
||||
* @author JSON.org |
||||
* @version 2016-05-13 |
||||
*/ |
||||
public class JSONPointerException extends JSONException { |
||||
private static final long serialVersionUID = 8872944667561856751L; |
||||
|
||||
public JSONPointerException(String message) { |
||||
super(message); |
||||
} |
||||
|
||||
public JSONPointerException(String message, Throwable cause) { |
||||
super(message, cause); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,18 @@ |
||||
package org.json; |
||||
/** |
||||
* The <code>JSONString</code> interface allows a <code>toJSONString()</code> |
||||
* method so that a class can change the behavior of |
||||
* <code>JSONObject.toString()</code>, <code>JSONArray.toString()</code>, |
||||
* and <code>JSONWriter.value(</code>Object<code>)</code>. The |
||||
* <code>toJSONString</code> method will be used instead of the default behavior |
||||
* of using the Object's <code>toString()</code> method and quoting the result. |
||||
*/ |
||||
public interface JSONString { |
||||
/** |
||||
* The <code>toJSONString</code> method allows a class to produce its own JSON |
||||
* serialization. |
||||
* |
||||
* @return A strictly syntactically correct JSON text. |
||||
*/ |
||||
public String toJSONString(); |
||||
} |
@ -0,0 +1,78 @@ |
||||
package org.json; |
||||
|
||||
/* |
||||
Copyright (c) 2006 JSON.org |
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
of this software and associated documentation files (the "Software"), to deal |
||||
in the Software without restriction, including without limitation the rights |
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
copies of the Software, and to permit persons to whom the Software is |
||||
furnished to do so, subject to the following conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be included in all |
||||
copies or substantial portions of the Software. |
||||
|
||||
The Software shall be used for Good, not Evil. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||
SOFTWARE. |
||||
*/ |
||||
|
||||
import java.io.StringWriter; |
||||
|
||||
/** |
||||
* JSONStringer provides a quick and convenient way of producing JSON text. |
||||
* The texts produced strictly conform to JSON syntax rules. No whitespace is |
||||
* added, so the results are ready for transmission or storage. Each instance of |
||||
* JSONStringer can produce one JSON text. |
||||
* <p> |
||||
* A JSONStringer instance provides a <code>value</code> method for appending |
||||
* values to the |
||||
* text, and a <code>key</code> |
||||
* method for adding keys before values in objects. There are <code>array</code> |
||||
* and <code>endArray</code> methods that make and bound array values, and |
||||
* <code>object</code> and <code>endObject</code> methods which make and bound |
||||
* object values. All of these methods return the JSONWriter instance, |
||||
* permitting cascade style. For example, <pre> |
||||
* myString = new JSONStringer() |
||||
* .object() |
||||
* .key("JSON") |
||||
* .value("Hello, World!") |
||||
* .endObject() |
||||
* .toString();</pre> which produces the string <pre> |
||||
* {"JSON":"Hello, World!"}</pre> |
||||
* <p> |
||||
* The first method called must be <code>array</code> or <code>object</code>. |
||||
* There are no methods for adding commas or colons. JSONStringer adds them for |
||||
* you. Objects and arrays can be nested up to 20 levels deep. |
||||
* <p> |
||||
* This can sometimes be easier than using a JSONObject to build a string. |
||||
* @author JSON.org |
||||
* @version 2015-12-09 |
||||
*/ |
||||
public class JSONStringer extends JSONWriter { |
||||
/** |
||||
* Make a fresh JSONStringer. It can be used to build one JSON text. |
||||
*/ |
||||
public JSONStringer() { |
||||
super(new StringWriter()); |
||||
} |
||||
|
||||
/** |
||||
* Return the JSON text. This method is used to obtain the product of the |
||||
* JSONStringer instance. It will return <code>null</code> if there was a |
||||
* problem in the construction of the JSON text (such as the calls to |
||||
* <code>array</code> were not properly balanced with calls to |
||||
* <code>endArray</code>). |
||||
* @return The JSON text. |
||||
*/ |
||||
public String toString() { |
||||
return this.mode == 'd' ? this.writer.toString() : null; |
||||
} |
||||
} |
@ -0,0 +1,475 @@ |
||||
package org.json; |
||||
|
||||
import java.io.BufferedReader; |
||||
import java.io.IOException; |
||||
import java.io.InputStream; |
||||
import java.io.InputStreamReader; |
||||
import java.io.Reader; |
||||
import java.io.StringReader; |
||||
|
||||
/* |
||||
Copyright (c) 2002 JSON.org |
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
of this software and associated documentation files (the "Software"), to deal |
||||
in the Software without restriction, including without limitation the rights |
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
copies of the Software, and to permit persons to whom the Software is |
||||
furnished to do so, subject to the following conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be included in all |
||||
copies or substantial portions of the Software. |
||||
|
||||
The Software shall be used for Good, not Evil. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||
SOFTWARE. |
||||
*/ |
||||
|
||||
/** |
||||
* A JSONTokener takes a source string and extracts characters and tokens from |
||||
* it. It is used by the JSONObject and JSONArray constructors to parse |
||||
* JSON source strings. |
||||
* @author JSON.org |
||||
* @version 2014-05-03 |
||||
*/ |
||||
public class JSONTokener { |
||||
|
||||
private long character; |
||||
private boolean eof; |
||||
private long index; |
||||
private long line; |
||||
private char previous; |
||||
private Reader reader; |
||||
private boolean usePrevious; |
||||
|
||||
|
||||
/** |
||||
* Construct a JSONTokener from a Reader. |
||||
* |
||||
* @param reader A reader. |
||||
*/ |
||||
public JSONTokener(Reader reader) { |
||||
this.reader = reader.markSupported() |
||||
? reader |
||||
: new BufferedReader(reader); |
||||
this.eof = false; |
||||
this.usePrevious = false; |
||||
this.previous = 0; |
||||
this.index = 0; |
||||
this.character = 1; |
||||
this.line = 1; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Construct a JSONTokener from an InputStream. |
||||
* @param inputStream The source. |
||||
*/ |
||||
public JSONTokener(InputStream inputStream) { |
||||
this(new InputStreamReader(inputStream)); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Construct a JSONTokener from a string. |
||||
* |
||||
* @param s A source string. |
||||
*/ |
||||
public JSONTokener(String s) { |
||||
this(new StringReader(s)); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Back up one character. This provides a sort of lookahead capability, |
||||
* so that you can test for a digit or letter before attempting to parse |
||||
* the next number or identifier. |
||||
* @throws JSONException Thrown if trying to step back more than 1 step |
||||
* or if already at the start of the string |
||||
*/ |
||||
public void back() throws JSONException { |
||||
if (this.usePrevious || this.index <= 0) { |
||||
throw new JSONException("Stepping back two steps is not supported"); |
||||
} |
||||
this.index -= 1; |
||||
this.character -= 1; |
||||
this.usePrevious = true; |
||||
this.eof = false; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Get the hex value of a character (base16). |
||||
* @param c A character between '0' and '9' or between 'A' and 'F' or |
||||
* between 'a' and 'f'. |
||||
* @return An int between 0 and 15, or -1 if c was not a hex digit. |
||||
*/ |
||||
public static int dehexchar(char c) { |
||||
if (c >= '0' && c <= '9') { |
||||
return c - '0'; |
||||
} |
||||
if (c >= 'A' && c <= 'F') { |
||||
return c - ('A' - 10); |
||||
} |
||||
if (c >= 'a' && c <= 'f') { |
||||
return c - ('a' - 10); |
||||
} |
||||
return -1; |
||||
} |
||||
|
||||
/** |
||||
* @return true if at the end of the file and we didn't step back |
||||
*/ |
||||
public boolean end() { |
||||
return this.eof && !this.usePrevious; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Determine if the source string still contains characters that next() |
||||
* can consume. |
||||
* @return true if not yet at the end of the source. |
||||
* @throws JSONException thrown if there is an error stepping forward |
||||
* or backward while checking for more data. |
||||
*/ |
||||
public boolean more() throws JSONException { |
||||
this.next(); |
||||
if (this.end()) { |
||||
return false; |
||||
} |
||||
this.back(); |
||||
return true; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Get the next character in the source string. |
||||
* |
||||
* @return The next character, or 0 if past the end of the source string. |
||||
* @throws JSONException Thrown if there is an error reading the source string. |
||||
*/ |
||||
public char next() throws JSONException { |
||||
int c; |
||||
if (this.usePrevious) { |
||||
this.usePrevious = false; |
||||
c = this.previous; |
||||
} else { |
||||
try { |
||||
c = this.reader.read(); |
||||
} catch (IOException exception) { |
||||
throw new JSONException(exception); |
||||
} |
||||
|
||||
if (c <= 0) { // End of stream
|
||||
this.eof = true; |
||||
c = 0; |
||||
} |
||||
} |
||||
this.index += 1; |
||||
if (this.previous == '\r') { |
||||
this.line += 1; |
||||
this.character = c == '\n' ? 0 : 1; |
||||
} else if (c == '\n') { |
||||
this.line += 1; |
||||
this.character = 0; |
||||
} else { |
||||
this.character += 1; |
||||
} |
||||
this.previous = (char) c; |
||||
return this.previous; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Consume the next character, and check that it matches a specified |
||||
* character. |
||||
* @param c The character to match. |
||||
* @return The character. |
||||
* @throws JSONException if the character does not match. |
||||
*/ |
||||
public char next(char c) throws JSONException { |
||||
char n = this.next(); |
||||
if (n != c) { |
||||
throw this.syntaxError("Expected '" + c + "' and instead saw '" + |
||||
n + "'"); |
||||
} |
||||
return n; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Get the next n characters. |
||||
* |
||||
* @param n The number of characters to take. |
||||
* @return A string of n characters. |
||||
* @throws JSONException |
||||
* Substring bounds error if there are not |
||||
* n characters remaining in the source string. |
||||
*/ |
||||
public String next(int n) throws JSONException { |
||||
if (n == 0) { |
||||
return ""; |
||||
} |
||||
|
||||
char[] chars = new char[n]; |
||||
int pos = 0; |
||||
|
||||
while (pos < n) { |
||||
chars[pos] = this.next(); |
||||
if (this.end()) { |
||||
throw this.syntaxError("Substring bounds error"); |
||||
} |
||||
pos += 1; |
||||
} |
||||
return new String(chars); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Get the next char in the string, skipping whitespace. |
||||
* @throws JSONException Thrown if there is an error reading the source string. |
||||
* @return A character, or 0 if there are no more characters. |
||||
*/ |
||||
public char nextClean() throws JSONException { |
||||
for (;;) { |
||||
char c = this.next(); |
||||
if (c == 0 || c > ' ') { |
||||
return c; |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Return the characters up to the next close quote character. |
||||
* Backslash processing is done. The formal JSON format does not |
||||
* allow strings in single quotes, but an implementation is allowed to |
||||
* accept them. |
||||
* @param quote The quoting character, either |
||||
* <code>"</code> <small>(double quote)</small> or |
||||
* <code>'</code> <small>(single quote)</small>. |
||||
* @return A String. |
||||
* @throws JSONException Unterminated string. |
||||
*/ |
||||
public String nextString(char quote) throws JSONException { |
||||
char c; |
||||
StringBuilder sb = new StringBuilder(); |
||||
for (;;) { |
||||
c = this.next(); |
||||
switch (c) { |
||||
case 0: |
||||
case '\n': |
||||
case '\r': |
||||
throw this.syntaxError("Unterminated string"); |
||||
case '\\': |
||||
c = this.next(); |
||||
switch (c) { |
||||
case 'b': |
||||
sb.append('\b'); |
||||
break; |
||||
case 't': |
||||
sb.append('\t'); |
||||
break; |
||||
case 'n': |
||||
sb.append('\n'); |
||||
break; |
||||
case 'f': |
||||
sb.append('\f'); |
||||
break; |
||||
case 'r': |
||||
sb.append('\r'); |
||||
break; |
||||
case 'u': |
||||
try { |
||||
sb.append((char)Integer.parseInt(this.next(4), 16)); |
||||
} catch (NumberFormatException e) { |
||||
throw this.syntaxError("Illegal escape.", e); |
||||
} |
||||
break; |
||||
case '"': |
||||
case '\'': |
||||
case '\\': |
||||
case '/': |
||||
sb.append(c); |
||||
break; |
||||
default: |
||||
throw this.syntaxError("Illegal escape."); |
||||
} |
||||
break; |
||||
default: |
||||
if (c == quote) { |
||||
return sb.toString(); |
||||
} |
||||
sb.append(c); |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Get the text up but not including the specified character or the |
||||
* end of line, whichever comes first. |
||||
* @param delimiter A delimiter character. |
||||
* @return A string. |
||||
* @throws JSONException Thrown if there is an error while searching |
||||
* for the delimiter |
||||
*/ |
||||
public String nextTo(char delimiter) throws JSONException { |
||||
StringBuilder sb = new StringBuilder(); |
||||
for (;;) { |
||||
char c = this.next(); |
||||
if (c == delimiter || c == 0 || c == '\n' || c == '\r') { |
||||
if (c != 0) { |
||||
this.back(); |
||||
} |
||||
return sb.toString().trim(); |
||||
} |
||||
sb.append(c); |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Get the text up but not including one of the specified delimiter |
||||
* characters or the end of line, whichever comes first. |
||||
* @param delimiters A set of delimiter characters. |
||||
* @return A string, trimmed. |
||||
* @throws JSONException Thrown if there is an error while searching |
||||
* for the delimiter |
||||
*/ |
||||
public String nextTo(String delimiters) throws JSONException { |
||||
char c; |
||||
StringBuilder sb = new StringBuilder(); |
||||
for (;;) { |
||||
c = this.next(); |
||||
if (delimiters.indexOf(c) >= 0 || c == 0 || |
||||
c == '\n' || c == '\r') { |
||||
if (c != 0) { |
||||
this.back(); |
||||
} |
||||
return sb.toString().trim(); |
||||
} |
||||
sb.append(c); |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Get the next value. The value can be a Boolean, Double, Integer, |
||||
* JSONArray, JSONObject, Long, or String, or the JSONObject.NULL object. |
||||
* @throws JSONException If syntax error. |
||||
* |
||||
* @return An object. |
||||
*/ |
||||
public Object nextValue() throws JSONException { |
||||
char c = this.nextClean(); |
||||
String string; |
||||
|
||||
switch (c) { |
||||
case '"': |
||||
case '\'': |
||||
return this.nextString(c); |
||||
case '{': |
||||
this.back(); |
||||
return new JSONObject(this); |
||||
case '[': |
||||
this.back(); |
||||
return new JSONArray(this); |
||||
} |
||||
|
||||
/* |
||||
* Handle unquoted text. This could be the values true, false, or |
||||
* null, or it can be a number. An implementation (such as this one) |
||||
* is allowed to also accept non-standard forms. |
||||
* |
||||
* Accumulate characters until we reach the end of the text or a |
||||
* formatting character. |
||||
*/ |
||||
|
||||
StringBuilder sb = new StringBuilder(); |
||||
while (c >= ' ' && ",:]}/\\\"[{;=#".indexOf(c) < 0) { |
||||
sb.append(c); |
||||
c = this.next(); |
||||
} |
||||
this.back(); |
||||
|
||||
string = sb.toString().trim(); |
||||
if ("".equals(string)) { |
||||
throw this.syntaxError("Missing value"); |
||||
} |
||||
return JSONObject.stringToValue(string); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Skip characters until the next character is the requested character. |
||||
* If the requested character is not found, no characters are skipped. |
||||
* @param to A character to skip to. |
||||
* @return The requested character, or zero if the requested character |
||||
* is not found. |
||||
* @throws JSONException Thrown if there is an error while searching |
||||
* for the to character |
||||
*/ |
||||
public char skipTo(char to) throws JSONException { |
||||
char c; |
||||
try { |
||||
long startIndex = this.index; |
||||
long startCharacter = this.character; |
||||
long startLine = this.line; |
||||
this.reader.mark(1000000); |
||||
do { |
||||
c = this.next(); |
||||
if (c == 0) { |
||||
this.reader.reset(); |
||||
this.index = startIndex; |
||||
this.character = startCharacter; |
||||
this.line = startLine; |
||||
return c; |
||||
} |
||||
} while (c != to); |
||||
} catch (IOException exception) { |
||||
throw new JSONException(exception); |
||||
} |
||||
this.back(); |
||||
return c; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Make a JSONException to signal a syntax error. |
||||
* |
||||
* @param message The error message. |
||||
* @return A JSONException object, suitable for throwing |
||||
*/ |
||||
public JSONException syntaxError(String message) { |
||||
return new JSONException(message + this.toString()); |
||||
} |
||||
|
||||
/** |
||||
* Make a JSONException to signal a syntax error. |
||||
* |
||||
* @param message The error message. |
||||
* @param causedBy The throwable that caused the error. |
||||
* @return A JSONException object, suitable for throwing |
||||
*/ |
||||
public JSONException syntaxError(String message, Throwable causedBy) { |
||||
return new JSONException(message + this.toString(), causedBy); |
||||
} |
||||
|
||||
/** |
||||
* Make a printable string of this JSONTokener. |
||||
* |
||||
* @return " at {index} [character {character} line {line}]" |
||||
*/ |
||||
@Override |
||||
public String toString() { |
||||
return " at " + this.index + " [character " + this.character + " line " + |
||||
this.line + "]"; |
||||
} |
||||
} |
@ -0,0 +1,326 @@ |
||||
package org.json; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
/* |
||||
Copyright (c) 2006 JSON.org |
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
of this software and associated documentation files (the "Software"), to deal |
||||
in the Software without restriction, including without limitation the rights |
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
copies of the Software, and to permit persons to whom the Software is |
||||
furnished to do so, subject to the following conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be included in all |
||||
copies or substantial portions of the Software. |
||||
|
||||
The Software shall be used for Good, not Evil. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||
SOFTWARE. |
||||
*/ |
||||
|
||||
/** |
||||
* JSONWriter provides a quick and convenient way of producing JSON text. |
||||
* The texts produced strictly conform to JSON syntax rules. No whitespace is |
||||
* added, so the results are ready for transmission or storage. Each instance of |
||||
* JSONWriter can produce one JSON text. |
||||
* <p> |
||||
* A JSONWriter instance provides a <code>value</code> method for appending |
||||
* values to the |
||||
* text, and a <code>key</code> |
||||
* method for adding keys before values in objects. There are <code>array</code> |
||||
* and <code>endArray</code> methods that make and bound array values, and |
||||
* <code>object</code> and <code>endObject</code> methods which make and bound |
||||
* object values. All of these methods return the JSONWriter instance, |
||||
* permitting a cascade style. For example, <pre> |
||||
* new JSONWriter(myWriter) |
||||
* .object() |
||||
* .key("JSON") |
||||
* .value("Hello, World!") |
||||
* .endObject();</pre> which writes <pre> |
||||
* {"JSON":"Hello, World!"}</pre> |
||||
* <p> |
||||
* The first method called must be <code>array</code> or <code>object</code>. |
||||
* There are no methods for adding commas or colons. JSONWriter adds them for |
||||
* you. Objects and arrays can be nested up to 200 levels deep. |
||||
* <p> |
||||
* This can sometimes be easier than using a JSONObject to build a string. |
||||
* @author JSON.org |
||||
* @version 2016-08-08 |
||||
*/ |
||||
public class JSONWriter { |
||||
private static final int maxdepth = 200; |
||||
|
||||
/** |
||||
* The comma flag determines if a comma should be output before the next |
||||
* value. |
||||
*/ |
||||
private boolean comma; |
||||
|
||||
/** |
||||
* The current mode. Values: |
||||
* 'a' (array), |
||||
* 'd' (done), |
||||
* 'i' (initial), |
||||
* 'k' (key), |
||||
* 'o' (object). |
||||
*/ |
||||
protected char mode; |
||||
|
||||
/** |
||||
* The object/array stack. |
||||
*/ |
||||
private final JSONObject stack[]; |
||||
|
||||
/** |
||||
* The stack top index. A value of 0 indicates that the stack is empty. |
||||
*/ |
||||
private int top; |
||||
|
||||
/** |
||||
* The writer that will receive the output. |
||||
*/ |
||||
protected Appendable writer; |
||||
|
||||
/** |
||||
* Make a fresh JSONWriter. It can be used to build one JSON text. |
||||
*/ |
||||
public JSONWriter(Appendable w) { |
||||
this.comma = false; |
||||
this.mode = 'i'; |
||||
this.stack = new JSONObject[maxdepth]; |
||||
this.top = 0; |
||||
this.writer = w; |
||||
} |
||||
|
||||
/** |
||||
* Append a value. |
||||
* @param string A string value. |
||||
* @return this |
||||
* @throws JSONException If the value is out of sequence. |
||||
*/ |
||||
private JSONWriter append(String string) throws JSONException { |
||||
if (string == null) { |
||||
throw new JSONException("Null pointer"); |
||||
} |
||||
if (this.mode == 'o' || this.mode == 'a') { |
||||
try { |
||||
if (this.comma && this.mode == 'a') { |
||||
this.writer.append(','); |
||||
} |
||||
this.writer.append(string); |
||||
} catch (IOException e) { |
||||
throw new JSONException(e); |
||||
} |
||||
if (this.mode == 'o') { |
||||
this.mode = 'k'; |
||||
} |
||||
this.comma = true; |
||||
return this; |
||||
} |
||||
throw new JSONException("Value out of sequence."); |
||||
} |
||||
|
||||
/** |
||||
* Begin appending a new array. All values until the balancing |
||||
* <code>endArray</code> will be appended to this array. The |
||||
* <code>endArray</code> method must be called to mark the array's end. |
||||
* @return this |
||||
* @throws JSONException If the nesting is too deep, or if the object is |
||||
* started in the wrong place (for example as a key or after the end of the |
||||
* outermost array or object). |
||||
*/ |
||||
public JSONWriter array() throws JSONException { |
||||
if (this.mode == 'i' || this.mode == 'o' || this.mode == 'a') { |
||||
this.push(null); |
||||
this.append("["); |
||||
this.comma = false; |
||||
return this; |
||||
} |
||||
throw new JSONException("Misplaced array."); |
||||
} |
||||
|
||||
/** |
||||
* End something. |
||||
* @param mode Mode |
||||
* @param c Closing character |
||||
* @return this |
||||
* @throws JSONException If unbalanced. |
||||
*/ |
||||
private JSONWriter end(char mode, char c) throws JSONException { |
||||
if (this.mode != mode) { |
||||
throw new JSONException(mode == 'a' |
||||
? "Misplaced endArray." |
||||
: "Misplaced endObject."); |
||||
} |
||||
this.pop(mode); |
||||
try { |
||||
this.writer.append(c); |
||||
} catch (IOException e) { |
||||
throw new JSONException(e); |
||||
} |
||||
this.comma = true; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* End an array. This method most be called to balance calls to |
||||
* <code>array</code>. |
||||
* @return this |
||||
* @throws JSONException If incorrectly nested. |
||||
*/ |
||||
public JSONWriter endArray() throws JSONException { |
||||
return this.end('a', ']'); |
||||
} |
||||
|
||||
/** |
||||
* End an object. This method most be called to balance calls to |
||||
* <code>object</code>. |
||||
* @return this |
||||
* @throws JSONException If incorrectly nested. |
||||
*/ |
||||
public JSONWriter endObject() throws JSONException { |
||||
return this.end('k', '}'); |
||||
} |
||||
|
||||
/** |
||||
* Append a key. The key will be associated with the next value. In an |
||||
* object, every value must be preceded by a key. |
||||
* @param string A key string. |
||||
* @return this |
||||
* @throws JSONException If the key is out of place. For example, keys |
||||
* do not belong in arrays or if the key is null. |
||||
*/ |
||||
public JSONWriter key(String string) throws JSONException { |
||||
if (string == null) { |
||||
throw new JSONException("Null key."); |
||||
} |
||||
if (this.mode == 'k') { |
||||
try { |
||||
this.stack[this.top - 1].putOnce(string, Boolean.TRUE); |
||||
if (this.comma) { |
||||
this.writer.append(','); |
||||
} |
||||
this.writer.append(JSONObject.quote(string)); |
||||
this.writer.append(':'); |
||||
this.comma = false; |
||||
this.mode = 'o'; |
||||
return this; |
||||
} catch (IOException e) { |
||||
throw new JSONException(e); |
||||
} |
||||
} |
||||
throw new JSONException("Misplaced key."); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Begin appending a new object. All keys and values until the balancing |
||||
* <code>endObject</code> will be appended to this object. The |
||||
* <code>endObject</code> method must be called to mark the object's end. |
||||
* @return this |
||||
* @throws JSONException If the nesting is too deep, or if the object is |
||||
* started in the wrong place (for example as a key or after the end of the |
||||
* outermost array or object). |
||||
*/ |
||||
public JSONWriter object() throws JSONException { |
||||
if (this.mode == 'i') { |
||||
this.mode = 'o'; |
||||
} |
||||
if (this.mode == 'o' || this.mode == 'a') { |
||||
this.append("{"); |
||||
this.push(new JSONObject()); |
||||
this.comma = false; |
||||
return this; |
||||
} |
||||
throw new JSONException("Misplaced object."); |
||||
|
||||
} |
||||
|
||||
|
||||
/** |
||||
* Pop an array or object scope. |
||||
* @param c The scope to close. |
||||
* @throws JSONException If nesting is wrong. |
||||
*/ |
||||
private void pop(char c) throws JSONException { |
||||
if (this.top <= 0) { |
||||
throw new JSONException("Nesting error."); |
||||
} |
||||
char m = this.stack[this.top - 1] == null ? 'a' : 'k'; |
||||
if (m != c) { |
||||
throw new JSONException("Nesting error."); |
||||
} |
||||
this.top -= 1; |
||||
this.mode = this.top == 0 |
||||
? 'd' |
||||
: this.stack[this.top - 1] == null |
||||
? 'a' |
||||
: 'k'; |
||||
} |
||||
|
||||
/** |
||||
* Push an array or object scope. |
||||
* @param jo The scope to open. |
||||
* @throws JSONException If nesting is too deep. |
||||
*/ |
||||
private void push(JSONObject jo) throws JSONException { |
||||
if (this.top >= maxdepth) { |
||||
throw new JSONException("Nesting too deep."); |
||||
} |
||||
this.stack[this.top] = jo; |
||||
this.mode = jo == null ? 'a' : 'k'; |
||||
this.top += 1; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Append either the value <code>true</code> or the value |
||||
* <code>false</code>. |
||||
* @param b A boolean. |
||||
* @return this |
||||
* @throws JSONException |
||||
*/ |
||||
public JSONWriter value(boolean b) throws JSONException { |
||||
return this.append(b ? "true" : "false"); |
||||
} |
||||
|
||||
/** |
||||
* Append a double value. |
||||
* @param d A double. |
||||
* @return this |
||||
* @throws JSONException If the number is not finite. |
||||
*/ |
||||
public JSONWriter value(double d) throws JSONException { |
||||
return this.value(new Double(d)); |
||||
} |
||||
|
||||
/** |
||||
* Append a long value. |
||||
* @param l A long. |
||||
* @return this |
||||
* @throws JSONException |
||||
*/ |
||||
public JSONWriter value(long l) throws JSONException { |
||||
return this.append(Long.toString(l)); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Append an object value. |
||||
* @param object The object to append. It can be null, or a Boolean, Number, |
||||
* String, JSONObject, or JSONArray, or an object that implements JSONString. |
||||
* @return this |
||||
* @throws JSONException If the value is out of sequence. |
||||
*/ |
||||
public JSONWriter value(Object object) throws JSONException { |
||||
return this.append(JSONObject.valueToString(object)); |
||||
} |
||||
} |
@ -0,0 +1,72 @@ |
||||
package org.json; |
||||
|
||||
/* |
||||
Copyright (c) 2002 JSON.org |
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
of this software and associated documentation files (the "Software"), to deal |
||||
in the Software without restriction, including without limitation the rights |
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
copies of the Software, and to permit persons to whom the Software is |
||||
furnished to do so, subject to the following conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be included in all |
||||
copies or substantial portions of the Software. |
||||
|
||||
The Software shall be used for Good, not Evil. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||
SOFTWARE. |
||||
*/ |
||||
|
||||
import java.util.Enumeration; |
||||
import java.util.Iterator; |
||||
import java.util.Properties; |
||||
|
||||
/** |
||||
* Converts a Property file data into JSONObject and back. |
||||
* @author JSON.org |
||||
* @version 2015-05-05 |
||||
*/ |
||||
public class Property { |
||||
/** |
||||
* Converts a property file object into a JSONObject. The property file object is a table of name value pairs. |
||||
* @param properties java.util.Properties |
||||
* @return JSONObject |
||||
* @throws JSONException |
||||
*/ |
||||
public static JSONObject toJSONObject(java.util.Properties properties) throws JSONException { |
||||
JSONObject jo = new JSONObject(); |
||||
if (properties != null && !properties.isEmpty()) { |
||||
Enumeration<?> enumProperties = properties.propertyNames(); |
||||
while(enumProperties.hasMoreElements()) { |
||||
String name = (String)enumProperties.nextElement(); |
||||
jo.put(name, properties.getProperty(name)); |
||||
} |
||||
} |
||||
return jo; |
||||
} |
||||
|
||||
/** |
||||
* Converts the JSONObject into a property file object. |
||||
* @param jo JSONObject |
||||
* @return java.util.Properties |
||||
* @throws JSONException |
||||
*/ |
||||
public static Properties toProperties(JSONObject jo) throws JSONException { |
||||
Properties properties = new Properties(); |
||||
if (jo != null) { |
||||
Iterator<String> keys = jo.keys(); |
||||
while (keys.hasNext()) { |
||||
String name = keys.next(); |
||||
properties.put(name, jo.getString(name)); |
||||
} |
||||
} |
||||
return properties; |
||||
} |
||||
} |
@ -0,0 +1,621 @@ |
||||
package org.json; |
||||
|
||||
/* |
||||
Copyright (c) 2015 JSON.org |
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
of this software and associated documentation files (the "Software"), to deal |
||||
in the Software without restriction, including without limitation the rights |
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
copies of the Software, and to permit persons to whom the Software is |
||||
furnished to do so, subject to the following conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be included in all |
||||
copies or substantial portions of the Software. |
||||
|
||||
The Software shall be used for Good, not Evil. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||
SOFTWARE. |
||||
*/ |
||||
|
||||
import java.util.Iterator; |
||||
|
||||
/** |
||||
* This provides static methods to convert an XML text into a JSONObject, and to |
||||
* covert a JSONObject into an XML text. |
||||
* |
||||
* @author JSON.org |
||||
* @version 2016-08-10 |
||||
*/ |
||||
@SuppressWarnings("boxing") |
||||
public class XML { |
||||
/** The Character '&'. */ |
||||
public static final Character AMP = '&'; |
||||
|
||||
/** The Character '''. */ |
||||
public static final Character APOS = '\''; |
||||
|
||||
/** The Character '!'. */ |
||||
public static final Character BANG = '!'; |
||||
|
||||
/** The Character '='. */ |
||||
public static final Character EQ = '='; |
||||
|
||||
/** The Character '>'. */ |
||||
public static final Character GT = '>'; |
||||
|
||||
/** The Character '<'. */ |
||||
public static final Character LT = '<'; |
||||
|
||||
/** The Character '?'. */ |
||||
public static final Character QUEST = '?'; |
||||
|
||||
/** The Character '"'. */ |
||||
public static final Character QUOT = '"'; |
||||
|
||||
/** The Character '/'. */ |
||||
public static final Character SLASH = '/'; |
||||
|
||||
/** |
||||
* Creates an iterator for navigating Code Points in a string instead of |
||||
* characters. Once Java7 support is dropped, this can be replaced with |
||||
* <code> |
||||
* string.codePoints() |
||||
* </code> |
||||
* which is available in Java8 and above. |
||||
* |
||||
* @see <a href= |
||||
* "http://stackoverflow.com/a/21791059/6030888">http://stackoverflow.com/a/21791059/6030888</a>
|
||||
*/ |
||||
private static Iterable<Integer> codePointIterator(final String string) { |
||||
return new Iterable<Integer>() { |
||||
@Override |
||||
public Iterator<Integer> iterator() { |
||||
return new Iterator<Integer>() { |
||||
private int nextIndex = 0; |
||||
private int length = string.length(); |
||||
|
||||
@Override |
||||
public boolean hasNext() { |
||||
return this.nextIndex < this.length; |
||||
} |
||||
|
||||
@Override |
||||
public Integer next() { |
||||
int result = string.codePointAt(this.nextIndex); |
||||
this.nextIndex += Character.charCount(result); |
||||
return result; |
||||
} |
||||
|
||||
@Override |
||||
public void remove() { |
||||
throw new UnsupportedOperationException(); |
||||
} |
||||
}; |
||||
} |
||||
}; |
||||
} |
||||
|
||||
/** |
||||
* Replace special characters with XML escapes: |
||||
* |
||||
* <pre> |
||||
* & <small>(ampersand)</small> is replaced by &amp; |
||||
* < <small>(less than)</small> is replaced by &lt; |
||||
* > <small>(greater than)</small> is replaced by &gt; |
||||
* " <small>(double quote)</small> is replaced by &quot; |
||||
* ' <small>(single quote / apostrophe)</small> is replaced by &apos; |
||||
* </pre> |
||||
* |
||||
* @param string |
||||
* The string to be escaped. |
||||
* @return The escaped string. |
||||
*/ |
||||
public static String escape(String string) { |
||||
StringBuilder sb = new StringBuilder(string.length()); |
||||
for (final int cp : codePointIterator(string)) { |
||||
switch (cp) { |
||||
case '&': |
||||
sb.append("&"); |
||||
break; |
||||
case '<': |
||||
sb.append("<"); |
||||
break; |
||||
case '>': |
||||
sb.append(">"); |
||||
break; |
||||
case '"': |
||||
sb.append("""); |
||||
break; |
||||
case '\'': |
||||
sb.append("'"); |
||||
break; |
||||
default: |
||||
if (mustEscape(cp)) { |
||||
sb.append("&#x"); |
||||
sb.append(Integer.toHexString(cp)); |
||||
sb.append(";"); |
||||
} else { |
||||
sb.appendCodePoint(cp); |
||||
} |
||||
} |
||||
} |
||||
return sb.toString(); |
||||
} |
||||
|
||||
/** |
||||
* @param cp code point to test |
||||
* @return true if the code point is not valid for an XML |
||||
*/ |
||||
private static boolean mustEscape(int cp) { |
||||
/* Valid range from https://www.w3.org/TR/REC-xml/#charsets
|
||||
* |
||||
* #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] |
||||
* |
||||
* any Unicode character, excluding the surrogate blocks, FFFE, and FFFF. |
||||
*/ |
||||
// isISOControl is true when (cp >= 0 && cp <= 0x1F) || (cp >= 0x7F && cp <= 0x9F)
|
||||
// all ISO control characters are out of range except tabs and new lines
|
||||
return (Character.isISOControl(cp) |
||||
&& cp != 0x9 |
||||
&& cp != 0xA |
||||
&& cp != 0xD |
||||
) || !( |
||||
// valid the range of acceptable characters that aren't control
|
||||
(cp >= 0x20 && cp <= 0xD7FF) |
||||
|| (cp >= 0xE000 && cp <= 0xFFFD) |
||||
|| (cp >= 0x10000 && cp <= 0x10FFFF) |
||||
) |
||||
; |
||||
} |
||||
|
||||
/** |
||||
* Removes XML escapes from the string. |
||||
* |
||||
* @param string |
||||
* string to remove escapes from |
||||
* @return string with converted entities |
||||
*/ |
||||
public static String unescape(String string) { |
||||
StringBuilder sb = new StringBuilder(string.length()); |
||||
for (int i = 0, length = string.length(); i < length; i++) { |
||||
char c = string.charAt(i); |
||||
if (c == '&') { |
||||
final int semic = string.indexOf(';', i); |
||||
if (semic > i) { |
||||
final String entity = string.substring(i + 1, semic); |
||||
if (entity.charAt(0) == '#') { |
||||
int cp; |
||||
if (entity.charAt(1) == 'x') { |
||||
// hex encoded unicode
|
||||
cp = Integer.parseInt(entity.substring(2), 16); |
||||
} else { |
||||
// decimal encoded unicode
|
||||
cp = Integer.parseInt(entity.substring(1)); |
||||
} |
||||
sb.appendCodePoint(cp); |
||||
} else { |
||||
if ("quot".equalsIgnoreCase(entity)) { |
||||
sb.append('"'); |
||||
} else if ("amp".equalsIgnoreCase(entity)) { |
||||
sb.append('&'); |
||||
} else if ("apos".equalsIgnoreCase(entity)) { |
||||
sb.append('\''); |
||||
} else if ("lt".equalsIgnoreCase(entity)) { |
||||
sb.append('<'); |
||||
} else if ("gt".equalsIgnoreCase(entity)) { |
||||
sb.append('>'); |
||||
} else { |
||||
sb.append('&').append(entity).append(';'); |
||||
} |
||||
} |
||||
// skip past the entity we just parsed.
|
||||
i += entity.length() + 1; |
||||
} else { |
||||
// this shouldn't happen in most cases since the parser
|
||||
// errors on unclosed enties.
|
||||
sb.append(c); |
||||
} |
||||
} else { |
||||
// not part of an entity
|
||||
sb.append(c); |
||||
} |
||||
} |
||||
return sb.toString(); |
||||
} |
||||
|
||||
/** |
||||
* Throw an exception if the string contains whitespace. Whitespace is not |
||||
* allowed in tagNames and attributes. |
||||
* |
||||
* @param string |
||||
* A string. |
||||
* @throws JSONException Thrown if the string contains whitespace or is empty. |
||||
*/ |
||||
public static void noSpace(String string) throws JSONException { |
||||
int i, length = string.length(); |
||||
if (length == 0) { |
||||
throw new JSONException("Empty string."); |
||||
} |
||||
for (i = 0; i < length; i += 1) { |
||||
if (Character.isWhitespace(string.charAt(i))) { |
||||
throw new JSONException("'" + string |
||||
+ "' contains a space character."); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Scan the content following the named tag, attaching it to the context. |
||||
* |
||||
* @param x |
||||
* The XMLTokener containing the source string. |
||||
* @param context |
||||
* The JSONObject that will include the new material. |
||||
* @param name |
||||
* The tag name. |
||||
* @return true if the close tag is processed. |
||||
* @throws JSONException |
||||
*/ |
||||
private static boolean parse(XMLTokener x, JSONObject context, String name, boolean keepStrings) |
||||
throws JSONException { |
||||
char c; |
||||
int i; |
||||
JSONObject jsonobject = null; |
||||
String string; |
||||
String tagName; |
||||
Object token; |
||||
|
||||
// Test for and skip past these forms:
|
||||
// <!-- ... -->
|
||||
// <! ... >
|
||||
// <![ ... ]]>
|
||||
// <? ... ?>
|
||||
// Report errors for these forms:
|
||||
// <>
|
||||
// <=
|
||||
// <<
|
||||
|
||||
token = x.nextToken(); |
||||
|
||||
// <!
|
||||
|
||||
if (token == BANG) { |
||||
c = x.next(); |
||||
if (c == '-') { |
||||
if (x.next() == '-') { |
||||
x.skipPast("-->"); |
||||
return false; |
||||
} |
||||
x.back(); |
||||
} else if (c == '[') { |
||||
token = x.nextToken(); |
||||
if ("CDATA".equals(token)) { |
||||
if (x.next() == '[') { |
||||
string = x.nextCDATA(); |
||||
if (string.length() > 0) { |
||||
context.accumulate("content", string); |
||||
} |
||||
return false; |
||||
} |
||||
} |
||||
throw x.syntaxError("Expected 'CDATA['"); |
||||
} |
||||
i = 1; |
||||
do { |
||||
token = x.nextMeta(); |
||||
if (token == null) { |
||||
throw x.syntaxError("Missing '>' after '<!'."); |
||||
} else if (token == LT) { |
||||
i += 1; |
||||
} else if (token == GT) { |
||||
i -= 1; |
||||
} |
||||
} while (i > 0); |
||||
return false; |
||||
} else if (token == QUEST) { |
||||
|
||||
// <?
|
||||
x.skipPast("?>"); |
||||
return false; |
||||
} else if (token == SLASH) { |
||||
|
||||
// Close tag </
|
||||
|
||||
token = x.nextToken(); |
||||
if (name == null) { |
||||
throw x.syntaxError("Mismatched close tag " + token); |
||||
} |
||||
if (!token.equals(name)) { |
||||
throw x.syntaxError("Mismatched " + name + " and " + token); |
||||
} |
||||
if (x.nextToken() != GT) { |
||||
throw x.syntaxError("Misshaped close tag"); |
||||
} |
||||
return true; |
||||
|
||||
} else if (token instanceof Character) { |
||||
throw x.syntaxError("Misshaped tag"); |
||||
|
||||
// Open tag <
|
||||
|
||||
} else { |
||||
tagName = (String) token; |
||||
token = null; |
||||
jsonobject = new JSONObject(); |
||||
for (;;) { |
||||
if (token == null) { |
||||
token = x.nextToken(); |
||||
} |
||||
// attribute = value
|
||||
if (token instanceof String) { |
||||
string = (String) token; |
||||
token = x.nextToken(); |
||||
if (token == EQ) { |
||||
token = x.nextToken(); |
||||
if (!(token instanceof String)) { |
||||
throw x.syntaxError("Missing value"); |
||||
} |
||||
jsonobject.accumulate(string, |
||||
keepStrings ? unescape((String)token) : stringToValue((String) token)); |
||||
token = null; |
||||
} else { |
||||
jsonobject.accumulate(string, ""); |
||||
} |
||||
|
||||
|
||||
} else if (token == SLASH) { |
||||
// Empty tag <.../>
|
||||
if (x.nextToken() != GT) { |
||||
throw x.syntaxError("Misshaped tag"); |
||||
} |
||||
if (jsonobject.length() > 0) { |
||||
context.accumulate(tagName, jsonobject); |
||||
} else { |
||||
context.accumulate(tagName, ""); |
||||
} |
||||
return false; |
||||
|
||||
} else if (token == GT) { |
||||
// Content, between <...> and </...>
|
||||
for (;;) { |
||||
token = x.nextContent(); |
||||
if (token == null) { |
||||
if (tagName != null) { |
||||
throw x.syntaxError("Unclosed tag " + tagName); |
||||
} |
||||
return false; |
||||
} else if (token instanceof String) { |
||||
string = (String) token; |
||||
if (string.length() > 0) { |
||||
jsonobject.accumulate("content", |
||||
keepStrings ? unescape(string) : stringToValue(string)); |
||||
} |
||||
|
||||
} else if (token == LT) { |
||||
// Nested element
|
||||
if (parse(x, jsonobject, tagName,keepStrings)) { |
||||
if (jsonobject.length() == 0) { |
||||
context.accumulate(tagName, ""); |
||||
} else if (jsonobject.length() == 1 |
||||
&& jsonobject.opt("content") != null) { |
||||
context.accumulate(tagName, |
||||
jsonobject.opt("content")); |
||||
} else { |
||||
context.accumulate(tagName, jsonobject); |
||||
} |
||||
return false; |
||||
} |
||||
} |
||||
} |
||||
} else { |
||||
throw x.syntaxError("Misshaped tag"); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* This method is the same as {@link JSONObject.stringToValue(String)} |
||||
* except that this also tries to unescape String values. |
||||
* |
||||
* @param string String to convert |
||||
* @return JSON value of this string or the string |
||||
*/ |
||||
public static Object stringToValue(String string) { |
||||
Object ret = JSONObject.stringToValue(string); |
||||
if(ret instanceof String){ |
||||
return unescape((String)ret); |
||||
} |
||||
return ret; |
||||
} |
||||
|
||||
/** |
||||
* Convert a well-formed (but not necessarily valid) XML string into a |
||||
* JSONObject. Some information may be lost in this transformation because |
||||
* JSON is a data format and XML is a document format. XML uses elements, |
||||
* attributes, and content text, while JSON uses unordered collections of |
||||
* name/value pairs and arrays of values. JSON does not does not like to |
||||
* distinguish between elements and attributes. Sequences of similar |
||||
* elements are represented as JSONArrays. Content text may be placed in a |
||||
* "content" member. Comments, prologs, DTDs, and <code><[ [ ]]></code> |
||||
* are ignored. |
||||
* |
||||
* @param string |
||||
* The source string. |
||||
* @return A JSONObject containing the structured data from the XML string. |
||||
* @throws JSONException Thrown if there is an errors while parsing the string |
||||
*/ |
||||
public static JSONObject toJSONObject(String string) throws JSONException { |
||||
return toJSONObject(string, false); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Convert a well-formed (but not necessarily valid) XML string into a |
||||
* JSONObject. Some information may be lost in this transformation because |
||||
* JSON is a data format and XML is a document format. XML uses elements, |
||||
* attributes, and content text, while JSON uses unordered collections of |
||||
* name/value pairs and arrays of values. JSON does not does not like to |
||||
* distinguish between elements and attributes. Sequences of similar |
||||
* elements are represented as JSONArrays. Content text may be placed in a |
||||
* "content" member. Comments, prologs, DTDs, and <code><[ [ ]]></code> |
||||
* are ignored. |
||||
* |
||||
* All values are converted as strings, for 1, 01, 29.0 will not be coerced to |
||||
* numbers but will instead be the exact value as seen in the XML document. |
||||
* |
||||
* @param string |
||||
* The source string. |
||||
* @param keepStrings If true, then values will not be coerced into boolean |
||||
* or numeric values and will instead be left as strings |
||||
* @return A JSONObject containing the structured data from the XML string. |
||||
* @throws JSONException Thrown if there is an errors while parsing the string |
||||
*/ |
||||
public static JSONObject toJSONObject(String string, boolean keepStrings) throws JSONException { |
||||
JSONObject jo = new JSONObject(); |
||||
XMLTokener x = new XMLTokener(string); |
||||
while (x.more() && x.skipPast("<")) { |
||||
parse(x, jo, null, keepStrings); |
||||
} |
||||
return jo; |
||||
} |
||||
/** |
||||
* Convert a JSONObject into a well-formed, element-normal XML string. |
||||
* |
||||
* @param object |
||||
* A JSONObject. |
||||
* @return A string. |
||||
* @throws JSONException Thrown if there is an error parsing the string |
||||
*/ |
||||
public static String toString(Object object) throws JSONException { |
||||
return toString(object, null); |
||||
} |
||||
|
||||
/** |
||||
* Convert a JSONObject into a well-formed, element-normal XML string. |
||||
* |
||||
* @param object |
||||
* A JSONObject. |
||||
* @param tagName |
||||
* The optional name of the enclosing tag. |
||||
* @return A string. |
||||
* @throws JSONException Thrown if there is an error parsing the string |
||||
*/ |
||||
public static String toString(Object object, String tagName) |
||||
throws JSONException { |
||||
StringBuilder sb = new StringBuilder(); |
||||
JSONArray ja; |
||||
JSONObject jo; |
||||
String key; |
||||
Iterator<String> keys; |
||||
String string; |
||||
Object value; |
||||
|
||||
if (object instanceof JSONObject) { |
||||
|
||||
// Emit <tagName>
|
||||
if (tagName != null) { |
||||
sb.append('<'); |
||||
sb.append(tagName); |
||||
sb.append('>'); |
||||
} |
||||
|
||||
// Loop thru the keys.
|
||||
jo = (JSONObject) object; |
||||
keys = jo.keys(); |
||||
while (keys.hasNext()) { |
||||
key = keys.next(); |
||||
value = jo.opt(key); |
||||
if (value == null) { |
||||
value = ""; |
||||
} else if (value.getClass().isArray()) { |
||||
value = new JSONArray(value); |
||||
} |
||||
string = value instanceof String ? (String) value : null; |
||||
|
||||
// Emit content in body
|
||||
if ("content".equals(key)) { |
||||
if (value instanceof JSONArray) { |
||||
ja = (JSONArray) value; |
||||
int i = 0; |
||||
for (Object val : ja) { |
||||
if (i > 0) { |
||||
sb.append('\n'); |
||||
} |
||||
sb.append(escape(val.toString())); |
||||
i++; |
||||
} |
||||
} else { |
||||
sb.append(escape(value.toString())); |
||||
} |
||||
|
||||
// Emit an array of similar keys
|
||||
|
||||
} else if (value instanceof JSONArray) { |
||||
ja = (JSONArray) value; |
||||
for (Object val : ja) { |
||||
if (val instanceof JSONArray) { |
||||
sb.append('<'); |
||||
sb.append(key); |
||||
sb.append('>'); |
||||
sb.append(toString(val)); |
||||
sb.append("</"); |
||||
sb.append(key); |
||||
sb.append('>'); |
||||
} else { |
||||
sb.append(toString(val, key)); |
||||
} |
||||
} |
||||
} else if ("".equals(value)) { |
||||
sb.append('<'); |
||||
sb.append(key); |
||||
sb.append("/>"); |
||||
|
||||
// Emit a new tag <k>
|
||||
|
||||
} else { |
||||
sb.append(toString(value, key)); |
||||
} |
||||
} |
||||
if (tagName != null) { |
||||
|
||||
// Emit the </tagname> close tag
|
||||
sb.append("</"); |
||||
sb.append(tagName); |
||||
sb.append('>'); |
||||
} |
||||
return sb.toString(); |
||||
|
||||
} |
||||
|
||||
if (object != null) { |
||||
if (object.getClass().isArray()) { |
||||
object = new JSONArray(object); |
||||
} |
||||
|
||||
if (object instanceof JSONArray) { |
||||
ja = (JSONArray) object; |
||||
for (Object val : ja) { |
||||
// XML does not have good support for arrays. If an array
|
||||
// appears in a place where XML is lacking, synthesize an
|
||||
// <array> element.
|
||||
sb.append(toString(val, tagName == null ? "array" : tagName)); |
||||
} |
||||
return sb.toString(); |
||||
} |
||||
} |
||||
|
||||
string = (object == null) ? "null" : escape(object.toString()); |
||||
return (tagName == null) ? "\"" + string + "\"" |
||||
: (string.length() == 0) ? "<" + tagName + "/>" : "<" + tagName |
||||
+ ">" + string + "</" + tagName + ">"; |
||||
|
||||
} |
||||
} |
@ -0,0 +1,365 @@ |
||||
package org.json; |
||||
|
||||
/* |
||||
Copyright (c) 2002 JSON.org |
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
of this software and associated documentation files (the "Software"), to deal |
||||
in the Software without restriction, including without limitation the rights |
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
copies of the Software, and to permit persons to whom the Software is |
||||
furnished to do so, subject to the following conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be included in all |
||||
copies or substantial portions of the Software. |
||||
|
||||
The Software shall be used for Good, not Evil. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||
SOFTWARE. |
||||
*/ |
||||
|
||||
/** |
||||
* The XMLTokener extends the JSONTokener to provide additional methods |
||||
* for the parsing of XML texts. |
||||
* @author JSON.org |
||||
* @version 2015-12-09 |
||||
*/ |
||||
public class XMLTokener extends JSONTokener { |
||||
|
||||
|
||||
/** The table of entity values. It initially contains Character values for |
||||
* amp, apos, gt, lt, quot. |
||||
*/ |
||||
public static final java.util.HashMap<String, Character> entity; |
||||
|
||||
static { |
||||
entity = new java.util.HashMap<String, Character>(8); |
||||
entity.put("amp", XML.AMP); |
||||
entity.put("apos", XML.APOS); |
||||
entity.put("gt", XML.GT); |
||||
entity.put("lt", XML.LT); |
||||
entity.put("quot", XML.QUOT); |
||||
} |
||||
|
||||
/** |
||||
* Construct an XMLTokener from a string. |
||||
* @param s A source string. |
||||
*/ |
||||
public XMLTokener(String s) { |
||||
super(s); |
||||
} |
||||
|
||||
/** |
||||
* Get the text in the CDATA block. |
||||
* @return The string up to the <code>]]></code>. |
||||
* @throws JSONException If the <code>]]></code> is not found. |
||||
*/ |
||||
public String nextCDATA() throws JSONException { |
||||
char c; |
||||
int i; |
||||
StringBuilder sb = new StringBuilder(); |
||||
for (;;) { |
||||
c = next(); |
||||
if (end()) { |
||||
throw syntaxError("Unclosed CDATA"); |
||||
} |
||||
sb.append(c); |
||||
i = sb.length() - 3; |
||||
if (i >= 0 && sb.charAt(i) == ']' && |
||||
sb.charAt(i + 1) == ']' && sb.charAt(i + 2) == '>') { |
||||
sb.setLength(i); |
||||
return sb.toString(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Get the next XML outer token, trimming whitespace. There are two kinds |
||||
* of tokens: the '<' character which begins a markup tag, and the content |
||||
* text between markup tags. |
||||
* |
||||
* @return A string, or a '<' Character, or null if there is no more |
||||
* source text. |
||||
* @throws JSONException |
||||
*/ |
||||
public Object nextContent() throws JSONException { |
||||
char c; |
||||
StringBuilder sb; |
||||
do { |
||||
c = next(); |
||||
} while (Character.isWhitespace(c)); |
||||
if (c == 0) { |
||||
return null; |
||||
} |
||||
if (c == '<') { |
||||
return XML.LT; |
||||
} |
||||
sb = new StringBuilder(); |
||||
for (;;) { |
||||
if (c == '<' || c == 0) { |
||||
back(); |
||||
return sb.toString().trim(); |
||||
} |
||||
if (c == '&') { |
||||
sb.append(nextEntity(c)); |
||||
} else { |
||||
sb.append(c); |
||||
} |
||||
c = next(); |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Return the next entity. These entities are translated to Characters: |
||||
* <code>& ' > < "</code>. |
||||
* @param ampersand An ampersand character. |
||||
* @return A Character or an entity String if the entity is not recognized. |
||||
* @throws JSONException If missing ';' in XML entity. |
||||
*/ |
||||
public Object nextEntity(char ampersand) throws JSONException { |
||||
StringBuilder sb = new StringBuilder(); |
||||
for (;;) { |
||||
char c = next(); |
||||
if (Character.isLetterOrDigit(c) || c == '#') { |
||||
sb.append(Character.toLowerCase(c)); |
||||
} else if (c == ';') { |
||||
break; |
||||
} else { |
||||
throw syntaxError("Missing ';' in XML entity: &" + sb); |
||||
} |
||||
} |
||||
String string = sb.toString(); |
||||
Object object = entity.get(string); |
||||
return object != null ? object : ampersand + string + ";"; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Returns the next XML meta token. This is used for skipping over <!...> |
||||
* and <?...?> structures. |
||||
* @return Syntax characters (<code>< > / = ! ?</code>) are returned as |
||||
* Character, and strings and names are returned as Boolean. We don't care |
||||
* what the values actually are. |
||||
* @throws JSONException If a string is not properly closed or if the XML |
||||
* is badly structured. |
||||
*/ |
||||
public Object nextMeta() throws JSONException { |
||||
char c; |
||||
char q; |
||||
do { |
||||
c = next(); |
||||
} while (Character.isWhitespace(c)); |
||||
switch (c) { |
||||
case 0: |
||||
throw syntaxError("Misshaped meta tag"); |
||||
case '<': |
||||
return XML.LT; |
||||
case '>': |
||||
return XML.GT; |
||||
case '/': |
||||
return XML.SLASH; |
||||
case '=': |
||||
return XML.EQ; |
||||
case '!': |
||||
return XML.BANG; |
||||
case '?': |
||||
return XML.QUEST; |
||||
case '"': |
||||
case '\'': |
||||
q = c; |
||||
for (;;) { |
||||
c = next(); |
||||
if (c == 0) { |
||||
throw syntaxError("Unterminated string"); |
||||
} |
||||
if (c == q) { |
||||
return Boolean.TRUE; |
||||
} |
||||
} |
||||
default: |
||||
for (;;) { |
||||
c = next(); |
||||
if (Character.isWhitespace(c)) { |
||||
return Boolean.TRUE; |
||||
} |
||||
switch (c) { |
||||
case 0: |
||||
case '<': |
||||
case '>': |
||||
case '/': |
||||
case '=': |
||||
case '!': |
||||
case '?': |
||||
case '"': |
||||
case '\'': |
||||
back(); |
||||
return Boolean.TRUE; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Get the next XML Token. These tokens are found inside of angle |
||||
* brackets. It may be one of these characters: <code>/ > = ! ?</code> or it |
||||
* may be a string wrapped in single quotes or double quotes, or it may be a |
||||
* name. |
||||
* @return a String or a Character. |
||||
* @throws JSONException If the XML is not well formed. |
||||
*/ |
||||
public Object nextToken() throws JSONException { |
||||
char c; |
||||
char q; |
||||
StringBuilder sb; |
||||
do { |
||||
c = next(); |
||||
} while (Character.isWhitespace(c)); |
||||
switch (c) { |
||||
case 0: |
||||
throw syntaxError("Misshaped element"); |
||||
case '<': |
||||
throw syntaxError("Misplaced '<'"); |
||||
case '>': |
||||
return XML.GT; |
||||
case '/': |
||||
return XML.SLASH; |
||||
case '=': |
||||
return XML.EQ; |
||||
case '!': |
||||
return XML.BANG; |
||||
case '?': |
||||
return XML.QUEST; |
||||
|
||||
// Quoted string
|
||||
|
||||
case '"': |
||||
case '\'': |
||||
q = c; |
||||
sb = new StringBuilder(); |
||||
for (;;) { |
||||
c = next(); |
||||
if (c == 0) { |
||||
throw syntaxError("Unterminated string"); |
||||
} |
||||
if (c == q) { |
||||
return sb.toString(); |
||||
} |
||||
if (c == '&') { |
||||
sb.append(nextEntity(c)); |
||||
} else { |
||||
sb.append(c); |
||||
} |
||||
} |
||||
default: |
||||
|
||||
// Name
|
||||
|
||||
sb = new StringBuilder(); |
||||
for (;;) { |
||||
sb.append(c); |
||||
c = next(); |
||||
if (Character.isWhitespace(c)) { |
||||
return sb.toString(); |
||||
} |
||||
switch (c) { |
||||
case 0: |
||||
return sb.toString(); |
||||
case '>': |
||||
case '/': |
||||
case '=': |
||||
case '!': |
||||
case '?': |
||||
case '[': |
||||
case ']': |
||||
back(); |
||||
return sb.toString(); |
||||
case '<': |
||||
case '"': |
||||
case '\'': |
||||
throw syntaxError("Bad character in a name"); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Skip characters until past the requested string. |
||||
* If it is not found, we are left at the end of the source with a result of false. |
||||
* @param to A string to skip past. |
||||
* @throws JSONException |
||||
*/ |
||||
public boolean skipPast(String to) throws JSONException { |
||||
boolean b; |
||||
char c; |
||||
int i; |
||||
int j; |
||||
int offset = 0; |
||||
int length = to.length(); |
||||
char[] circle = new char[length]; |
||||
|
||||
/* |
||||
* First fill the circle buffer with as many characters as are in the |
||||
* to string. If we reach an early end, bail. |
||||
*/ |
||||
|
||||
for (i = 0; i < length; i += 1) { |
||||
c = next(); |
||||
if (c == 0) { |
||||
return false; |
||||
} |
||||
circle[i] = c; |
||||
} |
||||
|
||||
/* We will loop, possibly for all of the remaining characters. */ |
||||
|
||||
for (;;) { |
||||
j = offset; |
||||
b = true; |
||||
|
||||
/* Compare the circle buffer with the to string. */ |
||||
|
||||
for (i = 0; i < length; i += 1) { |
||||
if (circle[j] != to.charAt(i)) { |
||||
b = false; |
||||
break; |
||||
} |
||||
j += 1; |
||||
if (j >= length) { |
||||
j -= length; |
||||
} |
||||
} |
||||
|
||||
/* If we exit the loop with b intact, then victory is ours. */ |
||||
|
||||
if (b) { |
||||
return true; |
||||
} |
||||
|
||||
/* Get the next character. If there isn't one, then defeat is ours. */ |
||||
|
||||
c = next(); |
||||
if (c == 0) { |
||||
return false; |
||||
} |
||||
/* |
||||
* Shove the character in the circle buffer and advance the |
||||
* circle offset. The offset is mod n. |
||||
*/ |
||||
circle[offset] = c; |
||||
offset += 1; |
||||
if (offset >= length) { |
||||
offset -= length; |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,55 @@ |
||||
package sig; |
||||
|
||||
import java.awt.Color; |
||||
import java.awt.Graphics; |
||||
import java.awt.event.MouseEvent; |
||||
import java.awt.event.MouseWheelEvent; |
||||
import java.awt.image.BufferedImage; |
||||
import java.io.File; |
||||
import java.io.IOException; |
||||
import java.util.Arrays; |
||||
|
||||
import javax.imageio.ImageIO; |
||||
|
||||
import sig.sigIRC; |
||||
import sig.modules.TouhouMotherModule; |
||||
import sig.utils.DrawUtils; |
||||
import sig.utils.FileUtils; |
||||
import sig.utils.TextUtils; |
||||
|
||||
public class BackgroundColorButton { |
||||
BufferedImage buttonimg; |
||||
int x=0; |
||||
int y=0; |
||||
boolean buttonEnabled = true; |
||||
|
||||
public BackgroundColorButton(File filename, int x, int y) { |
||||
this.x=x; |
||||
this.y=y; |
||||
try { |
||||
buttonimg = ImageIO.read(filename); |
||||
} catch (IOException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
|
||||
public void draw(Graphics g) { |
||||
if (buttonEnabled) { |
||||
g.drawImage(buttonimg, x, y, sigIRC.panel); |
||||
} |
||||
} |
||||
|
||||
public void onClickEvent(MouseEvent ev) { |
||||
if (buttonEnabled && !sigIRC.overlayMode) { |
||||
if (ev.getX()>=x && ev.getX()<=x+buttonimg.getWidth() && |
||||
ev.getY()>=y && ev.getY()<=y+buttonimg.getHeight()) { |
||||
sigIRC.backgroundcol=sigIRC.colorpanel.getBackgroundColor(); |
||||
if (sigIRC.backgroundcol!=null) { |
||||
sigIRC.config.setProperty("backgroundColor", Integer.toString(sigIRC.backgroundcol.getRGB())); |
||||
sigIRC.config.saveProperties(); |
||||
sigIRC.panel.setBackground(sigIRC.backgroundcol); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,24 @@ |
||||
package sig; |
||||
|
||||
import java.awt.Color; |
||||
import java.awt.Dimension; |
||||
|
||||
import javax.swing.JColorChooser; |
||||
import javax.swing.JPanel; |
||||
|
||||
public class ColorPanel extends JPanel{ |
||||
public ColorPanel() { |
||||
} |
||||
|
||||
public Color getBackgroundColor() { |
||||
return JColorChooser.showDialog(this, "Color Picker", sigIRC.backgroundcol); |
||||
} |
||||
|
||||
public Color getBackgroundColor(Color defaultColor) { |
||||
return JColorChooser.showDialog(this, "Color Picker", defaultColor); |
||||
} |
||||
|
||||
public Dimension getPreferredSize() { |
||||
return new Dimension(640,480); |
||||
} |
||||
} |
@ -0,0 +1,135 @@ |
||||
package sig; |
||||
|
||||
import java.awt.Color; |
||||
import java.io.File; |
||||
import java.io.FileNotFoundException; |
||||
import java.io.FileReader; |
||||
import java.io.FileWriter; |
||||
import java.io.IOException; |
||||
import java.util.Arrays; |
||||
import java.util.HashMap; |
||||
import java.util.Properties; |
||||
|
||||
import sig.modules.RabiRibi.EntityLookupData; |
||||
import sig.utils.FileUtils; |
||||
|
||||
public class ConfigFile { |
||||
String basepath; |
||||
Properties properties; |
||||
public static HashMap<String,String> configDefaults = new HashMap<String,String>(); |
||||
|
||||
public static void configureDefaultConfiguration() { |
||||
configDefaults.put("server", "irc.chat.twitch.tv"); |
||||
configDefaults.put("nickname", "SigoNitori"); |
||||
configDefaults.put("channel", "#sigonitori"); |
||||
configDefaults.put("dingThreshold", "6"); |
||||
configDefaults.put("backgroundColor", Integer.toString(Color.CYAN.getRGB())); |
||||
} |
||||
|
||||
public static void setAllDefaultProperties(ConfigFile conf) { |
||||
for (String key : configDefaults.keySet()) { |
||||
conf.setProperty(key, configDefaults.get(key)); |
||||
} |
||||
} |
||||
|
||||
public ConfigFile(String basepath) { |
||||
this.basepath=basepath; |
||||
properties = new Properties(); |
||||
try { |
||||
FileReader reader = GetFileReader(this.basepath); |
||||
if (reader!=null) { |
||||
properties.load(reader); |
||||
} |
||||
} catch (IOException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
|
||||
public String getProperty(String key) { |
||||
String val = properties.getProperty(key); |
||||
if (val==null) { |
||||
if (configDefaults.containsKey(key)) { |
||||
this.setProperty(key, configDefaults.get(key)); |
||||
this.saveProperties(); |
||||
return properties.getProperty(key); |
||||
} else { |
||||
return null; |
||||
} |
||||
} else { |
||||
return val; |
||||
} |
||||
} |
||||
|
||||
public String getProperty(String key, String def) { |
||||
String val = properties.getProperty(key); |
||||
if (val==null) { |
||||
this.setProperty(key, def); |
||||
this.saveProperties(); |
||||
return properties.getProperty(key); |
||||
} else { |
||||
return val; |
||||
} |
||||
} |
||||
|
||||
public boolean getBoolean(String key, boolean def) { |
||||
return Boolean.parseBoolean(getProperty(key,Boolean.toString(def))); |
||||
} |
||||
|
||||
public int getInteger(String key, int def) { |
||||
return Integer.parseInt(getProperty(key,Integer.toString(def))); |
||||
} |
||||
|
||||
public void setProperty(String key, String value) { |
||||
properties.setProperty(key, value); |
||||
} |
||||
|
||||
public void setBoolean(String key, boolean value) { |
||||
properties.setProperty(key, Boolean.toString(value)); |
||||
} |
||||
|
||||
public void setInteger(String key, int value) { |
||||
properties.setProperty(key, Integer.toString(value)); |
||||
} |
||||
|
||||
public void saveProperties() { |
||||
try { |
||||
properties.store(GetFileWriter(basepath), "Properties file for sigIRCv2\n"); |
||||
SortConfigProperties(); |
||||
for (Module m : sigIRC.modules) { |
||||
m.SaveConfig(); |
||||
} |
||||
System.out.println("Properties successfully saved."); |
||||
} catch (IOException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
|
||||
private void SortConfigProperties() { |
||||
String[] contents = FileUtils.readFromFile(sigIRC.BASEDIR+basepath); |
||||
Arrays.sort(contents); |
||||
//System.out.println(Arrays.toString(contents));
|
||||
FileUtils.writetoFile(contents, sigIRC.BASEDIR+basepath); |
||||
} |
||||
|
||||
private FileReader GetFileReader(String basepath) { |
||||
File file = new File(sigIRC.BASEDIR+basepath); |
||||
if (file.exists()) { |
||||
try { |
||||
return new FileReader(file); |
||||
} catch (FileNotFoundException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
private FileWriter GetFileWriter(String basepath) { |
||||
File file = new File(sigIRC.BASEDIR+basepath); |
||||
try { |
||||
return new FileWriter(file,false); |
||||
} catch (IOException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
return null; |
||||
} |
||||
} |
@ -0,0 +1,49 @@ |
||||
package sig; |
||||
|
||||
import sig.utils.SoundUtils; |
||||
|
||||
public class CustomSound { |
||||
final static int SOUNDCOOLDOWN = 108000; |
||||
private int cooldown = 0; |
||||
private String customsound; |
||||
private String username; |
||||
private FileManager manager; |
||||
|
||||
public String getUsername() { |
||||
return username; |
||||
} |
||||
|
||||
/** |
||||
* Initializes a <b>Custom Sound</b> object that will listen for a specific username. |
||||
* @param username The username to listen for playing this sound. |
||||
* @param customsound Just the filename of the custom sound. Not the absolute path. |
||||
*/ |
||||
public CustomSound(String username, String customsound) { |
||||
this.username=username; |
||||
this.customsound=customsound; |
||||
this.manager = new FileManager("sigIRC/sounds/"+customsound); |
||||
} |
||||
|
||||
public boolean isSoundAvailable() { |
||||
return cooldown<=0; |
||||
} |
||||
|
||||
public void decreaseCooldown(int amt) { |
||||
cooldown-=amt; |
||||
} |
||||
|
||||
public void playCustomSound() { |
||||
manager.verifyAndFetchFileFromServer(); |
||||
SoundUtils.playSound(sigIRC.BASEDIR+"sounds/"+customsound); |
||||
cooldown = SOUNDCOOLDOWN; |
||||
} |
||||
|
||||
public static CustomSound getCustomSound(String user) { |
||||
for (CustomSound cs : sigIRC.customsounds) { |
||||
if (cs.getUsername().equalsIgnoreCase(user)) { |
||||
return cs; |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
} |
@ -0,0 +1,87 @@ |
||||
package sig; |
||||
import java.awt.Font; |
||||
import java.awt.image.BufferedImage; |
||||
import java.io.File; |
||||
import java.io.IOException; |
||||
import java.net.URL; |
||||
|
||||
import javax.imageio.ImageIO; |
||||
|
||||
import sig.utils.TextUtils; |
||||
|
||||
public class Emoticon { |
||||
private BufferedImage image=null; |
||||
private String emotename=null; |
||||
private String spacefiller=""; |
||||
private String spacefillersmall=""; |
||||
|
||||
public Emoticon(String emoteName, URL onlinePath) { |
||||
try { |
||||
String imagePath = sigIRC.BASEDIR+"sigIRC/Emotes/"+emoteName+".png"; |
||||
File file = new File(imagePath); |
||||
if (file.exists()) { |
||||
image = ImageIO.read(file); |
||||
emotename = file.getName(); |
||||
} else { |
||||
//Download it from online.
|
||||
System.out.println("Could not find emote "+emoteName+". Downloading from server..."); |
||||
image = ImageIO.read(onlinePath); |
||||
System.out.println("Downloaded "+emoteName+".png"); |
||||
ImageIO.write(image, "png", file); |
||||
System.out.println("Saved to "+file.getName()+"."); |
||||
emotename = emoteName; |
||||
} |
||||
spacefiller = GetSpaceLength(sigIRC.panel.programFont); |
||||
spacefillersmall = GetSpaceLength(sigIRC.panel.userFont); |
||||
//System.out.println("Space size for "+emotename+" is "+spacefiller.length());
|
||||
} catch (IOException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
|
||||
public Emoticon(String emoteName, String fileName) { |
||||
try { |
||||
FileManager manager = new FileManager("sigIRC/Emotes/"+fileName+".png"); |
||||
manager.verifyAndFetchFileFromServer(); |
||||
String imagePath = sigIRC.BASEDIR+"sigIRC/Emotes/"+fileName+".png"; |
||||
File file = new File(imagePath); |
||||
if (file.exists()) { |
||||
image = ImageIO.read(file); |
||||
emotename = emoteName; |
||||
} |
||||
spacefiller = GetSpaceLength(sigIRC.panel.programFont); |
||||
spacefillersmall = GetSpaceLength(sigIRC.panel.userFont); |
||||
//System.out.println("Space size for "+emotename+" is "+spacefiller.length());
|
||||
} catch (IOException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
|
||||
private String GetSpaceLength(Font f) { |
||||
StringBuilder spaces = new StringBuilder(); |
||||
while (SpaceFilledIsSmallerThanImageWidth(spaces,f)) { |
||||
spaces.append(" "); |
||||
} |
||||
return spaces.toString(); |
||||
} |
||||
|
||||
public boolean SpaceFilledIsSmallerThanImageWidth(StringBuilder spaces, Font font) { |
||||
return TextUtils.calculateStringBoundsFont(spaces.toString(), font).getWidth()<image.getWidth(); |
||||
} |
||||
|
||||
public String getEmoteName() { |
||||
return emotename.replace(".png", ""); |
||||
} |
||||
|
||||
public BufferedImage getImage() { |
||||
return image; |
||||
} |
||||
|
||||
public String getSpaceFiller() { |
||||
return spacefiller; |
||||
} |
||||
|
||||
public String getSmallSpaceFiller() { |
||||
return spacefillersmall; |
||||
} |
||||
} |
@ -0,0 +1,61 @@ |
||||
package sig; |
||||
|
||||
import java.io.File; |
||||
import java.io.IOException; |
||||
import java.net.MalformedURLException; |
||||
import java.net.URL; |
||||
|
||||
import sig.utils.DebugUtils; |
||||
|
||||
public class FileManager { |
||||
String fileloc; |
||||
final String serverURL = "http://45.33.13.215/sigIRCv2/"; |
||||
boolean folder=false; |
||||
|
||||
public FileManager(String location) { |
||||
this.fileloc=location; |
||||
if (fileloc.contains(" ")) { |
||||
System.out.println("!!!!!!!!!!!!!!!!!!"); |
||||
System.out.println("!!!!!WARNING!!!!!!"); |
||||
System.out.println("There is a space in the global file location "+fileloc+". This is going to cause huge errors!"); |
||||
System.out.println("!!!!!!!!!!!!!!!!!!"); |
||||
DebugUtils.showStackTrace(); |
||||
} |
||||
this.folder=false; |
||||
} |
||||
|
||||
public FileManager(String location, boolean folder) { |
||||
this.fileloc=location; |
||||
this.folder=folder; |
||||
} |
||||
|
||||
public String getRelativeFileLocation() { |
||||
return fileloc; |
||||
} |
||||
|
||||
public void verifyAndFetchFileFromServer() { |
||||
File file = new File(sigIRC.BASEDIR+fileloc); |
||||
if (folder) { |
||||
if (!file.exists()) { |
||||
System.out.println("Could not find "+file.getAbsolutePath()+", creating Folder "+file.getName()+"."); |
||||
if (file.mkdirs()) { |
||||
System.out.println(" >> Successfully created "+file.getAbsolutePath()+"."); |
||||
} |
||||
} |
||||
} else { |
||||
if (!file.exists()) { |
||||
System.out.println("Could not find "+file.getAbsolutePath()+", retrieving file online from "+serverURL+file.getName()+"."); |
||||
try { |
||||
org.apache.commons.io.FileUtils.copyURLToFile(new URL(serverURL+fileloc),file); |
||||
if (file.exists()) { |
||||
System.out.println(" >> Successfully downloaded "+file.getAbsolutePath()+"."); |
||||
} |
||||
} catch (MalformedURLException e) { |
||||
e.printStackTrace(); |
||||
} catch (IOException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,178 @@ |
||||
package sig; |
||||
import java.awt.Color; |
||||
import java.awt.Cursor; |
||||
import java.awt.Graphics; |
||||
import java.awt.Point; |
||||
import java.awt.Rectangle; |
||||
import java.awt.event.KeyEvent; |
||||
import java.awt.event.MouseEvent; |
||||
import java.awt.event.MouseWheelEvent; |
||||
import java.awt.event.WindowEvent; |
||||
import java.awt.geom.Rectangle2D; |
||||
import java.awt.image.BufferedImage; |
||||
import java.util.Vector; |
||||
|
||||
import javax.swing.SwingUtilities; |
||||
|
||||
import sig.utils.DrawUtils; |
||||
import sig.utils.TextUtils; |
||||
|
||||
public class Module { |
||||
public Rectangle2D position; |
||||
protected boolean enabled; |
||||
protected String name; |
||||
public static BufferedImage IMG_DRAGBAR; |
||||
public static BufferedImage MSG_SEPARATOR; |
||||
public static boolean inDragZone=false; |
||||
|
||||
final protected int titleHeight; |
||||
|
||||
Point dragOffset; |
||||
boolean dragging=false; |
||||
public static boolean DRAGGING=false; |
||||
|
||||
public Module(Rectangle2D bounds, String moduleName) { |
||||
this.position = bounds; |
||||
this.name = moduleName; |
||||
this.enabled=true; |
||||
|
||||
this.titleHeight = (int)TextUtils.calculateStringBoundsFont(this.name, sigIRC.panel.userFont).getHeight(); |
||||
} |
||||
|
||||
public Module(Rectangle2D bounds, String moduleName, boolean enabled) { |
||||
this(bounds, moduleName); |
||||
this.enabled=enabled; |
||||
} |
||||
|
||||
protected void mouseModuleMousePress(MouseEvent ev) { |
||||
int mouseX = ev.getX(); |
||||
int mouseY = ev.getY(); |
||||
//System.out.println(mouseX + "," + mouseY);
|
||||
enableWindowDrag(mouseX,mouseY); |
||||
mousePressed(ev); |
||||
} |
||||
|
||||
private void enableWindowDrag(int mouseX, int mouseY) { |
||||
if (!sigIRC.overlayMode && !dragging && inDragBounds(mouseX,mouseY) && !DRAGGING) { |
||||
//Enable dragging.
|
||||
dragOffset = new Point((int)position.getX() - mouseX,(int)position.getY()-mouseY); |
||||
dragging=DRAGGING=true; |
||||
} |
||||
} |
||||
|
||||
public boolean inDragBounds(int x, int y) { |
||||
return x>=position.getX() && x<=position.getX()+position.getWidth() && |
||||
y>=(int)position.getY()-Module.IMG_DRAGBAR.getHeight() && |
||||
y<=(int)position.getY(); |
||||
} |
||||
|
||||
public void mousePressed(MouseEvent ev) { |
||||
} |
||||
|
||||
public void ApplyConfigWindowProperties() { |
||||
} |
||||
|
||||
public void SaveConfig() { |
||||
|
||||
} |
||||
|
||||
public void mouseReleased(MouseEvent ev) { |
||||
if (dragging) { |
||||
dragging=DRAGGING=false; |
||||
ApplyConfigWindowProperties(); |
||||
sigIRC.config.saveProperties(); |
||||
} |
||||
} |
||||
|
||||
protected void moduleRun() { |
||||
dragWindow(); |
||||
modifyCursor(); |
||||
run(); |
||||
} |
||||
|
||||
private void modifyCursor() { |
||||
if (!sigIRC.overlayMode) { |
||||
int cursortype = sigIRC.panel.getCursor().getType(); |
||||
if (inDragZone && |
||||
cursortype!=Cursor.MOVE_CURSOR) { |
||||
sigIRC.panel.setCursor(new Cursor(Cursor.MOVE_CURSOR)); |
||||
} else |
||||
if (!inDragZone && cursortype!=Cursor.DEFAULT_CURSOR) { |
||||
sigIRC.panel.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); |
||||
} |
||||
} |
||||
} |
||||
|
||||
private void dragWindow() { |
||||
if (dragging) { |
||||
//sigIRC.panel.repaint(getDrawBounds().getBounds());
|
||||
int mouseX = sigIRC.panel.lastMouseX+(int)dragOffset.getX(); |
||||
int mouseY = sigIRC.panel.lastMouseY+(int)dragOffset.getY(); |
||||
int oldX = (int)position.getX(); |
||||
int oldY = (int)position.getY(); |
||||
position = new Rectangle((int)Math.min(Math.max(0,mouseX),sigIRC.window.getWidth()-position.getWidth()), (int)Math.min(Math.max(titleHeight,mouseY),sigIRC.window.getHeight()-position.getHeight()-titleHeight*2),(int)position.getWidth(),(int)position.getHeight()); |
||||
//System.out.println(sigIRC.panel.lastMouseX+","+sigIRC.panel.lastMouseY);
|
||||
ModuleDragEvent(oldX,oldY,mouseX,mouseY); |
||||
} |
||||
if (inDragBounds(sigIRC.panel.lastMouseX,sigIRC.panel.lastMouseY)) { |
||||
inDragZone=true; |
||||
//System.out.println("In Drag Zone for Module "+name);
|
||||
//sigIRC.panel.setCursor(new Cursor(Cursor.MOVE_CURSOR));
|
||||
} /*else |
||||
if (sigIRC.panel.getCursor().getType()==Cursor.MOVE_CURSOR) { |
||||
sigIRC.panel.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); |
||||
}*/ |
||||
} |
||||
|
||||
public Rectangle2D getPosition() { |
||||
return position; |
||||
} |
||||
|
||||
public void run() { |
||||
} |
||||
|
||||
public void draw(Graphics g) { |
||||
drawModuleHeader(g); |
||||
/*SwingUtilities.invokeLater(new Runnable() { |
||||
public void run() { |
||||
sigIRC.panel.repaint(getDrawBounds().getBounds()); |
||||
} |
||||
});*/ |
||||
} |
||||
|
||||
private void drawModuleHeader(Graphics g) { |
||||
if (!sigIRC.overlayMode) { |
||||
g.drawImage(Module.IMG_DRAGBAR, |
||||
(int)position.getX()+2, |
||||
(int)position.getY()-Module.IMG_DRAGBAR.getHeight(), |
||||
(int)position.getWidth()-4, |
||||
Module.IMG_DRAGBAR.getHeight(), |
||||
sigIRC.panel); |
||||
DrawUtils.drawTextFont(g, sigIRC.panel.smallFont, (int)position.getX(), (int)position.getY()-titleHeight/2+4, Color.BLACK, this.name); |
||||
//g.fillRect((int)position.getX(), (int)position.getY(), (int)position.getWidth(), (int)position.getHeight());
|
||||
} |
||||
} |
||||
|
||||
private Rectangle2D getDrawBounds() { |
||||
Rectangle2D drawBounds = new Rectangle((int)position.getX()-2,(int)position.getY()-titleHeight+3-1,(int)position.getWidth()+2,(int)position.getHeight()+titleHeight+1); |
||||
return drawBounds; |
||||
} |
||||
|
||||
public void ModuleDragEvent(int oldX, int oldY, int newX, int newY) { |
||||
|
||||
} |
||||
|
||||
public void mouseWheel(MouseWheelEvent ev) { |
||||
} |
||||
|
||||
public void keypressed(KeyEvent ev) { |
||||
|
||||
} |
||||
|
||||
public void keyreleased(KeyEvent ev) { |
||||
} |
||||
|
||||
public void windowClosed(WindowEvent ev) { |
||||
|
||||
} |
||||
} |
@ -0,0 +1,254 @@ |
||||
package sig; |
||||
|
||||
import java.awt.Color; |
||||
import java.awt.Component; |
||||
import java.awt.Dimension; |
||||
import java.awt.Font; |
||||
import java.awt.Graphics; |
||||
import java.awt.GraphicsEnvironment; |
||||
import java.awt.MouseInfo; |
||||
import java.awt.PointerInfo; |
||||
import java.awt.Toolkit; |
||||
import java.awt.event.ActionEvent; |
||||
import java.awt.event.ActionListener; |
||||
import java.awt.event.ComponentEvent; |
||||
import java.awt.event.ComponentListener; |
||||
import java.awt.event.KeyEvent; |
||||
import java.awt.event.KeyListener; |
||||
import java.awt.event.MouseEvent; |
||||
import java.awt.event.MouseListener; |
||||
import java.awt.event.MouseMotionListener; |
||||
import java.awt.event.MouseWheelEvent; |
||||
import java.awt.event.MouseWheelListener; |
||||
import java.awt.event.WindowEvent; |
||||
import java.awt.event.WindowListener; |
||||
import java.io.File; |
||||
import java.io.IOException; |
||||
|
||||
import javax.swing.JColorChooser; |
||||
import javax.swing.JMenuItem; |
||||
import javax.swing.JPanel; |
||||
import javax.swing.JPopupMenu; |
||||
|
||||
import sig.modules.ChatLogModule; |
||||
import sig.modules.ChatLog.ChatLogMessage; |
||||
import sig.utils.FileUtils; |
||||
|
||||
public class MyPanel extends JPanel implements MouseListener, ActionListener, MouseWheelListener, KeyListener, ComponentListener, WindowListener{ |
||||
//List<String> messages = new ArrayList<String>();
|
||||
final public static Font programFont = new Font(sigIRC.messageFont,0,24); |
||||
final public static Font userFont = new Font(sigIRC.usernameFont,0,16); |
||||
final public static Font smallFont = new Font(sigIRC.touhoumotherConsoleFont,0,12); |
||||
final public static Font rabiRibiMoneyDisplayFont = new Font("CP Font",0,16); |
||||
final public static Font rabiRibiTinyDisplayFont = new Font("CP Font",0,12); |
||||
public int lastMouseX = 0; |
||||
public int lastMouseY = 0; |
||||
|
||||
public MyPanel() { |
||||
//setBorder(BorderFactory.createLineBorder(Color.black));
|
||||
addMouseListener(this); |
||||
addMouseWheelListener(this); |
||||
addComponentListener(this); |
||||
addKeyListener(this); |
||||
setFocusable(true); |
||||
} |
||||
|
||||
public Dimension getPreferredSize() { |
||||
return new Dimension(1280,480); |
||||
} |
||||
|
||||
public void paintComponent(Graphics g) { |
||||
super.paintComponent(g); |
||||
// Draw Text
|
||||
//int counter=18;
|
||||
if (sigIRC.panel!=null) { |
||||
lastMouseX = (int)(MouseInfo.getPointerInfo().getLocation().getX()-sigIRC.panel.getLocationOnScreen().getX()); |
||||
lastMouseY = (int)(MouseInfo.getPointerInfo().getLocation().getY()-sigIRC.panel.getLocationOnScreen().getY()); |
||||
//System.out.println("("+lastMouseX+","+lastMouseY+")");
|
||||
} |
||||
/*if (sigIRC.window!=null && sigIRC.window.getMousePosition(true)!=null && sigIRC.overlayMode) { |
||||
lastMouseX = (int)sigIRC.window.getMousePosition(true).getX(); |
||||
lastMouseY = (int)sigIRC.window.getMousePosition(true).getY(); |
||||
System.out.println("("+lastMouseX+","+lastMouseY+")"); |
||||
} else { |
||||
lastMouseX = -1; |
||||
lastMouseY = -1; |
||||
}*/ |
||||
//
|
||||
for (Module m : sigIRC.modules) { |
||||
m.draw(g); |
||||
} |
||||
for (int i=0;i<sigIRC.chatlogtwitchemoticons.size();i++) { |
||||
if (sigIRC.chatlogtwitchemoticons.get(i).textRefIsVisible()) { |
||||
sigIRC.chatlogtwitchemoticons.get(i).draw(g); |
||||
} |
||||
} |
||||
for (int i=0;i<sigIRC.textobj.size();i++) { |
||||
if (sigIRC.textobj.get(i).isActive()) { |
||||
if (sigIRC.overlayMode) { |
||||
if (!sigIRC.textobj.get(i).intersects(lastMouseX,lastMouseY)) { |
||||
sigIRC.textobj.get(i).setVisible(true); |
||||
sigIRC.textobj.get(i).draw(g); |
||||
} else { |
||||
//System.out.println("Setting to False.");
|
||||
sigIRC.textobj.get(i).setVisible(false); |
||||
} |
||||
} else { |
||||
sigIRC.textobj.get(i).draw(g); |
||||
} |
||||
} |
||||
} |
||||
for (int i=0;i<sigIRC.twitchemoticons.size();i++) { |
||||
if (sigIRC.twitchemoticons.get(i).isActive() && |
||||
sigIRC.twitchemoticons.get(i).textRefIsVisible()) { |
||||
sigIRC.twitchemoticons.get(i).draw(g); |
||||
} else { |
||||
break; |
||||
} |
||||
} |
||||
if (!sigIRC.overlayMode) { |
||||
sigIRC.button.draw(g); |
||||
} |
||||
} |
||||
|
||||
public void addMessage(String message) { |
||||
addMessage(message,true); |
||||
} |
||||
|
||||
public void addMessage(String message, boolean playSound) { |
||||
ScrollingText text = new ScrollingText(message,this.getWidth(),(int)(Math.random()*128),playSound); |
||||
TextRow row = TextRow.PickRandomTextRow(text.getUsername()); |
||||
sigIRC.textobj.add(text); |
||||
row.updateRow(text); |
||||
//ChatLogMessage.importMessages(message);
|
||||
} |
||||
|
||||
@Override |
||||
public void mouseClicked(MouseEvent ev) { |
||||
} |
||||
|
||||
@Override |
||||
public void mousePressed(MouseEvent ev) { |
||||
for (Module m : sigIRC.modules) { |
||||
m.mouseModuleMousePress(ev); |
||||
} |
||||
sigIRC.button.onClickEvent(ev); |
||||
} |
||||
|
||||
@Override |
||||
public void mouseReleased(MouseEvent ev) { |
||||
for (Module m : sigIRC.modules) { |
||||
m.mouseReleased(ev); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void mouseEntered(MouseEvent ev) { |
||||
} |
||||
|
||||
@Override |
||||
public void mouseExited(MouseEvent ev) { |
||||
} |
||||
|
||||
@Override |
||||
public void actionPerformed(ActionEvent ev) { |
||||
} |
||||
|
||||
@Override |
||||
public void mouseWheelMoved(MouseWheelEvent ev) { |
||||
for (Module m : sigIRC.modules) { |
||||
m.mouseWheel(ev); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void keyTyped(KeyEvent e) { |
||||
} |
||||
|
||||
@Override |
||||
public void keyPressed(KeyEvent ev) { |
||||
for (Module m : sigIRC.modules) { |
||||
m.keypressed(ev); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void keyReleased(KeyEvent ev) { |
||||
for (Module m : sigIRC.modules) { |
||||
m.keyreleased(ev); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void componentResized(ComponentEvent ev) { |
||||
UpdateComponent(ev.getComponent()); |
||||
} |
||||
|
||||
@Override |
||||
public void componentMoved(ComponentEvent ev) { |
||||
UpdateComponent(ev.getComponent()); |
||||
} |
||||
|
||||
public static void UpdateComponent(Component com) { |
||||
sigIRC.windowX = (int)sigIRC.window.getLocationOnScreen().getX(); |
||||
sigIRC.windowY = (int)sigIRC.window.getLocationOnScreen().getY(); |
||||
sigIRC.windowWidth = sigIRC.window.getWidth(); |
||||
sigIRC.windowHeight = sigIRC.window.getHeight(); |
||||
sigIRC.config.setInteger("windowX", sigIRC.windowX); |
||||
sigIRC.config.setInteger("windowY", sigIRC.windowY); |
||||
sigIRC.config.setInteger("windowWidth", sigIRC.windowWidth); |
||||
sigIRC.config.setInteger("windowHeight", sigIRC.windowHeight); |
||||
sigIRC.button.x = sigIRC.panel.getX()+sigIRC.panel.getWidth()-96; |
||||
sigIRC.button.y = 64+sigIRC.rowobj.size()*sigIRC.rowSpacing; |
||||
//com.repaint();
|
||||
//sigIRC.panel.repaint();
|
||||
sigIRC.config.saveProperties(); |
||||
} |
||||
|
||||
@Override |
||||
public void componentShown(ComponentEvent ev) { |
||||
} |
||||
|
||||
@Override |
||||
public void componentHidden(ComponentEvent ev) { |
||||
} |
||||
|
||||
@Override |
||||
public void windowActivated(WindowEvent ev) { |
||||
} |
||||
|
||||
@Override |
||||
public void windowClosed(WindowEvent ev) { |
||||
} |
||||
|
||||
@Override |
||||
public void windowClosing(WindowEvent ev) { |
||||
for (Module m : sigIRC.modules) { |
||||
m.windowClosed(ev); |
||||
} |
||||
sigIRC.config.saveProperties(); |
||||
if (sigIRC.autoUpdateProgram) { |
||||
try { |
||||
FileUtils.copyFile(new File(sigIRC.PROGRAM_UPDATE_FILE), new File(sigIRC.BASEDIR+"sigIRCv2.jar")); |
||||
} catch (IOException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void windowDeactivated(WindowEvent ev) { |
||||
} |
||||
|
||||
@Override |
||||
public void windowDeiconified(WindowEvent ev) { |
||||
} |
||||
|
||||
@Override |
||||
public void windowIconified(WindowEvent ev) { |
||||
} |
||||
|
||||
@Override |
||||
public void windowOpened(WindowEvent ev) { |
||||
} |
||||
} |
@ -0,0 +1,300 @@ |
||||
package sig; |
||||
import java.awt.Color; |
||||
import java.awt.Font; |
||||
import java.awt.Graphics; |
||||
import java.awt.font.FontRenderContext; |
||||
import java.awt.geom.Rectangle2D; |
||||
import java.io.File; |
||||
import java.io.IOException; |
||||
import java.util.ArrayList; |
||||
import java.util.Calendar; |
||||
import java.util.Date; |
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
import java.util.Random; |
||||
|
||||
import javax.sound.sampled.AudioInputStream; |
||||
import javax.sound.sampled.AudioSystem; |
||||
import javax.sound.sampled.Clip; |
||||
import javax.sound.sampled.LineUnavailableException; |
||||
import javax.sound.sampled.UnsupportedAudioFileException; |
||||
import javax.swing.SwingUtilities; |
||||
|
||||
import sig.utils.DrawUtils; |
||||
import sig.utils.FileUtils; |
||||
import sig.utils.SoundUtils; |
||||
import sig.utils.TextUtils; |
||||
|
||||
public class ScrollingText { |
||||
private String username; |
||||
private String message; |
||||
private double x; |
||||
private double y; |
||||
private int stringWidth; |
||||
private int stringHeight; |
||||
private boolean isAlive=true; |
||||
private Color userColor; |
||||
private TextRow myRow; |
||||
private int textMaxWidth; |
||||
private int textMaxHeight; |
||||
private boolean visible=true; |
||||
|
||||
public void setX(double x) { |
||||
this.x = x; |
||||
} |
||||
|
||||
public void setY(double y) { |
||||
this.y = y; |
||||
} |
||||
|
||||
public String getUsername() { |
||||
return username; |
||||
} |
||||
|
||||
public String getMessage() { |
||||
return message; |
||||
} |
||||
|
||||
public double getX() { |
||||
return x; |
||||
} |
||||
|
||||
public double getY() { |
||||
return y; |
||||
} |
||||
|
||||
public int getStringWidth() { |
||||
return stringWidth; |
||||
} |
||||
|
||||
public int getStringHeight() { |
||||
return stringHeight; |
||||
} |
||||
|
||||
public boolean isVisible() { |
||||
return visible; |
||||
} |
||||
|
||||
private int userstringWidth; |
||||
private int shadowSize; |
||||
|
||||
public ScrollingText(String msg, double x, double y) { |
||||
LogMessageToFile(msg); |
||||
this.username = GetUsername(msg); |
||||
this.userColor = GetUserNameColor(this.username); |
||||
this.message = GetMessage(msg); |
||||
this.x=x; |
||||
this.y=y; |
||||
|
||||
this.shadowSize=2; |
||||
|
||||
this.stringWidth = (int)TextUtils.calculateStringBoundsFont(this.message,MyPanel.programFont).getWidth(); |
||||
this.stringHeight = (int)TextUtils.calculateStringBoundsFont(this.message,MyPanel.programFont).getHeight(); |
||||
this.userstringWidth = (int)TextUtils.calculateStringBoundsFont(this.username,MyPanel.userFont).getWidth(); |
||||
} |
||||
|
||||
public ScrollingText(String msg, double x, double y, boolean playSound) { |
||||
this(msg,x,y); |
||||
|
||||
if (playSound) { |
||||
playMessageSound(username); |
||||
} |
||||
} |
||||
|
||||
private void playMessageSound(String user) { |
||||
CustomSound cs = CustomSound.getCustomSound(user); |
||||
if (cs!=null && cs.isSoundAvailable()) { |
||||
cs.playCustomSound(); |
||||
} else { |
||||
if (sigIRC.lastPlayedDing==0 && sigIRC.dingEnabled) { |
||||
String soundName = sigIRC.BASEDIR+"sigIRC/sounds/ping.wav"; |
||||
FileManager manager = new FileManager("sigIRC/sounds/ping.wav"); |
||||
manager.verifyAndFetchFileFromServer(); |
||||
SoundUtils.playSound(soundName); |
||||
sigIRC.lastPlayedDing=sigIRC.DINGTIMER; |
||||
} |
||||
} |
||||
} |
||||
|
||||
private void LogMessageToFile(String message) { |
||||
Calendar cal = Calendar.getInstance(); |
||||
FileUtils.logToFile(message, sigIRC.BASEDIR+"sigIRC/logs/log_"+(cal.get(Calendar.MONTH)+1)+"_"+cal.get(Calendar.DAY_OF_MONTH)+"_"+cal.get(Calendar.YEAR)+".txt",true); |
||||
} |
||||
|
||||
public static Color GetUserNameColor(String username) { |
||||
Random r = new Random(); |
||||
r.setSeed(username.toLowerCase().hashCode()); |
||||
int randomnumb = r.nextInt(3); |
||||
Color col; |
||||
switch (randomnumb) { |
||||
case 0:{ |
||||
col=new Color(255,r.nextInt(128)+64,r.nextInt(128)+64,255); |
||||
}break; |
||||
case 1:{ |
||||
col=new Color(r.nextInt(128)+64,255,r.nextInt(128)+64,255); |
||||
}break; |
||||
case 2:{ |
||||
col=new Color(r.nextInt(128)+64,r.nextInt(128)+64,255,255); |
||||
}break; |
||||
default:{ |
||||
col=Color.GREEN; |
||||
} |
||||
} |
||||
return col; |
||||
} |
||||
|
||||
public boolean run() { |
||||
x-=myRow.getScrollSpd(); |
||||
//System.out.println("X: "+x);
|
||||
/*SwingUtilities.invokeLater(new Runnable() { |
||||
public void run() { |
||||
sigIRC.panel.repaint( |
||||
FindLeftMostCornerInDisplay(), |
||||
FindTopMostCornerInDisplay()-32, |
||||
(int)Math.max(FindRightMostCornerInDisplay(),(int)TextUtils.calculateStringBoundsFont(username, MyPanel.userFont).getWidth())+4, |
||||
FindBottomMostCornerInDisplay()+(stringHeight*2)+4); |
||||
} |
||||
});*/ |
||||
//sigIRC.panel.repaint();
|
||||
if (x+stringWidth<0) { |
||||
isAlive=false; |
||||
return false; |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
public boolean isActive() { |
||||
return isAlive; |
||||
} |
||||
|
||||
public void setVisible(boolean isVisible) { |
||||
this.visible=isVisible; |
||||
} |
||||
|
||||
public void draw(Graphics g) { |
||||
if (isAlive && WithinBounds(x,y,Math.max(TextUtils.calculateStringBoundsFont(username, MyPanel.userFont).getWidth(), TextUtils.calculateStringBoundsFont(message, MyPanel.programFont).getWidth()),Math.max(TextUtils.calculateStringBoundsFont(username, MyPanel.userFont).getHeight(), TextUtils.calculateStringBoundsFont(message, MyPanel.programFont).getHeight()))) { |
||||
//DrawUtils.drawTextFont(g, MyPanel.userFont, x+8, y+stringHeight-20, Color.GREEN, username);
|
||||
DrawUtils.drawOutlineText(g, MyPanel.userFont, x+8, y+stringHeight-20, 2, userColor, Color.BLACK, username); |
||||
DrawUtils.drawOutlineText(g, MyPanel.programFont, x, y+stringHeight, 2, Color.WHITE, Color.BLACK, message); |
||||
} |
||||
} |
||||
|
||||
private boolean WithinBounds(double x, double y, double w, double h) { |
||||
if (x<sigIRC.panel.getWidth() && x+w>0 && y<sigIRC.panel.getHeight() && y+h>0) { |
||||
return true; |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
public int FindLeftMostCornerInDisplay() { |
||||
if (x-shadowSize>0) { |
||||
return Math.min((int)x-shadowSize, sigIRC.panel.getWidth()); |
||||
} else { |
||||
return 0; |
||||
} |
||||
} |
||||
public int FindTopMostCornerInDisplay() { |
||||
if (y-shadowSize>0) { |
||||
return Math.min((int)y-shadowSize, sigIRC.panel.getHeight()); |
||||
} else { |
||||
return 0; |
||||
} |
||||
} |
||||
public int FindRightMostCornerInDisplay() { |
||||
if (x+stringWidth+(int)sigIRC.BASESCROLLSPD+1+shadowSize+1>0) { |
||||
return Math.min(Math.max(stringWidth,userstringWidth+8)+(int)sigIRC.BASESCROLLSPD+1+shadowSize+1, sigIRC.panel.getWidth()-(int)x); |
||||
} else { |
||||
return 0; |
||||
} |
||||
} |
||||
public int FindBottomMostCornerInDisplay() { |
||||
if (y+stringHeight+shadowSize>0) { |
||||
return Math.min(stringHeight+shadowSize+4, sigIRC.panel.getHeight()-(int)y); |
||||
} else { |
||||
return 0; |
||||
} |
||||
} |
||||
|
||||
public void setTextRow(TextRow row) { |
||||
this.myRow=row; |
||||
} |
||||
|
||||
private String GetMessage(String msg) { |
||||
String basemsg = " "+msg.substring(msg.indexOf(":")+2, msg.length())+" "; |
||||
//basemsg = ConvertMessageSymbols(basemsg);
|
||||
basemsg = ReplaceMessageWithEmoticons(basemsg); |
||||
return basemsg.replaceFirst(" ", "").substring(0,basemsg.length()-1); |
||||
} |
||||
|
||||
private String ConvertMessageSymbols(String basemsg) { |
||||
basemsg = basemsg.replace("/", "SLASH").replace(":", "COLON").replace("/", "BACKSLASH").replace("|", "BAR").replace(">", "GREATERTHAN").replace("<", "LESSTHAN"); |
||||
return basemsg; |
||||
} |
||||
|
||||
private String ReplaceMessageWithEmoticons(String basemsg) { |
||||
int marker = basemsg.indexOf(" "); |
||||
while (marker<basemsg.length()) { |
||||
//Find a space.
|
||||
int space = basemsg.indexOf(" ", marker+1); |
||||
if (space>0) { |
||||
String word = basemsg.substring(marker+1, space); |
||||
//System.out.println("Word is '"+word+"'");
|
||||
sigIRC.emoticons.addAll(sigIRC.emoticon_queue); |
||||
sigIRC.emoticon_queue.clear(); |
||||
for (Emoticon e : sigIRC.emoticons) { |
||||
//System.out.println("Checking for emoticon "+e.getEmoteName());
|
||||
try { |
||||
if (e.getEmoteName().equals(word)) { |
||||
if (e instanceof SubEmoticon) { |
||||
SubEmoticon se = (SubEmoticon)e; |
||||
if (!se.canUserUseEmoticon(username)) { |
||||
//System.out.println("User "+username+" is not subscribed to "+se.channelName+"'s channel!");
|
||||
break; |
||||
} |
||||
} |
||||
//System.out.println(" Found one!");
|
||||
basemsg = TextUtils.replaceFirst(basemsg, e.getEmoteName(), e.getSpaceFiller()); |
||||
GenerateEmoticon(marker+1, basemsg, e); |
||||
space = basemsg.indexOf(" ", marker+1); |
||||
break; |
||||
} |
||||
} catch (NullPointerException ex) { |
||||
ex.printStackTrace(); |
||||
} |
||||
} |
||||
marker=space; |
||||
} else { |
||||
break; |
||||
} |
||||
} |
||||
textMaxWidth = (int)TextUtils.calculateStringBoundsFont(basemsg, sigIRC.panel.programFont).getWidth(); |
||||
textMaxHeight = Math.max(textMaxHeight,(int)TextUtils.calculateStringBoundsFont(basemsg, sigIRC.panel.programFont).getHeight()); |
||||
return basemsg; |
||||
} |
||||
|
||||
private boolean EmoteExists(Emoticon e, String basemsg) { |
||||
//Emote exists if it is standalone (no other words in message),
|
||||
//Contains spaces on both sides,
|
||||
//OR contains spaces in front/behind and ends the message with the emote.
|
||||
String tempstr = " "+basemsg+" "; |
||||
return tempstr.contains(" "+e.getEmoteName()+" "); |
||||
} |
||||
|
||||
private void GenerateEmoticon(int pos, String basemsg, Emoticon e) { |
||||
String cutstring = basemsg.substring(0, pos); |
||||
double width = TextUtils.calculateStringBoundsFont(cutstring, sigIRC.panel.programFont).getWidth(); |
||||
//System.out.println("Width of '"+cutstring+"' is "+width);
|
||||
sigIRC.createEmoticon(e, this, (int)(width), 0); |
||||
textMaxHeight = Math.max(textMaxHeight, e.getImage().getHeight()); |
||||
//textMaxWidth = (int)(width + e.getImage().getWidth()+1);
|
||||
} |
||||
|
||||
private String GetUsername(String msg) { |
||||
return msg.substring(0,msg.indexOf(":")); |
||||
} |
||||
|
||||
public boolean intersects(int x, int y) { |
||||
return (x>=this.x && x<=this.x+this.textMaxWidth && |
||||
y>=this.y && y<=this.y+this.textMaxHeight); |
||||
} |
||||
} |
@ -0,0 +1,67 @@ |
||||
package sig; |
||||
|
||||
import java.net.URL; |
||||
|
||||
import com.mb3364.twitch.api.handlers.ChannelResponseHandler; |
||||
import com.mb3364.twitch.api.handlers.ChannelSubscriptionResponseHandler; |
||||
import com.mb3364.twitch.api.handlers.UserSubscriptionResponseHandler; |
||||
import com.mb3364.twitch.api.models.Channel; |
||||
import com.mb3364.twitch.api.models.ChannelSubscription; |
||||
import com.mb3364.twitch.api.models.UserSubscription; |
||||
|
||||
public class SubEmoticon extends Emoticon{ |
||||
String channelName = ""; |
||||
static boolean userCanUseEmoticon=false; |
||||
|
||||
public SubEmoticon(String emoteName, String fileName, String channelName) { |
||||
super(emoteName, fileName); |
||||
this.channelName=channelName; |
||||
} |
||||
public SubEmoticon(String emoteName, URL onlinePath, String channelName) { |
||||
super(emoteName,onlinePath); |
||||
this.channelName=channelName; |
||||
} |
||||
|
||||
public boolean canUserUseEmoticon(String username) { |
||||
userCanUseEmoticon=false; |
||||
/*System.out.println("User: "+username+", Channel: "+channelName+"|"); |
||||
sigIRC.manager.channels().getSubscription(username.trim(), channelName.trim(), new ChannelSubscriptionResponseHandler() { |
||||
|
||||
@Override |
||||
public void onFailure(Throwable arg0) { |
||||
System.out.println(arg0.getMessage()); |
||||
} |
||||
|
||||
@Override |
||||
public void onFailure(int arg0, String arg1, String arg2) { |
||||
System.out.println(arg0+","+arg1+","+arg2); |
||||
} |
||||
|
||||
@Override |
||||
public void onSuccess(ChannelSubscription arg0) { |
||||
System.out.println("User is subscribed to channel "+channelName+"!"); |
||||
userCanUseEmoticon=true; |
||||
} |
||||
|
||||
});*/ |
||||
/*sigIRC.manager.users().getSubscription( new UserSubscriptionResponseHandler() { |
||||
|
||||
@Override |
||||
public void onFailure(Throwable arg0) { |
||||
System.out.println(arg0.getMessage()); |
||||
} |
||||
|
||||
@Override |
||||
public void onFailure(int arg0, String arg1, String arg2) { |
||||
System.out.println(arg0+","+arg1+","+arg2); |
||||
} |
||||
|
||||
@Override |
||||
public void onSuccess(UserSubscription arg0) { |
||||
System.out.println("User is subscribed to channel "+channelName+"!"); |
||||
userCanUseEmoticon=true; |
||||
} |
||||
});*/ |
||||
return true; |
||||
} |
||||
} |
@ -0,0 +1,54 @@ |
||||
package sig; |
||||
import java.util.Random; |
||||
|
||||
public class TextRow { |
||||
private int maxX = 0; //Defines the greatest X position of all the messages in this row.
|
||||
private int ypos = 0; |
||||
final int MESSAGE_SEPARATION=200; |
||||
private int scrollSpd = sigIRC.BASESCROLLSPD; |
||||
|
||||
public TextRow(int ypos) { |
||||
this.ypos=ypos; |
||||
} |
||||
|
||||
public int getY() { |
||||
return ypos; |
||||
} |
||||
|
||||
public void setY(int ypos) { |
||||
this.ypos = ypos; |
||||
} |
||||
|
||||
public int getMaxX() { |
||||
return maxX; |
||||
} |
||||
|
||||
public int getScrollSpd() { |
||||
return scrollSpd; |
||||
} |
||||
|
||||
public void updateRow(ScrollingText text) { |
||||
text.setX(maxX+sigIRC.panel.getWidth()+MESSAGE_SEPARATION); |
||||
text.setY(ypos); |
||||
text.setTextRow(this); |
||||
maxX+=text.getStringWidth()+MESSAGE_SEPARATION; |
||||
} |
||||
|
||||
public void update() { |
||||
scrollSpd = DetermineScrollSpd(); |
||||
if (maxX>0) { |
||||
maxX-=scrollSpd; |
||||
} |
||||
} |
||||
|
||||
private int DetermineScrollSpd() { |
||||
return maxX/Math.max(1000,sigIRC.windowWidth)+sigIRC.chatScrollSpd; |
||||
} |
||||
|
||||
public static TextRow PickRandomTextRow(String username) { |
||||
Random r = new Random(); |
||||
r.setSeed(username.hashCode()); |
||||
int randomnumb = r.nextInt(sigIRC.rowobj.size()); |
||||
return sigIRC.rowobj.get(randomnumb); |
||||
} |
||||
} |
@ -0,0 +1,59 @@ |
||||
package sig; |
||||
import java.awt.Graphics; |
||||
|
||||
import javax.swing.SwingUtilities; |
||||
|
||||
public class TwitchEmote { |
||||
Emoticon emote; |
||||
int x=0; //X Offset
|
||||
int y=0; //Y Offset
|
||||
ScrollingText text; |
||||
boolean active=true; |
||||
|
||||
public TwitchEmote(Emoticon emote, ScrollingText textref, int x, int y) { |
||||
this.emote=emote; |
||||
this.x=x; |
||||
this.y=y+32-emote.getImage().getHeight(); |
||||
this.text = textref; |
||||
} |
||||
|
||||
public boolean run() { |
||||
//this.x-=paint.TEXTSCROLLSPD;
|
||||
/*SwingUtilities.invokeLater(new Runnable() { |
||||
public void run() { |
||||
sigIRC.panel.repaint( |
||||
Math.max(x,0), |
||||
Math.max(y, 0), |
||||
Math.min(sigIRC.panel.getWidth()-x,emote.getImage().getWidth()), |
||||
Math.min(sigIRC.panel.getHeight()-y,emote.getImage().getHeight())); |
||||
} |
||||
});*/ |
||||
if (x+emote.getImage().getWidth()<0 || text==null || !text.isActive()) { |
||||
active=false; |
||||
return false; |
||||
} else { |
||||
return true; |
||||
} |
||||
} |
||||
|
||||
public void draw(Graphics g) { |
||||
if (WithinBounds((int)(text.getX()+x), (int)(text.getY()+y), emote.getImage().getWidth(), emote.getImage().getHeight())) { |
||||
g.drawImage(emote.getImage(), (int)(text.getX()+x), (int)(text.getY()+y), sigIRC.panel); |
||||
} |
||||
} |
||||
|
||||
public boolean isActive() { |
||||
return active; |
||||
} |
||||
|
||||
private boolean WithinBounds(double x, double y, double w, double h) { |
||||
if (x<sigIRC.panel.getWidth() && x+w>0 && y<sigIRC.panel.getHeight() && y+h>0) { |
||||
return true; |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
public boolean textRefIsVisible() { |
||||
return text.isVisible(); |
||||
} |
||||
} |
@ -0,0 +1,197 @@ |
||||
package sig; |
||||
import java.awt.Component; |
||||
import java.awt.event.ActionEvent; |
||||
import java.awt.event.ActionListener; |
||||
import java.io.File; |
||||
import java.io.IOException; |
||||
import java.util.Calendar; |
||||
|
||||
import org.json.JSONException; |
||||
import org.json.JSONObject; |
||||
|
||||
import sig.utils.FileUtils; |
||||
|
||||
public class UpdateEvent implements ActionListener{ |
||||
final static int MSGTIMER = 300; |
||||
final static int AUTOSAVETIMER = 600; |
||||
int last_authentication_msg = MSGTIMER; |
||||
int last_autosave = AUTOSAVETIMER; |
||||
long lasttime = System.currentTimeMillis(); |
||||
int avgfps = 30; |
||||
int counter = 0; |
||||
int windowUpdateCounter=30; |
||||
|
||||
@Override |
||||
public void actionPerformed(ActionEvent ev) { |
||||
if (ev!=null) { |
||||
UpdateScrollingText(); |
||||
UpdateAuthenticationCountdownMessage(); |
||||
UpdateWindowPosition(); |
||||
UpdateSubEmoticons(); |
||||
} |
||||
} |
||||
|
||||
private void UpdateSubEmoticons() { |
||||
if (!sigIRC.downloadedSubEmotes && |
||||
sigIRC.subchannelCount==sigIRC.subchannelIds.size()) { |
||||
Thread downloadThread = new Thread(){ |
||||
public void run() { |
||||
JSONObject data = GetSubEmoteJson(); |
||||
sigIRC.downloadSubEmotes(data); |
||||
sigIRC.subEmotesCompleted=true; |
||||
} |
||||
}; |
||||
downloadThread.start(); |
||||
sigIRC.downloadedSubEmotes=true; |
||||
} |
||||
} |
||||
|
||||
private JSONObject GetSubEmoteJson() { |
||||
JSONObject subemotes = null; |
||||
try { |
||||
File filer = new File(sigIRC.SUBEMOTELISTFILE); |
||||
if (!filer.exists()) { |
||||
System.out.println("Local copy of Sub emotes not found. Downloading in background..."); |
||||
subemotes = FileUtils.readJsonFromUrlWithFilter("https://twitchemotes.com/api_cache/v3/subscriber.json",sigIRC.subchannelIds,sigIRC.SUBEMOTELISTFILE,true); |
||||
} else { |
||||
if (sigIRC.lastSubEmoteUpdate == Calendar.getInstance().get(Calendar.DAY_OF_YEAR)) { |
||||
System.out.println("Using local copy of Sub emote JSON."); |
||||
subemotes = FileUtils.readJsonFromFileWithFilter(sigIRC.SUBEMOTELISTFILE,sigIRC.subchannelIds); |
||||
} else { |
||||
System.out.println("Local copy of Sub emote JSON out-of-date! Re-downloading in background..."); |
||||
subemotes = FileUtils.readJsonFromFileWithFilter(sigIRC.SUBEMOTELISTFILE,sigIRC.subchannelIds); |
||||
new Thread(){ |
||||
public void run() { |
||||
try { |
||||
FileUtils.readJsonFromUrlWithFilter("https://twitchemotes.com/api_cache/v3/subscriber.json",sigIRC.subchannelIds,sigIRC.SUBEMOTELISTFILE,true); |
||||
} catch (JSONException e) { |
||||
e.printStackTrace(); |
||||
} catch (IOException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
}.start(); |
||||
} |
||||
} |
||||
} catch (JSONException | IOException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
sigIRC.lastSubEmoteUpdate = Calendar.getInstance().get(Calendar.DAY_OF_YEAR); |
||||
sigIRC.config.setInteger("lastSubEmote_APIUpdate", sigIRC.lastSubEmoteUpdate); |
||||
return subemotes; |
||||
} |
||||
|
||||
private void UpdateWindowPosition() { |
||||
if (windowUpdateCounter--<=0) { |
||||
if (sigIRC.lastWindowX!=(int)sigIRC.window.getLocationOnScreen().getX() || |
||||
sigIRC.lastWindowY!=(int)sigIRC.window.getLocationOnScreen().getY()) { |
||||
sigIRC.lastWindowX = (int)sigIRC.window.getLocationOnScreen().getX(); |
||||
sigIRC.lastWindowY = (int)sigIRC.window.getLocationOnScreen().getY(); |
||||
//Trigger Window Update.
|
||||
for (Component c : sigIRC.window.getComponents()) { |
||||
MyPanel.UpdateComponent(c); |
||||
} |
||||
} |
||||
windowUpdateCounter=30; |
||||
} |
||||
} |
||||
|
||||
private void UpdateAuthenticationCountdownMessage() { |
||||
if (sigIRC.downloadsComplete) { |
||||
if ((!sigIRC.authenticated || sigIRC.testMode) && last_authentication_msg<MSGTIMER) { |
||||
last_authentication_msg++; |
||||
} else |
||||
if ((!sigIRC.authenticated || sigIRC.testMode) && last_authentication_msg>=MSGTIMER) { |
||||
last_authentication_msg=0; |
||||
if (!sigIRC.authenticated && !sigIRC.testMode) { |
||||
sigIRC.panel.addMessage("SYSTEM: Your oauthToken was not successful. Please go to the sigIRC folder and make sure your oauthToken.txt file is correct!!! SwiftRage",!sigIRC.playedoAuthSoundOnce); |
||||
if (!sigIRC.playedoAuthSoundOnce) { |
||||
sigIRC.playedoAuthSoundOnce=true; |
||||
} |
||||
} else { |
||||
sigIRC.panel.addMessage("SYSTEM: This is a test message for your testing convenience. mikansBox",!sigIRC.playedoAuthSoundOnce); |
||||
} |
||||
} |
||||
if (last_autosave<AUTOSAVETIMER) { |
||||
last_authentication_msg++; |
||||
} else |
||||
if (last_autosave>=AUTOSAVETIMER) { |
||||
last_autosave=0; |
||||
sigIRC.windowX = (int)sigIRC.window.getLocationOnScreen().getX(); |
||||
sigIRC.windowY = (int)sigIRC.window.getLocationOnScreen().getY(); |
||||
sigIRC.windowWidth = sigIRC.window.getWidth(); |
||||
sigIRC.windowHeight = sigIRC.window.getHeight(); |
||||
sigIRC.config.setInteger("windowX", sigIRC.windowX); |
||||
sigIRC.config.setInteger("windowY", sigIRC.windowY); |
||||
sigIRC.config.setInteger("windowWidth", sigIRC.windowWidth); |
||||
sigIRC.config.setInteger("windowHeight", sigIRC.windowHeight); |
||||
sigIRC.config.saveProperties(); |
||||
} |
||||
if (sigIRC.lastPlayedDing>0) { |
||||
sigIRC.lastPlayedDing--; |
||||
} |
||||
updateFPSCounter(); |
||||
sigIRC.window.setTitle("sigIRCv2 - "+(avgfps)+" FPS"); |
||||
lasttime=System.currentTimeMillis(); |
||||
} |
||||
} |
||||
|
||||
public void updateFPSCounter() { |
||||
if (System.currentTimeMillis()-lasttime>1000/avgfps) { |
||||
//System.out.println("WARNING! Last update took "+(System.currentTimeMillis()-lasttime)+"ms! Lagging?");
|
||||
if (counter<30) { |
||||
counter++; |
||||
} else { |
||||
counter=0; |
||||
avgfps--; |
||||
} |
||||
} else { |
||||
if (counter>-30) { |
||||
counter--; |
||||
} else { |
||||
counter=0; |
||||
avgfps++; |
||||
} |
||||
} |
||||
} |
||||
|
||||
public void UpdateScrollingText() { |
||||
for (int i=0;i<sigIRC.twitchemoticons.size();i++) { |
||||
boolean keep = sigIRC.twitchemoticons.get(i).run(); |
||||
if (!keep) { |
||||
sigIRC.twitchemoticons.remove(i--); |
||||
} |
||||
} |
||||
for (int i=0;i<sigIRC.textobj.size();i++) { |
||||
boolean keep = sigIRC.textobj.get(i).run(); |
||||
if (!keep) { |
||||
sigIRC.textobj.remove(i--); |
||||
} |
||||
} |
||||
ProcessTextRows(); |
||||
for (CustomSound cs : sigIRC.customsounds) { |
||||
if (!cs.isSoundAvailable()) { |
||||
cs.decreaseCooldown(1); |
||||
} |
||||
} |
||||
Module.inDragZone=false; |
||||
for (Module m : sigIRC.modules) { |
||||
m.moduleRun(); |
||||
} |
||||
for (int i=0;i<sigIRC.chatlogtwitchemoticons.size();i++) { |
||||
boolean keep = sigIRC.chatlogtwitchemoticons.get(i).run(); |
||||
if (!keep) { |
||||
sigIRC.chatlogtwitchemoticons.remove(i--); |
||||
} |
||||
} |
||||
sigIRC.panel.repaint(); |
||||
} |
||||
|
||||
private void ProcessTextRows() { |
||||
for (TextRow tr : sigIRC.rowobj) { |
||||
tr.update(); |
||||
} |
||||
sigIRC.dingEnabled = (sigIRC.textobj.size()<=sigIRC.dingThreshold); |
||||
//System.out.println(sigIRC.textobj.size()+"/"+sigIRC.dingThreshold+sigIRC.dingEnabled);
|
||||
} |
||||
} |
@ -0,0 +1,299 @@ |
||||
package sig.modules.ChatLog; |
||||
|
||||
import java.awt.Color; |
||||
import java.awt.Graphics; |
||||
import java.awt.Point; |
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
import java.util.Random; |
||||
|
||||
import javax.swing.SwingUtilities; |
||||
|
||||
import sig.Emoticon; |
||||
import sig.Module; |
||||
import sig.SubEmoticon; |
||||
import sig.sigIRC; |
||||
import sig.modules.ChatLogModule; |
||||
import sig.utils.DrawUtils; |
||||
import sig.utils.TextUtils; |
||||
|
||||
public class ChatLogMessage { |
||||
String rawMessage; |
||||
Point messageDisplaySize; //The amount of screen space (w,h) this message takes up.
|
||||
public Point position; |
||||
ChatLogModule refModule; |
||||
String username; |
||||
List<String> displayMessage = new ArrayList<String>(); |
||||
final static public int MESSAGE_SPACING = 24; |
||||
final static public int BORDER_SPACING = 8; |
||||
final static public Color SHADOW_COL = new Color(35,35,35,255); |
||||
int usernameWidth = 0; |
||||
boolean active=true; |
||||
|
||||
public ChatLogMessage(String rawMessage) { |
||||
this.refModule = ChatLogModule.chatlogmodule; |
||||
this.rawMessage = rawMessage; |
||||
this.position = new Point(0,(int)refModule.getPosition().getHeight()-MESSAGE_SPACING); |
||||
WrapText(); |
||||
for (ChatLogMessage clm : this.refModule.messageHistory) { |
||||
clm.position.setLocation( |
||||
clm.position.getX(), |
||||
clm.position.getY()-messageDisplaySize.getY()); |
||||
//System.out.println(clm.rawMessage+": "+clm.position);
|
||||
} |
||||
this.position.setLocation(this.position.getX(), this.position.getY()-messageDisplaySize.getY()+ChatLogModule.chatlogmodule.scrolllog_yoffset); |
||||
//System.out.println(displayMessage);
|
||||
this.username = DetectUsername(displayMessage); |
||||
if (this.username!=null) { |
||||
displayMessage.set(0,GetMessage(displayMessage.get(0)+" ")); |
||||
usernameWidth = (int)TextUtils.calculateStringBoundsFont(this.username, sigIRC.panel.userFont).getWidth(); |
||||
} |
||||
for (int i=0;i<displayMessage.size();i++) { |
||||
//System.out.println("displayMessage["+i+"] before: "+displayMessage.get(i));
|
||||
displayMessage.set(i, ReplaceMessageWithEmoticons(" "+displayMessage.get(i)+" ",(i==0)?usernameWidth:0,i*MESSAGE_SPACING)); |
||||
//System.out.println("displayMessage["+i+"] after: "+displayMessage.get(i));
|
||||
} |
||||
} |
||||
|
||||
private String ReplaceMessageWithEmoticons(String basemsg, int xpos, int ypos) { |
||||
int marker = basemsg.indexOf(" "); |
||||
while (marker<basemsg.length()) { |
||||
//Find a space.
|
||||
int space = basemsg.indexOf(" ", marker+1); |
||||
//System.out.println(" Marker is at position "+space+" for word \""+basemsg+"\"");
|
||||
if (space>0) { |
||||
String word = basemsg.substring(marker+1, space); |
||||
//System.out.println(" Word is '"+word+"'");
|
||||
sigIRC.emoticons.addAll(sigIRC.emoticon_queue); |
||||
sigIRC.emoticon_queue.clear(); |
||||
for (Emoticon e : sigIRC.emoticons) { |
||||
//System.out.println("Checking for emoticon "+e.getEmoteName()+" vs \""+word+"\"");
|
||||
try { |
||||
if (e.getEmoteName().equals(word)) { |
||||
if (e instanceof SubEmoticon) { |
||||
SubEmoticon se = (SubEmoticon)e; |
||||
if (!se.canUserUseEmoticon(username)) { |
||||
//System.out.println("User "+username+" is not subscribed to "+se.channelName+"'s channel!");
|
||||
break; |
||||
} |
||||
} |
||||
//System.out.println(" Found one!");
|
||||
basemsg = TextUtils.replaceFirst(basemsg, e.getEmoteName(), e.getSmallSpaceFiller()); |
||||
GenerateEmoticon(marker+1, xpos, ypos, basemsg, e); |
||||
space = basemsg.indexOf(" ", marker+1); |
||||
break; |
||||
} |
||||
} catch (NullPointerException ex) { |
||||
ex.printStackTrace(); |
||||
} |
||||
} |
||||
marker=space; |
||||
} else { |
||||
break; |
||||
} |
||||
} |
||||
//textMaxWidth = (int)TextUtils.calculateStringBoundsFont(basemsg, sigIRC.panel.programFont).getWidth();
|
||||
//textMaxHeight = Math.max(textMaxHeight,(int)TextUtils.calculateStringBoundsFont(basemsg, sigIRC.panel.programFont).getHeight());
|
||||
return basemsg; |
||||
} |
||||
|
||||
private void GenerateEmoticon(int textpos, int xpos, int ypos, String basemsg, Emoticon e) { |
||||
String cutstring = basemsg.substring(0, textpos); |
||||
double width = TextUtils.calculateStringBoundsFont(cutstring, sigIRC.panel.userFont).getWidth(); |
||||
//System.out.println("Width of '"+cutstring+"' is "+width);
|
||||
//System.out.println("Offsetting emote by "+xpos+"+"+width);
|
||||
sigIRC.createEmoticon(e, this, (int)(xpos+width), ypos+16); |
||||
//textMaxHeight = Math.max(textMaxHeight, e.getImage().getHeight());
|
||||
//textMaxWidth = (int)(width + e.getImage().getWidth()+1);
|
||||
} |
||||
|
||||
private String GetMessage(String msg) { |
||||
String basemsg = " "+msg.substring(msg.indexOf(":")+2, msg.length())+" "; |
||||
//basemsg = ConvertMessageSymbols(basemsg);
|
||||
//basemsg = ReplaceMessageWithEmoticons(basemsg);
|
||||
return basemsg.substring(0,basemsg.length()-1); |
||||
} |
||||
|
||||
private String DetectUsername(List<String> messages) { |
||||
if (messages.size()>0) { |
||||
String username = GetUsername(messages.get(0)); |
||||
if (username!=null) { |
||||
return username; |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
private Color GetUserNameColor(String username) { |
||||
Random r = new Random(); |
||||
r.setSeed(username.hashCode()); |
||||
int randomnumb = r.nextInt(3); |
||||
Color col; |
||||
switch (randomnumb) { |
||||
case 0:{ |
||||
col=new Color(255,r.nextInt(128)+64,r.nextInt(128)+64,255); |
||||
}break; |
||||
case 1:{ |
||||
col=new Color(r.nextInt(128)+64,255,r.nextInt(128)+64,255); |
||||
}break; |
||||
case 2:{ |
||||
col=new Color(r.nextInt(128)+64,r.nextInt(128)+64,255,255); |
||||
}break; |
||||
default:{ |
||||
col=Color.GREEN; |
||||
} |
||||
} |
||||
return col; |
||||
} |
||||
|
||||
private String GetUsername(String msg) { |
||||
if (msg.contains(":")) { |
||||
return msg.substring(0,msg.indexOf(":")); |
||||
} else { |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
private void WrapText() { |
||||
String rawmessage = rawMessage; |
||||
int textWidth = (int)TextUtils.calculateStringBoundsFont(rawmessage, sigIRC.panel.userFont).getWidth(); |
||||
int maxWidth = (int)refModule.getPosition().getWidth()-BORDER_SPACING; |
||||
do { |
||||
rawmessage = BreakTextAtNextSection(rawmessage+" ",maxWidth); |
||||
textWidth = (int)TextUtils.calculateStringBoundsFont(rawmessage, sigIRC.panel.userFont).getWidth(); |
||||
} while (textWidth>maxWidth); |
||||
if (rawmessage.length()>0) { |
||||
displayMessage.add(rawmessage); |
||||
} |
||||
messageDisplaySize = new Point((int)(refModule.getPosition().getWidth()-BORDER_SPACING),(int)(displayMessage.size()*MESSAGE_SPACING)); |
||||
//System.out.println(displayMessage+": "+messageDisplaySize);
|
||||
} |
||||
|
||||
private String BreakTextAtNextSection(String msg, int maxWidth) { |
||||
int marker = 1; |
||||
int textWidth = (int)TextUtils.calculateStringBoundsFont(msg.substring(0, marker), sigIRC.panel.userFont).getWidth(); |
||||
while (textWidth<maxWidth) { |
||||
if (marker<msg.length()) { |
||||
int tempmarker = msg.indexOf(' ', marker); |
||||
if (tempmarker!=-1) { |
||||
textWidth = (int)TextUtils.calculateStringBoundsFont(msg.substring(0, tempmarker), sigIRC.panel.userFont).getWidth(); |
||||
if (textWidth<maxWidth) { |
||||
marker = tempmarker+1; |
||||
} |
||||
//System.out.println(msg.substring(0, marker)+" | "+textWidth);
|
||||
} else { |
||||
marker=msg.length(); |
||||
break; |
||||
} |
||||
} else { |
||||
break; |
||||
} |
||||
} |
||||
String currentText = msg.substring(0, marker); |
||||
displayMessage.add(currentText); |
||||
return msg.substring(marker, msg.length()); |
||||
} |
||||
|
||||
public boolean run() { |
||||
/*SwingUtilities.invokeLater(new Runnable() { |
||||
public void run() { |
||||
sigIRC.panel.repaint( |
||||
(int)Math.max(refModule.getPosition().getX()+position.getX(),0), |
||||
(int)Math.max(refModule.getPosition().getY()+position.getY(),0), |
||||
(int)Math.min(sigIRC.panel.getWidth()-(refModule.getPosition().getX()+position.getX()+messageDisplaySize.getX()),messageDisplaySize.getX()), |
||||
(int)Math.min(sigIRC.panel.getHeight()-(refModule.getPosition().getY()+position.getY()+messageDisplaySize.getY()),messageDisplaySize.getY())); |
||||
} |
||||
});*/ |
||||
//System.out.println(refModule.getPosition()+","+position);
|
||||
return true; |
||||
} |
||||
|
||||
public void draw(Graphics g) { |
||||
if (isVisible()) { |
||||
for (int i=0;i<displayMessage.size();i++) { |
||||
//System.out.println(displayMessage.get(i));
|
||||
if (username!=null && i==0) { |
||||
DrawUtils.drawOutlineText(g, sigIRC.panel.userFont, refModule.getPosition().getX()+position.getX(), refModule.getPosition().getY()+position.getY()+(i*MESSAGE_SPACING)+32, 2, GetUserNameColor(this.username), SHADOW_COL, this.username); |
||||
DrawUtils.drawTextFont(g, sigIRC.panel.userFont, refModule.getPosition().getX()+position.getX()+usernameWidth+2, refModule.getPosition().getY()+position.getY()+(i*MESSAGE_SPACING)+32, Color.BLACK, displayMessage.get(i)); |
||||
} else { |
||||
DrawUtils.drawTextFont(g, sigIRC.panel.userFont, refModule.getPosition().getX()+position.getX(), refModule.getPosition().getY()+position.getY()+(i*MESSAGE_SPACING)+32, Color.BLACK, displayMessage.get(i)); |
||||
} |
||||
} |
||||
g.drawImage(Module.MSG_SEPARATOR, (int)(refModule.getPosition().getX()+position.getX()+8), (int)(refModule.getPosition().getY()+position.getY()+messageDisplaySize.getY()+12), (int)(messageDisplaySize.getX()-8), 1, sigIRC.panel); |
||||
//g.drawLine((int)(refModule.getPosition().getX()+position.getX()+8), (int)(refModule.getPosition().getY()+position.getY()+messageDisplaySize.getY()+32), (int)(refModule.getPosition().getX()+position.getX()+messageDisplaySize.getX()-8), (int)(refModule.getPosition().getY()+position.getY()+messageDisplaySize.getY()+32));
|
||||
} |
||||
} |
||||
|
||||
public static void importMessages(String...logContents) { |
||||
if (sigIRC.chatlogmodule_enabled) { |
||||
for (String s : logContents) { |
||||
if (s!=null) { |
||||
if (ChatLogModule.chatlogmodule.messageHistory.size()>=ChatLogModule.messageHistoryCount) { |
||||
ChatLogModule.chatlogmodule.messageHistory.remove(0).cleanup(); |
||||
} |
||||
ChatLogModule.chatlogmodule.messageHistory.add(new ChatLogMessage(s)); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
public void cleanup() { |
||||
active=false; |
||||
} |
||||
|
||||
public boolean isVisible() { |
||||
return (refModule.getPosition().getY()+position.getY()+MESSAGE_SPACING)>refModule.getPosition().getY() && |
||||
(refModule.getPosition().getY()+position.getY()+messageDisplaySize.getY())<refModule.getPosition().getY()+refModule.getPosition().getHeight()-16; |
||||
} |
||||
|
||||
/* |
||||
private String ReplaceMessageWithEmoticons(String basemsg) { |
||||
int marker = basemsg.indexOf(" "); |
||||
while (marker<basemsg.length()) { |
||||
//Find a space.
|
||||
int space = basemsg.indexOf(" ", marker+1); |
||||
if (space>0) { |
||||
String word = basemsg.substring(marker+1, space); |
||||
//System.out.println("Word is '"+word+"'");
|
||||
sigIRC.emoticons.addAll(sigIRC.emoticon_queue); |
||||
sigIRC.emoticon_queue.clear(); |
||||
for (Emoticon e : sigIRC.emoticons) { |
||||
//System.out.println("Checking for emoticon "+e.getEmoteName());
|
||||
try { |
||||
if (e.getEmoteName().equals(word)) { |
||||
if (e instanceof SubEmoticon) { |
||||
SubEmoticon se = (SubEmoticon)e; |
||||
if (!se.canUserUseEmoticon(username)) { |
||||
//System.out.println("User "+username+" is not subscribed to "+se.channelName+"'s channel!");
|
||||
break; |
||||
} |
||||
} |
||||
//System.out.println(" Found one!");
|
||||
basemsg = TextUtils.replaceFirst(basemsg, e.getEmoteName(), e.getSpaceFiller()); |
||||
GenerateEmoticon(marker+1, basemsg, e); |
||||
space = basemsg.indexOf(" ", marker+1); |
||||
break; |
||||
} |
||||
} catch (NullPointerException ex) { |
||||
ex.printStackTrace(); |
||||
} |
||||
} |
||||
marker=space; |
||||
} else { |
||||
break; |
||||
} |
||||
} |
||||
textMaxWidth = (int)TextUtils.calculateStringBoundsFont(basemsg, sigIRC.panel.programFont).getWidth(); |
||||
textMaxHeight = Math.max(textMaxHeight,(int)TextUtils.calculateStringBoundsFont(basemsg, sigIRC.panel.programFont).getHeight()); |
||||
return basemsg; |
||||
} |
||||
|
||||
private void GenerateEmoticon(int pos, String basemsg, Emoticon e) { |
||||
String cutstring = basemsg.substring(0, pos); |
||||
double width = TextUtils.calculateStringBoundsFont(cutstring, sigIRC.panel.programFont).getWidth(); |
||||
//System.out.println("Width of '"+cutstring+"' is "+width);
|
||||
sigIRC.createEmoticon(e, this, (int)(width), 0); |
||||
textMaxHeight = Math.max(textMaxHeight, e.getImage().getHeight()); |
||||
//textMaxWidth = (int)(width + e.getImage().getWidth()+1);
|
||||
}*/ |
||||
} |
@ -0,0 +1,60 @@ |
||||
package sig.modules.ChatLog; |
||||
|
||||
import java.awt.Graphics; |
||||
|
||||
import javax.swing.SwingUtilities; |
||||
|
||||
import sig.Emoticon; |
||||
import sig.ScrollingText; |
||||
import sig.sigIRC; |
||||
|
||||
public class ChatLogTwitchEmote { |
||||
Emoticon emote; |
||||
int x=0; //X Offset
|
||||
int y=0; //Y Offset
|
||||
ChatLogMessage text; |
||||
|
||||
public ChatLogTwitchEmote(Emoticon emote, ChatLogMessage textref, int x, int y) { |
||||
this.emote=emote; |
||||
this.x=x; |
||||
this.y=y+24-emote.getImage().getHeight(); |
||||
this.text = textref; |
||||
} |
||||
|
||||
public boolean run() { |
||||
//this.x-=paint.TEXTSCROLLSPD;
|
||||
/*if (textRefIsVisible()) { |
||||
SwingUtilities.invokeLater(new Runnable() { |
||||
public void run() { |
||||
sigIRC.panel.repaint( |
||||
Math.max(x,0), |
||||
Math.max(y, 0), |
||||
Math.min(sigIRC.panel.getWidth()-x,emote.getImage().getWidth()), |
||||
Math.min(sigIRC.panel.getHeight()-y,emote.getImage().getHeight())); |
||||
} |
||||
}); |
||||
}*/ |
||||
if (text==null || !text.active) { |
||||
return false; |
||||
} else { |
||||
return true; |
||||
} |
||||
} |
||||
|
||||
public void draw(Graphics g) { |
||||
if (WithinBounds((int)(text.position.getX()+x), (int)(text.position.getY()+y), emote.getImage().getWidth(), emote.getImage().getHeight())) { |
||||
g.drawImage(emote.getImage(), (int)(text.refModule.getPosition().getX()+text.position.getX()+x), (int)(text.refModule.getPosition().getY()+text.position.getY()+y), sigIRC.panel); |
||||
} |
||||
} |
||||
|
||||
private boolean WithinBounds(double x, double y, double w, double h) { |
||||
if (x<sigIRC.panel.getWidth() && x+w>0 && y<sigIRC.panel.getHeight() && y+h>0) { |
||||
return true; |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
public boolean textRefIsVisible() { |
||||
return text.isVisible(); |
||||
} |
||||
} |
@ -0,0 +1,192 @@ |
||||
package sig.modules; |
||||
|
||||
import java.awt.Color; |
||||
import java.awt.Graphics; |
||||
import java.awt.event.KeyEvent; |
||||
import java.awt.event.MouseWheelEvent; |
||||
import java.awt.geom.Rectangle2D; |
||||
import java.io.File; |
||||
import java.util.ArrayList; |
||||
import java.util.Arrays; |
||||
import java.util.Calendar; |
||||
import java.util.ConcurrentModificationException; |
||||
import java.util.List; |
||||
|
||||
import javax.imageio.ImageIO; |
||||
import javax.swing.SwingUtilities; |
||||
|
||||
import sig.Module; |
||||
import sig.sigIRC; |
||||
import sig.modules.ChatLog.ChatLogMessage; |
||||
import sig.utils.DrawUtils; |
||||
import sig.utils.FileUtils; |
||||
|
||||
public class ChatLogModule extends Module{ |
||||
public static int messageHistoryCount = 50; |
||||
public List<ChatLogMessage> messageHistory = new ArrayList<ChatLogMessage>(); |
||||
int delay = 150; |
||||
boolean initialized=false; |
||||
public static ChatLogModule chatlogmodule; |
||||
public int scrolllog_yoffset = 0; |
||||
public Color backgroundColor; |
||||
|
||||
public ChatLogModule(Rectangle2D bounds, String moduleName) { |
||||
super(bounds, moduleName); |
||||
//Initialize();
|
||||
chatlogmodule = this; |
||||
backgroundColor = DrawUtils.convertStringToColor(sigIRC.chatlogmodule_backgroundColor); |
||||
} |
||||
|
||||
private void Initialize() { |
||||
messageHistoryCount = sigIRC.chatlogMessageHistory; |
||||
Calendar cal = Calendar.getInstance(); |
||||
String logFileLoc = sigIRC.BASEDIR+"sigIRC/logs/log_"+(cal.get(Calendar.MONTH)+1)+"_"+cal.get(Calendar.DAY_OF_MONTH)+"_"+cal.get(Calendar.YEAR)+".txt"; |
||||
File todaysLogFile = new File(logFileLoc); |
||||
if (todaysLogFile.exists()) { |
||||
String[] logContents = FileUtils.readFromFile(logFileLoc); |
||||
if (logContents.length>messageHistoryCount) { |
||||
logContents = Arrays.copyOfRange(logContents, logContents.length-messageHistoryCount-1, logContents.length); |
||||
} |
||||
ChatLogMessage.importMessages(logContents); |
||||
} |
||||
} |
||||
|
||||
public void run() { |
||||
super.run(); |
||||
if (delay>0 && sigIRC.subEmotesCompleted) { |
||||
delay--; |
||||
} else |
||||
if (!initialized) |
||||
{ |
||||
Initialize(); |
||||
initialized=true; |
||||
} |
||||
for (int i=0; i<messageHistory.size();i++) { |
||||
ChatLogMessage clm = messageHistory.get(i); |
||||
if (clm!=null) { |
||||
try { |
||||
clm.run(); |
||||
} catch (ConcurrentModificationException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
public void draw(Graphics g) { |
||||
super.draw(g); |
||||
g.setColor(backgroundColor); |
||||
g.fill3DRect((int)position.getX(), (int)position.getY(), (int)position.getWidth(), (int)position.getHeight(), true); |
||||
g.setColor(Color.BLACK); |
||||
for (int i=0; i<messageHistory.size();i++) { |
||||
ChatLogMessage clm = messageHistory.get(i); |
||||
if (clm!=null) { |
||||
try { |
||||
clm.draw(g); |
||||
} catch (ConcurrentModificationException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
public void ApplyConfigWindowProperties() { |
||||
sigIRC.chatlogmodule_X=(int)position.getX(); |
||||
sigIRC.chatlogmodule_Y=(int)position.getY(); |
||||
sigIRC.config.setInteger("CHATLOG_module_X", sigIRC.chatlogmodule_X); |
||||
sigIRC.config.setInteger("CHATLOG_module_Y", sigIRC.chatlogmodule_Y); |
||||
} |
||||
|
||||
public void mouseWheel(MouseWheelEvent ev) { |
||||
if (mouseInBounds(ev.getX(),ev.getY())) { |
||||
int scrollMult = 8; |
||||
int scrollAmt = -ev.getWheelRotation()*scrollMult; |
||||
if (scrollAmt>0) { |
||||
if (HighestMessageIsVisible()) { |
||||
return; |
||||
} |
||||
} |
||||
if (scrolllog_yoffset+scrollAmt>0) { |
||||
scrolllog_yoffset+=scrollAmt; |
||||
moveAllMessages(scrollAmt); |
||||
//System.out.println("Moving all messages by "+(-(ev.getWheelRotation()*scrollMult)));
|
||||
} else |
||||
{ |
||||
//System.out.println("Cannot move beyond lower bound. Moving all messages by -"+(scrolllog_yoffset)+".");
|
||||
moveAllMessages(-scrolllog_yoffset); |
||||
scrolllog_yoffset=0; |
||||
} |
||||
} |
||||
} |
||||
|
||||
private boolean HighestMessageIsVisible() { |
||||
if (messageHistory.size()>0) { |
||||
ChatLogMessage clm = messageHistory.get(0); |
||||
return clm.isVisible(); |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
public void moveAllMessages(int yAmt) { |
||||
for (int i=0;i<messageHistory.size();i++) { |
||||
ChatLogMessage clm = messageHistory.get(i); |
||||
if (clm!=null) { |
||||
try { |
||||
clm.position.setLocation(clm.position.getX(), clm.position.getY()+yAmt); |
||||
} catch (ConcurrentModificationException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
private boolean mouseInBounds(int mouseX, int mouseY) { |
||||
return mouseX>=position.getX() && |
||||
mouseX<=position.getX()+position.getWidth() && |
||||
mouseY>=position.getX() && |
||||
mouseY<=position.getX()+position.getHeight(); |
||||
} |
||||
|
||||
|
||||
public void keypressed(KeyEvent ev) { |
||||
int key = ev.getKeyCode(); |
||||
int scroll = 0; |
||||
if (key==KeyEvent.VK_PAGE_UP) { |
||||
scroll=8; |
||||
} else |
||||
if (key==KeyEvent.VK_PAGE_DOWN) { |
||||
scroll=-8; |
||||
} |
||||
if (key==KeyEvent.VK_HOME) { |
||||
scroll=Math.abs(GetHighestMessagePosition()); |
||||
} |
||||
if (key==KeyEvent.VK_END) { |
||||
moveAllMessages(-scrolllog_yoffset); |
||||
scrolllog_yoffset=0; |
||||
return; |
||||
} |
||||
if (scroll>0) { |
||||
if (HighestMessageIsVisible()) { |
||||
return; |
||||
} |
||||
} |
||||
if (scrolllog_yoffset+scroll>0) { |
||||
scrolllog_yoffset+=scroll; |
||||
moveAllMessages(scroll); |
||||
//System.out.println("Moving all messages by "+(-(ev.getWheelRotation()*scrollMult)));
|
||||
} else |
||||
{ |
||||
//System.out.println("Cannot move beyond lower bound. Moving all messages by -"+(scrolllog_yoffset)+".");
|
||||
moveAllMessages(-scrolllog_yoffset); |
||||
scrolllog_yoffset=0; |
||||
} |
||||
} |
||||
|
||||
private int GetHighestMessagePosition() { |
||||
if (messageHistory.size()>0) { |
||||
ChatLogMessage clm = messageHistory.get(0); |
||||
return (int)clm.position.getY(); |
||||
} |
||||
return 0; |
||||
} |
||||
} |
@ -0,0 +1,348 @@ |
||||
package sig.modules.Controller; |
||||
|
||||
import java.awt.Color; |
||||
import java.awt.Graphics; |
||||
import java.awt.geom.Rectangle2D; |
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
import sig.sigIRC; |
||||
import sig.modules.ControllerModule; |
||||
|
||||
public class Axis extends Element{ |
||||
List<Integer> identifiers = new ArrayList<Integer>(); |
||||
boolean twoWayAxis = false; //True = 4-way, False = 2-way
|
||||
Color backgroundColor=Color.BLACK,indicatorColor=Color.WHITE; |
||||
Controller parent_controller; |
||||
ControllerModule parent; |
||||
double range1,range2; //Range of motion.
|
||||
int orientation; //0=Left-to-Right, 1=Right-to-Left, 2=Bottom-to-Top, 3=Top-to-Bottom
|
||||
boolean visible=false; |
||||
boolean x_invert,y_invert,axis_invert; |
||||
|
||||
/** |
||||
* 4-way axis Constructor. |
||||
*/ |
||||
public Axis(Rectangle2D.Double rect, |
||||
Controller parent_controller, |
||||
Integer identifier, |
||||
Integer identifier2, |
||||
Color background_color, |
||||
Color indicator_color, |
||||
boolean x_invert, |
||||
boolean y_invert, |
||||
boolean axis_invert, |
||||
ControllerModule module) { |
||||
this.twoWayAxis=false; |
||||
this.pct_x = rect.getX(); |
||||
this.pct_y = rect.getY(); |
||||
this.pct_width=rect.getWidth(); |
||||
this.pct_height=rect.getHeight(); |
||||
if (identifier!=null) { |
||||
identifiers.add(identifier); |
||||
} |
||||
if (identifier2!=null) { |
||||
identifiers.add(identifier2); |
||||
} |
||||
this.parent_controller = parent_controller; |
||||
this.parent = module; |
||||
this.backgroundColor = background_color; |
||||
this.indicatorColor = indicator_color; |
||||
this.x_invert = x_invert; |
||||
this.y_invert = y_invert; |
||||
this.axis_invert = axis_invert; |
||||
} |
||||
|
||||
/** |
||||
* 2-way axis Constructor. |
||||
*/ |
||||
public Axis(Rectangle2D.Double rect, |
||||
Controller parent_controller, |
||||
Integer identifier, |
||||
double starting_range, |
||||
double ending_range, |
||||
int orientation, |
||||
Color background_color, |
||||
Color indicator_color, |
||||
boolean x_invert, |
||||
ControllerModule module) { |
||||
this.twoWayAxis=true; |
||||
this.pct_x = rect.getX(); |
||||
this.pct_y = rect.getY(); |
||||
this.pct_width=rect.getWidth(); |
||||
this.pct_height=rect.getHeight(); |
||||
if (identifier!=null) { |
||||
identifiers.add(identifier); |
||||
} |
||||
this.parent_controller = parent_controller; |
||||
this.parent = module; |
||||
this.range1 = starting_range; |
||||
this.range2 = ending_range; |
||||
this.orientation = orientation; |
||||
this.backgroundColor = background_color; |
||||
this.indicatorColor = indicator_color; |
||||
this.x_invert = x_invert; |
||||
} |
||||
|
||||
public void draw(Graphics g) { |
||||
if (visible) { |
||||
GetAxisDisplay(g,this, |
||||
parent.getPosition().getX()+pct_x*parent.getControllerImage().getWidth(sigIRC.panel), |
||||
parent.getPosition().getY()+pct_y*parent.getControllerImage().getHeight(sigIRC.panel), |
||||
pct_width*parent.getControllerImage().getWidth(sigIRC.panel), |
||||
pct_height*parent.getControllerImage().getHeight(sigIRC.panel)); |
||||
} |
||||
} |
||||
|
||||
public void drawIndicator(Graphics g) { |
||||
if (visible) { |
||||
GetAxisIndicatorDisplay(g,this, |
||||
parent.getPosition().getX()+pct_x*parent.getControllerImage().getWidth(sigIRC.panel), |
||||
parent.getPosition().getY()+pct_y*parent.getControllerImage().getHeight(sigIRC.panel), |
||||
pct_width*parent.getControllerImage().getWidth(sigIRC.panel), |
||||
pct_height*parent.getControllerImage().getHeight(sigIRC.panel)); |
||||
} |
||||
} |
||||
|
||||
public Color getSelectionColor() { |
||||
return backgroundColor; |
||||
} |
||||
|
||||
public boolean is_Xinverted() { |
||||
return x_invert; |
||||
} |
||||
|
||||
public boolean is_Yinverted() { |
||||
return y_invert; |
||||
} |
||||
|
||||
public boolean is_Axisinverted() { |
||||
return axis_invert; |
||||
} |
||||
|
||||
public void setupBoundsRectangle(Rectangle2D.Double rect) { |
||||
this.pct_x = rect.getX(); |
||||
this.pct_y = rect.getY(); |
||||
this.pct_width=rect.getWidth(); |
||||
this.pct_height=rect.getHeight(); |
||||
} |
||||
|
||||
public boolean isTwoWayAxis() { |
||||
return twoWayAxis; |
||||
} |
||||
|
||||
public Color getBackgroundColor() { |
||||
return backgroundColor; |
||||
} |
||||
|
||||
public List<Integer> getIdentifiers() { |
||||
return identifiers; |
||||
} |
||||
|
||||
public Color getIndicatorColor() { |
||||
return indicatorColor; |
||||
} |
||||
|
||||
public double getPctX() { |
||||
return pct_x; |
||||
} |
||||
|
||||
public double getPctY() { |
||||
return pct_y; |
||||
} |
||||
|
||||
public double getPctWidth() { |
||||
return pct_width; |
||||
} |
||||
|
||||
public double getPctHeight() { |
||||
return pct_height; |
||||
} |
||||
|
||||
public Controller getController() { |
||||
return parent_controller; |
||||
} |
||||
|
||||
public ControllerModule getModule() { |
||||
return parent; |
||||
} |
||||
|
||||
public double getRange1() { |
||||
return range1; |
||||
} |
||||
|
||||
public double getRange2() { |
||||
return range2; |
||||
} |
||||
|
||||
public int getOrientation() { |
||||
return orientation; |
||||
} |
||||
|
||||
public boolean isVisible() { |
||||
return visible; |
||||
} |
||||
|
||||
public void setVisible(boolean visible) { |
||||
this.visible=visible; |
||||
} |
||||
|
||||
public static void GetAxisDisplay(Graphics g, Axis a, double x, double y, double xscale, double yscale) { |
||||
if (a.twoWayAxis) { |
||||
Color color_identity = g.getColor(); |
||||
g.setColor(a.backgroundColor); |
||||
g.fillRect((int)x, (int)y, (int)xscale, (int)yscale); |
||||
g.setColor(a.indicatorColor); |
||||
double val = 0; |
||||
if (a.identifiers.size()>=1 && a.identifiers.get(0)!=-1) { |
||||
val=a.parent_controller.getAxisValue(a.identifiers.get(0))*((a.x_invert)?-1:1); |
||||
//val=a.parent_controller.getComponent(a.identifiers.get(0)).getPollData();
|
||||
} |
||||
double val1 = a.range1; |
||||
double val2 = a.range2; |
||||
double range_of_motion = (Math.abs(val1)+Math.abs(val2)); |
||||
double smallest_val = 0; |
||||
if (val1<0 || val2<0) { |
||||
smallest_val = Math.abs(Math.min(val1, val2)); |
||||
} |
||||
double area_covered_x = (int)(((val+smallest_val)/range_of_motion)*xscale); |
||||
double area_covered_y = (int)(((val+smallest_val)/range_of_motion)*yscale); |
||||
switch (a.orientation) { |
||||
case 0:{ |
||||
g.fillRect((int)x, (int)y, (int)area_covered_x, (int)yscale); |
||||
}break; |
||||
case 1:{ |
||||
g.fillRect((int)(xscale-area_covered_x+x), (int)y, (int)area_covered_x, (int)yscale); |
||||
}break; |
||||
case 2:{ |
||||
g.fillRect((int)x, (int)(yscale-area_covered_y+y), (int)xscale, (int)area_covered_y); |
||||
}break; |
||||
case 3:{ |
||||
g.fillRect((int)x, (int)y, (int)xscale, (int)area_covered_y); |
||||
}break; |
||||
} |
||||
g.setColor(color_identity); |
||||
} else { |
||||
double xval=0; |
||||
double yval=0; |
||||
if (a.identifiers.size()>0 && a.identifiers.get(0)!=null) { |
||||
xval = a.parent_controller.getAxisValue(a.identifiers.get(0))*((a.x_invert)?-1:1); |
||||
} |
||||
if (a.identifiers.size()>1 && a.identifiers.get(1)!=null) { |
||||
yval = a.parent_controller.getAxisValue(a.identifiers.get(1))*((a.y_invert)?-1:1); |
||||
} |
||||
Color color_identity = g.getColor(); |
||||
g.setColor(a.backgroundColor); |
||||
g.fillOval((int)x, (int)y, (int)xscale, (int)yscale); |
||||
g.setColor(color_identity); |
||||
} |
||||
} |
||||
|
||||
|
||||
|
||||
public static void GetAxisIndicatorDisplay(Graphics g, Axis a, double x, double y, double xscale, double yscale) { |
||||
if (!a.twoWayAxis) { |
||||
double xval=0; |
||||
double yval=0; |
||||
if (a.identifiers.size()>0 && a.identifiers.get(0)!=null) { |
||||
xval = a.parent_controller.getAxisValue(a.identifiers.get(0))*((a.x_invert)?-1:1); |
||||
} |
||||
if (a.identifiers.size()>1 && a.identifiers.get(1)!=null) { |
||||
yval = a.parent_controller.getAxisValue(a.identifiers.get(1))*((a.y_invert)?-1:1); |
||||
} |
||||
DrawIndicator(g, a, x, y, xscale, yscale, xval, yval); |
||||
} |
||||
} |
||||
|
||||
private static void DrawIndicator(Graphics g, Axis a, double x, double y, double xscale, double yscale, double xval, |
||||
double yval) { |
||||
g.setColor(a.indicatorColor); |
||||
for (int i=-1;i<2;i++) { |
||||
for (int j=-1;j<2;j++) { |
||||
g.drawOval((int)(((xval+1)*12*(xscale/32d))+i+x), (int)(((yval+1)*12*(yscale/32d))+j+y), (int)(8d*(xscale/32d)), (int)(8d*(yscale/32d))); |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
|
||||
public String getSaveString() { |
||||
StringBuilder sb = new StringBuilder(); |
||||
sb.append(pct_x);sb.append(","); |
||||
sb.append(pct_y);sb.append(","); |
||||
sb.append(pct_width);sb.append(","); |
||||
sb.append(pct_height);sb.append(","); |
||||
sb.append(twoWayAxis);sb.append(","); |
||||
if (twoWayAxis) { |
||||
sb.append((identifiers.size()>0 && |
||||
identifiers.get(0)!=null)?identifiers.get(0):"null");sb.append(","); |
||||
sb.append(range1);sb.append(","); |
||||
sb.append(range2);sb.append(","); |
||||
sb.append(orientation);sb.append(","); |
||||
} else { |
||||
sb.append((identifiers.size()>0 && |
||||
identifiers.get(0)!=null)?identifiers.get(0):"null");sb.append(","); |
||||
sb.append((identifiers.size()>1 && |
||||
identifiers.get(1)!=null)?identifiers.get(1):"null");sb.append(","); |
||||
} |
||||
sb.append(backgroundColor.getRed());sb.append(","); |
||||
sb.append(backgroundColor.getGreen());sb.append(","); |
||||
sb.append(backgroundColor.getBlue());sb.append(","); |
||||
sb.append(backgroundColor.getAlpha());sb.append(","); |
||||
sb.append(indicatorColor.getRed());sb.append(","); |
||||
sb.append(indicatorColor.getGreen());sb.append(","); |
||||
sb.append(indicatorColor.getBlue());sb.append(","); |
||||
sb.append(indicatorColor.getAlpha());sb.append(","); |
||||
sb.append(x_invert);sb.append(","); |
||||
if (!twoWayAxis) { |
||||
sb.append(y_invert);sb.append(","); |
||||
sb.append(axis_invert); |
||||
} |
||||
return sb.toString(); |
||||
} |
||||
|
||||
public static Axis loadFromString(String s, Controller controller, ControllerModule module) { |
||||
String[] split = s.split(","); |
||||
int i=0; |
||||
Rectangle2D.Double rect = new Rectangle2D.Double(Double.parseDouble(split[i++]), Double.parseDouble(split[i++]), Double.parseDouble(split[i++]), Double.parseDouble(split[i++])); |
||||
boolean twoway = Boolean.parseBoolean(split[i++]); |
||||
if (twoway) { |
||||
return new Axis(rect,controller, |
||||
Integer.parseInt(split[i++]), |
||||
Double.parseDouble(split[i++]), |
||||
Double.parseDouble(split[i++]), |
||||
Integer.parseInt(split[i++]), |
||||
new Color(Integer.parseInt(split[i++]),Integer.parseInt(split[i++]),Integer.parseInt(split[i++]),Integer.parseInt(split[i++])), |
||||
new Color(Integer.parseInt(split[i++]),Integer.parseInt(split[i++]),Integer.parseInt(split[i++]),Integer.parseInt(split[i++])), |
||||
Boolean.parseBoolean(split[i++]), |
||||
module |
||||
); |
||||
} else { |
||||
return new Axis(rect,controller, |
||||
Integer.parseInt(split[i++]), |
||||
Integer.parseInt(split[i++]), |
||||
new Color(Integer.parseInt(split[i++]),Integer.parseInt(split[i++]),Integer.parseInt(split[i++]),Integer.parseInt(split[i++])), |
||||
new Color(Integer.parseInt(split[i++]),Integer.parseInt(split[i++]),Integer.parseInt(split[i++]),Integer.parseInt(split[i++])), |
||||
Boolean.parseBoolean(split[i++]), |
||||
Boolean.parseBoolean(split[i++]), |
||||
Boolean.parseBoolean(split[i++]), |
||||
module |
||||
); |
||||
} |
||||
/*Double.parseDouble(split[i++]), |
||||
Double.parseDouble(split[i++]), |
||||
Double.parseDouble(split[i++]), |
||||
Double.parseDouble(split[i++]), |
||||
controller, |
||||
GrabIdentifierFromString(split[i++],controller), |
||||
Float.parseFloat(split[i++]), |
||||
new Color( |
||||
Integer.parseInt(split[i++]), |
||||
Integer.parseInt(split[i++]), |
||||
Integer.parseInt(split[i++]), |
||||
Integer.parseInt(split[i++]) |
||||
), |
||||
module, |
||||
Boolean.parseBoolean(split[i++]));*/ |
||||
} |
||||
} |
@ -0,0 +1,107 @@ |
||||
package sig.modules.Controller; |
||||
|
||||
import java.awt.Color; |
||||
import java.awt.Graphics; |
||||
import java.awt.geom.Rectangle2D; |
||||
|
||||
import sig.sigIRC; |
||||
import sig.modules.ControllerModule; |
||||
|
||||
public class Button extends Element{ |
||||
int ident; |
||||
byte value; |
||||
Controller parent_controller; |
||||
Color pressed_col; |
||||
ControllerModule parent; |
||||
boolean square; |
||||
|
||||
public Button(Rectangle2D.Double rect, Controller parent_controller, int button_identifier, byte button_val, Color col, ControllerModule module) { |
||||
this(rect.getX(),rect.getY(),rect.getWidth(),rect.getHeight(),parent_controller,button_identifier,button_val,col,module,false); |
||||
} |
||||
|
||||
public Button(Rectangle2D.Double rect, Controller parent_controller, int button_identifier, byte button_val, Color col, ControllerModule module, boolean square) { |
||||
this(rect.getX(),rect.getY(),rect.getWidth(),rect.getHeight(),parent_controller,button_identifier,button_val,col,module,square); |
||||
} |
||||
|
||||
public Button(double pct_x, double pct_y, double pct_width, double pct_height, Controller parent_controller, int button_identifier, byte button_val, Color col, ControllerModule module) { |
||||
this(pct_x,pct_y,pct_width,pct_height,parent_controller,button_identifier,button_val,col,module,false); |
||||
} |
||||
|
||||
public Button(double pct_x, double pct_y, double pct_width, double pct_height, Controller parent_controller, int button_identifier, byte button_val, Color col, ControllerModule module, boolean square) { |
||||
this.pct_x = pct_x; |
||||
this.pct_y = pct_y; |
||||
this.pct_width=pct_width; |
||||
this.pct_height=pct_height; |
||||
this.parent_controller=parent_controller; |
||||
this.ident = button_identifier; |
||||
this.pressed_col=col; |
||||
this.parent = module; |
||||
this.square = square; |
||||
this.value = button_val; |
||||
module.setStoredRectangle(new Rectangle2D.Double(pct_x, pct_y, pct_width, pct_height)); |
||||
} |
||||
|
||||
public Color getSelectionColor() { |
||||
return pressed_col; |
||||
} |
||||
|
||||
public void draw(Graphics g) { |
||||
if (parent_controller.getButtonValue(ident)==value) { |
||||
Color col_identity = g.getColor(); |
||||
g.setColor(pressed_col); |
||||
if (square) { |
||||
g.fillRect((int)(parent.getPosition().getX() |
||||
+parent.getControllerImage().getWidth(sigIRC.panel)*pct_x) |
||||
,(int)(parent.getPosition().getY() |
||||
+parent.getControllerImage().getHeight(sigIRC.panel)*pct_y) |
||||
,(int)(parent.getControllerImage().getWidth(sigIRC.panel)*pct_width), |
||||
(int)(parent.getControllerImage().getHeight(sigIRC.panel)*pct_height)); |
||||
} else { |
||||
g.fillOval((int)(parent.getPosition().getX() |
||||
+parent.getControllerImage().getWidth(sigIRC.panel)*pct_x) |
||||
,(int)(parent.getPosition().getY() |
||||
+parent.getControllerImage().getHeight(sigIRC.panel)*pct_y) |
||||
,(int)(parent.getControllerImage().getWidth(sigIRC.panel)*pct_width), |
||||
(int)(parent.getControllerImage().getHeight(sigIRC.panel)*pct_height)); |
||||
} |
||||
g.setColor(col_identity); |
||||
} |
||||
} |
||||
|
||||
public String getSaveString() { |
||||
StringBuilder sb = new StringBuilder(); |
||||
sb.append(pct_x);sb.append(","); |
||||
sb.append(pct_y);sb.append(","); |
||||
sb.append(pct_width);sb.append(","); |
||||
sb.append(pct_height);sb.append(","); |
||||
sb.append(ident);sb.append(","); |
||||
sb.append(value);sb.append(","); |
||||
sb.append(pressed_col.getRed());sb.append(","); |
||||
sb.append(pressed_col.getGreen());sb.append(","); |
||||
sb.append(pressed_col.getBlue());sb.append(","); |
||||
sb.append(pressed_col.getAlpha());sb.append(","); |
||||
sb.append(square); |
||||
return sb.toString(); |
||||
} |
||||
|
||||
public static Button loadFromString(String s, Controller controller, ControllerModule module) { |
||||
String[] split = s.split(","); |
||||
int i=0; |
||||
return new Button( |
||||
Double.parseDouble(split[i++]), |
||||
Double.parseDouble(split[i++]), |
||||
Double.parseDouble(split[i++]), |
||||
Double.parseDouble(split[i++]), |
||||
controller, |
||||
Integer.parseInt(split[i++]), |
||||
Byte.parseByte(split[i++]), |
||||
new Color( |
||||
Integer.parseInt(split[i++]), |
||||
Integer.parseInt(split[i++]), |
||||
Integer.parseInt(split[i++]), |
||||
Integer.parseInt(split[i++]) |
||||
), |
||||
module, |
||||
Boolean.parseBoolean(split[i++])); |
||||
} |
||||
} |
@ -0,0 +1,58 @@ |
||||
package sig.modules.Controller; |
||||
|
||||
import java.awt.Color; |
||||
import java.awt.Graphics; |
||||
import java.awt.Rectangle; |
||||
import java.awt.event.MouseEvent; |
||||
|
||||
import sig.Module; |
||||
import sig.sigIRC; |
||||
import sig.modules.ControllerModule; |
||||
import sig.utils.DrawUtils; |
||||
import sig.utils.TextUtils; |
||||
|
||||
public class ClickableButton { |
||||
protected int x,y,width,height; |
||||
protected String label; |
||||
protected ControllerModule module; |
||||
|
||||
public ClickableButton(Rectangle position, String button_label) { |
||||
this(position,button_label,null); |
||||
} |
||||
|
||||
public ClickableButton(Rectangle position, String button_label, ControllerModule parent_module) { |
||||
this.x = (int)position.getX(); |
||||
this.y = (int)position.getY(); |
||||
this.width = (int)position.getWidth(); |
||||
this.height = (int)position.getHeight(); |
||||
this.label=button_label; |
||||
this.module = parent_module; |
||||
} |
||||
|
||||
public void onClickEvent(MouseEvent ev) { |
||||
/*if (mouseInsideBounds(ev)) { |
||||
//System.out.println("Click performed!");
|
||||
}*/ |
||||
} |
||||
|
||||
public void setButtonLabel(String text) { |
||||
this.label = text; |
||||
} |
||||
|
||||
public boolean mouseInsideBounds(MouseEvent ev) { |
||||
return ev.getX()>=module.getPosition().getX()+x && ev.getX()<=module.getPosition().getX()+x+width && |
||||
ev.getY()>=module.getPosition().getY()+y && ev.getY()<=module.getPosition().getY()+y+height; |
||||
} |
||||
|
||||
public void draw(Graphics g) { |
||||
Color color_identity = g.getColor(); |
||||
g.setColor(Color.WHITE); |
||||
g.drawRect((int)module.getPosition().getX()+x, |
||||
(int)module.getPosition().getY()+y, width, height); |
||||
g.setColor(Color.BLACK); |
||||
g.fillRect((int)module.getPosition().getX()+x+1, |
||||
(int)module.getPosition().getY()+y+1, width-1, height-1); |
||||
DrawUtils.drawTextFont(g, sigIRC.panel.userFont, module.getPosition().getX()+x-TextUtils.calculateStringBoundsFont(label, sigIRC.panel.userFont).getWidth()/2+width/2, module.getPosition().getY()+y+height-1, Color.WHITE, label); |
||||
g.setColor(color_identity); |
||||
} |
||||
} |
@ -0,0 +1,25 @@ |
||||
package sig.modules.Controller; |
||||
|
||||
public class Component { |
||||
|
||||
public boolean isAnalog() { |
||||
// TODO Auto-generated method stub
|
||||
return false; |
||||
} |
||||
|
||||
public float getPollData() { |
||||
// TODO Auto-generated method stub
|
||||
return 0; |
||||
} |
||||
|
||||
public Identifier getIdentifier() { |
||||
// TODO Auto-generated method stub
|
||||
return null; |
||||
} |
||||
|
||||
public String getName() { |
||||
// TODO Auto-generated method stub
|
||||
return null; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,637 @@ |
||||
package sig.modules.Controller; |
||||
|
||||
import java.awt.BorderLayout; |
||||
import java.awt.Checkbox; |
||||
import java.awt.Color; |
||||
import java.awt.Container; |
||||
import java.awt.Dimension; |
||||
import java.awt.Graphics; |
||||
import java.awt.LayoutManager; |
||||
import java.awt.event.ActionEvent; |
||||
import java.awt.event.ActionListener; |
||||
import java.awt.event.WindowEvent; |
||||
import java.awt.event.WindowListener; |
||||
import java.awt.geom.Rectangle2D; |
||||
import java.io.File; |
||||
import java.io.IOException; |
||||
import java.text.DecimalFormat; |
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
import javax.imageio.ImageIO; |
||||
import javax.swing.BorderFactory; |
||||
import javax.swing.Box; |
||||
import javax.swing.BoxLayout; |
||||
import javax.swing.ButtonGroup; |
||||
import javax.swing.JButton; |
||||
import javax.swing.JCheckBox; |
||||
import javax.swing.JComponent; |
||||
import javax.swing.JDialog; |
||||
import javax.swing.JFrame; |
||||
import javax.swing.JLabel; |
||||
import javax.swing.JLayeredPane; |
||||
import javax.swing.JOptionPane; |
||||
import javax.swing.JPanel; |
||||
import javax.swing.JRadioButton; |
||||
import javax.swing.JTextField; |
||||
import javax.swing.SwingUtilities; |
||||
import javax.swing.border.Border; |
||||
import javax.swing.event.DocumentEvent; |
||||
import javax.swing.event.DocumentListener; |
||||
|
||||
import sig.ColorPanel; |
||||
import sig.sigIRC; |
||||
import sig.modules.ControllerModule; |
||||
import sig.utils.TextUtils; |
||||
|
||||
public class ControlConfigurationWindow extends JFrame implements WindowListener{ |
||||
DialogType dialog; |
||||
List<JPanel> panels = new ArrayList<JPanel>(); |
||||
List<Integer> analog_controller_components = new ArrayList<Integer>(); |
||||
List<JCheckBox> analog_controller_component_labels = new ArrayList<JCheckBox>(); |
||||
ControllerModule module; |
||||
DecimalFormat df = new DecimalFormat("0.000"); |
||||
PreviewPanel previewpanel; |
||||
JRadioButton two_axis_button; |
||||
Container twowayAxis_adjustContainer; |
||||
Container twowayAxis_adjustOrientationContainer; |
||||
LinkedTextField twowayAxis_range1,twowayAxis_range2; |
||||
Color axis_background_col = Color.BLACK; |
||||
Color axis_indicator_col = Color.WHITE; |
||||
int axis_width=32,axis_height=32; |
||||
JButton backgroundColor,indicatorColor; |
||||
boolean x_invert,y_invert,axis_invert; |
||||
public static Color lastpicked_back_col = Color.BLACK; |
||||
public static Color lastpicked_indicator_col = Color.WHITE; |
||||
int orientation=0; //0=Left-to-Right, 1=Right-to-Left, 2=Bottom-to-Top, 3=Top-to-Bottom
|
||||
JCheckBox width_invert,height_invert; |
||||
java.awt.Component extra_space; |
||||
ActionListener checkboxListener = new ActionListener(){ |
||||
@Override |
||||
public void actionPerformed(ActionEvent ev) { |
||||
int checkedamt=0; |
||||
for (JCheckBox cb : analog_controller_component_labels) { |
||||
checkedamt+=(cb.isSelected())?1:0; |
||||
} |
||||
if (previewpanel.twoAxis && checkedamt>1) { |
||||
UncheckPreviouslyCheckedbox(ev); |
||||
} else |
||||
if (!previewpanel.twoAxis && checkedamt>2) { |
||||
UncheckPreviouslyCheckedbox(ev); |
||||
} |
||||
} |
||||
|
||||
private void UncheckPreviouslyCheckedbox(ActionEvent ev) { |
||||
for (int i=0;i<analog_controller_components.size();i++) { |
||||
if (Integer.toString(analog_controller_components.get(i)).equals(ev.getActionCommand())) { |
||||
analog_controller_component_labels.get(i).setSelected(false); |
||||
} |
||||
} |
||||
} |
||||
}; |
||||
ActionListener axisListener = new ActionListener(){ |
||||
|
||||
@Override |
||||
public void actionPerformed(ActionEvent ev) { |
||||
switch (ev.getActionCommand()) { |
||||
case "four":{ |
||||
previewpanel.setAxis(false); |
||||
twowayAxis_adjustContainer.setVisible(false); |
||||
twowayAxis_adjustOrientationContainer.setVisible(false); |
||||
height_invert.setVisible(true); |
||||
}break; |
||||
case "two":{ |
||||
previewpanel.setAxis(true); |
||||
boolean firstBox=false; |
||||
for (int i=0;i<analog_controller_components.size();i++) { |
||||
if (analog_controller_component_labels.get(i).isSelected()) { |
||||
if (!firstBox) { |
||||
firstBox=true; |
||||
} else { |
||||
analog_controller_component_labels.get(i).setSelected(false); |
||||
} |
||||
} |
||||
} |
||||
twowayAxis_adjustContainer.setVisible(true); |
||||
twowayAxis_adjustOrientationContainer.setVisible(true); |
||||
height_invert.setVisible(false); |
||||
}break; |
||||
} |
||||
extra_space.setVisible(two_axis_button.isSelected()); |
||||
} |
||||
}; |
||||
ActionListener backgroundColorListener = new ActionListener(){ |
||||
@Override |
||||
public void actionPerformed(ActionEvent e) { |
||||
Color selectedcol = sigIRC.colorpanel.getBackgroundColor(lastpicked_back_col); |
||||
if (selectedcol!=null) { |
||||
lastpicked_back_col = selectedcol; |
||||
axis_background_col = selectedcol; |
||||
backgroundColor.setBackground(axis_background_col); |
||||
} |
||||
} |
||||
}; |
||||
ActionListener indicatorColorListener = new ActionListener(){ |
||||
@Override |
||||
public void actionPerformed(ActionEvent e) { |
||||
Color selectedcol = sigIRC.colorpanel.getBackgroundColor(lastpicked_indicator_col); |
||||
if (selectedcol!=null) { |
||||
lastpicked_indicator_col = selectedcol; |
||||
axis_indicator_col = selectedcol; |
||||
indicatorColor.setBackground(axis_indicator_col); |
||||
} |
||||
} |
||||
}; |
||||
ActionListener twoWayAxis_OrientationListener = new ActionListener(){ |
||||
@Override |
||||
public void actionPerformed(ActionEvent e) { |
||||
orientation=Integer.parseInt(e.getActionCommand()); |
||||
} |
||||
}; |
||||
ActionListener createbuttonListener = new ActionListener(){ |
||||
@Override |
||||
public void actionPerformed(ActionEvent ev) { |
||||
DataValidationReason err_check = DataIsValid(); |
||||
if (err_check == DataValidationReason.GOOD) { |
||||
Axis a = ConstructTemporaryAxis(); |
||||
module.setTemporaryAxis(a); |
||||
module.setMode(EditMode.DRAGAXISSELECTION); |
||||
//module.setMouseWaitTimer(4);
|
||||
module.getConfigurationWindow().dispatchEvent(new WindowEvent(module.getConfigurationWindow(),WindowEvent.WINDOW_CLOSING)); |
||||
//module.getConfigurationWindow().setVisible(false);
|
||||
//module.getConfigurationWindow().dispose();
|
||||
} else { |
||||
DisplayError(err_check); |
||||
} |
||||
} |
||||
|
||||
private void DisplayError(DataValidationReason err_check) { |
||||
switch (err_check) { |
||||
case AXIS_MISSING: |
||||
JOptionPane.showMessageDialog(module.getConfigurationWindow(), "You did not select the correct number of axes to make this axis control!", "Error", JOptionPane.WARNING_MESSAGE); |
||||
break; |
||||
case INVALID_RANGE_SIZE: |
||||
JOptionPane.showMessageDialog(module.getConfigurationWindow(), "You did not specify valid range numbers for your axis. (Usually it's between -1.0 and 1.0. Make sure the box is not red.)", "Error", JOptionPane.WARNING_MESSAGE); |
||||
break; |
||||
} |
||||
} |
||||
|
||||
private DataValidationReason DataIsValid() { |
||||
if ((!TextUtils.isNumeric(twowayAxis_range1.getTextField().getText()) || |
||||
!TextUtils.isNumeric(twowayAxis_range2.getTextField().getText())) && |
||||
two_axis_button.isSelected()) { |
||||
return DataValidationReason.INVALID_RANGE_SIZE; |
||||
} else |
||||
{ |
||||
int numb_checked = 0; |
||||
int requirement = (two_axis_button.isSelected())?1:2; |
||||
for (JCheckBox cb : analog_controller_component_labels) { |
||||
if (cb.isSelected()) { |
||||
numb_checked++; |
||||
} |
||||
} |
||||
if (numb_checked!=requirement) { |
||||
return DataValidationReason.AXIS_MISSING; |
||||
} |
||||
} |
||||
return DataValidationReason.GOOD; |
||||
} |
||||
}; |
||||
ActionListener invertListener = new ActionListener(){ |
||||
@Override |
||||
public void actionPerformed(ActionEvent ev) { |
||||
if (ev.getActionCommand().equals("x")) { |
||||
x_invert=width_invert.isSelected(); |
||||
} else { |
||||
y_invert=height_invert.isSelected(); |
||||
} |
||||
} |
||||
}; |
||||
ActionListener addButtonListener = new ActionListener(){ |
||||
@Override |
||||
public void actionPerformed(ActionEvent ev) { |
||||
switch (ev.getActionCommand()) { |
||||
case "add_button":{ |
||||
module.setMode(EditMode.DRAGSELECTION); |
||||
//System.out.println("Called Drag Selection mode.");
|
||||
sigIRC.panel.grabFocus(); |
||||
module.getConfigurationWindow().dispatchEvent(new WindowEvent(module.getConfigurationWindow(),WindowEvent.WINDOW_CLOSING)); |
||||
}break; |
||||
case "add_similar":{ |
||||
if (module.getStoredRectangle()!=null) { |
||||
module.setMode(EditMode.POSITIONSELECTION); |
||||
sigIRC.panel.grabFocus(); |
||||
module.getConfigurationWindow().dispatchEvent(new WindowEvent(module.getConfigurationWindow(),WindowEvent.WINDOW_CLOSING)); |
||||
} else { |
||||
new JDialog(module.getConfigurationWindow(),"Please create a new button first."); |
||||
} |
||||
}break; |
||||
case "add_axis":{ |
||||
new ControlConfigurationWindow(DialogType.BUTTON_AXIS_SELECTION,module); |
||||
}break; |
||||
} |
||||
} |
||||
}; |
||||
|
||||
public void setDialogType(DialogType type) { |
||||
this.dialog=type; |
||||
} |
||||
|
||||
public ControlConfigurationWindow(DialogType type, ControllerModule parent_module) { |
||||
this.setVisible(true); |
||||
this.module = parent_module; |
||||
if (module.getConfigurationWindow()!=null) { |
||||
module.getConfigurationWindow().dispatchEvent(new WindowEvent(module.getConfigurationWindow(),WindowEvent.WINDOW_CLOSING)); |
||||
module.setConfigureWindow(null); |
||||
} |
||||
this.module.setConfigureWindow(this); |
||||
this.dialog = type; |
||||
|
||||
JTextField twowayAxis_range1 = new JTextField("-1.0",2); |
||||
JTextField twowayAxis_range2 = new JTextField("1.0",2); |
||||
this.twowayAxis_range1 = new LinkedTextField(twowayAxis_range1); |
||||
this.twowayAxis_range2 = new LinkedTextField(twowayAxis_range2); |
||||
this.setTitle("Axis Configuration Window"); |
||||
this.setIconImage(sigIRC.programIcon); |
||||
|
||||
switch (dialog) { |
||||
case AXIS_OPTIONS: |
||||
|
||||
break; |
||||
case BUTTON_AXIS_SELECTION: |
||||
JPanel container = new JPanel(); |
||||
JPanel axisPanel = new JPanel(); |
||||
ButtonGroup axisSelection = new ButtonGroup(); |
||||
axisPanel.setLayout(new BoxLayout(axisPanel,BoxLayout.LINE_AXIS)); |
||||
JPanel selectionFrame = new JPanel(); |
||||
selectionFrame.setLayout(new BoxLayout(selectionFrame,BoxLayout.LINE_AXIS)); |
||||
JPanel selectionPanel1 = new JPanel(){ |
||||
public void paintComponent(Graphics g) { |
||||
super.paintComponent(g); |
||||
try { |
||||
g.drawImage(ImageIO.read(new File(ControllerModule.CONTROLLERPATH+"4-way_axis.png")), 0, 0, this); |
||||
} catch (IOException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
}; |
||||
JPanel selectionPanel2 = new JPanel(){ |
||||
public void paintComponent(Graphics g) { |
||||
super.paintComponent(g); |
||||
try { |
||||
g.drawImage(ImageIO.read(new File(ControllerModule.CONTROLLERPATH+"2-way_axis.png")), 0, 0, this); |
||||
} catch (IOException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
}; |
||||
//selectionPanel.setLayout(new BoxLayout(selectionPanel,BoxLayout.LINE_AXIS));
|
||||
selectionFrame.add(selectionPanel1); |
||||
JRadioButton four_axis_button = new JRadioButton("4-way Axis",true); |
||||
four_axis_button.setActionCommand("four"); |
||||
four_axis_button.addActionListener(axisListener); |
||||
selectionFrame.add(selectionPanel2); |
||||
two_axis_button = new JRadioButton("2-way Axis"); |
||||
two_axis_button.setActionCommand("two"); |
||||
two_axis_button.addActionListener(axisListener); |
||||
axisSelection.add(four_axis_button); |
||||
axisSelection.add(two_axis_button); |
||||
selectionPanel1.add(four_axis_button); |
||||
selectionPanel2.add(two_axis_button); |
||||
selectionPanel1.setBackground(new Color(0,0,255,96)); |
||||
selectionPanel2.setBackground(new Color(0,0,255,96)); |
||||
int counter=0; |
||||
for (Controller c : module.getControllers()) { |
||||
for (int i=0;i<c.getAxes().length;i++) { |
||||
float axis = c.getAxisValue(i); |
||||
analog_controller_components.add(i); |
||||
JCheckBox component_checkbox = new JCheckBox(GetComponentValue(i),false); |
||||
component_checkbox.setActionCommand(Integer.toString(i)); |
||||
component_checkbox.addActionListener(checkboxListener); |
||||
analog_controller_component_labels.add(component_checkbox); |
||||
axisPanel.add(component_checkbox); |
||||
counter=Math.floorMod(counter+1, 5); |
||||
if (counter==0) { |
||||
panels.add(axisPanel); |
||||
axisPanel = new JPanel(); |
||||
axisPanel.setLayout(new BoxLayout(axisPanel,BoxLayout.LINE_AXIS)); |
||||
} |
||||
} |
||||
} |
||||
for (JPanel panel : panels) { |
||||
container.add(panel); |
||||
} |
||||
container.add(axisPanel); |
||||
container.add(selectionFrame); |
||||
|
||||
JComponent previewLabelPanel = new JPanel(); |
||||
twowayAxis_adjustContainer = new Container(); |
||||
JPanel twowayAxis_adjustPanel1 = new JPanel(); |
||||
JLabel twowayAxis_fromLabel = new JLabel("From"); |
||||
JLabel twowayAxis_toLabel = new JLabel("to"); |
||||
JPanel twowayAxis_adjustPanel2 = new JPanel(); |
||||
twowayAxis_adjustContainer.setLayout(new BoxLayout(twowayAxis_adjustContainer,BoxLayout.PAGE_AXIS)); |
||||
twowayAxis_adjustPanel2.setLayout(new BoxLayout(twowayAxis_adjustPanel2,BoxLayout.LINE_AXIS)); |
||||
JLabel twowayAxis_label = new JLabel("Axis Range:",JLabel.LEFT); |
||||
|
||||
twowayAxis_range1.getDocument().addDocumentListener(this.twowayAxis_range1); |
||||
twowayAxis_range2.getDocument().addDocumentListener(this.twowayAxis_range2); |
||||
|
||||
twowayAxis_adjustPanel1.add(twowayAxis_label); |
||||
twowayAxis_adjustPanel2.add(twowayAxis_fromLabel); |
||||
twowayAxis_adjustPanel2.add(twowayAxis_range1); |
||||
twowayAxis_adjustPanel2.add(twowayAxis_toLabel); |
||||
twowayAxis_adjustPanel2.add(twowayAxis_range2); |
||||
|
||||
twowayAxis_adjustContainer.add(twowayAxis_adjustPanel1); |
||||
twowayAxis_adjustContainer.add(twowayAxis_adjustPanel2); |
||||
|
||||
JLabel previewLabel = new JLabel("Axis Preview: "); |
||||
previewLabel.setVerticalAlignment(JLabel.TOP); |
||||
previewLabel.setHorizontalAlignment(JLabel.RIGHT); |
||||
previewLabelPanel.setPreferredSize(new Dimension(120,24)); |
||||
previewpanel = new PreviewPanel(); |
||||
previewpanel.setWindow(this); |
||||
previewpanel.setPreferredSize(new Dimension(32,32)); |
||||
//Border previewBorder = BorderFactory.createEmptyBorder(axis_width, axis_height, axis_width, axis_height);
|
||||
//previewLabelPanel.setBorder(BorderFactory.createTitledBorder("Axis Preview"));
|
||||
//previewpanel.add(previewLabel);
|
||||
|
||||
if (!two_axis_button.isSelected()) { |
||||
twowayAxis_adjustContainer.setVisible(false); |
||||
} |
||||
|
||||
Container sizePanel = new Container(); |
||||
sizePanel.setLayout(new BoxLayout(sizePanel,BoxLayout.PAGE_AXIS)); |
||||
JPanel widthPanel = new JPanel(); |
||||
widthPanel.setLayout(new BoxLayout(widthPanel,BoxLayout.LINE_AXIS)); |
||||
widthPanel.setPreferredSize(new Dimension(164,20)); |
||||
JPanel heightPanel = new JPanel(); |
||||
heightPanel.setPreferredSize(new Dimension(164,20)); |
||||
heightPanel.setLayout(new BoxLayout(heightPanel,BoxLayout.LINE_AXIS)); |
||||
JLabel widthLabel = new JLabel("Width: "); |
||||
JTextField width_field = new JTextField("32",3); |
||||
width_field.setPreferredSize(new Dimension(32,20)); |
||||
width_field.setMaximumSize(new Dimension(32,20)); |
||||
width_invert = new JCheckBox("Inverted"); |
||||
width_invert.addActionListener(invertListener); |
||||
width_invert.setActionCommand("x"); |
||||
ResizeTextField width_field_listener = new ResizeTextField(width_field,this,SizeType.WIDTH); |
||||
width_field.getDocument().addDocumentListener(width_field_listener); |
||||
JLabel heightLabel = new JLabel("Height: "); |
||||
JTextField height_field = new JTextField("32",3); |
||||
height_field.setPreferredSize(new Dimension(32,20)); |
||||
height_field.setMaximumSize(new Dimension(32,20)); |
||||
height_invert = new JCheckBox("Inverted"); |
||||
height_invert.addActionListener(invertListener); |
||||
extra_space = Box.createRigidArea(height_invert.getMaximumSize()); |
||||
extra_space.setVisible(two_axis_button.isSelected()); |
||||
width_invert.setActionCommand("y"); |
||||
ResizeTextField height_field_listener = new ResizeTextField(height_field,this,SizeType.HEIGHT); |
||||
height_field.getDocument().addDocumentListener(height_field_listener); |
||||
|
||||
widthPanel.add(widthLabel); |
||||
widthPanel.add(width_field); |
||||
widthPanel.add(width_invert); |
||||
heightPanel.add(heightLabel); |
||||
heightPanel.add(height_field); |
||||
heightPanel.add(height_invert); |
||||
heightPanel.add(extra_space); |
||||
|
||||
sizePanel.add(widthPanel); |
||||
sizePanel.add(Box.createRigidArea(new Dimension(0,8))); |
||||
sizePanel.add(heightPanel); |
||||
sizePanel.setPreferredSize(new Dimension(164,64)); |
||||
|
||||
ButtonGroup twoWayAxisOrientationGroup = new ButtonGroup(); |
||||
JRadioButton twoWayAxis_LeftToRight = new JRadioButton("Left-to-Right",true); |
||||
twoWayAxis_LeftToRight.setActionCommand("0"); |
||||
twoWayAxis_LeftToRight.addActionListener(twoWayAxis_OrientationListener); |
||||
JRadioButton twoWayAxis_RightToLeft = new JRadioButton("Right-to-Left"); |
||||
twoWayAxis_RightToLeft.setActionCommand("1"); |
||||
twoWayAxis_RightToLeft.addActionListener(twoWayAxis_OrientationListener); |
||||
JRadioButton twoWayAxis_BottomToTop = new JRadioButton("Bottom-to-Top"); |
||||
twoWayAxis_BottomToTop.setActionCommand("2"); |
||||
twoWayAxis_BottomToTop.addActionListener(twoWayAxis_OrientationListener); |
||||
JRadioButton twoWayAxis_TopToBottom = new JRadioButton("Top-to-Bottom"); |
||||
twoWayAxis_TopToBottom.setActionCommand("3"); |
||||
twoWayAxis_TopToBottom.addActionListener(twoWayAxis_OrientationListener); |
||||
twoWayAxisOrientationGroup.add(twoWayAxis_LeftToRight); |
||||
twoWayAxisOrientationGroup.add(twoWayAxis_RightToLeft); |
||||
twoWayAxisOrientationGroup.add(twoWayAxis_BottomToTop); |
||||
twoWayAxisOrientationGroup.add(twoWayAxis_TopToBottom); |
||||
|
||||
twowayAxis_adjustOrientationContainer = new Container(); |
||||
twowayAxis_adjustOrientationContainer.setLayout(new BoxLayout(twowayAxis_adjustOrientationContainer,BoxLayout.LINE_AXIS)); |
||||
|
||||
twowayAxis_adjustOrientationContainer.add(twoWayAxis_LeftToRight); |
||||
twowayAxis_adjustOrientationContainer.add(twoWayAxis_RightToLeft); |
||||
twowayAxis_adjustOrientationContainer.add(twoWayAxis_BottomToTop); |
||||
twowayAxis_adjustOrientationContainer.add(twoWayAxis_TopToBottom); |
||||
|
||||
if (!two_axis_button.isSelected()) { |
||||
twowayAxis_adjustOrientationContainer.setVisible(false); |
||||
} |
||||
|
||||
Container colorPickerContainer = new Container(); |
||||
colorPickerContainer.setLayout(new BoxLayout(colorPickerContainer,BoxLayout.LINE_AXIS)); |
||||
colorPickerContainer.setPreferredSize(new Dimension(640,64)); |
||||
backgroundColor = new JButton(""); |
||||
indicatorColor = new JButton(""); |
||||
backgroundColor.setBackground(Color.BLACK); |
||||
backgroundColor.setPreferredSize(new Dimension(32,32)); |
||||
backgroundColor.addActionListener(backgroundColorListener); |
||||
indicatorColor.setBackground(Color.WHITE); |
||||
indicatorColor.setPreferredSize(new Dimension(32,32)); |
||||
indicatorColor.addActionListener(indicatorColorListener); |
||||
|
||||
JPanel backgroundColorPanel = new JPanel(); |
||||
backgroundColorPanel.setPreferredSize(new Dimension(32,32)); |
||||
backgroundColorPanel.setBorder(BorderFactory.createTitledBorder("Background Color")); |
||||
JPanel indicatorColorPanel = new JPanel(); |
||||
indicatorColorPanel.setPreferredSize(new Dimension(32,32)); |
||||
indicatorColorPanel.setBorder(BorderFactory.createTitledBorder("Indicator Color")); |
||||
backgroundColorPanel.add(backgroundColor); |
||||
indicatorColorPanel.add(indicatorColor); |
||||
|
||||
colorPickerContainer.add(Box.createHorizontalGlue()); |
||||
colorPickerContainer.add(backgroundColorPanel); |
||||
colorPickerContainer.add(indicatorColorPanel); |
||||
colorPickerContainer.add(Box.createHorizontalGlue()); |
||||
|
||||
JPanel submitPanel = new JPanel(); |
||||
submitPanel.setPreferredSize(new Dimension(640,32)); |
||||
JButton createButton = new JButton("Create Axis"); |
||||
submitPanel.add(createButton); |
||||
createButton.addActionListener(createbuttonListener); |
||||
createButton.setMaximumSize(new Dimension(64,24)); |
||||
|
||||
previewLabelPanel.add(twowayAxis_adjustContainer); |
||||
previewLabelPanel.add(Box.createRigidArea(new Dimension(10,1))); |
||||
previewLabelPanel.add(previewLabel); |
||||
previewLabelPanel.add(previewpanel); |
||||
previewLabelPanel.add(Box.createHorizontalBox()); |
||||
previewLabelPanel.add(sizePanel); |
||||
previewLabelPanel.add(twowayAxis_adjustOrientationContainer); |
||||
previewLabelPanel.add(colorPickerContainer); |
||||
previewLabelPanel.add(submitPanel); |
||||
//previewLabelPanel.setBackground(Color.BLUE);
|
||||
|
||||
|
||||
container.add(previewLabelPanel); |
||||
container.setLayout(new BoxLayout(container,BoxLayout.PAGE_AXIS)); |
||||
|
||||
this.setMinimumSize(new Dimension(640,548)); |
||||
this.add(container); |
||||
//this.pack();
|
||||
this.repaint(); |
||||
break; |
||||
case BUTTON_OPTIONS: |
||||
|
||||
break; |
||||
case CREATE_CONTROL: |
||||
container = new JPanel(); |
||||
|
||||
JButton newbutton = new JButton("Add new button"); |
||||
newbutton.setActionCommand("add_button"); |
||||
newbutton.addActionListener(addButtonListener); |
||||
newbutton.setMinimumSize(new Dimension(320,24)); |
||||
JButton copybutton = new JButton("Add similar button"); |
||||
copybutton.setActionCommand("add_similar"); |
||||
copybutton.addActionListener(addButtonListener); |
||||
copybutton.setMinimumSize(new Dimension(320,24)); |
||||
copybutton.setToolTipText("Adds a button with the same size as the previously created button, but lets you specify a new gamepad input and new color."); |
||||
JButton newaxis = new JButton("Add new axis"); |
||||
newaxis.setActionCommand("add_axis"); |
||||
newaxis.addActionListener(addButtonListener); |
||||
newaxis.setMinimumSize(new Dimension(320,24)); |
||||
|
||||
container.add(newbutton); |
||||
container.add(copybutton); |
||||
container.add(newaxis); |
||||
|
||||
//container.setLayout(new BorderLayout());
|
||||
this.setMinimumSize(new Dimension(320,120)); |
||||
this.setPreferredSize(new Dimension(320,120)); |
||||
this.add(container); |
||||
this.pack(); |
||||
//this.pack();
|
||||
this.repaint(); |
||||
break; |
||||
} |
||||
} |
||||
|
||||
private String GetComponentValue(int axis) { |
||||
float val = module.getControllers().get(0).getAxisValue(axis); |
||||
return "Axis "+axis+": "+df.format(val)+" "; |
||||
} |
||||
|
||||
public void run() { |
||||
switch (dialog) { |
||||
case AXIS_OPTIONS: |
||||
break; |
||||
case BUTTON_AXIS_SELECTION: |
||||
for (int i=0;i<analog_controller_components.size();i++) { |
||||
JCheckBox mycheckbox = analog_controller_component_labels.get(i); |
||||
mycheckbox.setText(GetComponentValue(analog_controller_components.get(i))); |
||||
} |
||||
if (previewpanel!=null) { |
||||
previewpanel.repaint(); |
||||
} |
||||
break; |
||||
case BUTTON_OPTIONS: |
||||
break; |
||||
case CREATE_CONTROL: |
||||
break; |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void windowClosing(WindowEvent ev) { |
||||
this.module.setConfigureWindow(null); |
||||
} |
||||
|
||||
@Override |
||||
public void windowActivated(WindowEvent arg0) { |
||||
} |
||||
|
||||
@Override |
||||
public void windowClosed(WindowEvent arg0) { |
||||
} |
||||
|
||||
@Override |
||||
public void windowDeactivated(WindowEvent arg0) { |
||||
} |
||||
|
||||
@Override |
||||
public void windowDeiconified(WindowEvent arg0) { |
||||
} |
||||
|
||||
@Override |
||||
public void windowIconified(WindowEvent arg0) { |
||||
} |
||||
|
||||
@Override |
||||
public void windowOpened(WindowEvent arg0) { |
||||
} |
||||
|
||||
protected Axis ConstructTemporaryAxis() { |
||||
Axis a; |
||||
if (two_axis_button.isSelected()) { |
||||
int ident=-1; |
||||
for (int i=0;i<analog_controller_component_labels.size();i++) { |
||||
if (analog_controller_component_labels.get(i).isSelected()) { |
||||
ident=analog_controller_components.get(i); |
||||
break; |
||||
} |
||||
} |
||||
a = new Axis(new Rectangle2D.Double(), |
||||
module.getControllers().get(0), |
||||
ident, |
||||
Double.parseDouble((!TextUtils.isNumeric(twowayAxis_range1.getTextField().getText())?Double.toString(-1):twowayAxis_range1.getTextField().getText())), |
||||
Double.parseDouble((!TextUtils.isNumeric(twowayAxis_range2.getTextField().getText())?Double.toString(1):twowayAxis_range2.getTextField().getText())), |
||||
orientation, |
||||
axis_background_col, |
||||
axis_indicator_col, |
||||
x_invert, |
||||
module); |
||||
} else { |
||||
List<Integer> ident=new ArrayList<Integer>(); |
||||
ident.add(null); |
||||
ident.add(null); |
||||
int count=0; |
||||
for (int i=0;i<analog_controller_component_labels.size();i++) { |
||||
if (analog_controller_component_labels.get(i).isSelected()) { |
||||
ident.set(count++,analog_controller_components.get(i)); |
||||
} |
||||
} |
||||
a = new Axis(new Rectangle2D.Double(), |
||||
module.getControllers().get(0), |
||||
ident.get(0), |
||||
ident.get(1), |
||||
axis_background_col, |
||||
axis_indicator_col, |
||||
x_invert, |
||||
y_invert, |
||||
axis_invert, |
||||
module); |
||||
} |
||||
return a; |
||||
} |
||||
} |
||||
|
||||
class PreviewPanel extends JPanel{ |
||||
public boolean twoAxis=false; |
||||
ControlConfigurationWindow window; |
||||
public void setWindow(ControlConfigurationWindow window) { |
||||
this.window=window; |
||||
} |
||||
public void setAxis(boolean twoAxis) { |
||||
this.twoAxis=twoAxis; |
||||
} |
||||
public void paintComponent(Graphics g) { |
||||
super.paintComponent(g); |
||||
Axis.GetAxisDisplay(g,window.ConstructTemporaryAxis(),0,0,window.axis_width,window.axis_height); |
||||
Axis.GetAxisIndicatorDisplay(g,window.ConstructTemporaryAxis(),0,0,window.axis_width,window.axis_height); |
||||
} |
||||
} |
@ -0,0 +1,80 @@ |
||||
package sig.modules.Controller; |
||||
|
||||
import java.nio.ByteBuffer; |
||||
import java.nio.FloatBuffer; |
||||
import java.util.Arrays; |
||||
|
||||
import org.lwjgl.glfw.GLFW; |
||||
|
||||
|
||||
public class Controller { |
||||
int identifier; |
||||
float[] axes; |
||||
byte[] buttons; |
||||
|
||||
public Controller(int identifier) { |
||||
this.identifier=identifier; |
||||
FloatBuffer axisBuffer = GLFW.glfwGetJoystickAxes(identifier); |
||||
axes = new float[axisBuffer.limit()]; |
||||
axisBuffer.get(axes); |
||||
ByteBuffer buttonBuffer = GLFW.glfwGetJoystickButtons(identifier); |
||||
buttons = new byte[buttonBuffer.limit()]; |
||||
buttonBuffer.get(buttons); |
||||
} |
||||
|
||||
public String outputAxes() { |
||||
return Arrays.toString(axes); |
||||
} |
||||
|
||||
public String outputButtons() { |
||||
return Arrays.toString(buttons); |
||||
} |
||||
|
||||
public float[] getAxes() { |
||||
return axes; |
||||
} |
||||
|
||||
public byte[] getButtons() { |
||||
return buttons; |
||||
} |
||||
|
||||
public float getAxisValue(int axisNumber) { |
||||
return axes[axisNumber]; |
||||
} |
||||
|
||||
public byte getButtonValue(int buttonNumber) { |
||||
return buttons[buttonNumber]; |
||||
} |
||||
|
||||
@Deprecated |
||||
public Type getType() { |
||||
return null; |
||||
} |
||||
|
||||
@Deprecated |
||||
public String getName() { |
||||
return null; |
||||
} |
||||
|
||||
public void poll() { |
||||
//System.out.println(Glfw.glfwGetJoystickParam(identifier, 1));
|
||||
FloatBuffer axisBuffer = GLFW.glfwGetJoystickAxes(identifier); |
||||
axes = new float[axisBuffer.limit()]; |
||||
axisBuffer.get(axes); |
||||
ByteBuffer buttonBuffer = GLFW.glfwGetJoystickButtons(identifier); |
||||
buttons = new byte[buttonBuffer.limit()]; |
||||
buttonBuffer.get(buttons); |
||||
//System.out.println(outputAxes()+","+outputButtons());
|
||||
} |
||||
|
||||
@Deprecated |
||||
public Component[] getComponents() { |
||||
return new Component[]{}; |
||||
} |
||||
|
||||
@Deprecated |
||||
public Component getComponent(Identifier identifier2) { |
||||
return null; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,7 @@ |
||||
package sig.modules.Controller; |
||||
|
||||
public enum DataValidationReason { |
||||
GOOD, |
||||
INVALID_RANGE_SIZE, |
||||
AXIS_MISSING; |
||||
} |
@ -0,0 +1,8 @@ |
||||
package sig.modules.Controller; |
||||
|
||||
public enum DialogType { |
||||
BUTTON_AXIS_SELECTION, |
||||
AXIS_OPTIONS, |
||||
BUTTON_OPTIONS, |
||||
CREATE_CONTROL |
||||
} |
@ -0,0 +1,12 @@ |
||||
package sig.modules.Controller; |
||||
|
||||
public enum EditMode { |
||||
DRAGSELECTION, //Drag to set size of button.
|
||||
DRAGAXISSELECTION, //Drag to set size of button.
|
||||
SELECTION, //Selects a button for editing
|
||||
DELETESELECTION, //Delete a button.
|
||||
BUTTONSET, //Asks for a controller button to set this button to.
|
||||
COLORSET, |
||||
DEFAULT, |
||||
POSITIONSELECTION; |
||||
} |
@ -0,0 +1,51 @@ |
||||
package sig.modules.Controller; |
||||
|
||||
import java.awt.Color; |
||||
import java.awt.Image; |
||||
import java.awt.geom.Rectangle2D; |
||||
|
||||
import sig.sigIRC; |
||||
import sig.modules.ControllerModule; |
||||
|
||||
public class Element { |
||||
protected double pct_x = 0; |
||||
protected double pct_y = 0; |
||||
protected double pct_width = 0; |
||||
protected double pct_height = 0; |
||||
|
||||
public Rectangle2D.Double getBounds() { |
||||
return new Rectangle2D.Double(pct_x,pct_y,pct_width,pct_height); |
||||
} |
||||
public Rectangle2D.Double getPixelBounds(Image controller_img) { |
||||
return new Rectangle2D.Double(pct_x*controller_img.getWidth(sigIRC.panel),pct_y*controller_img.getHeight(sigIRC.panel),pct_width*controller_img.getWidth(sigIRC.panel),pct_height*controller_img.getHeight(sigIRC.panel)); |
||||
} |
||||
|
||||
public void setBounds(Rectangle2D.Double rect) { |
||||
this.pct_x = rect.getX(); |
||||
this.pct_y = rect.getY(); |
||||
this.pct_width = rect.getWidth(); |
||||
this.pct_height = rect.getHeight(); |
||||
} |
||||
|
||||
public Color getElementColor() { |
||||
if (this instanceof Button) { |
||||
Button b = (Button)this; |
||||
return b.getSelectionColor(); |
||||
} else |
||||
if (this instanceof Axis) { |
||||
Axis a = (Axis)this; |
||||
return a.getSelectionColor(); |
||||
} |
||||
return null; |
||||
} |
||||
public void remove(ControllerModule module) { |
||||
if (this instanceof Button) { |
||||
module.getButtons().remove(this); |
||||
module.SaveButtonData(); |
||||
} else |
||||
if (this instanceof Axis) { |
||||
module.getAxes().remove(this); |
||||
module.SaveAxisData(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,11 @@ |
||||
package sig.modules.Controller; |
||||
|
||||
import java.awt.geom.RectangularShape; |
||||
|
||||
public class Identifier { |
||||
|
||||
public String getName() { |
||||
return null; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,50 @@ |
||||
package sig.modules.Controller; |
||||
|
||||
import java.awt.Color; |
||||
|
||||
import javax.swing.JTextField; |
||||
import javax.swing.event.DocumentEvent; |
||||
import javax.swing.event.DocumentListener; |
||||
|
||||
import sig.utils.TextUtils; |
||||
|
||||
public class LinkedTextField implements DocumentListener{ |
||||
JTextField field; |
||||
public LinkedTextField(JTextField field) { |
||||
this.field=field; |
||||
} |
||||
|
||||
public JTextField getTextField() { |
||||
return field; |
||||
} |
||||
|
||||
public DocumentListener getListener() { |
||||
return this; |
||||
} |
||||
|
||||
@Override |
||||
public void changedUpdate(DocumentEvent e) { |
||||
} |
||||
|
||||
protected boolean fieldIsInvalid() { |
||||
return !TextUtils.isNumeric(field.getText()); |
||||
} |
||||
|
||||
@Override |
||||
public void insertUpdate(DocumentEvent e) { |
||||
ValidateForm(); |
||||
} |
||||
|
||||
protected void ValidateForm() { |
||||
if (fieldIsInvalid()) { |
||||
field.setBackground(Color.RED); |
||||
} else { |
||||
field.setBackground(Color.WHITE); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void removeUpdate(DocumentEvent e) { |
||||
ValidateForm(); |
||||
} |
||||
} |
@ -0,0 +1,79 @@ |
||||
package sig.modules.Controller; |
||||
|
||||
import sig.modules.ControllerModule; |
||||
import sig.utils.FileUtils; |
||||
|
||||
public class RepeatedKey { |
||||
int keycode; |
||||
boolean isKeyPressed; |
||||
Thread schedulerThread; |
||||
Runnable action; |
||||
Element element; |
||||
ControllerModule module; |
||||
boolean held_down=false,repeat=false; |
||||
final static int HOLD_DELAY=500; |
||||
final static int REPEAT_DELAY=100; |
||||
|
||||
public RepeatedKey(int keycode, ControllerModule module, |
||||
Runnable action) { |
||||
this.keycode=keycode; |
||||
this.module=module; |
||||
this.action=action; |
||||
} |
||||
|
||||
public int getKeyCode() { |
||||
return keycode; |
||||
} |
||||
|
||||
public boolean isKeyPressed() { |
||||
return this.isKeyPressed; |
||||
} |
||||
|
||||
public void setHeldStatus(boolean heldDown) { |
||||
this.held_down=heldDown; |
||||
} |
||||
|
||||
public void setRepeatStatus(boolean repeat) { |
||||
this.repeat = repeat; |
||||
} |
||||
|
||||
public void setKeyPressed(boolean isPressed) { |
||||
this.isKeyPressed=isPressed; |
||||
if (!held_down) { |
||||
held_down=true; |
||||
schedulerThread = new Thread() { |
||||
public void run() { |
||||
try { |
||||
Thread.sleep(HOLD_DELAY); |
||||
if (!isKeyPressed()) { |
||||
setHeldStatus(false); |
||||
} else { |
||||
setRepeatStatus(true); |
||||
} |
||||
} catch (InterruptedException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
}; |
||||
} else { |
||||
if (repeat) { |
||||
schedulerThread = new Thread() { |
||||
public void run() { |
||||
try { |
||||
while (repeat) { |
||||
action.run(); |
||||
Thread.sleep(REPEAT_DELAY); |
||||
if (!isKeyPressed()) { |
||||
repeat=false; |
||||
held_down=false; |
||||
} |
||||
} |
||||
} catch (InterruptedException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
}; |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,51 @@ |
||||
package sig.modules.Controller; |
||||
|
||||
import java.awt.Color; |
||||
import java.awt.Dimension; |
||||
|
||||
import javax.swing.JTextField; |
||||
import javax.swing.event.DocumentEvent; |
||||
|
||||
public class ResizeTextField extends LinkedTextField{ |
||||
ControlConfigurationWindow window; |
||||
SizeType type; |
||||
|
||||
public ResizeTextField(JTextField field,ControlConfigurationWindow window,SizeType type) { |
||||
super(field); |
||||
this.window=window; |
||||
this.type=type; |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void insertUpdate(DocumentEvent e) { |
||||
ValidateFormAndResizeComponent(); |
||||
} |
||||
|
||||
@Override |
||||
public void removeUpdate(DocumentEvent e) { |
||||
ValidateFormAndResizeComponent(); |
||||
} |
||||
|
||||
|
||||
private void ValidateFormAndResizeComponent() { |
||||
ValidateForm(); |
||||
ResizeComponent(); |
||||
} |
||||
|
||||
|
||||
private void ResizeComponent() { |
||||
if (!fieldIsInvalid()) { |
||||
switch (type) { |
||||
case HEIGHT: |
||||
window.axis_height=Integer.parseInt(field.getText()); |
||||
break; |
||||
case WIDTH: |
||||
window.axis_width=Integer.parseInt(field.getText()); |
||||
break; |
||||
} |
||||
window.previewpanel.setPreferredSize(new Dimension(window.axis_width,window.axis_height)); |
||||
} |
||||
} |
||||
|
||||
} |
@ -0,0 +1,6 @@ |
||||
package sig.modules.Controller; |
||||
|
||||
public enum SizeType { |
||||
WIDTH, |
||||
HEIGHT |
||||
} |
@ -0,0 +1,5 @@ |
||||
package sig.modules.Controller; |
||||
|
||||
public enum Type { |
||||
GAMEPAD |
||||
} |
@ -0,0 +1,29 @@ |
||||
package sig.modules.Controller.clickablebutton; |
||||
|
||||
import java.awt.Rectangle; |
||||
import java.awt.event.MouseEvent; |
||||
|
||||
import sig.modules.ControllerModule; |
||||
import sig.modules.Controller.ClickableButton; |
||||
import sig.modules.Controller.ControlConfigurationWindow; |
||||
import sig.modules.Controller.DialogType; |
||||
import sig.modules.Controller.EditMode; |
||||
|
||||
public class AddClickableButton extends ClickableButton{ |
||||
|
||||
public AddClickableButton(Rectangle position, String button_label, ControllerModule parent_module) { |
||||
super(position, button_label, parent_module); |
||||
} |
||||
|
||||
public void onClickEvent(MouseEvent ev) { |
||||
super.onClickEvent(ev); |
||||
/*if (mouseInsideBounds(ev)) { |
||||
module.setMode(EditMode.DRAGSELECTION); |
||||
module.resetDragPoints(); |
||||
}*/ |
||||
if (mouseInsideBounds(ev)) { |
||||
new ControlConfigurationWindow(DialogType.CREATE_CONTROL,module); |
||||
module.resetDragPoints(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,24 @@ |
||||
package sig.modules.Controller.clickablebutton; |
||||
|
||||
import java.awt.Rectangle; |
||||
import java.awt.event.MouseEvent; |
||||
|
||||
import sig.modules.ControllerModule; |
||||
import sig.modules.Controller.ClickableButton; |
||||
import sig.modules.Controller.ControlConfigurationWindow; |
||||
import sig.modules.Controller.DialogType; |
||||
import sig.modules.Controller.EditMode; |
||||
|
||||
public class CopyClickableButton extends ClickableButton{ |
||||
|
||||
public CopyClickableButton(Rectangle position, String button_label, ControllerModule parent_module) { |
||||
super(position, button_label, parent_module); |
||||
} |
||||
|
||||
public void onClickEvent(MouseEvent ev) { |
||||
super.onClickEvent(ev); |
||||
if (mouseInsideBounds(ev)) { |
||||
module.resetDragPoints(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,803 @@ |
||||
package sig.modules; |
||||
|
||||
import java.awt.Color; |
||||
import java.awt.Cursor; |
||||
import java.awt.Graphics; |
||||
import java.awt.Image; |
||||
import java.awt.Point; |
||||
import java.awt.Rectangle; |
||||
import java.awt.event.KeyEvent; |
||||
import java.awt.event.MouseEvent; |
||||
import java.awt.event.WindowEvent; |
||||
import java.awt.geom.Rectangle2D; |
||||
import java.io.File; |
||||
import java.io.IOException; |
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
import javax.imageio.ImageIO; |
||||
import javax.swing.JOptionPane; |
||||
|
||||
import org.lwjgl.glfw.GLFW; |
||||
|
||||
import sig.Module; |
||||
import sig.sigIRC; |
||||
import sig.modules.Controller.Axis; |
||||
import sig.modules.Controller.Button; |
||||
import sig.modules.Controller.ClickableButton; |
||||
import sig.modules.Controller.Component; |
||||
import sig.modules.Controller.ControlConfigurationWindow; |
||||
import sig.modules.Controller.Controller; |
||||
import sig.modules.Controller.EditMode; |
||||
import sig.modules.Controller.Element; |
||||
import sig.modules.Controller.Identifier; |
||||
import sig.modules.Controller.RepeatedKey; |
||||
import sig.modules.Controller.Type; |
||||
import sig.modules.Controller.clickablebutton.AddClickableButton; |
||||
import sig.modules.Controller.clickablebutton.CopyClickableButton; |
||||
import sig.utils.DrawUtils; |
||||
import sig.utils.FileUtils; |
||||
|
||||
public class ControllerModule extends Module{ |
||||
public final static String CONTROLLERPATH = sigIRC.BASEDIR+"sigIRC/controller/"; |
||||
List<Controller> controllers = new ArrayList<Controller>(); |
||||
Image controller_img,controller_overlay_img; |
||||
double imgratio = 1; |
||||
List<Button> buttons = new ArrayList<Button>(); |
||||
List<Axis> axes = new ArrayList<Axis>(); |
||||
List<ClickableButton> click_buttons = new ArrayList<ClickableButton>(); |
||||
EditMode MODE = EditMode.DEFAULT; |
||||
String status = ""; |
||||
Point start_drag,end_drag; |
||||
Rectangle2D.Double stored_rect; |
||||
int stored_controller_button; |
||||
float stored_controller_value; |
||||
Color buttoncol; |
||||
Controller controller; |
||||
ControlConfigurationWindow configure_window; |
||||
Axis temporary_axis=null; |
||||
int mouseclickwait_timer=0; |
||||
Element selectedElement; |
||||
boolean dragging=false; |
||||
int resizing_direction=0; |
||||
/*1=North |
||||
3=North-east |
||||
2=East |
||||
6=South-east |
||||
4=South |
||||
12=South-west |
||||
8=West |
||||
9=North-west*/ |
||||
Point resize_refpoint; |
||||
boolean resizing=false; |
||||
double xoffset=0,yoffset=0; |
||||
final static int RESIZE_BORDER = 5; |
||||
final static double MINIMUM_ELEMENT_SIZE=8; |
||||
boolean proportionalResize=false; |
||||
|
||||
public ControllerModule(Rectangle2D bounds, String moduleName) { |
||||
super(bounds, moduleName); |
||||
if (!GLFW.glfwInit()) { |
||||
System.out.println("Failed to initialize GLFW!"); |
||||
} else { |
||||
System.out.println("Successfully initialized GLFW."); |
||||
} |
||||
List<Controller> ca = new ArrayList<Controller>(); |
||||
for (int i=0;i<GLFW.GLFW_JOYSTICK_LAST;i++) { |
||||
//System.out.println("Joystick "+i+": "+GLFW.glfwGetJoystickName(i));
|
||||
if (GLFW.glfwGetJoystickName(i)!=null) { |
||||
Controller c = new Controller(i); |
||||
ca.add(c); |
||||
System.out.println("Recognized "+GLFW.glfwGetJoystickName(i)+": "+c.outputAxes()+","+c.outputButtons()); |
||||
} |
||||
} |
||||
controllers.addAll(ca); |
||||
try { |
||||
controller_img = ImageIO.read(new File(CONTROLLERPATH+"controller_template.png")).getScaledInstance((int)position.getWidth(), -1, 0); |
||||
controller_overlay_img = ImageIO.read(new File(CONTROLLERPATH+"controller_overlay.png")).getScaledInstance((int)position.getWidth(), -1, 0); |
||||
//System.out.println("Size of controller: "+controller_img.getWidth(sigIRC.panel)+","+controller_img.getHeight(sigIRC.panel));
|
||||
} catch (IOException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
//buttons.add(new Button(0.1,0.05,0.1,0.05,controllers.get(0),Identifier.Button._3,Color.RED,this));
|
||||
LoadButtonAndAxisData(); |
||||
click_buttons.add(new AddClickableButton(new Rectangle( |
||||
0,(int)position.getHeight()-21,96,20),"Add Button",this)); |
||||
} |
||||
|
||||
public List<Controller> getControllers() { |
||||
return controllers; |
||||
} |
||||
|
||||
public void resetDragPoints() { |
||||
this.start_drag=null; |
||||
this.end_drag=null; |
||||
} |
||||
|
||||
public void setMouseWaitTimer(int ticks) { |
||||
this.mouseclickwait_timer=ticks; |
||||
} |
||||
|
||||
public Axis getTemporaryAxis() { |
||||
return temporary_axis; |
||||
} |
||||
|
||||
public void setTemporaryAxis(Axis a) { |
||||
this.temporary_axis=a; |
||||
} |
||||
|
||||
public void setDragPoints(Point startpoint,Point endpoint) { |
||||
this.start_drag=startpoint; |
||||
this.end_drag=endpoint; |
||||
} |
||||
|
||||
public ControlConfigurationWindow getConfigurationWindow() { |
||||
return configure_window; |
||||
} |
||||
|
||||
public EditMode getMode() { |
||||
return MODE; |
||||
} |
||||
|
||||
public void setMode(EditMode mode) { |
||||
MODE = mode; |
||||
} |
||||
|
||||
public void setStoredRectangle(Rectangle2D.Double rect) { |
||||
this.stored_rect=rect; |
||||
} |
||||
|
||||
public Rectangle2D.Double getStoredRectangle() { |
||||
return stored_rect; |
||||
} |
||||
|
||||
public List<Button> getButtons() { |
||||
return buttons; |
||||
} |
||||
public List<Axis> getAxes() { |
||||
return axes; |
||||
} |
||||
|
||||
public void ApplyConfigWindowProperties() { |
||||
sigIRC.controllermodule_X=(int)position.getX(); |
||||
sigIRC.controllermodule_Y=(int)position.getY(); |
||||
sigIRC.config.setInteger("CONTROLLER_module_X", sigIRC.controllermodule_X); |
||||
sigIRC.config.setInteger("CONTROLLER_module_Y", sigIRC.controllermodule_Y); |
||||
} |
||||
|
||||
public void mousePressed(MouseEvent ev) { |
||||
if (dragging || resizing) { |
||||
return; |
||||
} |
||||
if (mouseInsideBounds(ev)) { |
||||
Point mouse_position = new Point((int)(ev.getX()-getPosition().getX()),(int)(ev.getY()-getPosition().getY())); |
||||
switch (MODE) { |
||||
case DRAGSELECTION: |
||||
case DRAGAXISSELECTION:{ |
||||
if (start_drag==null) { |
||||
start_drag = mouse_position; |
||||
} |
||||
}break; |
||||
case DEFAULT:{ |
||||
for (ClickableButton cb : click_buttons) { |
||||
cb.onClickEvent(ev); |
||||
} |
||||
if (selectedElement!=null && resizing_direction!=0 && !resizing && extendBoundaries(selectedElement.getPixelBounds(controller_img),3).contains(mouse_position)) { |
||||
resizing=true; |
||||
resize_refpoint=mouse_position; |
||||
} else |
||||
if (selectedElement!=null && !resizing && selectedElement.getPixelBounds(controller_img).contains(mouse_position)) { |
||||
dragging=true; |
||||
xoffset = selectedElement.getPixelBounds(controller_img).getX()-mouse_position.getX(); |
||||
yoffset = selectedElement.getPixelBounds(controller_img).getY()-mouse_position.getY(); |
||||
} else { |
||||
selectedElement = findMouseoverElement(mouse_position); |
||||
} |
||||
} |
||||
} |
||||
//System.out.println("Selected element "+selectedElement+". Mouse Point: "+ev.getPoint());
|
||||
} |
||||
super.mousePressed(ev); |
||||
} |
||||
|
||||
private Element findMouseoverElement(Point mouse_position) { |
||||
for (Element e : buttons) { |
||||
//System.out.println("Checking bounds "+e.getPixelBounds(controller_img));
|
||||
if (e.getPixelBounds(controller_img).contains(mouse_position)) { |
||||
return e; |
||||
} |
||||
} |
||||
for (Element e : axes) { |
||||
//System.out.println("Checking bounds "+e.getPixelBounds(controller_img));
|
||||
if (e.getPixelBounds(controller_img).contains(mouse_position)) { |
||||
return e; |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
public void mouseReleased(MouseEvent ev) { |
||||
//System.out.println("Mode before is "+MODE);
|
||||
if (resizing) { |
||||
Point mouse_position = new Point((int)(ev.getX()-getPosition().getX()),(int)(ev.getY()-getPosition().getY())); |
||||
PerformResize(mouse_position); |
||||
setConstraints(); |
||||
resizing=false; |
||||
resizing_direction=0; |
||||
SaveElementData(); |
||||
return; |
||||
} |
||||
if (dragging) { |
||||
Point mouse_position = new Point((int)(ev.getX()-getPosition().getX()),(int)(ev.getY()-getPosition().getY())); |
||||
selectedElement.setBounds(new Rectangle2D.Double((mouse_position.getX()+xoffset)/controller_img.getWidth(sigIRC.panel), |
||||
(mouse_position.getY()+yoffset)/controller_img.getHeight(sigIRC.panel), |
||||
selectedElement.getBounds().getWidth(), |
||||
selectedElement.getBounds().getHeight())); |
||||
setConstraints(); |
||||
dragging=false; |
||||
SaveElementData(); |
||||
return; |
||||
} |
||||
super.mouseReleased(ev); |
||||
if (mouseInsideBounds(ev)) { |
||||
switch (MODE) { |
||||
case DRAGSELECTION: |
||||
case DRAGAXISSELECTION: |
||||
{ |
||||
if (start_drag!=null) { |
||||
end_drag = new Point((int)(ev.getX()-getPosition().getX()),(int)(ev.getY()-getPosition().getY())); |
||||
double width = (end_drag.getX()-start_drag.getX())/controller_img.getWidth(sigIRC.panel); |
||||
double height = (end_drag.getY()-start_drag.getY())/controller_img.getHeight(sigIRC.panel); |
||||
stored_rect = new Rectangle2D.Double( |
||||
(width<0)?end_drag.getX()/controller_img.getWidth(sigIRC.panel):start_drag.getX()/controller_img.getWidth(sigIRC.panel), |
||||
(height<0)?end_drag.getY()/controller_img.getHeight(sigIRC.panel):start_drag.getY()/controller_img.getHeight(sigIRC.panel), |
||||
Math.max(MINIMUM_ELEMENT_SIZE/controller_img.getWidth(sigIRC.panel),Math.abs((end_drag.getX()-start_drag.getX())/controller_img.getWidth(sigIRC.panel))), |
||||
Math.max(MINIMUM_ELEMENT_SIZE/controller_img.getHeight(sigIRC.panel),Math.abs((end_drag.getY()-start_drag.getY())/controller_img.getHeight(sigIRC.panel)))); |
||||
//buttons.add(new Button(pct_rect.getX(),pct_rect.getY(),pct_rect.getWidth(),pct_rect.getHeight(),controllers.get(0),Identifier.Button._3,Color.RED,this));
|
||||
//resetDragPoints();
|
||||
if (!inDragZone) { |
||||
sigIRC.panel.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); |
||||
} |
||||
//System.out.println(MODE);
|
||||
if (MODE==EditMode.DRAGSELECTION) { |
||||
MODE=EditMode.BUTTONSET; |
||||
//System.out.println("Set Button");
|
||||
} else |
||||
if (MODE==EditMode.DRAGAXISSELECTION) { |
||||
//System.out.println("Add Axis");
|
||||
AddAxis(); |
||||
MODE=EditMode.DEFAULT; |
||||
//System.out.println(MODE);
|
||||
} |
||||
} |
||||
}break; |
||||
case POSITIONSELECTION:{ |
||||
Point mouse_click = new Point((int)(ev.getX()-getPosition().getX()),(int)(ev.getY()-getPosition().getY())); |
||||
stored_rect = new Rectangle2D.Double( |
||||
(mouse_click.getX()-(stored_rect.getWidth()*controller_img.getWidth(sigIRC.panel))/2)/controller_img.getWidth(sigIRC.panel), |
||||
(mouse_click.getY()-(stored_rect.getHeight()*controller_img.getHeight(sigIRC.panel))/2)/controller_img.getHeight(sigIRC.panel), |
||||
stored_rect.getWidth(), |
||||
stored_rect.getHeight()); |
||||
MODE=EditMode.BUTTONSET; |
||||
}break; |
||||
} |
||||
} |
||||
//System.out.println("Mode after is "+MODE);
|
||||
} |
||||
|
||||
private void PerformResize(Point mouse_position) { |
||||
double aspectRatio = (double)selectedElement.getBounds().getWidth()/selectedElement.getBounds().getHeight(); |
||||
switch (resizing_direction) { |
||||
case 1:{ |
||||
AdjustY(mouse_position); |
||||
}break; |
||||
case 2:{ |
||||
AdjustWidth(mouse_position); |
||||
}break; |
||||
case 3:{ |
||||
AdjustWidth(mouse_position); |
||||
AdjustY(mouse_position); |
||||
}break; |
||||
case 6:{ |
||||
AdjustWidth(mouse_position); |
||||
AdjustHeight(mouse_position); |
||||
}break; |
||||
case 4:{ |
||||
AdjustHeight(mouse_position); |
||||
}break; |
||||
case 12:{ |
||||
AdjustX(mouse_position); |
||||
AdjustHeight(mouse_position); |
||||
}break; |
||||
case 8:{ |
||||
AdjustX(mouse_position); |
||||
}break; |
||||
case 9:{ |
||||
AdjustX(mouse_position); |
||||
AdjustY(mouse_position); |
||||
}break; |
||||
} |
||||
if (proportionalResize) { |
||||
resizeProportionally(aspectRatio); |
||||
} |
||||
resize_refpoint=mouse_position; |
||||
} |
||||
|
||||
private void resizeProportionally(double aspectRatio) { |
||||
boolean xAxisLarger = false; |
||||
xAxisLarger = (selectedElement.getBounds().getWidth()>selectedElement.getBounds().getHeight()); |
||||
selectedElement.setBounds(new Rectangle2D.Double( |
||||
selectedElement.getBounds().getX(), |
||||
selectedElement.getBounds().getY(), |
||||
(xAxisLarger)?selectedElement.getBounds().getWidth():(selectedElement.getBounds().getHeight()*aspectRatio), |
||||
(xAxisLarger)?selectedElement.getBounds().getWidth()*(1/aspectRatio):(selectedElement.getBounds().getHeight()))); |
||||
} |
||||
|
||||
private void AdjustY(Point mouse_position) { |
||||
selectedElement.setBounds(new Rectangle2D.Double(selectedElement.getBounds().getX(), |
||||
(mouse_position.getY()-resize_refpoint.getY()+selectedElement.getPixelBounds(controller_img).getY())/controller_img.getHeight(sigIRC.panel), |
||||
selectedElement.getBounds().getWidth(), |
||||
Math.max(MINIMUM_ELEMENT_SIZE/controller_img.getHeight(sigIRC.panel),(resize_refpoint.getY()-mouse_position.getY()+selectedElement.getPixelBounds(controller_img).getHeight())/controller_img.getHeight(sigIRC.panel)))); |
||||
} |
||||
|
||||
private void AdjustX(Point mouse_position) { |
||||
selectedElement.setBounds(new Rectangle2D.Double((mouse_position.getX()-resize_refpoint.getX()+selectedElement.getPixelBounds(controller_img).getX())/controller_img.getWidth(sigIRC.panel), |
||||
selectedElement.getBounds().getY(), |
||||
Math.max(MINIMUM_ELEMENT_SIZE/controller_img.getWidth(sigIRC.panel),(resize_refpoint.getX()-mouse_position.getX()+selectedElement.getPixelBounds(controller_img).getWidth())/controller_img.getWidth(sigIRC.panel)), |
||||
selectedElement.getBounds().getHeight())); |
||||
} |
||||
|
||||
private void AdjustHeight(Point mouse_position) { |
||||
selectedElement.setBounds(new Rectangle2D.Double(selectedElement.getBounds().getX(), |
||||
selectedElement.getBounds().getY(), |
||||
selectedElement.getBounds().getWidth(), |
||||
Math.max(MINIMUM_ELEMENT_SIZE/controller_img.getHeight(sigIRC.panel),(mouse_position.getY()-resize_refpoint.getY()+selectedElement.getPixelBounds(controller_img).getHeight())/controller_img.getHeight(sigIRC.panel)))); |
||||
} |
||||
|
||||
private void AdjustWidth(Point mouse_position) { |
||||
selectedElement.setBounds(new Rectangle2D.Double(selectedElement.getBounds().getX(), |
||||
selectedElement.getBounds().getY(), |
||||
Math.max(MINIMUM_ELEMENT_SIZE/controller_img.getWidth(sigIRC.panel),(mouse_position.getX()-resize_refpoint.getX()+selectedElement.getPixelBounds(controller_img).getWidth())/controller_img.getWidth(sigIRC.panel)), |
||||
selectedElement.getBounds().getHeight())); |
||||
} |
||||
|
||||
protected boolean mouseInsideBounds(MouseEvent ev) { |
||||
return mouseclickwait_timer<=0 && ev.getX()>=getPosition().getX() && ev.getX()<=getPosition().getX()+getPosition().getWidth() && |
||||
ev.getY()>=getPosition().getY() && ev.getY()<=getPosition().getY()+getPosition().getHeight(); |
||||
} |
||||
|
||||
public Rectangle2D getPosition() { |
||||
return position; |
||||
} |
||||
|
||||
public void setConfigureWindow(ControlConfigurationWindow window) { |
||||
this.configure_window=window; |
||||
} |
||||
|
||||
Rectangle2D.Double extendBoundaries(Rectangle2D.Double rect, double amt) { |
||||
return new Rectangle2D.Double(rect.getX()-amt, rect.getY()-amt, rect.getWidth()+amt*2, rect.getHeight()+amt*2); |
||||
} |
||||
|
||||
public void run() { |
||||
Point mouse_position = new Point((int)(sigIRC.panel.lastMouseX-getPosition().getX()),(int)(sigIRC.panel.lastMouseY-getPosition().getY())); |
||||
if (resizing) { |
||||
PerformResize(mouse_position); |
||||
setConstraints(); |
||||
} |
||||
if (dragging) { |
||||
selectedElement.setBounds(new Rectangle2D.Double((mouse_position.getX()+xoffset)/controller_img.getWidth(sigIRC.panel), |
||||
(mouse_position.getY()+yoffset)/controller_img.getHeight(sigIRC.panel), |
||||
selectedElement.getBounds().getWidth(), |
||||
selectedElement.getBounds().getHeight())); |
||||
setConstraints(); |
||||
} |
||||
if (!inDragZone && selectedElement==null) { |
||||
if (findMouseoverElement(mouse_position)!=null) { |
||||
int cursortype = sigIRC.panel.getCursor().getType(); |
||||
if (cursortype!=Cursor.HAND_CURSOR) { |
||||
sigIRC.panel.setCursor(new Cursor(Cursor.HAND_CURSOR)); |
||||
} |
||||
} else { |
||||
int cursortype = sigIRC.panel.getCursor().getType(); |
||||
if (cursortype!=Cursor.DEFAULT_CURSOR && |
||||
!inDragZone) { |
||||
sigIRC.panel.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); |
||||
} |
||||
} |
||||
} |
||||
if (selectedElement!=null && extendBoundaries(selectedElement.getPixelBounds(controller_img),3).contains(mouse_position)) { |
||||
if (!resizing) { |
||||
resizing_direction=0; |
||||
if (mouse_position.getY()-selectedElement.getPixelBounds(controller_img).getY()<=RESIZE_BORDER && |
||||
mouse_position.getY()-selectedElement.getPixelBounds(controller_img).getY()>=-RESIZE_BORDER) { |
||||
resizing_direction+=1; |
||||
} else |
||||
if (mouse_position.getY()-(selectedElement.getPixelBounds(controller_img).getY()+selectedElement.getPixelBounds(controller_img).getHeight())<=RESIZE_BORDER && |
||||
mouse_position.getY()-(selectedElement.getPixelBounds(controller_img).getY()+selectedElement.getPixelBounds(controller_img).getHeight())>=-RESIZE_BORDER) { |
||||
resizing_direction+=4; |
||||
} |
||||
if (mouse_position.getX()-selectedElement.getPixelBounds(controller_img).getX()<=RESIZE_BORDER && |
||||
mouse_position.getX()-selectedElement.getPixelBounds(controller_img).getX()>=-RESIZE_BORDER) { |
||||
resizing_direction+=8; |
||||
} else |
||||
if (mouse_position.getX()-(selectedElement.getPixelBounds(controller_img).getX()+selectedElement.getPixelBounds(controller_img).getWidth())<=RESIZE_BORDER && |
||||
mouse_position.getX()-(selectedElement.getPixelBounds(controller_img).getX()+selectedElement.getPixelBounds(controller_img).getWidth())>=-RESIZE_BORDER) { |
||||
resizing_direction+=2; |
||||
} |
||||
} |
||||
switch (resizing_direction) { |
||||
case 1:{ |
||||
int cursortype = sigIRC.panel.getCursor().getType(); |
||||
if (cursortype!=Cursor.N_RESIZE_CURSOR) { |
||||
sigIRC.panel.setCursor(new Cursor(Cursor.N_RESIZE_CURSOR)); |
||||
} |
||||
}break; |
||||
case 2:{ |
||||
int cursortype = sigIRC.panel.getCursor().getType(); |
||||
if (cursortype!=Cursor.E_RESIZE_CURSOR) { |
||||
sigIRC.panel.setCursor(new Cursor(Cursor.E_RESIZE_CURSOR)); |
||||
} |
||||
}break; |
||||
case 3:{ |
||||
int cursortype = sigIRC.panel.getCursor().getType(); |
||||
if (cursortype!=Cursor.NE_RESIZE_CURSOR) { |
||||
sigIRC.panel.setCursor(new Cursor(Cursor.NE_RESIZE_CURSOR)); |
||||
} |
||||
}break; |
||||
case 6:{ |
||||
int cursortype = sigIRC.panel.getCursor().getType(); |
||||
if (cursortype!=Cursor.SE_RESIZE_CURSOR) { |
||||
sigIRC.panel.setCursor(new Cursor(Cursor.SE_RESIZE_CURSOR)); |
||||
} |
||||
}break; |
||||
case 4:{ |
||||
int cursortype = sigIRC.panel.getCursor().getType(); |
||||
if (cursortype!=Cursor.S_RESIZE_CURSOR) { |
||||
sigIRC.panel.setCursor(new Cursor(Cursor.S_RESIZE_CURSOR)); |
||||
} |
||||
}break; |
||||
case 12:{ |
||||
int cursortype = sigIRC.panel.getCursor().getType(); |
||||
if (cursortype!=Cursor.SW_RESIZE_CURSOR) { |
||||
sigIRC.panel.setCursor(new Cursor(Cursor.SW_RESIZE_CURSOR)); |
||||
} |
||||
}break; |
||||
case 8:{ |
||||
int cursortype = sigIRC.panel.getCursor().getType(); |
||||
if (cursortype!=Cursor.W_RESIZE_CURSOR) { |
||||
sigIRC.panel.setCursor(new Cursor(Cursor.W_RESIZE_CURSOR)); |
||||
} |
||||
}break; |
||||
case 9:{ |
||||
int cursortype = sigIRC.panel.getCursor().getType(); |
||||
if (cursortype!=Cursor.NW_RESIZE_CURSOR) { |
||||
sigIRC.panel.setCursor(new Cursor(Cursor.NW_RESIZE_CURSOR)); |
||||
} |
||||
}break; |
||||
default: |
||||
int cursortype = sigIRC.panel.getCursor().getType(); |
||||
if (cursortype!=Cursor.DEFAULT_CURSOR && |
||||
!inDragZone) { |
||||
sigIRC.panel.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); |
||||
} |
||||
} |
||||
} |
||||
for (Controller c : controllers) { |
||||
//System.out.println("Data for "+c.getName()+" ("+c.getType()+"):");
|
||||
c.poll(); |
||||
/*for (Component cp : c.getComponents()) { |
||||
if (!cp.isAnalog()) { |
||||
if (cp.getPollData()!=0) { |
||||
//System.out.println("Button "+cp.getIdentifier()+" held down!");
|
||||
FileUtils.logToFile("Button "+cp.getIdentifier()+" held down!", CONTROLLERPATH+"test"); |
||||
} |
||||
} |
||||
}*/ |
||||
} |
||||
if (resizing_direction==0) { |
||||
if (selectedElement!=null && selectedElement.getPixelBounds(controller_img).contains(mouse_position)) { |
||||
int cursortype = sigIRC.panel.getCursor().getType(); |
||||
if (cursortype!=Cursor.MOVE_CURSOR) { |
||||
sigIRC.panel.setCursor(new Cursor(Cursor.MOVE_CURSOR)); |
||||
} |
||||
} else |
||||
if (selectedElement!=null) { |
||||
int cursortype = sigIRC.panel.getCursor().getType(); |
||||
if (cursortype!=Cursor.DEFAULT_CURSOR && !inDragZone) { |
||||
sigIRC.panel.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); |
||||
} |
||||
} |
||||
} |
||||
if (mouseclickwait_timer>0) { |
||||
mouseclickwait_timer--; |
||||
} |
||||
switch (MODE) { |
||||
case DRAGSELECTION:{ |
||||
int cursortype = sigIRC.panel.getCursor().getType(); |
||||
if (cursortype!=Cursor.CROSSHAIR_CURSOR) { |
||||
sigIRC.panel.setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR)); |
||||
} |
||||
status="Drag a button onto the controller template."; |
||||
}break; |
||||
case BUTTONSET:{ |
||||
status="Press controller button to set button"; |
||||
}break; |
||||
case COLORSET:{ |
||||
status="Select a color from the panel."; |
||||
}break; |
||||
case DRAGAXISSELECTION:{ |
||||
int cursortype = sigIRC.panel.getCursor().getType(); |
||||
if (cursortype!=Cursor.CROSSHAIR_CURSOR) { |
||||
sigIRC.panel.setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR)); |
||||
} |
||||
status="Drag the axis onto the controller template."; |
||||
}break; |
||||
case POSITIONSELECTION:{ |
||||
status="Click where you want this new button placed."; |
||||
int cursortype = sigIRC.panel.getCursor().getType(); |
||||
if (cursortype!=Cursor.CROSSHAIR_CURSOR) { |
||||
sigIRC.panel.setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR)); |
||||
} |
||||
}break; |
||||
default:{ |
||||
status=""; |
||||
} |
||||
} |
||||
super.run(); |
||||
if (MODE==EditMode.BUTTONSET) { |
||||
stored_controller_button=-1; |
||||
for (Controller c : controllers) { |
||||
for (int i=0;i<c.getButtons().length;i++) { |
||||
byte b = c.getButtonValue(i); |
||||
if (b!=(byte)0) { |
||||
stored_controller_button = i; |
||||
stored_controller_value = b; |
||||
controller=c; |
||||
MODE=EditMode.COLORSET; |
||||
buttoncol = PopupColorPanel(); |
||||
AddButton(); |
||||
MODE=EditMode.DEFAULT; |
||||
break; |
||||
} |
||||
} |
||||
if (stored_controller_button!=-1) { |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
if (configure_window!=null) { |
||||
configure_window.run(); |
||||
} |
||||
} |
||||
|
||||
public void setConstraints() { |
||||
selectedElement.setBounds(new Rectangle2D.Double(Math.max(0, Math.min((this.getPosition().getWidth()/controller_img.getWidth(sigIRC.panel))-selectedElement.getBounds().getWidth(), selectedElement.getBounds().getX())), |
||||
Math.max(0, Math.min((this.getPosition().getHeight()/controller_img.getHeight(sigIRC.panel))-selectedElement.getBounds().getHeight(), selectedElement.getBounds().getY())), |
||||
selectedElement.getBounds().getWidth(), |
||||
selectedElement.getBounds().getHeight())); |
||||
//System.out.println(selectedElement.getBounds());
|
||||
} |
||||
|
||||
public Image getControllerImage() { |
||||
return controller_img; |
||||
} |
||||
|
||||
public void draw(Graphics g) { |
||||
super.draw(g); |
||||
if (controllers.size()>0) { |
||||
//System.out.println(controllers.get(0).outputAxes()+","+controllers.get(0).outputButtons());
|
||||
for (int i=0;i<controllers.get(0).getComponents().length;i++) { |
||||
Component cp = controllers.get(0).getComponents()[i]; |
||||
/*if (!cp.isAnalog()) { |
||||
if (cp.getPollData()!=0) { |
||||
//System.out.println("Button "+cp.getIdentifier()+" held down! Value: "+cp.getPollData());
|
||||
//DrawUtils.drawText(g,position.getX(),position.getY(),Color.BLACK,"Button "+cp.getIdentifier()+" held down!");
|
||||
} |
||||
}*/ |
||||
} |
||||
g.drawImage(controller_img, (int)(position.getX()), (int)(position.getY()), sigIRC.panel); |
||||
for (ClickableButton cb : click_buttons) { |
||||
cb.draw(g); |
||||
} |
||||
for (Axis a : axes) { |
||||
a.draw(g); |
||||
} |
||||
for (Button b : buttons) { |
||||
b.draw(g); |
||||
} |
||||
if (MODE==EditMode.DRAGSELECTION) { |
||||
if (start_drag!=null) { |
||||
Color color_identity = g.getColor(); |
||||
g.setColor(Color.GRAY); |
||||
int width = sigIRC.panel.lastMouseX- |
||||
((int)position.getX()+(int)start_drag.getX()); |
||||
int height = sigIRC.panel.lastMouseY- |
||||
((int)position.getY()+(int)start_drag.getY()); |
||||
g.fillOval( |
||||
(width<0)?sigIRC.panel.lastMouseX:(int)position.getX()+(int)start_drag.getX(), |
||||
(height<0)?sigIRC.panel.lastMouseY:(int)position.getY()+(int)start_drag.getY(), |
||||
Math.abs(width), Math.abs(height)); |
||||
g.setColor(color_identity); |
||||
} |
||||
} else |
||||
if (MODE==EditMode.POSITIONSELECTION) { |
||||
Color color_identity = g.getColor(); |
||||
g.setColor(Color.GRAY); |
||||
int width = (int)((stored_rect.getWidth()*controller_img.getWidth(sigIRC.panel))); |
||||
int height = (int)((stored_rect.getHeight()*controller_img.getHeight(sigIRC.panel))); |
||||
g.fillOval( |
||||
sigIRC.panel.lastMouseX-width/2, |
||||
sigIRC.panel.lastMouseY-height/2, |
||||
Math.abs(width), Math.abs(height)); |
||||
g.setColor(color_identity); |
||||
} else |
||||
if (MODE==EditMode.DRAGAXISSELECTION) { |
||||
if (start_drag!=null) { |
||||
Color color_identity = g.getColor(); |
||||
g.setColor(temporary_axis.getBackgroundColor()); |
||||
int width = sigIRC.panel.lastMouseX- |
||||
((int)position.getX()+(int)start_drag.getX()); |
||||
int height = sigIRC.panel.lastMouseY- |
||||
((int)position.getY()+(int)start_drag.getY()); |
||||
if (temporary_axis.isTwoWayAxis()) { |
||||
g.fillRect( |
||||
(width<0)?sigIRC.panel.lastMouseX:(int)position.getX()+(int)start_drag.getX(), |
||||
(height<0)?sigIRC.panel.lastMouseY:(int)position.getY()+(int)start_drag.getY(), |
||||
Math.abs(width), Math.abs(height)); |
||||
} else { |
||||
g.fillOval( |
||||
(width<0)?sigIRC.panel.lastMouseX:(int)position.getX()+(int)start_drag.getX(), |
||||
(height<0)?sigIRC.panel.lastMouseY:(int)position.getY()+(int)start_drag.getY(), |
||||
Math.abs(width), Math.abs(height)); |
||||
} |
||||
g.setColor(color_identity); |
||||
} |
||||
} |
||||
g.drawImage(controller_overlay_img, (int)(position.getX()), (int)(position.getY()), sigIRC.panel); |
||||
|
||||
for (Axis a : axes) { |
||||
a.drawIndicator(g); |
||||
} |
||||
|
||||
if (selectedElement!=null) { |
||||
Rectangle2D.Double rect = selectedElement.getPixelBounds(controller_img); |
||||
Color color_identity = g.getColor(); |
||||
g.setColor(DrawUtils.invertColor(selectedElement.getElementColor())); |
||||
for (int i=-1;i<2;i++) { |
||||
for (int j=-1;j<2;j++) { |
||||
g.draw3DRect((int)(rect.getX()+position.getX())+i, (int)(rect.getY()+position.getY())+j, (int)rect.getWidth(), (int)rect.getHeight(), true); |
||||
} |
||||
} |
||||
g.setColor(color_identity); |
||||
} |
||||
DrawUtils.drawText(g, position.getX(), position.getY()+8, Color.BLACK, status); |
||||
} else { |
||||
DrawUtils.drawText(g, position.getX(), position.getY()+8, Color.BLACK, "No controller detected!"); |
||||
} |
||||
} |
||||
|
||||
private void LoadButtonAndAxisData() { |
||||
String[] buttondata = FileUtils.readFromFile(CONTROLLERPATH+"button_data.txt"); |
||||
if (controllers.size()>0) { |
||||
for (String s : buttondata) { |
||||
if (s.length()>0) { |
||||
buttons.add(Button.loadFromString(s, controllers.get(0), this)); |
||||
} |
||||
} |
||||
} |
||||
String[] axisdata = FileUtils.readFromFile(CONTROLLERPATH+"axis_data.txt"); |
||||
if (controllers.size()>0) { |
||||
for (String s : axisdata) { |
||||
if (s.length()>0) { |
||||
//System.out.println("Creating new axis using string "+s+".");
|
||||
Axis a = Axis.loadFromString(s, controllers.get(0), this); |
||||
a.setVisible(true); |
||||
axes.add(a); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
public void keypressed(KeyEvent ev) { |
||||
if (ev.getKeyCode()==KeyEvent.VK_DELETE && |
||||
selectedElement!=null) { |
||||
if (JOptionPane.showConfirmDialog(sigIRC.panel, "Are you sure you want to remove this "+((selectedElement instanceof Button)?"button":"axis")+"?","Confirm Delete",JOptionPane.YES_NO_OPTION)==JOptionPane.YES_OPTION) { |
||||
selectedElement.remove(this); |
||||
selectedElement=null; |
||||
} |
||||
} |
||||
if (ev.getKeyCode()==KeyEvent.VK_SHIFT) { |
||||
proportionalResize = true; |
||||
} |
||||
/*for (RepeatedKey rk : repeatKeys) { |
||||
if (rk.getKeyCode()==ev.getKeyCode()) { |
||||
rk.setKeyPressed(true); |
||||
} |
||||
}*/ |
||||
if (selectedElement!=null) { |
||||
boolean adjust=false; |
||||
int[] move = new int[]{0,0}; |
||||
switch (ev.getKeyCode()) { |
||||
case (KeyEvent.VK_RIGHT):{ |
||||
adjust=true; |
||||
move[0]+=1; |
||||
}break; |
||||
case (KeyEvent.VK_UP):{ |
||||
adjust=true; |
||||
move[1]-=1; |
||||
}break; |
||||
case (KeyEvent.VK_DOWN):{ |
||||
adjust=true; |
||||
move[1]+=1; |
||||
}break; |
||||
case (KeyEvent.VK_LEFT):{ |
||||
adjust=true; |
||||
move[0]-=1; |
||||
}break; |
||||
} |
||||
if (adjust) { |
||||
selectedElement.setBounds( |
||||
new Rectangle2D.Double(selectedElement.getBounds().getX()+(move[0]*(1d/controller_img.getWidth(sigIRC.panel))), |
||||
selectedElement.getBounds().getY()+(move[1]*(1d/controller_img.getWidth(sigIRC.panel))), |
||||
selectedElement.getBounds().getWidth(), |
||||
selectedElement.getBounds().getHeight())); |
||||
setConstraints(); |
||||
SaveElementData(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
public void keyreleased(KeyEvent ev) { |
||||
if (ev.getKeyCode()==KeyEvent.VK_SHIFT) { |
||||
proportionalResize = false; |
||||
} |
||||
/*for (RepeatedKey rk : repeatKeys) { |
||||
if (rk.getKeyCode()==ev.getKeyCode()) { |
||||
rk.setKeyPressed(false); |
||||
} |
||||
}*/ |
||||
} |
||||
|
||||
private void AddAxis() { |
||||
temporary_axis.setupBoundsRectangle(stored_rect); |
||||
temporary_axis.setVisible(true); |
||||
axes.add(temporary_axis); |
||||
temporary_axis=null; |
||||
SaveAxisData(); |
||||
} |
||||
|
||||
public void SaveAxisData() { |
||||
StringBuilder sb = new StringBuilder(); |
||||
for (Axis a : axes) { |
||||
sb.append(a.getSaveString()+"\n"); |
||||
} |
||||
FileUtils.writetoFile(new String[]{sb.toString()}, CONTROLLERPATH+"axis_data.txt"); |
||||
} |
||||
|
||||
private void AddButton() { |
||||
buttons.add(new Button(stored_rect,controller,stored_controller_button,(byte)stored_controller_value,buttoncol,this)); |
||||
SaveButtonData(); |
||||
} |
||||
|
||||
public void SaveButtonData() { |
||||
StringBuilder sb = new StringBuilder(); |
||||
for (Button b : buttons) { |
||||
sb.append(b.getSaveString()+"\n"); |
||||
} |
||||
FileUtils.writetoFile(new String[]{sb.toString()}, CONTROLLERPATH+"button_data.txt"); |
||||
} |
||||
|
||||
private void SaveElementData() { |
||||
SaveButtonData(); |
||||
SaveAxisData(); |
||||
} |
||||
|
||||
private Color PopupColorPanel() { |
||||
Color col=null; |
||||
do { |
||||
col=sigIRC.colorpanel.getBackgroundColor(ControlConfigurationWindow.lastpicked_back_col); |
||||
ControlConfigurationWindow.lastpicked_back_col=col; |
||||
} while (col==null); |
||||
return col; |
||||
} |
||||
} |
@ -0,0 +1,55 @@ |
||||
package sig.modules.RabiRace; |
||||
|
||||
import java.awt.Color; |
||||
import java.awt.Graphics; |
||||
import java.awt.Rectangle; |
||||
import java.awt.event.MouseEvent; |
||||
|
||||
import sig.Module; |
||||
import sig.sigIRC; |
||||
import sig.modules.ControllerModule; |
||||
import sig.modules.RabiRaceModule; |
||||
import sig.utils.DrawUtils; |
||||
import sig.utils.TextUtils; |
||||
|
||||
public class ClickableButton { |
||||
protected int x,y,width,height; |
||||
protected String label; |
||||
protected RabiRaceModule module; |
||||
|
||||
public ClickableButton(Rectangle position, String button_label, RabiRaceModule parent_module) { |
||||
this.x = (int)position.getX(); |
||||
this.y = (int)position.getY(); |
||||
this.width = (int)position.getWidth(); |
||||
this.height = (int)position.getHeight(); |
||||
this.label=button_label; |
||||
this.module = parent_module; |
||||
} |
||||
|
||||
public void onClickEvent(MouseEvent ev) { |
||||
/*if (mouseInsideBounds(ev)) { |
||||
//System.out.println("Click performed!");
|
||||
}*/ |
||||
} |
||||
|
||||
public void setButtonLabel(String text) { |
||||
this.label = text; |
||||
} |
||||
|
||||
public boolean mouseInsideBounds(MouseEvent ev) { |
||||
return ev.getX()>=module.getPosition().getX()+x && ev.getX()<=module.getPosition().getX()+x+width && |
||||
ev.getY()>=module.getPosition().getY()+y && ev.getY()<=module.getPosition().getY()+y+height; |
||||
} |
||||
|
||||
public void draw(Graphics g) { |
||||
Color color_identity = g.getColor(); |
||||
g.setColor(Color.WHITE); |
||||
g.drawRect((int)module.getPosition().getX()+x, |
||||
(int)module.getPosition().getY()+y, width, height); |
||||
g.setColor(Color.BLACK); |
||||
g.fillRect((int)module.getPosition().getX()+x+1, |
||||
(int)module.getPosition().getY()+y+1, width-1, height-1); |
||||
DrawUtils.drawTextFont(g, sigIRC.panel.userFont, module.getPosition().getX()+x-TextUtils.calculateStringBoundsFont(label, sigIRC.panel.userFont).getWidth()/2+width/2, module.getPosition().getY()+y+height-1, Color.WHITE, label); |
||||
g.setColor(color_identity); |
||||
} |
||||
} |
@ -0,0 +1,71 @@ |
||||
package sig.modules.RabiRace; |
||||
|
||||
import java.awt.Color; |
||||
|
||||
public class ColorCycler { |
||||
int r = 0; |
||||
int g = 0; |
||||
int b = 0; |
||||
int a = 255; |
||||
int cyclespd = 0; |
||||
int stage = 1; //1 = Green+, 2 = Red-, 3 = Blue+, 4 = Green-, 5 = Red+, 6 = Blue-
|
||||
|
||||
public ColorCycler(Color startingColor, int cyclespd) { |
||||
this.r = startingColor.getRed(); |
||||
this.g = startingColor.getGreen(); |
||||
this.b = startingColor.getBlue(); |
||||
this.a = startingColor.getAlpha(); |
||||
this.cyclespd=cyclespd; |
||||
} |
||||
|
||||
public void run() { |
||||
switch (stage) { |
||||
case 1:{ |
||||
if (g<255) { |
||||
g=Math.min(255, g+cyclespd); |
||||
} else { |
||||
stage++; |
||||
} |
||||
}break; |
||||
case 2:{ |
||||
if (r>0) { |
||||
r=Math.max(0, r-cyclespd); |
||||
} else { |
||||
stage++; |
||||
} |
||||
}break; |
||||
case 3:{ |
||||
if (b<255) { |
||||
b=Math.min(255, b+cyclespd); |
||||
} else { |
||||
stage++; |
||||
} |
||||
}break; |
||||
case 4:{ |
||||
if (g>0) { |
||||
g=Math.max(0, g-cyclespd); |
||||
} else { |
||||
stage++; |
||||
} |
||||
}break; |
||||
case 5:{ |
||||
if (r<255) { |
||||
r=Math.min(255, r+cyclespd); |
||||
} else { |
||||
stage++; |
||||
} |
||||
}break; |
||||
case 6:{ |
||||
if (b>0) { |
||||
b=Math.max(0, b-cyclespd); |
||||
} else { |
||||
stage=1; |
||||
} |
||||
}break; |
||||
} |
||||
} |
||||
|
||||
public Color getCycleColor() { |
||||
return new Color(r,g,b,a); |
||||
} |
||||
} |
@ -0,0 +1,18 @@ |
||||
package sig.modules.RabiRace; |
||||
|
||||
import java.awt.Rectangle; |
||||
import java.awt.event.MouseEvent; |
||||
|
||||
import sig.Module; |
||||
import sig.modules.RabiRaceModule; |
||||
|
||||
public class CreateButton extends ClickableButton{ |
||||
|
||||
public CreateButton(Rectangle position, String button_label, RabiRaceModule module) { |
||||
super(position, button_label, module); |
||||
} |
||||
|
||||
public void onClickEvent(MouseEvent ev) { |
||||
RabiRaceModule.createwindow.setVisible(true); |
||||
} |
||||
} |
@ -0,0 +1,35 @@ |
||||
package sig.modules.RabiRace; |
||||
|
||||
import java.awt.Rectangle; |
||||
import java.awt.event.MouseEvent; |
||||
import java.io.File; |
||||
import java.io.IOException; |
||||
import java.net.MalformedURLException; |
||||
import java.net.URL; |
||||
|
||||
import sig.Module; |
||||
import sig.sigIRC; |
||||
import sig.modules.RabiRaceModule; |
||||
|
||||
public class JoinButton extends ClickableButton{ |
||||
|
||||
public JoinButton(Rectangle position, String button_label, RabiRaceModule module) { |
||||
super(position,button_label,module); |
||||
} |
||||
|
||||
public void onClickEvent(MouseEvent ev) { |
||||
if (RabiRaceModule.mySession==null) { |
||||
RabiRaceModule.module.window.setVisible(true); |
||||
} else { |
||||
File file = new File(sigIRC.BASEDIR+"sigIRC/tmp.data"); |
||||
try { |
||||
org.apache.commons.io.FileUtils.copyURLToFile(new URL("http://45.33.13.215/rabirace/send.php?key=leavesession&name="+RabiRaceModule.module.myProfile.username+"&session="+RabiRaceModule.mySession.id),file); |
||||
RabiRaceModule.mySession=null; |
||||
} catch (MalformedURLException e) { |
||||
e.printStackTrace(); |
||||
} catch (IOException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,105 @@ |
||||
package sig.modules.RabiRace; |
||||
|
||||
import java.awt.Image; |
||||
|
||||
import sig.modules.RabiRaceModule; |
||||
import sig.modules.RabiRibi.MemoryOffset; |
||||
|
||||
public enum MemoryData { |
||||
HAMMER(MemoryOffset.HAMMER,"Hammer","piko_hammer.png",true), |
||||
AIR_JUMP(MemoryOffset.AIR_JUMP,"Air Jump","air_jump.png",true), |
||||
SLIDING_POWDER(MemoryOffset.SLIDING_POWDER,"Sliding Powder","sliding_powder.png",true), |
||||
CARROT_BOMB(MemoryOffset.CARROT_BOMB,"Carrot Bomb","carrot_bomb.png",true), |
||||
HOURGLASS(MemoryOffset.HOURGLASS,"Hourglass","hourglass.png",true), |
||||
SPEED_BOOST(MemoryOffset.SPEED_BOOST,"Speed Boost","speed_boost.png",true), |
||||
AUTO_EARRINGS(MemoryOffset.AUTO_EARRINGS,"Auto Earrings","auto_earrings.png",true), |
||||
RIBBON(MemoryOffset.RIBBON,"Ribbon","ribbon.png",true), |
||||
SOUL_HEART(MemoryOffset.SOUL_HEART,"Soul Heart","soul_heart.png",true), |
||||
RABI_SLIPPERS(MemoryOffset.RABI_SLIPPERS,"Rabi Slippers","rabi_slippers.png",true), |
||||
BUNNY_WHIRL(MemoryOffset.BUNNY_WHIRL,"Bunny Whirl","bunny_whirl.png",true), |
||||
QUICK_BARRETTE(MemoryOffset.QUICK_BARETTE,"Quick Barrette","quick_barrette.png",true), |
||||
BOOK_OF_CARROT(MemoryOffset.BOOK_OF_CARROT,"Book of Carrot","book_of_carrot.png",true), |
||||
CHAOS_ROD(MemoryOffset.CHAOS_ROD,"Chaos Rod","chaos_rod.png",true), |
||||
HAMMER_WAVE(MemoryOffset.HAMMER_WAVE,"Hammer Wave","hammer_wave.png",true), |
||||
HAMMER_ROLL(MemoryOffset.HAMMER_ROLL,"Hammer Roll","hammer_roll.png",true), |
||||
LIGHT_ORB(MemoryOffset.LIGHT_ORB,"Light Orb","light_orb.png",true), |
||||
WATER_ORB(MemoryOffset.WATER_ORB,"Water Orb","water_orb.png",true), |
||||
FIRE_ORB(MemoryOffset.FIRE_ORB,"Fire Orb","fire_orb.png",true), |
||||
NATURE_ORB(MemoryOffset.NATURE_ORB,"Nature Orb","nature_orb.png",true), |
||||
P_HAIRPIN(MemoryOffset.P_HAIRPIN,"P. Hairpin","p_hairpin.png",true), |
||||
SUNNY_BEAM(MemoryOffset.SUNNY_BEAM,"Sunny Beam","sunny_beam.png",true), |
||||
PLUS_NECKLACE(MemoryOffset.PLUS_NECKLACE,"Plus Necklace","plus_necklace.png",true), |
||||
CYBER_FLOWER(MemoryOffset.CYBER_FLOWER,"Cyber Flower","cyber_flower.png",true), |
||||
HEALING_STAFF(MemoryOffset.HEALING_STAFF,"Healing Staff","healing_staff.png",true), |
||||
MAX_BRACELET(MemoryOffset.MAX_BRACELET,"Max Bracelet","max_bracelet.png",true), |
||||
EXPLODE_SHOT(MemoryOffset.EXPLODE_SHOT,"Explode Shot","explode_shot.png",true), |
||||
AIR_DASH(MemoryOffset.AIR_DASH,"Air Dash","air_dash.png",true), |
||||
BUNNY_STRIKE(MemoryOffset.BUNNY_STRIKE,"Bunny Strike","bunny_strike.png",true), |
||||
STRANGE_BOX(MemoryOffset.STRANGE_BOX,"Strage Box","strange_box.png",true), |
||||
WALL_JUMP(MemoryOffset.WALL_JUMP,"Wall Jump","wall_jump.png",true), |
||||
SPIKE_BARRIER(MemoryOffset.SPIKE_BARRIER,"Spike Barrier","spike_barrier.png",true), |
||||
BUNNY_AMULET(MemoryOffset.BUNNY_AMULET,"Bunny Amulet","bunny_amulet.png",true), |
||||
CHARGE_RING(MemoryOffset.CHARGE_RING,"Charge Ring","charge_ring.png",true), |
||||
CARROT_SHOOTER(MemoryOffset.CARROT_SHOOTER,"Carrot Shooter","carrot_shooter.png",true), |
||||
SUPER_CARROT(MemoryOffset.SUPER_CARROT,"Super Carrot","super_carrot.png",true), |
||||
/*DLC_ITEM1(MemoryOffset.DLC_ITEM1,"","",true), |
||||
DLC_ITEM2(MemoryOffset.DLC_ITEM2,"","",true), |
||||
DLC_ITEM4(MemoryOffset.DLC_ITEM4,"","",true),*/ |
||||
BUNNY_CLOVER(MemoryOffset.BUNNY_CLOVER,"Bunny Clover","bunny_clover.png",true), |
||||
FAIRYS_FLUTE(MemoryOffset.FAIRYS_FLUTE,"Fairy's Flute","fairy_s_flute.png",true), |
||||
BUNNY_MEMORIES(MemoryOffset.BUNNY_MEMORIES,"Bunny Memories","bunny_memories.png",true), |
||||
WIND_BLESSING(MemoryOffset.WIND_BLESSING,"Wind Blessing","wind_blessing.png",true), |
||||
BADGE_HEALTH_PLUS(MemoryOffset.BADGE_HEALTH_PLUS,"Health Plus","health_plus.png",false), |
||||
BADGE_HEALTH_SURGE(MemoryOffset.BADGE_HEALTH_SURGE,"Health Surge","health_surge.png",false), |
||||
BADGE_MANA_PLUS(MemoryOffset.BADGE_MANA_PLUS,"Mana Plus","mana_plus.png",false), |
||||
BADGE_MANA_SURGE(MemoryOffset.BADGE_MANA_SURGE,"Mana Surge","mana_surge.png",false), |
||||
BADGE_CRISIS_BOOST(MemoryOffset.BADGE_CRISIS_BOOST,"Crisis Boost","crisis_boost.png",false), |
||||
BADGE_ATK_GROW(MemoryOffset.BADGE_ATK_GROW,"ATK Grow","atk_grow.png",false), |
||||
BADGE_DEF_GROW(MemoryOffset.BADGE_DEF_GROW,"DEF Grow","def_grow.png",false), |
||||
BADGE_ATK_TRADE(MemoryOffset.BADGE_ATK_TRADE,"ATK Trade","atk_trade.png",false), |
||||
BADGE_DEF_TRADE(MemoryOffset.BADGE_DEF_TRADE,"DEF Trade","def_trade.png",false), |
||||
BADGE_ARM_STRENGTH(MemoryOffset.BADGE_ARM_STRENGTH,"Arm Strength","arm_strength.png",false), |
||||
BADGE_CARROT_BOOST(MemoryOffset.BADGE_CARROT_BOOST,"Carrot Boost","carrot_boost.png",false), |
||||
BADGE_WEAKEN(MemoryOffset.BADGE_WEAKEN,"Weaken","weaken.png",false), |
||||
BADGE_SELF_DEFENSE(MemoryOffset.BADGE_SELF_DEFENSE,"Self Defense","self_defense.png",false), |
||||
BADGE_ARMORED(MemoryOffset.BADGE_ARMORED,"Armored","armored.png",false), |
||||
BADGE_LUCKY_SEVEN(MemoryOffset.BADGE_LUCKY_SEVEN,"Lucky Seven","lucky_seven.png",false), |
||||
BADGE_HEX_CANCEL(MemoryOffset.BADGE_HEX_CANCEL,"Hex Cancel","hex_cancel.png",false), |
||||
BADGE_PURE_LOVE(MemoryOffset.BADGE_PURE_LOVE,"Pure Love","pure_love.png",false), |
||||
BADGE_TOXIC_STRIKE(MemoryOffset.BADGE_TOXIC_STRIKE,"Toxic Strike","toxic_strike.png",false), |
||||
BADGE_FRAME_CANCEL(MemoryOffset.BADGE_FRAME_CANCEL,"Frame Cancel","frame_cancel.png",false), |
||||
BADGE_HEALTH_WAGER(MemoryOffset.BADGE_HEALTH_WAGER,"Health Wager","health_wager.png",false), |
||||
BADGE_MANA_WAGER(MemoryOffset.BADGE_MANA_WAGER,"Mana Wager","mana_wager.png",false), |
||||
BADGE_STAMINA_PLUS(MemoryOffset.BADGE_STAMINA_PLUS,"Stamina Plus","stamina_plus.png",false), |
||||
BADGE_BLESSED(MemoryOffset.BADGE_BLESSED,"Blessed","blessed.png",false), |
||||
BADGE_HITBOX_DOWN(MemoryOffset.BADGE_HITBOX_DOWN,"Hitbox Down","hitbox_down.png",false), |
||||
BADGE_CASHBACK(MemoryOffset.BADGE_CASHBACK,"Cashback","cashback.png",false), |
||||
BADGE_SURVIVAL(MemoryOffset.BADGE_SURVIVAL,"Survival","survival.png",false), |
||||
BADGE_TOP_FORM(MemoryOffset.BADGE_TOP_FORM,"Top Form","top_form.png",false), |
||||
BADGE_TOUGH_SKIN(MemoryOffset.BADGE_TOUGH_SKIN,"Tough Skin","tough_skin.png",false), |
||||
BADGE_ERINA_BADGE(MemoryOffset.BADGE_ERINA_BADGE,"Erina","erina_badge.png",false), |
||||
BADGE_RIBBON_BADGE(MemoryOffset.BADGE_RIBBON_BADGE,"Ribbon","ribbon_badge.png",false), |
||||
BADGE_AUTO_TRIGGER(MemoryOffset.BADGE_AUTO_TRIGGER,"Auto Trigger","auto_trigger.png",false), |
||||
BADGE_LILITHS_GIFT(MemoryOffset.BADGE_LILITHS_GIFT,"Lilith's Gift","lilith_s_gift.png",false), |
||||
; |
||||
|
||||
public MemoryOffset mem; |
||||
public String name; |
||||
public String img_path; |
||||
public boolean key_item; //Set to true if it's a key item. False if it's a badge.
|
||||
|
||||
MemoryData(MemoryOffset mem, String name, String icon_name, boolean isKeyItem) { |
||||
this.mem = mem; |
||||
this.name = name; |
||||
this.img_path = icon_name; |
||||
this.key_item = isKeyItem; |
||||
} |
||||
|
||||
public Image getImage() { |
||||
return RabiRaceModule.image_map.get(img_path); |
||||
} |
||||
|
||||
public String getDisplayName() { |
||||
return (key_item)?name:name+" Badge"; |
||||
} |
||||
} |
@ -0,0 +1,5 @@ |
||||
package sig.modules.RabiRace; |
||||
|
||||
public class Player { |
||||
|
||||
} |
@ -0,0 +1,457 @@ |
||||
package sig.modules.RabiRace; |
||||
|
||||
import java.awt.Color; |
||||
import java.awt.Graphics; |
||||
import java.awt.Graphics2D; |
||||
import java.awt.Image; |
||||
import java.awt.Point; |
||||
import java.awt.image.BufferedImage; |
||||
import java.io.File; |
||||
import java.io.IOException; |
||||
import java.lang.reflect.Field; |
||||
import java.net.MalformedURLException; |
||||
import java.net.URL; |
||||
import java.text.DecimalFormat; |
||||
import java.util.ArrayList; |
||||
import java.util.Arrays; |
||||
import java.util.ConcurrentModificationException; |
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
|
||||
import sig.ScrollingText; |
||||
import sig.sigIRC; |
||||
import sig.modules.RabiRaceModule; |
||||
import sig.utils.DrawUtils; |
||||
import sig.utils.FileUtils; |
||||
import sig.utils.TextUtils; |
||||
|
||||
public class Profile { |
||||
public String username = sigIRC.nickname.toLowerCase(); |
||||
public String displayName = sigIRC.nickname; |
||||
public int avatar = 0; |
||||
public int playtime = 0; |
||||
public int healthUps = 0; |
||||
public int attackUps = 0; |
||||
public int manaUps = 0; |
||||
public int regenUps = 0; |
||||
public int packUps = 0; |
||||
public int rainbowEggCount = 0; |
||||
public boolean isPaused = false; |
||||
public int difficulty = 0; |
||||
public int loop = 0; |
||||
public float itempct = 0; |
||||
public float mappct = 0; |
||||
public HashMap<MemoryData,Integer> key_items = new HashMap<MemoryData,Integer>(); |
||||
public HashMap<MemoryData,Integer> badges = new HashMap<MemoryData,Integer>(); |
||||
public List<String> updates = new ArrayList<String>(); |
||||
RabiRaceModule parent; |
||||
public long lastWebUpdate = System.currentTimeMillis(); |
||||
DecimalFormat df = new DecimalFormat("0.0"); |
||||
Profile oldProfile; |
||||
public boolean isArchive = false; |
||||
|
||||
public Profile(RabiRaceModule module) { |
||||
this(module,true); |
||||
} |
||||
public Profile(RabiRaceModule module, boolean archive) { |
||||
this.isArchive = archive; |
||||
if (!isArchive) { |
||||
oldProfile = new Profile(module,true); |
||||
} |
||||
this.parent = module; |
||||
} |
||||
|
||||
public void archiveAllValues() { |
||||
oldProfile.healthUps = healthUps; |
||||
oldProfile.attackUps = attackUps; |
||||
oldProfile.manaUps = manaUps; |
||||
oldProfile.regenUps = regenUps; |
||||
oldProfile.packUps = packUps; |
||||
oldProfile.rainbowEggCount = rainbowEggCount; |
||||
oldProfile.key_items = (HashMap<MemoryData, Integer>)key_items.clone(); |
||||
oldProfile.badges = (HashMap<MemoryData, Integer>)badges.clone(); |
||||
} |
||||
|
||||
public void compareAndAnnounceAllChangedValues() { |
||||
//System.out.println(oldProfile.key_items.get(MemoryData.HAMMER)+","+key_items.get(MemoryData.HAMMER));
|
||||
String announcement = ""; |
||||
int count=0; |
||||
if (oldProfile.healthUps==healthUps-1) { |
||||
announcement = "has obtained a Health Up! ("+healthUps+" total)"; |
||||
count++; |
||||
} |
||||
if (oldProfile.attackUps==attackUps-1) { |
||||
announcement = "has obtained an Attack Up! ("+attackUps+" total)"; |
||||
count++; |
||||
} |
||||
if (oldProfile.manaUps==manaUps-1) { |
||||
announcement = "has obtained a Mana Up! ("+manaUps+" total)"; |
||||
count++; |
||||
} |
||||
if (oldProfile.regenUps==regenUps-1) { |
||||
announcement = "has obtained a Regen Up! ("+regenUps+" total)"; |
||||
count++; |
||||
} |
||||
if (oldProfile.packUps==packUps-1) { |
||||
announcement = "has obtained a Pack Up! ("+packUps+" total)"; |
||||
count++; |
||||
} |
||||
if (oldProfile.rainbowEggCount==rainbowEggCount-1) { |
||||
if (5-rainbowEggCount==0) { |
||||
announcement = "has obtained 5 Rainbow Eggs! (NAME) has completed the race!"; |
||||
count++; |
||||
} else if (5-rainbowEggCount>0) |
||||
{ |
||||
announcement = "has obtained a Rainbow Egg! ("+Math.max(5-rainbowEggCount, 0)+" to go!)"; |
||||
count++; |
||||
} |
||||
} |
||||
for (MemoryData md : key_items.keySet()) { |
||||
if (!oldProfile.key_items.containsKey(md) && |
||||
key_items.containsKey(md)) { |
||||
announcement = "has obtained "+md.name+"!"; |
||||
count++; |
||||
} |
||||
} |
||||
for (MemoryData md : badges.keySet()) { |
||||
if (!oldProfile.badges.containsKey(md) && |
||||
badges.containsKey(md)) { |
||||
announcement = "has obtained the "+md.name+" badge!"; |
||||
count++; |
||||
} |
||||
} |
||||
if (count==1) { |
||||
SendAnnouncement(announcement); |
||||
} |
||||
} |
||||
|
||||
private void SendAnnouncement(String string) { |
||||
string = displayName+" "+string.replaceAll("(NAME)", displayName); |
||||
string = string.replaceAll(" ", "%20"); |
||||
|
||||
File file = new File(sigIRC.BASEDIR+"sigIRC/tmp.data"); |
||||
try { |
||||
org.apache.commons.io.FileUtils.copyURLToFile(new URL("http://45.33.13.215/rabirace/send.php?key=addupdate&session="+RabiRaceModule.mySession.id+"&message="+string),file); |
||||
} catch (MalformedURLException e) { |
||||
e.printStackTrace(); |
||||
} catch (IOException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
public void updateClientValues() { |
||||
for (MemoryData md : RabiRaceModule.key_items_list) { |
||||
//System.out.println("Checking "+md.getDisplayName());
|
||||
int val = parent.readIntFromMemory(md.mem); |
||||
if (val!=0) { |
||||
key_items.put(md, val); |
||||
//System.out.println("Obtained "+md.getDisplayName());
|
||||
} else { |
||||
key_items.remove(md); |
||||
} |
||||
} |
||||
for (MemoryData md : RabiRaceModule.badges_list) { |
||||
int val = parent.readIntFromMemory(md.mem); |
||||
if (val!=0) { |
||||
badges.put(md, val); |
||||
//System.out.println("Obtained "+md.getDisplayName());
|
||||
} else { |
||||
badges.remove(md); |
||||
} |
||||
} |
||||
} |
||||
|
||||
public void uploadProfile() { |
||||
if (sigIRC.authenticated) { |
||||
File file = new File(sigIRC.BASEDIR+"tmp"); |
||||
try { |
||||
org.apache.commons.io.FileUtils.copyURLToFile(new URL("http://45.33.13.215/rabirace/send.php?key=playerdata&name="+sigIRC.nickname.toLowerCase()+"&data="+getDataString()),file); |
||||
} catch (MalformedURLException e) { |
||||
e.printStackTrace(); |
||||
} catch (IOException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
public void downloadProfile() { |
||||
if (sigIRC.authenticated) { |
||||
File file = new File(sigIRC.BASEDIR+"tmp_profile"); |
||||
try { |
||||
org.apache.commons.io.FileUtils.copyURLToFile(new URL("http://45.33.13.215/rabirace/send.php?key=retrievedata&name="+username.toLowerCase()),file); |
||||
} catch (MalformedURLException e) { |
||||
e.printStackTrace(); |
||||
} catch (IOException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
String[] data = FileUtils.readFromFile(sigIRC.BASEDIR+"tmp_profile"); |
||||
//System.out.println(Arrays.toString(data));
|
||||
if (data.length>=18) { |
||||
int i=0; |
||||
displayName = data[i++]; |
||||
avatar = Integer.parseInt(data[i++]); |
||||
playtime = Integer.parseInt(data[i++]); |
||||
healthUps = Integer.parseInt(data[i++]); |
||||
manaUps = Integer.parseInt(data[i++]); |
||||
regenUps = Integer.parseInt(data[i++]); |
||||
packUps = Integer.parseInt(data[i++]); |
||||
attackUps = Integer.parseInt(data[i++]); |
||||
rainbowEggCount = Integer.parseInt(data[i++]); |
||||
isPaused = Boolean.parseBoolean(data[i++]); |
||||
difficulty = Integer.parseInt(data[i++]); |
||||
loop = Integer.parseInt(data[i++]); |
||||
itempct = Float.parseFloat(data[i++]); |
||||
mappct = Float.parseFloat(data[i++]); |
||||
i+=2; |
||||
String nextval = data[i++]; |
||||
if (!nextval.equalsIgnoreCase("BADGES:")) { |
||||
do { |
||||
String[] parse = nextval.split(";"); |
||||
key_items.put(MemoryData.valueOf(parse[0]), Integer.parseInt(parse[1])); |
||||
//System.out.println("Added "+Arrays.toString(parse));
|
||||
nextval = data[i++]; |
||||
} |
||||
while (!nextval.equalsIgnoreCase("BADGES:")); |
||||
} |
||||
nextval = data[i++]; |
||||
if (!nextval.equalsIgnoreCase("UPDATES:")) { |
||||
do { |
||||
String[] parse = nextval.split(";"); |
||||
badges.put(MemoryData.valueOf(parse[0]), Integer.parseInt(parse[1])); |
||||
//System.out.println("Added "+Arrays.toString(parse));
|
||||
nextval = data[i++]; |
||||
} |
||||
while (!nextval.equalsIgnoreCase("UPDATES:")); |
||||
} |
||||
lastWebUpdate = System.currentTimeMillis(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
private String getDataString() { |
||||
StringBuilder sb = new StringBuilder(); |
||||
appendData(sigIRC.nickname,sb); |
||||
appendData(avatar,sb); |
||||
appendData(playtime,sb); |
||||
appendData(healthUps,sb); |
||||
appendData(manaUps,sb); |
||||
appendData(regenUps,sb); |
||||
appendData(packUps,sb); |
||||
appendData(attackUps,sb); |
||||
appendData(rainbowEggCount,sb); |
||||
appendData(isPaused,sb); |
||||
appendData(difficulty,sb); |
||||
appendData(loop,sb); |
||||
appendData(itempct,sb); |
||||
appendData(mappct,sb); |
||||
appendData(0,sb); |
||||
appendData("KEYITEMS:",sb); |
||||
for (MemoryData data : key_items.keySet()) { |
||||
Integer val = key_items.get(data); |
||||
appendData(data.name()+";"+val,sb); |
||||
} |
||||
appendData("BADGES:",sb); |
||||
for (MemoryData data : badges.keySet()) { |
||||
Integer val = badges.get(data); |
||||
appendData(data.name()+";"+val,sb); |
||||
} |
||||
appendData("UPDATES:",sb); |
||||
return sb.toString(); |
||||
} |
||||
|
||||
private void appendData(Object data, StringBuilder str) { |
||||
if (str.length()!=0) { |
||||
str.append(","); |
||||
} |
||||
str.append(data); |
||||
} |
||||
|
||||
public Image getStatText(int w) { |
||||
BufferedImage tmp = new BufferedImage(400,175,BufferedImage.TYPE_INT_ARGB); |
||||
Graphics2D g2 = tmp.createGraphics(); |
||||
|
||||
g2.setColor(Color.BLACK); |
||||
g2.fillRect(1, 1, 32, 32); |
||||
g2.setColor(ScrollingText.GetUserNameColor(displayName)); |
||||
DrawUtils.drawOutlineText(g2, sigIRC.panel.rabiRibiMoneyDisplayFont, 36, 26, 1, g2.getColor(), Color.BLACK, displayName); |
||||
DrawUtils.drawCenteredOutlineText(g2, sigIRC.panel.rabiRibiTinyDisplayFont, (int)(tmp.getWidth()*0.2), 50, 1, GetDifficultyColor(), Color.BLACK, GetDifficultyName()); |
||||
String text = TextUtils.convertSecondsToTimeFormat(playtime/60); |
||||
if (isPaused) { |
||||
g2.setColor(new Color(128,96,0)); |
||||
} else { |
||||
g2.setColor(Color.BLACK); |
||||
} |
||||
DrawUtils.drawOutlineText(g2, sigIRC.panel.rabiRibiMoneyDisplayFont, (int)(tmp.getWidth() - TextUtils.calculateStringBoundsFont(text, sigIRC.panel.rabiRibiMoneyDisplayFont).getWidth()) - 2, 16, 1, g2.getColor(), Color.GRAY, text); |
||||
text = "Map "+df.format(mappct)+"% Item "+df.format(itempct)+"%"; |
||||
//DrawUtils.drawOutlineText(g2, sigIRC.panel.rabiRibiMoneyDisplayFont, (int)(parent.position.getWidth() - TextUtils.calculateStringBoundsFont(text, sigIRC.panel.rabiRibiMoneyDisplayFont).getWidth()) - 2, 16, 1, g2.getColor(), Color.GRAY, text);
|
||||
DrawUtils.drawCenteredOutlineText(g2, sigIRC.panel.rabiRibiTinyDisplayFont, (int)(tmp.getWidth()*0.6), 50, 2, Color.WHITE, Color.BLACK, text); |
||||
|
||||
return tmp.getScaledInstance(w, -1, Image.SCALE_AREA_AVERAGING); |
||||
} |
||||
|
||||
private Color GetDifficultyColor() { |
||||
Color[] color_list = new Color[]{ |
||||
new Color(99, 159, 255), |
||||
new Color(119, 98, 255), |
||||
new Color(60, 201, 112), |
||||
new Color(200, 209, 100), |
||||
new Color(209, 159, 12), |
||||
new Color(209, 54, 11), |
||||
new Color(68, 24, 12), |
||||
}; |
||||
Color colorval = Color.BLACK; |
||||
if (difficulty<color_list.length) { |
||||
colorval = color_list[difficulty]; |
||||
} else { |
||||
colorval = color_list[color_list.length-1]; |
||||
} |
||||
return colorval; |
||||
} |
||||
|
||||
private String GetDifficultyName() { |
||||
String[] difficulty_list = new String[]{ |
||||
"Casual", |
||||
"Novice", |
||||
"Normal", |
||||
"Hard", |
||||
"Hell", |
||||
"BEX", |
||||
"???", |
||||
}; |
||||
String diffstring = ""; |
||||
if (difficulty<difficulty_list.length) { |
||||
diffstring = difficulty_list[difficulty]+((loop>0)?" Loop "+loop:""); |
||||
} else { |
||||
diffstring = difficulty_list[difficulty_list.length-1]+((loop>0)?" Loop "+loop:""); |
||||
} |
||||
return diffstring; |
||||
} |
||||
|
||||
public Image getStatPanel(int w) { |
||||
//DrawUtils.drawTextFont(g, sigIRC.panel.userFont, parent.position.getX(), parent.position.getY()+26, Color.BLACK, "Values: "+readIntFromMemory(MemoryOffset.DLC_ITEM1)+","+readIntFromMemory(MemoryOffset.DLC_ITEM2)+","+readIntFromMemory(MemoryOffset.DLC_ITEM3)+","+readIntFromMemory(MemoryOffset.DLC_ITEM4));
|
||||
BufferedImage tmp = new BufferedImage(400,175,BufferedImage.TYPE_INT_ARGB); |
||||
Graphics2D g2 = tmp.createGraphics(); |
||||
final int border=20; |
||||
final int width=(int)(tmp.getWidth()-border*2); |
||||
final int spacing=width/5; |
||||
for (int i=0;i<5;i++) { |
||||
Image img = RabiRaceModule.image_map.get("easter_egg.png"); |
||||
Color col = (rainbowEggCount>i)?RabiRaceModule.rainbowcycler.getCycleColor():new Color(0,0,0,192); |
||||
DrawUtils.drawImage(g2, img, (int)(border+i*spacing-img.getWidth(sigIRC.panel)/4),(int)(36),col,sigIRC.panel); |
||||
} |
||||
int size = key_items.size(); |
||||
final int icon_size = 24; |
||||
int count = 0; |
||||
try { |
||||
for (MemoryData data : key_items.keySet()) { |
||||
if (key_items.get(data)<0) { |
||||
Image img = data.getImage().getScaledInstance(icon_size, icon_size, Image.SCALE_DEFAULT); |
||||
if (size*icon_size<width) { |
||||
DrawUtils.drawImage(g2, img, (int)(+border+((count++)*icon_size)), (int)(+96+8), new Color(0,0,0,128), sigIRC.panel); |
||||
} else { |
||||
DrawUtils.drawImage(g2, img, (int)(+border+((width/size)*(count++))), (int)(+96+8), new Color(0,0,0,128), sigIRC.panel); |
||||
} |
||||
} else { |
||||
if (size*icon_size<width) { |
||||
g2.drawImage(data.getImage(), (int)(+border+((count++)*icon_size)), (int)(+96+8), (int)icon_size, (int)icon_size, sigIRC.panel); |
||||
} else { |
||||
g2.drawImage(data.getImage(), (int)(+border+((width/size)*(count++))), (int)(+96+8), (int)icon_size, (int)icon_size, sigIRC.panel); |
||||
} |
||||
} |
||||
} |
||||
count=0; |
||||
size = badges.size(); |
||||
for (MemoryData data : badges.keySet()) { |
||||
if (size*icon_size<width) { |
||||
g2.drawImage(data.getImage(), (int)(+border+((count++)*icon_size)), (int)(+96+32), (int)icon_size, (int)icon_size, sigIRC.panel); |
||||
} else { |
||||
g2.drawImage(data.getImage(), (int)(+border+((width/size)*(count++))), (int)(+96+32), (int)icon_size, (int)icon_size, sigIRC.panel); |
||||
} |
||||
} |
||||
int i=0; |
||||
Image[] imgs = new Image[]{RabiRaceModule.image_map.get("health_up.png"), |
||||
RabiRaceModule.image_map.get("mana_up.png"), |
||||
RabiRaceModule.image_map.get("regen_up.png"), |
||||
RabiRaceModule.image_map.get("pack_up.png"), |
||||
RabiRaceModule.image_map.get("attack_up.png")}; |
||||
int[] amts = new int[]{ |
||||
healthUps, |
||||
manaUps, |
||||
regenUps, |
||||
packUps, |
||||
attackUps, |
||||
}; |
||||
//g2.drawImage(RabiRaceModule.image_map.get("bunny_strike.png"),(int)(+border+(i++)*(spacing)-img2.getWidth(sigIRC.panel)/4),(int)(+96+56), (int)icon_size, (int)icon_size, sigIRC.panel);
|
||||
for (Image img : imgs) { |
||||
g2.drawImage(img,(int)(+border+((i)*(spacing))-icon_size/2),(int)(+96+56), (int)icon_size, (int)icon_size, sigIRC.panel); |
||||
DrawUtils.drawCenteredOutlineText(g2, sigIRC.panel.programFont, (int)((+border+((i)*(spacing))-icon_size/2)+(spacing/2)+4), (int)(+96+56+icon_size+12), 1, Color.WHITE, Color.BLUE, Integer.toString(amts[i++])); |
||||
} |
||||
} catch (ConcurrentModificationException e) { |
||||
|
||||
} |
||||
return tmp.getScaledInstance(w, -1, Image.SCALE_AREA_AVERAGING); |
||||
//g.drawImage(tmp, (int)parent.position.getX(), (int)parent.position.getY(), 120, 64, sigIRC.panel);
|
||||
} |
||||
|
||||
public String toString() { |
||||
StringBuilder sb = new StringBuilder(); |
||||
sb.append(this.getClass().getName()+"("); |
||||
boolean first=false; |
||||
for (Field f : this.getClass().getDeclaredFields()) { |
||||
if (!first) { |
||||
try { |
||||
sb.append(f.getName()+"="+f.get(this)); |
||||
first=true; |
||||
} catch (IllegalArgumentException e) { |
||||
e.printStackTrace(); |
||||
} catch (IllegalAccessException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} else { |
||||
try { |
||||
sb.append(","+f.getName()+"="+f.get(this)); |
||||
} catch (IllegalArgumentException e) { |
||||
e.printStackTrace(); |
||||
} catch (IllegalAccessException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
} |
||||
sb.append(")"); |
||||
return sb.toString(); |
||||
} |
||||
|
||||
public static Point calculateMultiPanelView(int elements) { |
||||
int x = 1; |
||||
int y = 1; |
||||
while (x*y<elements) { |
||||
if (x==y) { |
||||
y++; |
||||
} else { |
||||
x++; |
||||
} |
||||
} |
||||
//System.out.println(x+","+y);
|
||||
return new Point(x,y); |
||||
} |
||||
|
||||
public static void DrawMultiPanel(Graphics g, int x, int y, int w, List<Profile> players) { |
||||
int cols = calculateMultiPanelView(players.size()).x; |
||||
int rows = calculateMultiPanelView(players.size()).y; |
||||
|
||||
int xx = 0; |
||||
int yy = 0; |
||||
|
||||
for (Profile p : players) { |
||||
Image panel = p.getStatPanel(w); |
||||
Image panel2 = p.getStatText(w); |
||||
g.drawImage(panel,(int)(x+xx*panel.getWidth(sigIRC.panel)/((rows+cols)/2d)),(int)(y+yy*panel.getHeight(sigIRC.panel)/((rows+cols)/2d)),(int)(panel.getWidth(sigIRC.panel)/((rows+cols)/2d)),(int)(panel.getHeight(sigIRC.panel)/((rows+cols)/2d)),sigIRC.panel); |
||||
g.drawImage(panel2,(int)(x+xx*panel2.getWidth(sigIRC.panel)/((rows+cols)/2d)),(int)(y+yy*panel2.getHeight(sigIRC.panel)/((rows+cols)/2d)),(int)(panel2.getWidth(sigIRC.panel)/((rows+cols)/2d)),(int)(panel2.getHeight(sigIRC.panel)/((rows+cols)/2d)),sigIRC.panel); |
||||
if (xx+1<cols) { |
||||
xx++; |
||||
} else { |
||||
yy++; |
||||
xx=0; |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,97 @@ |
||||
package sig.modules.RabiRace; |
||||
|
||||
import java.lang.reflect.Field; |
||||
import java.util.ArrayList; |
||||
import java.util.Arrays; |
||||
import java.util.List; |
||||
|
||||
import sig.modules.RabiRaceModule; |
||||
import sig.utils.ReflectUtils; |
||||
|
||||
public class Session { |
||||
long creationTime = 0; |
||||
long updateTime = 0; |
||||
String name = ""; |
||||
int maxPlayers = 0; |
||||
String password = ""; |
||||
int id = 0; |
||||
List<Profile> players = new ArrayList<Profile>(); |
||||
|
||||
public Session(String dataString) { |
||||
String[] split = dataString.split(","); |
||||
|
||||
int i=0; |
||||
|
||||
id = Integer.parseInt(split[i++]); |
||||
creationTime = Long.parseLong(split[i++]); |
||||
updateTime = Long.parseLong(split[i++]); |
||||
name = split[i++]; |
||||
maxPlayers = Integer.parseInt(split[i++]); |
||||
password = split[i++]; |
||||
//System.out.println(this.toString());
|
||||
if (split.length>=7) { |
||||
String val = split[i++]; |
||||
String[] playerlist = val.split(";"); |
||||
//System.out.println(Arrays.toString(playerlist));
|
||||
if (playerlist.length>0) { |
||||
for (String s : playerlist) { |
||||
Profile p = new Profile(RabiRaceModule.module,true); |
||||
p.username=s; |
||||
//System.out.println("Player "+p.username);
|
||||
p.downloadProfile(); |
||||
if (RabiRaceModule.mySession==null && p.username.equalsIgnoreCase(RabiRaceModule.module.myProfile.username)) { |
||||
RabiRaceModule.mySession = this; |
||||
} |
||||
//System.out.println("Adding Player "+p);
|
||||
players.add(p); |
||||
} |
||||
} else { |
||||
Profile p = new Profile(RabiRaceModule.module,true); |
||||
p.username=val; |
||||
//System.out.println("Player "+p.username);
|
||||
p.downloadProfile(); |
||||
if (RabiRaceModule.mySession==null && p.username.equalsIgnoreCase(RabiRaceModule.module.myProfile.username)) { |
||||
RabiRaceModule.mySession = this; |
||||
} |
||||
//System.out.println("Adding Player "+p);
|
||||
players.add(p); |
||||
} |
||||
} |
||||
} |
||||
|
||||
public int getID() { |
||||
return id; |
||||
} |
||||
|
||||
public List<Profile> getPlayers() { |
||||
return players; |
||||
} |
||||
|
||||
public String toString() { |
||||
StringBuilder sb = new StringBuilder(); |
||||
sb.append(this.getClass().getName()+"("); |
||||
boolean first=false; |
||||
for (Field f : this.getClass().getDeclaredFields()) { |
||||
if (!first) { |
||||
try { |
||||
sb.append(f.getName()+"="+f.get(this)); |
||||
first=true; |
||||
} catch (IllegalArgumentException e) { |
||||
e.printStackTrace(); |
||||
} catch (IllegalAccessException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} else { |
||||
try { |
||||
sb.append(","+f.getName()+"="+f.get(this)); |
||||
} catch (IllegalArgumentException e) { |
||||
e.printStackTrace(); |
||||
} catch (IllegalAccessException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
} |
||||
sb.append(")"); |
||||
return sb.toString(); |
||||
} |
||||
} |
@ -0,0 +1,226 @@ |
||||
package sig.modules.RabiRace; |
||||
|
||||
import java.awt.Color; |
||||
import java.awt.Dimension; |
||||
import java.awt.event.ActionEvent; |
||||
import java.awt.event.ActionListener; |
||||
import java.io.File; |
||||
import java.io.IOException; |
||||
import java.net.MalformedURLException; |
||||
import java.net.URL; |
||||
|
||||
import javax.swing.Box; |
||||
import javax.swing.BoxLayout; |
||||
import javax.swing.JButton; |
||||
import javax.swing.JFrame; |
||||
import javax.swing.JLabel; |
||||
import javax.swing.JOptionPane; |
||||
import javax.swing.JPanel; |
||||
import javax.swing.JPasswordField; |
||||
import javax.swing.JTextField; |
||||
import javax.swing.event.DocumentEvent; |
||||
import javax.swing.event.DocumentListener; |
||||
|
||||
import sig.sigIRC; |
||||
import sig.modules.RabiRaceModule; |
||||
import sig.utils.FileUtils; |
||||
import sig.utils.TextUtils; |
||||
|
||||
public class SessionCreateWindow extends JFrame{ |
||||
JPanel container = new JPanel(); |
||||
LengthValidationField session_name = new LengthValidationField(16); |
||||
NumberValidationField maxplayers = new NumberValidationField(); |
||||
JPasswordField pass = new JPasswordField(); |
||||
JButton create = new JButton("Create"); |
||||
|
||||
public SessionCreateWindow() { |
||||
this.setTitle("Create Rabi-Race Session"); |
||||
this.setIconImage(sigIRC.programIcon); |
||||
this.setVisible(false); |
||||
JPanel namepanel = new JPanel(); |
||||
JPanel playerpanel = new JPanel(); |
||||
JPanel passwordpanel = new JPanel(); |
||||
|
||||
JPanel[] panel_list = new JPanel[]{ |
||||
namepanel,playerpanel,passwordpanel |
||||
}; |
||||
|
||||
for (JPanel panel : panel_list) { |
||||
panel.setLayout(new BoxLayout(panel,BoxLayout.LINE_AXIS)); |
||||
panel.setSize(400, 24); |
||||
panel.setMinimumSize(new Dimension(400, 24)); |
||||
panel.add(Box.createRigidArea(new Dimension(24,24))); |
||||
} |
||||
|
||||
JLabel nameLabel = new JLabel("Session Name: "); |
||||
String label = RabiRaceModule.module.myProfile.displayName+"'s Race"; |
||||
if (label.length()>16) { |
||||
label = "My Rabi-Race!"; |
||||
} |
||||
session_name.setText(label); |
||||
|
||||
namepanel.add(nameLabel); |
||||
namepanel.add(session_name); |
||||
|
||||
JLabel playerLabel = new JLabel("Max Players: "); |
||||
maxplayers.setText("4"); |
||||
|
||||
playerpanel.add(playerLabel); |
||||
playerpanel.add(maxplayers); |
||||
|
||||
JLabel passwordLabel = new JLabel("🔑 Password (Optional): "); |
||||
|
||||
playerpanel.add(passwordLabel); |
||||
playerpanel.add(pass); |
||||
|
||||
for (JPanel panel : panel_list) { |
||||
panel.add(Box.createRigidArea(new Dimension(24,24))); |
||||
} |
||||
|
||||
create.setSize(164,24); |
||||
create.setMinimumSize(new Dimension(164,24)); |
||||
create.addActionListener(new ActionListener(){ |
||||
@Override |
||||
public void actionPerformed(ActionEvent ev) { |
||||
if (session_name.getText().length()>session_name.length) { |
||||
JOptionPane.showMessageDialog(RabiRaceModule.createwindow, "Your session name is too long!", "Error!", JOptionPane.WARNING_MESSAGE); |
||||
return; |
||||
} |
||||
if (session_name.getText().length()<=2) { |
||||
JOptionPane.showMessageDialog(RabiRaceModule.createwindow, "Your session name is too short!", "Error!", JOptionPane.WARNING_MESSAGE); |
||||
return; |
||||
} |
||||
if (!TextUtils.isAlphanumeric(session_name.getText())) { |
||||
JOptionPane.showMessageDialog(RabiRaceModule.createwindow, "Your session name has invalid characters! Only A-Z,0-9,!,-,.,? and spaces allowed!", "Error!", JOptionPane.WARNING_MESSAGE); |
||||
return; |
||||
} |
||||
if (!TextUtils.isInteger(maxplayers.getText(), 10)) { |
||||
JOptionPane.showMessageDialog(RabiRaceModule.createwindow, "Your max player count is invalid!", "Error!", JOptionPane.WARNING_MESSAGE); |
||||
return; |
||||
} |
||||
if (Integer.parseInt(maxplayers.getText())>48 || Integer.parseInt(maxplayers.getText())<2) { |
||||
JOptionPane.showMessageDialog(RabiRaceModule.createwindow, "Your max player count needs to be between 2-48!", "Error!", JOptionPane.WARNING_MESSAGE); |
||||
return; |
||||
} |
||||
String hashpass = ""; |
||||
if (String.copyValueOf(pass.getPassword()).length()>0) { |
||||
hashpass = SessionListWindow.GetHashedPassword(String.copyValueOf(pass.getPassword())); |
||||
} |
||||
session_name.setText(session_name.getText().replaceAll(" ", "%20")); |
||||
File file = new File(sigIRC.BASEDIR+"sigIRC/tmp.data"); |
||||
try { |
||||
org.apache.commons.io.FileUtils.copyURLToFile(new URL("http://45.33.13.215/rabirace/send.php?key=sessioncreate&name="+session_name.getText()+"&players="+maxplayers.getText()+"&password="+((hashpass.length()>0)?hashpass:"none")),file); |
||||
String[] contents = FileUtils.readFromFile(sigIRC.BASEDIR+"sigIRC/tmp.data"); |
||||
int sessionID=-1; |
||||
if (contents.length>=2) { |
||||
sessionID=Integer.parseInt(contents[0]); |
||||
} |
||||
if (sessionID!=-1) { |
||||
RabiRaceModule.module.getSessionList(); |
||||
//RabiRaceModule.module.session_listing.data.put(sessionID, new Session());
|
||||
Session session = RabiRaceModule.module.session_listing.data.get(sessionID); |
||||
SessionListWindow.ConnectToSession(session, hashpass); |
||||
setVisible(false); |
||||
} |
||||
//SessionListWindow.ConnectToSession(session, hashedPass);
|
||||
} catch (MalformedURLException e) { |
||||
e.printStackTrace(); |
||||
} catch (IOException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
}); |
||||
|
||||
//create.add(Box.createRigidArea(new Dimension(24,24)));
|
||||
|
||||
container.setLayout(new BoxLayout(container,BoxLayout.PAGE_AXIS)); |
||||
|
||||
container.add(Box.createRigidArea(new Dimension(24,24))); |
||||
container.add(namepanel); |
||||
container.add(playerpanel); |
||||
container.add(passwordpanel); |
||||
container.add(create); |
||||
container.add(Box.createRigidArea(new Dimension(24,24))); |
||||
|
||||
this.add(container); |
||||
this.setSize(400, 192); |
||||
this.setMinimumSize(new Dimension(400, 192)); |
||||
this.setMaximumSize(new Dimension(400, 192)); |
||||
this.setResizable(false); |
||||
} |
||||
|
||||
class LengthValidationField extends JTextField implements DocumentListener{ |
||||
int length = 10; |
||||
|
||||
public LengthValidationField(int maxLength) { |
||||
this.length = maxLength; |
||||
getDocument().addDocumentListener(this); |
||||
} |
||||
|
||||
@Override |
||||
public void changedUpdate(DocumentEvent arg0) { |
||||
} |
||||
|
||||
@Override |
||||
public void insertUpdate(DocumentEvent arg0) { |
||||
ValidateForm(); |
||||
} |
||||
|
||||
protected void ValidateForm() { |
||||
if (fieldIsInvalid()) { |
||||
setBackground(Color.RED); |
||||
} else { |
||||
setBackground(Color.WHITE); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void removeUpdate(DocumentEvent arg0) { |
||||
ValidateForm(); |
||||
} |
||||
|
||||
protected boolean fieldIsInvalid() { |
||||
return getText().length()>length || getText().length()<=2 || !TextUtils.isAlphanumeric(getText()); |
||||
} |
||||
} |
||||
|
||||
class NumberValidationField extends JTextField implements DocumentListener{ |
||||
|
||||
public NumberValidationField() { |
||||
getDocument().addDocumentListener(this); |
||||
} |
||||
|
||||
@Override |
||||
public void changedUpdate(DocumentEvent arg0) { |
||||
} |
||||
|
||||
@Override |
||||
public void insertUpdate(DocumentEvent arg0) { |
||||
ValidateForm(); |
||||
} |
||||
|
||||
protected void ValidateForm() { |
||||
if (fieldIsInvalid()) { |
||||
setBackground(Color.RED); |
||||
} else { |
||||
setBackground(Color.WHITE); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void removeUpdate(DocumentEvent arg0) { |
||||
ValidateForm(); |
||||
} |
||||
|
||||
protected boolean fieldIsInvalid() { |
||||
if (!TextUtils.isInteger(getText(), 10)) { |
||||
return true; |
||||
} |
||||
int val = Integer.parseInt(getText()); |
||||
if (val>48 || val<2) { |
||||
return true; |
||||
} |
||||
return false; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,34 @@ |
||||
package sig.modules.RabiRace; |
||||
|
||||
import java.util.HashMap; |
||||
|
||||
import sig.modules.RabiRaceModule; |
||||
|
||||
public class SessionListData { |
||||
HashMap<Integer,Session> data = new HashMap<Integer,Session>(); |
||||
|
||||
public SessionListData() { |
||||
|
||||
} |
||||
|
||||
public void UpdateData(String[] data) { |
||||
//this.data.clear();
|
||||
for (String session : data) { |
||||
if (session.length()>0) { |
||||
//System.out.println("Adding session "+session);
|
||||
//this.data.add(new Session(session));
|
||||
int sessionID = Integer.parseInt(session.split(",")[0]); |
||||
Session s = new Session(session); |
||||
this.data.put(sessionID, s); |
||||
if (RabiRaceModule.module.mySession!=null && RabiRaceModule.module.mySession.id==sessionID) { |
||||
RabiRaceModule.module.mySession = s; |
||||
} |
||||
} |
||||
} |
||||
//System.out.println(this.data);
|
||||
} |
||||
|
||||
public HashMap<Integer,Session> getSessions() { |
||||
return data; |
||||
} |
||||
} |
@ -0,0 +1,286 @@ |
||||
package sig.modules.RabiRace; |
||||
|
||||
import java.awt.Dimension; |
||||
import java.awt.Graphics; |
||||
import java.awt.event.ActionEvent; |
||||
import java.awt.event.ActionListener; |
||||
import java.io.File; |
||||
import java.io.IOException; |
||||
import java.net.URL; |
||||
import java.security.MessageDigest; |
||||
import java.security.NoSuchAlgorithmException; |
||||
import java.util.concurrent.Executors; |
||||
import java.util.concurrent.ScheduledExecutorService; |
||||
import java.util.concurrent.TimeUnit; |
||||
|
||||
import javax.swing.Box; |
||||
import javax.swing.BoxLayout; |
||||
import javax.swing.DefaultListModel; |
||||
import javax.swing.JButton; |
||||
import javax.swing.JFrame; |
||||
import javax.swing.JLabel; |
||||
import javax.swing.JList; |
||||
import javax.swing.JOptionPane; |
||||
import javax.swing.JPanel; |
||||
import javax.swing.JPasswordField; |
||||
import javax.swing.JScrollPane; |
||||
import javax.swing.ListSelectionModel; |
||||
import javax.swing.event.ListSelectionEvent; |
||||
import javax.swing.event.ListSelectionListener; |
||||
|
||||
import sig.sigIRC; |
||||
import sig.modules.RabiRaceModule; |
||||
import sig.utils.DebugUtils; |
||||
import sig.utils.FileUtils; |
||||
|
||||
public class SessionListWindow extends JFrame{ |
||||
JPanel container = new JPanel(); |
||||
public JList<String> sessionlist = new JList<String>(); |
||||
public DefaultListModel<String> sessionlist_model = new DefaultListModel<String>(); |
||||
public int selected = -1; |
||||
public DataPanel previewPanel = new DataPanel(); |
||||
public JButton joinButton = new JButton("Join"); |
||||
public JScrollPane scrolllist = new JScrollPane(); |
||||
public PasswordBox box = new PasswordBox(); |
||||
public String enteredPassword = ""; |
||||
|
||||
|
||||
public SessionListWindow(){ |
||||
this.setTitle("Rabi-Race Sessions List"); |
||||
this.setIconImage(sigIRC.programIcon); |
||||
|
||||
previewPanel.setWindow(this); |
||||
|
||||
scrolllist.setViewportView(sessionlist); |
||||
scrolllist.setPreferredSize(new Dimension(160,150)); |
||||
scrolllist.setMinimumSize(new Dimension(160,150)); |
||||
scrolllist.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); |
||||
JPanel sessionPanel = new JPanel(); |
||||
|
||||
sessionlist.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); |
||||
sessionlist.setLayoutOrientation(JList.VERTICAL); |
||||
sessionlist.setVisibleRowCount(6); |
||||
|
||||
sessionPanel.setLayout(new BoxLayout(sessionPanel,BoxLayout.PAGE_AXIS)); |
||||
sessionPanel.setSize(130,200); |
||||
sessionPanel.setMinimumSize(new Dimension(130,200)); |
||||
|
||||
sessionPanel.add(scrolllist); |
||||
sessionPanel.add(Box.createRigidArea(new Dimension(10,10))); |
||||
sessionPanel.add(joinButton); |
||||
|
||||
UpdateSessionList(); |
||||
joinButton.setEnabled(false); |
||||
joinButton.addActionListener(new ActionListener() { |
||||
@Override |
||||
public void actionPerformed(ActionEvent ev) { |
||||
|
||||
if (sessionlist.getSelectedIndex()!=-1) { |
||||
selected = sessionlist.getSelectedIndex(); |
||||
Session session = RabiRaceModule.module.session_listing.data.get(getSelectedID()); |
||||
|
||||
if (!session.password.equalsIgnoreCase("none")) { |
||||
box.displayPasswordBox(); |
||||
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); |
||||
scheduler.scheduleWithFixedDelay(()->{ |
||||
if (enteredPassword.length()!=0) { |
||||
File file = new File(sigIRC.BASEDIR+"sigIRC/tmp.data"); |
||||
|
||||
String hashedPass = GetHashedPassword(enteredPassword); |
||||
|
||||
ConnectToSession(session, hashedPass); |
||||
|
||||
enteredPassword=""; |
||||
|
||||
scheduler.shutdownNow(); |
||||
} |
||||
}, 1000l, 1000l, TimeUnit.MILLISECONDS); |
||||
} else { |
||||
ConnectToSession(session, ""); |
||||
} |
||||
if (RabiRaceModule.mySession!=null) { |
||||
setVisible(false); |
||||
} |
||||
//Attempt to join the session.
|
||||
|
||||
|
||||
} |
||||
} |
||||
}); |
||||
|
||||
sessionlist.setModel(sessionlist_model); |
||||
sessionlist.addListSelectionListener(new ListSelectionListener() { |
||||
|
||||
@Override |
||||
public void valueChanged(ListSelectionEvent arg0) { |
||||
if (sessionlist.getSelectedIndex()!=-1) { |
||||
selected = sessionlist.getSelectedIndex(); |
||||
Session session = RabiRaceModule.module.session_listing.data.get(getSelectedID()); |
||||
if (RabiRaceModule.module.mySession==null && |
||||
session.maxPlayers!=session.players.size()) { |
||||
joinButton.setEnabled(true); |
||||
} else { |
||||
joinButton.setEnabled(false); |
||||
} |
||||
} else { |
||||
joinButton.setEnabled(false); |
||||
} |
||||
} |
||||
|
||||
}); |
||||
|
||||
container.add(Box.createRigidArea(new Dimension(10,1))); |
||||
container.add(sessionPanel); |
||||
container.add(Box.createRigidArea(new Dimension(10,1))); |
||||
container.add(previewPanel); |
||||
previewPanel.setPreferredSize(new Dimension(400,300)); |
||||
|
||||
|
||||
this.add(container); |
||||
this.setMinimumSize(new Dimension(640,480)); |
||||
} |
||||
|
||||
public static void ConnectToSession(Session session, String hashedPass) { |
||||
try { |
||||
if (hashedPass.length()==0) { |
||||
hashedPass="none"; |
||||
} |
||||
File file = new File(sigIRC.BASEDIR+"sigIRC/tmp_session.data"); |
||||
org.apache.commons.io.FileUtils.copyURLToFile(new URL("http://45.33.13.215/rabirace/send.php?key=joinsession&name="+RabiRaceModule.module.myProfile.username+"&session="+session.id+"&password="+hashedPass),file); |
||||
String[] data = FileUtils.readFromFile(sigIRC.BASEDIR+"sigIRC/tmp_session.data"); |
||||
|
||||
if (data.length==1) { |
||||
int errorCode = Integer.parseInt(data[0]); |
||||
switch (errorCode) { |
||||
case 400: |
||||
case 404:{ |
||||
JOptionPane.showMessageDialog(RabiRaceModule.module.window, "Invalid format sent. Please contact the dev! This should not be happening! \n"+DebugUtils.getStackTrace(), "Error "+errorCode, JOptionPane.WARNING_MESSAGE); |
||||
}break; |
||||
case 403:{ |
||||
JOptionPane.showMessageDialog(RabiRaceModule.module.window, "Session does not exist!", "Error "+errorCode, JOptionPane.WARNING_MESSAGE); |
||||
}break; |
||||
case 405:{ |
||||
JOptionPane.showMessageDialog(RabiRaceModule.module.window, "Session room is full!", "Error "+errorCode, JOptionPane.WARNING_MESSAGE); |
||||
}break; |
||||
case 406:{ |
||||
JOptionPane.showMessageDialog(RabiRaceModule.module.window, "Incorrect Password! "+hashedPass, "Error "+errorCode, JOptionPane.WARNING_MESSAGE); |
||||
}break; |
||||
case 0:{ |
||||
RabiRaceModule.mySession = session; |
||||
}break; |
||||
} |
||||
} |
||||
} catch (IOException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
|
||||
public void run() { |
||||
this.repaint(); |
||||
} |
||||
|
||||
public static String GetHashedPassword(String input) { |
||||
try { |
||||
java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5"); |
||||
byte[] array = md.digest(input.getBytes()); |
||||
StringBuffer sb = new StringBuffer(); |
||||
for (int i = 0; i < array.length; ++i) { |
||||
sb.append(Integer.toHexString((array[i] & 0xFF) | 0x100).substring(1,3)); |
||||
} |
||||
return sb.toString(); |
||||
} catch (java.security.NoSuchAlgorithmException e) { |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
public void UpdateSessionList() { |
||||
selected = sessionlist.getSelectedIndex(); |
||||
int selectedID = getSelectedID(); |
||||
sessionlist_model.clear(); |
||||
int count=0; |
||||
for (Integer id : RabiRaceModule.module.session_listing.data.keySet()) { |
||||
Session session = RabiRaceModule.module.session_listing.data.get(id); |
||||
sessionlist_model.addElement((session.password.equalsIgnoreCase("none")?"":"🔑 ")+session.id+" - "+session.name+" ("+session.players.size()+"/"+session.maxPlayers+")"); |
||||
if (id == selectedID && sessionlist_model.getSize()>count) { |
||||
sessionlist.setSelectedIndex(count); |
||||
} |
||||
count++; |
||||
} |
||||
//System.out.println("Selected is "+selected);
|
||||
//Try to find ID in list.
|
||||
} |
||||
|
||||
public int getSelectedID() { |
||||
if (selected!=-1) { |
||||
return Integer.parseInt(sessionlist_model.getElementAt(selected).replaceAll("🔑", "").split(" - ")[0].trim()); |
||||
} |
||||
return -1; |
||||
} |
||||
|
||||
class DataPanel extends JPanel{ |
||||
SessionListWindow window; |
||||
public void setWindow(SessionListWindow window) { |
||||
this.window=window; |
||||
} |
||||
public void paintComponent(Graphics g) { |
||||
super.paintComponent(g); |
||||
//Axis.GetAxisDisplay(g,window.ConstructTemporaryAxis(),0,0,window.axis_width,window.axis_height);
|
||||
//Axis.GetAxisIndicatorDisplay(g,window.ConstructTemporaryAxis(),0,0,window.axis_width,window.axis_height);
|
||||
if (selected!=-1 && |
||||
RabiRaceModule.module.session_listing.data.size()>selected) { |
||||
int selectedID = getSelectedID(); |
||||
//Get the players from that session.
|
||||
Session s = RabiRaceModule.module.session_listing.data.get(selectedID); |
||||
|
||||
Profile.DrawMultiPanel(g,0,0,400,s.players); |
||||
} |
||||
} |
||||
} |
||||
|
||||
class PasswordBox extends JFrame{ |
||||
JPasswordField pass = new JPasswordField(); |
||||
JButton okay = new JButton("Submit"); |
||||
JPanel container = new JPanel(); |
||||
public PasswordBox(){ |
||||
this.setVisible(false); |
||||
container.setLayout(new BoxLayout(container,BoxLayout.PAGE_AXIS)); |
||||
container.add(Box.createRigidArea(new Dimension(240,20))); |
||||
JPanel label_panel = new JPanel(); |
||||
label_panel.setLayout(new BoxLayout(label_panel,BoxLayout.LINE_AXIS)); |
||||
label_panel.add(Box.createRigidArea(new Dimension(20,5))); |
||||
JLabel label = new JLabel("Please enter the password required to join this session:"); |
||||
label_panel.add(label); |
||||
label_panel.add(Box.createRigidArea(new Dimension(20,5))); |
||||
label.setLayout(new BoxLayout(label,BoxLayout.LINE_AXIS)); |
||||
container.add(label_panel); |
||||
container.add(Box.createRigidArea(new Dimension(240,5))); |
||||
JPanel pass_row = new JPanel(); |
||||
pass_row.setLayout(new BoxLayout(pass_row,BoxLayout.LINE_AXIS)); |
||||
pass.setMinimumSize(new Dimension(120,20)); |
||||
pass.setPreferredSize(new Dimension(120,20)); |
||||
pass_row.setSize(240,20); |
||||
pass_row.add(Box.createRigidArea(new Dimension(20,5))); |
||||
pass_row.add(pass); |
||||
pass_row.add(Box.createRigidArea(new Dimension(20,5))); |
||||
|
||||
okay.addActionListener(new ActionListener(){ |
||||
@Override |
||||
public void actionPerformed(ActionEvent ev) { |
||||
enteredPassword = String.copyValueOf(pass.getPassword()); |
||||
box.setVisible(false); |
||||
} |
||||
}); |
||||
|
||||
container.add(pass_row); |
||||
container.add(okay); |
||||
container.add(Box.createRigidArea(new Dimension(240,20))); |
||||
this.add(container); |
||||
this.pack(); |
||||
} |
||||
|
||||
public void displayPasswordBox() { |
||||
this.setVisible(true); |
||||
pass.setText(""); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,463 @@ |
||||
package sig.modules; |
||||
|
||||
import java.awt.Color; |
||||
import java.awt.Graphics; |
||||
import java.awt.Image; |
||||
import java.awt.Rectangle; |
||||
import java.awt.event.MouseEvent; |
||||
import java.awt.geom.Rectangle2D; |
||||
import java.awt.image.BufferedImage; |
||||
import java.io.File; |
||||
import java.io.IOException; |
||||
import java.net.MalformedURLException; |
||||
import java.net.URL; |
||||
import java.util.ArrayList; |
||||
import java.util.Arrays; |
||||
import java.util.ConcurrentModificationException; |
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
import java.util.concurrent.Executors; |
||||
import java.util.concurrent.ScheduledExecutorService; |
||||
import java.util.concurrent.TimeUnit; |
||||
|
||||
import javax.imageio.ImageIO; |
||||
|
||||
import com.sun.jna.Memory; |
||||
import com.sun.jna.Pointer; |
||||
import com.sun.jna.platform.win32.Kernel32; |
||||
import com.sun.jna.platform.win32.WinNT; |
||||
import com.sun.jna.platform.win32.WinNT.HANDLE; |
||||
|
||||
import sig.FileManager; |
||||
import sig.Module; |
||||
import sig.sigIRC; |
||||
import sig.modules.RabiRace.ClickableButton; |
||||
import sig.modules.RabiRace.ColorCycler; |
||||
import sig.modules.RabiRace.CreateButton; |
||||
import sig.modules.RabiRace.JoinButton; |
||||
import sig.modules.RabiRace.MemoryData; |
||||
import sig.modules.RabiRace.Profile; |
||||
import sig.modules.RabiRace.Session; |
||||
import sig.modules.RabiRace.SessionCreateWindow; |
||||
import sig.modules.RabiRace.SessionListData; |
||||
import sig.modules.RabiRace.SessionListWindow; |
||||
import sig.modules.RabiRibi.MemoryOffset; |
||||
import sig.modules.RabiRibi.MemoryType; |
||||
import sig.modules.utils.PsapiTools; |
||||
import sig.utils.DrawUtils; |
||||
import sig.utils.FileUtils; |
||||
import sig.utils.TextUtils; |
||||
|
||||
public class RabiRaceModule extends Module{ |
||||
final static String ITEMS_DIRECTORY = sigIRC.BASEDIR+"sigIRC/rabi-ribi/items/"; |
||||
final int PROCESS_PERMISSIONS = WinNT.PROCESS_QUERY_INFORMATION | WinNT.PROCESS_VM_READ; |
||||
boolean foundRabiRibi = false; |
||||
int rabiRibiPID = -1; |
||||
long rabiRibiMemOffset = 0; |
||||
public HANDLE rabiribiProcess = null; |
||||
public static HashMap<String,Image> image_map = new HashMap<String,Image>(); |
||||
public static ColorCycler rainbowcycler = new ColorCycler(new Color(255,0,0,96),8); |
||||
public Profile myProfile = new Profile(this,false); |
||||
public static RabiRaceModule module; |
||||
public static SessionListWindow window; |
||||
public static SessionCreateWindow createwindow; |
||||
public static Session mySession; |
||||
boolean firstCheck=false; |
||||
public List<ScrollingText> messages = new ArrayList<ScrollingText>(); |
||||
public static int lastScrollX = 0; |
||||
boolean firstUpdate=true; |
||||
|
||||
public SessionListData session_listing = new SessionListData(); |
||||
|
||||
ClickableButton join_button,create_button; |
||||
|
||||
public static List<MemoryData> key_items_list = new ArrayList<MemoryData>(); |
||||
public static List<MemoryData> badges_list = new ArrayList<MemoryData>(); |
||||
|
||||
public RabiRaceModule(Rectangle2D bounds, String moduleName) { |
||||
super(bounds, moduleName); |
||||
//Initialize();
|
||||
Initialize(); |
||||
module = this; |
||||
window = new SessionListWindow(); |
||||
window.setVisible(false); |
||||
createwindow = new SessionCreateWindow(); |
||||
createwindow.setVisible(false); |
||||
//System.out.println("Money value is: "+readIntFromMemory(MemoryOffset.MONEY));
|
||||
} |
||||
|
||||
private void Initialize() { |
||||
CheckRabiRibiClient(); |
||||
|
||||
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); |
||||
scheduler.scheduleWithFixedDelay(()->{ |
||||
CheckRabiRibiClient(); |
||||
if (foundRabiRibi) { |
||||
myProfile.uploadProfile(); |
||||
getSessionList(); |
||||
getMessageUpdates(); |
||||
//trimeadProfile.downloadProfile();
|
||||
firstCheck=true; |
||||
if (mySession!=null) { |
||||
File file = new File(sigIRC.BASEDIR+"sigIRC/tmp.data"); |
||||
try { |
||||
org.apache.commons.io.FileUtils.copyURLToFile(new URL("http://45.33.13.215/rabirace/send.php?key=keepalivesession&session="+mySession.getID()),file); |
||||
} catch (MalformedURLException e) { |
||||
e.printStackTrace(); |
||||
} catch (IOException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
} |
||||
}, 5000, 5000, TimeUnit.MILLISECONDS); |
||||
ScheduledExecutorService scheduler2 = Executors.newScheduledThreadPool(1); |
||||
scheduler2.scheduleWithFixedDelay(()->{ |
||||
if (foundRabiRibi) { |
||||
UpdateMyProfile(); |
||||
} |
||||
}, 250, 250, TimeUnit.MILLISECONDS); |
||||
|
||||
File dir = new File(ITEMS_DIRECTORY); |
||||
|
||||
for (MemoryData data : MemoryData.values()) { |
||||
//Attempt to fetch from server.
|
||||
new FileManager("sigIRC/rabi-ribi/items/"+data.img_path).verifyAndFetchFileFromServer(); |
||||
} |
||||
new FileManager("sigIRC/rabi-ribi/items/easter_egg.png").verifyAndFetchFileFromServer(); |
||||
new FileManager("sigIRC/rabi-ribi/items/health_up.png").verifyAndFetchFileFromServer(); |
||||
new FileManager("sigIRC/rabi-ribi/items/mana_up.png").verifyAndFetchFileFromServer(); |
||||
new FileManager("sigIRC/rabi-ribi/items/regen_up.png").verifyAndFetchFileFromServer(); |
||||
new FileManager("sigIRC/rabi-ribi/items/pack_up.png").verifyAndFetchFileFromServer(); |
||||
new FileManager("sigIRC/rabi-ribi/items/attack_up.png").verifyAndFetchFileFromServer(); |
||||
|
||||
String[] images = dir.list(); |
||||
List<String> filtered_images = new ArrayList<String>(); |
||||
for (String file : images) { |
||||
File f = new File(ITEMS_DIRECTORY+file); |
||||
if (!f.isDirectory()) { |
||||
filtered_images.add(file); |
||||
} |
||||
} |
||||
images = filtered_images.toArray(new String[filtered_images.size()]); |
||||
for (String image : images) { |
||||
try { |
||||
//System.out.println("Loaded "+image);
|
||||
image_map.put(image, ImageIO.read(new File(ITEMS_DIRECTORY+image))); |
||||
} catch (IOException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
|
||||
for (MemoryData md : MemoryData.values()) { |
||||
if (md.key_item) { |
||||
key_items_list.add(md); |
||||
} else { |
||||
badges_list.add(md); |
||||
} |
||||
} |
||||
|
||||
//trimeadProfile.username = "trimead";
|
||||
|
||||
join_button = new JoinButton(new Rectangle(2,(int)(position.getHeight()-18),120,18),"Join Session (0)",this); |
||||
create_button = new CreateButton(new Rectangle(122,(int)(position.getHeight()-18),120,18),"Create Session",this); |
||||
} |
||||
|
||||
private void getMessageUpdates() { |
||||
File file = new File(sigIRC.BASEDIR+"sigIRC/messages"); |
||||
try { |
||||
org.apache.commons.io.FileUtils.copyURLToFile(new URL("http://45.33.13.215/rabirace/send.php?key=getupdates&name="+myProfile.username),file); |
||||
} catch (MalformedURLException e) { |
||||
e.printStackTrace(); |
||||
} catch (IOException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
String[] data = FileUtils.readFromFile(sigIRC.BASEDIR+"sigIRC/messages"); |
||||
for (String s : data) { |
||||
if (s.length()>0) { |
||||
messages.add(new ScrollingText(s,(int)(lastScrollX+position.getWidth()+24),(int)(position.getHeight()-28))); |
||||
} |
||||
} |
||||
} |
||||
|
||||
public void getSessionList() { |
||||
File file = new File(sigIRC.BASEDIR+"sessions"); |
||||
try { |
||||
org.apache.commons.io.FileUtils.copyURLToFile(new URL("http://45.33.13.215/rabirace/send.php?key=getsessions"),file); |
||||
String[] data = FileUtils.readFromFile(sigIRC.BASEDIR+"sessions"); |
||||
//System.out.println("Data is "+Arrays.toString(data));
|
||||
session_listing.UpdateData(data); |
||||
} catch (IOException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
if (mySession==null) { |
||||
join_button.setButtonLabel("Join Session ("+session_listing.getSessions().size()+")"); |
||||
} else { |
||||
join_button.setButtonLabel("Leave Session"); |
||||
} |
||||
window.UpdateSessionList(); |
||||
} |
||||
|
||||
public void mousePressed(MouseEvent ev) { |
||||
if (firstCheck && join_button.mouseInsideBounds(ev)) { |
||||
join_button.onClickEvent(ev); |
||||
} |
||||
if (firstCheck && mySession==null && create_button.mouseInsideBounds(ev)) { |
||||
create_button.onClickEvent(ev); |
||||
} |
||||
} |
||||
|
||||
private void CheckRabiRibiClient() { |
||||
List<Integer> pids; |
||||
try { |
||||
pids = PsapiTools.getInstance().enumProcesses(); |
||||
boolean found=false; |
||||
for (Integer pid : pids) { |
||||
HANDLE process = Kernel32.INSTANCE.OpenProcess(PROCESS_PERMISSIONS, true, pid); |
||||
List<sig.modules.utils.Module> hModules; |
||||
try { |
||||
hModules = PsapiTools.getInstance().EnumProcessModules(process); |
||||
for(sig.modules.utils.Module m: hModules){ |
||||
//System.out.println(m.getFileName()+":"+m.getEntryPoint());
|
||||
if (m.getFileName().contains("rabiribi")) { |
||||
found=true; |
||||
if (!foundRabiRibi) { |
||||
rabiRibiMemOffset = Pointer.nativeValue(m.getLpBaseOfDll().getPointer()); |
||||
System.out.println("Found an instance of Rabi-Ribi at 0x"+Long.toHexString(rabiRibiMemOffset)+" | File:"+m.getFileName()+","+m.getBaseName()); |
||||
rabiRibiPID=pid; |
||||
foundRabiRibi=true; |
||||
rabiribiProcess=process; |
||||
break; |
||||
} |
||||
break; |
||||
} |
||||
} |
||||
if (found) { |
||||
break; |
||||
} |
||||
} catch (Exception e) { |
||||
e.printStackTrace(); |
||||
} |
||||
if (process!=null) { |
||||
Kernel32.INSTANCE.CloseHandle(process); |
||||
} |
||||
} |
||||
if (!found && foundRabiRibi) { |
||||
foundRabiRibi=false; |
||||
System.out.println("Rabi-Ribi process lost."); |
||||
} |
||||
} catch (Exception e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
|
||||
public void run() { |
||||
if (foundRabiRibi) { |
||||
rainbowcycler.run(); |
||||
if (window!=null) { |
||||
window.run(); |
||||
} |
||||
for (int i=0;i<messages.size();i++) { |
||||
if (!messages.get(i).run()) { |
||||
messages.remove(i--); |
||||
} |
||||
} |
||||
if (lastScrollX>0) { |
||||
lastScrollX-=ScrollingText.SCROLLSPD; |
||||
} |
||||
} |
||||
} |
||||
|
||||
private void UpdateMyProfile() { |
||||
if (foundRabiRibi) { |
||||
//System.out.println("Called.");
|
||||
int paused = readIntFromMemory(MemoryOffset.PAUSED); |
||||
float itempct = readFloatFromMemory(MemoryOffset.ITEM_PERCENT); |
||||
myProfile.isPaused = paused==1; |
||||
//System.out.println(itempct+","+paused);
|
||||
if (paused==0 && itempct>=0) { |
||||
if (mySession!=null) { |
||||
myProfile.archiveAllValues(); |
||||
} |
||||
myProfile.rainbowEggCount = readIntFromMemory(MemoryOffset.RAINBOW_EGG_COUNT); |
||||
myProfile.attackUps = readItemCountFromMemory(MemoryOffset.ATTACKUP_START,MemoryOffset.ATTACKUP_END); |
||||
myProfile.healthUps = readItemCountFromMemory(MemoryOffset.HEALTHUP_START,MemoryOffset.HEALTHUP_END); |
||||
myProfile.manaUps = readItemCountFromMemory(MemoryOffset.MANAUP_START,MemoryOffset.MANAUP_END); |
||||
myProfile.regenUps = readItemCountFromMemory(MemoryOffset.REGENUP_START,MemoryOffset.REGENUP_END); |
||||
myProfile.packUps = readItemCountFromMemory(MemoryOffset.PACKUP_START,MemoryOffset.PACKUP_END); |
||||
myProfile.itempct = itempct; |
||||
myProfile.mappct = readFloatFromMemory(MemoryOffset.MAP_PERCENT); |
||||
myProfile.playtime = readIntFromMemory(MemoryOffset.PLAYTIME); |
||||
myProfile.difficulty = readIntFromMemory(MemoryOffset.GAME_DIFFICULTY); |
||||
myProfile.loop = readIntFromMemory(MemoryOffset.GAME_LOOP); |
||||
myProfile.updateClientValues(); |
||||
if (mySession!=null && !firstUpdate) { |
||||
myProfile.compareAndAnnounceAllChangedValues(); |
||||
} |
||||
firstUpdate=false; |
||||
} |
||||
} |
||||
} |
||||
|
||||
public void ApplyConfigWindowProperties() { |
||||
sigIRC.rabiracemodule_X=(int)position.getX(); |
||||
sigIRC.rabiracemodule_Y=(int)position.getY(); |
||||
sigIRC.config.setInteger("RABIRACE_module_X", sigIRC.rabiracemodule_X); |
||||
sigIRC.config.setInteger("RABIRACE_module_Y", sigIRC.rabiracemodule_Y); |
||||
} |
||||
|
||||
/*public int readIntFromErinaData(MemoryOffset val) { |
||||
return readIntFromPointer(val,MemoryOffset.ENTITY_ARRAY); |
||||
} |
||||
|
||||
public float readFloatFromErinaData(MemoryOffset val) { |
||||
return readFloatFromPointer(val,MemoryOffset.ENTITY_ARRAY); |
||||
}*/ |
||||
|
||||
public int readIntFromMemory(long offset) { |
||||
Memory mem = new Memory(4); |
||||
Kernel32.INSTANCE.ReadProcessMemory(rabiribiProcess, new Pointer(rabiRibiMemOffset+offset), mem, 4, null); |
||||
return mem.getInt(0); |
||||
} |
||||
|
||||
public float readFloatFromMemory(long offset) { |
||||
Memory mem = new Memory(4); |
||||
Kernel32.INSTANCE.ReadProcessMemory(rabiribiProcess, new Pointer(rabiRibiMemOffset+offset), mem, 4, null); |
||||
return mem.getFloat(0); |
||||
} |
||||
|
||||
public float readFloatFromMemoryOffset(MemoryOffset val, long pointer) { |
||||
Memory mem = new Memory(4); |
||||
Kernel32.INSTANCE.ReadProcessMemory(rabiribiProcess, new Pointer(pointer+val.getOffset()), mem, 4, null); |
||||
return mem.getFloat(0); |
||||
} |
||||
|
||||
public int readIntFromMemoryOffset(MemoryOffset val, long pointer) { |
||||
Memory mem = new Memory(4); |
||||
Kernel32.INSTANCE.ReadProcessMemory(rabiribiProcess, new Pointer(pointer+val.getOffset()), mem, 4, null); |
||||
return mem.getInt(0); |
||||
} |
||||
|
||||
public float readDirectFloatFromMemoryLocation(long pointer) { |
||||
Memory mem = new Memory(4); |
||||
Kernel32.INSTANCE.ReadProcessMemory(rabiribiProcess, new Pointer(pointer), mem, 4, null); |
||||
return mem.getFloat(0); |
||||
} |
||||
|
||||
public int readDirectIntFromMemoryLocation(long pointer) { |
||||
Memory mem = new Memory(4); |
||||
Kernel32.INSTANCE.ReadProcessMemory(rabiribiProcess, new Pointer(pointer), mem, 4, null); |
||||
return mem.getInt(0); |
||||
} |
||||
|
||||
public int readIntFromPointer(MemoryOffset val, MemoryOffset pointer) { |
||||
Memory mem = new Memory(4); |
||||
Kernel32.INSTANCE.ReadProcessMemory(rabiribiProcess, new Pointer(readIntFromMemory(pointer.getOffset())+val.getOffset()), mem, 4, null); |
||||
return mem.getInt(0); |
||||
} |
||||
|
||||
public float readFloatFromPointer(MemoryOffset val, MemoryOffset pointer) { |
||||
Memory mem = new Memory(4); |
||||
Kernel32.INSTANCE.ReadProcessMemory(rabiribiProcess, new Pointer(readIntFromMemory(pointer.getOffset())+val.getOffset()), mem, 4, null); |
||||
return mem.getFloat(0); |
||||
} |
||||
|
||||
public int readIntFromMemory(MemoryOffset val) { |
||||
return (int)readFromMemory(val,MemoryType.INTEGER); |
||||
} |
||||
|
||||
public float readFloatFromMemory(MemoryOffset val) { |
||||
return (float)readFromMemory(val,MemoryType.FLOAT); |
||||
} |
||||
|
||||
Object readFromMemory(MemoryOffset val, MemoryType type) { |
||||
Memory mem = new Memory(type.getSize()); |
||||
Kernel32.INSTANCE.ReadProcessMemory(rabiribiProcess, new Pointer(rabiRibiMemOffset+val.getOffset()), mem, type.getSize(), null); |
||||
switch (type) { |
||||
case FLOAT: |
||||
return mem.getFloat(0); |
||||
case INTEGER: |
||||
return mem.getInt(0); |
||||
default: |
||||
System.out.println("WARNING! Type "+type+" does not have a defined value."); |
||||
return -1; |
||||
} |
||||
} |
||||
|
||||
int readItemCountFromMemory(MemoryOffset start_range, |
||||
MemoryOffset end_range) { |
||||
int count=0; |
||||
for (long i=start_range.getOffset();i<=end_range.getOffset();i++) { |
||||
if (readIntFromMemory(i)==1) { |
||||
count++; |
||||
} |
||||
} |
||||
return count; |
||||
} |
||||
|
||||
public void draw(Graphics g) { |
||||
super.draw(g); |
||||
|
||||
if (!foundRabiRibi) { |
||||
DrawUtils.drawTextFont(g, sigIRC.panel.userFont, position.getX(), position.getY()+26, Color.BLACK, "Rabi-Ribi not found! Please start it."); |
||||
} else { |
||||
//myProfile.draw(g);
|
||||
Image panel = myProfile.getStatPanel((int)position.getWidth()); |
||||
g.drawImage(panel, (int)position.getX(), (int)position.getY(), sigIRC.panel); |
||||
g.drawImage(myProfile.getStatText((int)position.getWidth()), (int)position.getX(), (int)position.getY(), sigIRC.panel); |
||||
|
||||
//Profile.DrawMultiPanel(g, (int)(position.getX()), (int)(position.getY())+panel.getHeight(sigIRC.panel), (int)position.getWidth(), testing);
|
||||
if (mySession!=null) { |
||||
List<Profile> sessionPlayers = new ArrayList<Profile>(); |
||||
for (Profile p : mySession.getPlayers()) { |
||||
if (!p.username.equalsIgnoreCase(myProfile.username)) { |
||||
sessionPlayers.add(p); |
||||
//System.out.println("Found unique player "+p);
|
||||
} |
||||
} |
||||
Profile.DrawMultiPanel(g, (int)(position.getX()), (int)(position.getY())+panel.getHeight(sigIRC.panel), (int)position.getWidth(), sessionPlayers); |
||||
} |
||||
|
||||
if (firstCheck) { |
||||
join_button.draw(g); |
||||
if (mySession==null) { |
||||
create_button.draw(g); |
||||
} |
||||
} |
||||
g.setColor(Color.BLACK); |
||||
g.fillRect((int)(position.getX()), (int)(position.getY()+position.getHeight()-28-20), (int)(position.getWidth()), 20); |
||||
for (int i=0;i<messages.size();i++) { |
||||
messages.get(i).draw(g); |
||||
} |
||||
} |
||||
} |
||||
|
||||
class ScrollingText{ |
||||
String msg; |
||||
int x; |
||||
int y; |
||||
Rectangle2D bounds; |
||||
final static int SCROLLSPD = 4; |
||||
|
||||
public ScrollingText(String message, int x, int y) { |
||||
this.msg = message; |
||||
this.x = x; |
||||
this.y = y; |
||||
this.bounds = TextUtils.calculateStringBoundsFont(message, sigIRC.panel.rabiRibiTinyDisplayFont); |
||||
RabiRaceModule.lastScrollX += bounds.getWidth() + 96; |
||||
} |
||||
|
||||
public boolean run() { |
||||
x-=SCROLLSPD; |
||||
if (x+bounds.getWidth()<0) { |
||||
return false; |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
public void draw(Graphics g) { |
||||
if (x<position.getWidth()) { |
||||
DrawUtils.drawOutlineText(g, sigIRC.panel.rabiRibiTinyDisplayFont, position.getX()+x, position.getY()+y-6, 2, Color.WHITE, Color.GRAY, msg); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,218 @@ |
||||
package sig.modules.RabiRibi; |
||||
|
||||
import java.awt.Point; |
||||
import java.lang.reflect.Field; |
||||
import java.util.concurrent.Executors; |
||||
import java.util.concurrent.ScheduledExecutorService; |
||||
import java.util.concurrent.TimeUnit; |
||||
|
||||
import com.sun.jna.Memory; |
||||
import com.sun.jna.Pointer; |
||||
import com.sun.jna.platform.win32.Kernel32; |
||||
|
||||
import sig.modules.RabiRibiModule; |
||||
import sig.modules.RabiRibi.SmoothObjects.EntityMarker; |
||||
import sig.utils.ReflectUtils; |
||||
|
||||
public class Entity { |
||||
int id = 0; |
||||
int uuid = 0; |
||||
int hp = 0; |
||||
int maxhp = 0; |
||||
boolean active = false; |
||||
int animation = 0; |
||||
float x = 0; |
||||
float y = 0; |
||||
RabiRibiModule parent = null; |
||||
int lastTookDamage = 0; |
||||
long pointer; |
||||
int color = 0; |
||||
public EntityMarker marker; |
||||
public static int taskDone=1; //1 = Free, 0 = In Progress, -1 = Stop all current processes
|
||||
|
||||
boolean killed=false; |
||||
|
||||
public Entity(long memoryOffset, int uuid, RabiRibiModule parent) { |
||||
this.parent=parent; |
||||
pointer = memoryOffset; |
||||
this.uuid = uuid; |
||||
this.marker = new EntityMarker((int)x,(int)y,(int)x,(int)y,this,parent); |
||||
UpdateValues(); |
||||
this.active = readIntFromMemoryOffset(MemoryOffset.ENTITY_ISACTIVE, pointer)==1 && |
||||
/*id!=0 && id!=1 &&*/ maxhp!=0; |
||||
if (this.active) { |
||||
parent.overlay.objects.add(this.marker); |
||||
} |
||||
} |
||||
|
||||
public boolean run() { |
||||
this.active = readIntFromMemoryOffset(MemoryOffset.ENTITY_ISACTIVE, pointer)==1 && |
||||
id!=0 && id!=1 && maxhp!=0; |
||||
|
||||
if (!active) { |
||||
return false; |
||||
} |
||||
|
||||
if (readIntFromMemoryOffset(MemoryOffset.ENTITY_HP, pointer)<hp) { |
||||
lastTookDamage = parent.readIntFromMemory(MemoryOffset.PLAYTIME); |
||||
} |
||||
|
||||
UpdateValues(); |
||||
return true; |
||||
} |
||||
|
||||
/*public Point getScreenPosition() { |
||||
//The screen supports 20x11.5 tiles per map tile.
|
||||
//A map tile is 1280x720
|
||||
//float xtile = x
|
||||
}*/ |
||||
|
||||
public int getHealth() { |
||||
return hp; |
||||
} |
||||
|
||||
public int getMaxHealth() { |
||||
return maxhp; |
||||
} |
||||
|
||||
public int getLastHitTime() { |
||||
return lastTookDamage; |
||||
} |
||||
|
||||
public int getID() { |
||||
return id; |
||||
} |
||||
|
||||
private void UpdateValues() { |
||||
this.id = readIntFromMemoryOffset(MemoryOffset.ENTITY_ID, pointer); |
||||
this.animation = readIntFromMemoryOffset(MemoryOffset.ENTITY_ANIMATION, pointer); |
||||
if (this.animation!=-9999) { |
||||
this.hp = readIntFromMemoryOffset(MemoryOffset.ENTITY_HP, pointer); |
||||
} else { |
||||
if (active && !killed) { |
||||
killed=true; |
||||
if (taskDone==1 && !RabiUtils.isGamePaused()) { |
||||
RetrieveMoneyValueForLookupData(id,color); |
||||
} |
||||
EntityLookupData data = EntityLookupData.getEntityLookupData(id, color); |
||||
data.increaseKills(1); |
||||
} |
||||
this.hp = 0; |
||||
} |
||||
this.maxhp = readIntFromMemoryOffset(MemoryOffset.ENTITY_MAXHP, pointer); |
||||
this.x = readFloatFromMemoryOffset(MemoryOffset.ENTITY_XPOS, pointer); |
||||
this.y = readFloatFromMemoryOffset(MemoryOffset.ENTITY_YPOS, pointer); |
||||
this.color = readIntFromMemoryOffset(MemoryOffset.ENTITY_COLOR, pointer); |
||||
this.marker.setTarget(parent.overlay.getScreenPosition(x,y)); |
||||
} |
||||
|
||||
private void RetrieveMoneyValueForLookupData(int id, int color) { |
||||
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); |
||||
scheduler.scheduleWithFixedDelay(new MoneyUpdateTask(scheduler,id,color,parent),500,500,TimeUnit.MILLISECONDS); |
||||
} |
||||
|
||||
public int getUniqueID() { |
||||
return uuid; |
||||
} |
||||
|
||||
public boolean isActive() { |
||||
return active; |
||||
} |
||||
|
||||
public float readFloatFromMemoryOffset(MemoryOffset val, long pointer) { |
||||
Memory mem = new Memory(4); |
||||
Kernel32.INSTANCE.ReadProcessMemory(parent.rabiribiProcess, new Pointer(pointer+val.getOffset()), mem, 4, null); |
||||
return mem.getFloat(0); |
||||
} |
||||
|
||||
public int readIntFromMemoryOffset(MemoryOffset val, long pointer) { |
||||
Memory mem = new Memory(4); |
||||
Kernel32.INSTANCE.ReadProcessMemory(parent.rabiribiProcess, new Pointer(pointer+val.getOffset()), mem, 4, null); |
||||
return mem.getInt(0); |
||||
} |
||||
|
||||
public String toString() { |
||||
StringBuilder sb = new StringBuilder(); |
||||
sb.append(this.getClass().getName()+"("); |
||||
boolean first=false; |
||||
for (Field f : this.getClass().getDeclaredFields()) { |
||||
//if (!ReflectUtils.isCloneable(f)) {
|
||||
if (!first) { |
||||
try { |
||||
sb.append(f.getName()+"="+f.get(this)); |
||||
first=true; |
||||
} catch (IllegalArgumentException e) { |
||||
e.printStackTrace(); |
||||
} catch (IllegalAccessException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} else { |
||||
try { |
||||
sb.append(","+f.getName()+"="+f.get(this)); |
||||
} catch (IllegalArgumentException e) { |
||||
e.printStackTrace(); |
||||
} catch (IllegalAccessException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
//}
|
||||
} |
||||
sb.append(")"); |
||||
return sb.toString(); |
||||
} |
||||
|
||||
class MoneyUpdateTask implements Runnable{ |
||||
ScheduledExecutorService scheduler; |
||||
RabiRibiModule parent; |
||||
int prev_money_val = -1; |
||||
int starting_money_val = 0; |
||||
int id, col; |
||||
int checkcount=0; |
||||
|
||||
MoneyUpdateTask(ScheduledExecutorService scheduler, int id, int col, RabiRibiModule parent) { |
||||
this.scheduler=scheduler; |
||||
this.parent=parent; |
||||
UpdateMoney(); |
||||
starting_money_val = prev_money_val; |
||||
this.id=id; |
||||
this.col=col; |
||||
//System.out.println("Starting Money Value: "+starting_money_val);
|
||||
} |
||||
|
||||
private void UpdateMoney() { |
||||
prev_money_val = parent.readIntFromMemory(MemoryOffset.MONEY); |
||||
} |
||||
|
||||
@Override |
||||
public void run() { |
||||
if (Entity.taskDone==-1) { |
||||
System.out.println("Quitting early, killed an extra enemy."); |
||||
Entity.taskDone=1; |
||||
scheduler.shutdownNow(); |
||||
return; |
||||
} |
||||
if (RabiUtils.isGamePaused()) { |
||||
return; |
||||
} |
||||
int current_money = parent.readIntFromMemory(MemoryOffset.MONEY); |
||||
if (current_money==prev_money_val && (current_money!=starting_money_val || checkcount>5)) { |
||||
//System.out.println("Money Value matches, adding "+(current_money-starting_money_val)+" to "+lookup_data+" with ID "+id+","+color);
|
||||
String hashcode = EntityLookupData.getHashCode(id, color); |
||||
if (parent.lookup_table.containsKey(hashcode)) { |
||||
EntityLookupData lookup_data = parent.lookup_table.get(hashcode); |
||||
lookup_data.setMoney(lookup_data.getMoney()+(current_money-starting_money_val)); |
||||
} else { |
||||
EntityLookupData lookup_data = new EntityLookupData(current_money-starting_money_val); |
||||
parent.lookup_table.put(hashcode,lookup_data); |
||||
parent.setStatusMessage("Adding "+(current_money-starting_money_val)+" to hash ID "+id+","+color); |
||||
} |
||||
Entity.taskDone=1; |
||||
scheduler.shutdownNow(); |
||||
} else { |
||||
checkcount++; |
||||
UpdateMoney(); |
||||
} |
||||
} |
||||
|
||||
} |
||||
} |
@ -0,0 +1,159 @@ |
||||
package sig.modules.RabiRibi; |
||||
|
||||
import java.io.File; |
||||
import java.lang.reflect.Field; |
||||
import java.util.ArrayList; |
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
|
||||
import sig.sigIRC; |
||||
import sig.modules.RabiRibiModule; |
||||
import sig.utils.FileUtils; |
||||
|
||||
public class EntityLookupData { |
||||
final static String RABIRIBI_DIR = sigIRC.BASEDIR+"sigIRC/rabi-ribi/"; |
||||
final static String LOOKUP_DATA_FILE = RABIRIBI_DIR+"lookupdata.txt"; |
||||
int en=-1; |
||||
int kills=0; |
||||
public static RabiRibiModule parent; |
||||
|
||||
public EntityLookupData(){ |
||||
}; |
||||
|
||||
public EntityLookupData(int en){ |
||||
this(); |
||||
this.en=en; |
||||
}; |
||||
|
||||
public EntityLookupData(String[] parse_string){ |
||||
this(); |
||||
int i=1; |
||||
if (parse_string.length>=i++) { |
||||
this.en = Integer.parseInt(parse_string[0]); |
||||
} |
||||
if (parse_string.length>=i++) { |
||||
this.kills = Integer.parseInt(parse_string[1]); |
||||
} |
||||
}; |
||||
|
||||
public static int getMoney(int id, int color) { |
||||
String hashcode = EntityLookupData.getHashCode(id, color); |
||||
System.out.println("Hashcode is "+hashcode); |
||||
if (parent.lookup_table.containsKey(hashcode)) { |
||||
return parent.lookup_table.get(hashcode).getMoney(); |
||||
} else { |
||||
return -1; |
||||
} |
||||
} |
||||
|
||||
public int getMoney() { |
||||
return en; |
||||
} |
||||
|
||||
public void setMoney(int money) { |
||||
en = money; |
||||
} |
||||
|
||||
public int getKills() { |
||||
return kills; |
||||
} |
||||
|
||||
public void increaseKills(int amt) { |
||||
kills += amt; |
||||
} |
||||
|
||||
public String getSaveString() { |
||||
StringBuilder sb = new StringBuilder(); |
||||
sb.append(en); |
||||
sb.append(","); |
||||
sb.append(kills); |
||||
sb.append(","); |
||||
return sb.toString(); |
||||
} |
||||
|
||||
public static EntityLookupData getEntityLookupData(int id, int color) { |
||||
String hashcode = EntityLookupData.getHashCode(id, color); |
||||
if (parent.lookup_table.containsKey(hashcode)) { |
||||
return parent.lookup_table.get(hashcode); |
||||
} else { |
||||
EntityLookupData data = new EntityLookupData(0); |
||||
parent.lookup_table.put(getHashCode(id,color), data); |
||||
return data; |
||||
} |
||||
} |
||||
|
||||
public static String getHashCode(int id, int color) { |
||||
StringBuilder sb = new StringBuilder(); |
||||
sb.append(id); |
||||
sb.append("_"); |
||||
sb.append(color); |
||||
sb.append("_"); |
||||
sb.append(parent.readIntFromMemory(MemoryOffset.GAME_DIFFICULTY)); |
||||
sb.append("_"); |
||||
sb.append(parent.readIntFromMemory(MemoryOffset.GAME_LOOP)); |
||||
return sb.toString(); |
||||
} |
||||
|
||||
public static void saveEntityLookupData(HashMap<String,EntityLookupData> vals) { |
||||
File dir = new File(RABIRIBI_DIR); |
||||
if (!dir.exists()) { |
||||
dir.mkdirs(); |
||||
} |
||||
List<String> data = new ArrayList<String>(); |
||||
for (String s : vals.keySet()) { |
||||
EntityLookupData lookup_data = vals.get(s); |
||||
data.add(s+":"+lookup_data.getSaveString()); |
||||
} |
||||
FileUtils.writetoFile(data.toArray(new String[data.size()]), LOOKUP_DATA_FILE); |
||||
} |
||||
|
||||
public static void loadEntityLookupData(HashMap<String,EntityLookupData> map) { |
||||
File file = new File(LOOKUP_DATA_FILE); |
||||
map.clear(); |
||||
if (file.exists()) { |
||||
String[] data = FileUtils.readFromFile(LOOKUP_DATA_FILE); |
||||
for (String s : data) { |
||||
String[] key_split = s.split(":"); |
||||
String[] split = key_split[1].split(","); |
||||
|
||||
EntityLookupData lookup_data = new EntityLookupData( |
||||
split |
||||
); |
||||
|
||||
map.put(key_split[0], |
||||
lookup_data |
||||
); |
||||
} |
||||
} |
||||
} |
||||
|
||||
public String toString() { |
||||
StringBuilder sb = new StringBuilder(); |
||||
sb.append(this.getClass().getName()+"("); |
||||
boolean first=false; |
||||
for (Field f : this.getClass().getDeclaredFields()) { |
||||
//if (!ReflectUtils.isCloneable(f)) {
|
||||
if (!first) { |
||||
try { |
||||
sb.append(f.getName()+"="+f.get(this)); |
||||
first=true; |
||||
} catch (IllegalArgumentException e) { |
||||
e.printStackTrace(); |
||||
} catch (IllegalAccessException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} else { |
||||
try { |
||||
sb.append(","+f.getName()+"="+f.get(this)); |
||||
} catch (IllegalArgumentException e) { |
||||
e.printStackTrace(); |
||||
} catch (IllegalAccessException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
//}
|
||||
} |
||||
sb.append(")"); |
||||
return sb.toString(); |
||||
} |
||||
} |
@ -0,0 +1,178 @@ |
||||
package sig.modules.RabiRibi; |
||||
|
||||
public enum MemoryOffset { |
||||
MONEY(0xD654CC,0x12DA99C+OffsetHelper.KEY_ITEM_OFFSET_V185_TO_V1851), |
||||
PLAYTIME(0xD642D8,0x12D97A8+OffsetHelper.KEY_ITEM_OFFSET_V185_TO_V1851), //In frames (Rabi-Ribi runs at 60FPS).
|
||||
//UNKNOWN1(0xD65BDC), //???? Originally assumed to be "Health Ups".
|
||||
HEALTHUP_START(0xD6342C,0xD6342C+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
HEALTHUP_END(0xD63528,0xD63528+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
ATTACKUP_START(0xD6352C,0xD6352C+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
ATTACKUP_END(0xD63628,0xD63628+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
MANAUP_START(0xD6362C,0xD6362C+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
MANAUP_END(0xD63728,0xD63728+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
REGENUP_START(0xD6372C,0xD6372C+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
REGENUP_END(0xD63828,0xD63828+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
PACKUP_START(0xD6382C,0xD6382C+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
PACKUP_END(0xD63928,0xD63928+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
ENTITY_ARRAY(0x0096DA3C,0x012E3B08), //Erina Data Pointer.
|
||||
ERINA_HP(0x4D8,0X4D8), |
||||
ERINA_MAXHP(0x4E8,0x4E8), |
||||
ERINA_XPOS(0xC,0xC), |
||||
ERINA_YPOS(0x10,0x10), |
||||
ERINA_XSPEED(0x470,0x470), //Relative to Entity Array.
|
||||
ERINA_YSPEED(0x474,0x474), //Relative to Entity Array.
|
||||
MAPID(0xA600AC,0x9FF3BC), |
||||
CAMERA_XPOS(0x991AF4,0x12EED24), |
||||
CAMERA_XPOSVIEW(0,0xC969A4), |
||||
CAMERA_YPOS(0xABD0A4,0x12FB7E4), |
||||
CAMERA_YPOSVIEW(0,0xCA8AB4), |
||||
//ENTITY_SIZE(0x704),
|
||||
ENTITY_ID(0x4F4,0x4F8), |
||||
ENTITY_HP(0x4D8,0x4D8), |
||||
ENTITY_MAXHP(0x4E8,0x4E8), |
||||
ENTITY_ISACTIVE(0x674,0x674), |
||||
ENTITY_ANIMATION(0x678,0x678), |
||||
ENTITY_XPOS(0xC,0xC), |
||||
ENTITY_YPOS(0x10,0x10), |
||||
ENTITY_COLOR(0x1C,0x1C), |
||||
//TRANSITION_COUNTER(0xA7661C),*/
|
||||
WARP_TRANSITION_COUNTER(0,0x582CE0+OffsetHelper.KEY_ITEM_OFFSET_V185_TO_V1851), //Detects pausing
|
||||
|
||||
|
||||
|
||||
GAME_DIFFICULTY(0xD64338,0xD64338+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
GAME_LOOP(0xD6D05C,0xD6D05C+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
|
||||
HAMMER(0xD632B0,0xD632B0+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
AIR_JUMP(0xD632B4,0xD632B4+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
SLIDING_POWDER(0xD632B8,0xD632B8+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
CARROT_BOMB(0xD632BC,0xD632BC+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
HOURGLASS(0xD632C0,0xD632C0+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
SPEED_BOOST(0xD632C4,0xD632C4+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
AUTO_EARRINGS(0xD632C8,0xD632C8+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
RIBBON(0xD632CC,0xD632CC+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
SOUL_HEART(0xD632D0,0xD632D0+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
RABI_SLIPPERS(0xD632D4,0xD632D4+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
BUNNY_WHIRL(0xD632D8,0xD632D8+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
QUICK_BARETTE(0xD632DC,0xD632DC+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
BOOK_OF_CARROT(0xD632E0,0xD632E0+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
CHAOS_ROD(0xD632E4,0xD632E4+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
HAMMER_WAVE(0xD632E8,0xD632E8+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
HAMMER_ROLL(0xD632EC,0xD632EC+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
LIGHT_ORB(0xD632F0,0xD632F0+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
WATER_ORB(0xD632F4,0xD632F4+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
FIRE_ORB(0xD632F8,0xD632F8+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
NATURE_ORB(0xD632FC,0xD632FC+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
P_HAIRPIN(0xD63300,0x12D87D0+OffsetHelper.KEY_ITEM_OFFSET_V185_TO_V1851), |
||||
SUNNY_BEAM(0xD63304,0xD63304+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
PLUS_NECKLACE(0xD63308,0xD63308+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
CYBER_FLOWER(0xD6330C,0xD6330C+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
HEALING_STAFF(0xD63310,0xD63310+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
MAX_BRACELET(0xD63314,0xD63314+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
EXPLODE_SHOT(0xD63318,0xD63318+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
AIR_DASH(0xD6331C,0xD6331C+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
BUNNY_STRIKE(0xD63320,0xD63320+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
STRANGE_BOX(0xD63324,0xD63324+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
WALL_JUMP(0xD63328,0xD63328+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
SPIKE_BARRIER(0xD6332C,0xD6332C+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
BUNNY_AMULET(0xD63330,0xD63330+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
CHARGE_RING(0xD63334,0xD63334+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
CARROT_SHOOTER(0xD63338,0xD63338+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
SUPER_CARROT(0xD6333C,0xD6333C+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
RUMI_DONUT(0xD63340,0xD63340+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
RUMI_CAKE(0xD63344,0xD63344+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
GOLD_CARROT(0xD63348,0xD63348+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
COCOA_BOMB(0xD6334C,0xD6334C+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
UNKNOWN_ITEM1(0xD63350,0xD63350+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
TROPHY(0xD63354,0xD63354+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
EXCLAMATION_POINT(0xD63358,0xD63358+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
UNKNOWN_ITEM2(0xD6335C,0xD6335C+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
UNKNOWN_ITEM3(0xD63360,0xD63360+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
UNKNOWN_ITEM4(0xD63364,0xD63364+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
RAINBOW_MAGIC(0xD63368,0xD63368+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
UNKNOWN_ITEM5(0xD6336C,0xD6336C+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
UNKNOWN_ITEM6(0xD63370,0xD63370+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
UNKNOWN_ITEM7(0xD63374,0xD63374+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
UNKNOWN_ITEM8(0xD63378,0xD63378+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
UNKNOWN_ITEM9(0xD6337C,0xD6337C+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
UNKNOWN_ITEM10(0xD63380,0xD63380+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
UNKNOWN_ITEM11(0xD63384,0xD63384+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
UNKNOWN_ITEM12(0xD63388,0xD63388+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
UNKNOWN_ITEM13(0xD6338C,0xD6338C+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
UNKNOWN_ITEM14(0xD63390,0xD63390+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
/*DLC_ITEM1(0xD63394,0xD63394+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
DLC_ITEM2(0xD63398,0xD63398+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851),*/ |
||||
BUNNY_CLOVER(0xD6339C,0xD6339C+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
FAIRYS_FLUTE(0,0x12D8874+OffsetHelper.KEY_ITEM_OFFSET_V185_TO_V1851), |
||||
BUNNY_MEMORIES(0,0x12D7878), |
||||
WIND_BLESSING(0,0x12D7870), |
||||
DLC_ITEM4(0xD633A0,0xD633A0+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
BADGE_HEALTH_PLUS(0xD633AC,0xD633AC+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
BADGE_HEALTH_SURGE(0xD633B0,0xD633B0+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
BADGE_MANA_PLUS(0xD633B4,0xD633B4+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
BADGE_MANA_SURGE(0xD633B8,0xD633B8+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
BADGE_CRISIS_BOOST(0xD633BC,0xD633BC+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
BADGE_ATK_GROW(0xD633C0,0xD633C0+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
BADGE_DEF_GROW(0xD633C4,0xD633C4+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
BADGE_ATK_TRADE(0xD633C8,0xD633C8+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
BADGE_DEF_TRADE(0xD633CC,0xD633CC+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
BADGE_ARM_STRENGTH(0xD633D0,0xD633D0+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
BADGE_CARROT_BOOST(0xD633D4,0xD633D4+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
BADGE_WEAKEN(0xD633D8,0xD633D8+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
BADGE_SELF_DEFENSE(0xD633DC,0xD633DC+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
BADGE_ARMORED(0xD633E0,0xD633E0+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
BADGE_LUCKY_SEVEN(0xD633E4,0xD633E4+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
BADGE_HEX_CANCEL(0xD633E8,0xD633E8+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
BADGE_PURE_LOVE(0xD633EC,0xD633EC+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
BADGE_TOXIC_STRIKE(0xD633F0,0xD633F0+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
BADGE_FRAME_CANCEL(0xD633F4,0xD633F4+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
BADGE_HEALTH_WAGER(0xD633F8,0xD633F8+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
BADGE_MANA_WAGER(0xD633FC,0xD633FC+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
BADGE_STAMINA_PLUS(0xD63400,0xD63400+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
BADGE_BLESSED(0xD63404,0xD63404+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
BADGE_HITBOX_DOWN(0xD63408,0xD63408+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
BADGE_CASHBACK(0xD6340C,0xD6340C+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
BADGE_SURVIVAL(0xD63410,0xD63410+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
BADGE_TOP_FORM(0xD63414,0xD63414+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
BADGE_TOUGH_SKIN(0xD63418,0xD63418+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
BADGE_ERINA_BADGE(0xD6341C,0xD6341C+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
BADGE_RIBBON_BADGE(0xD63420,0xD63420+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
BADGE_AUTO_TRIGGER(0xD63424,0xD63424+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
BADGE_LILITHS_GIFT(0xD63428,0xD63428+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
//13413E8
|
||||
ITEM_PERCENT(0,0x13413E8), |
||||
MAP_PERCENT(0,0x13413E4), |
||||
RAINBOW_EGG_COUNT(0xD65FD4,0xD65FD4+OffsetHelper.KEY_ITEM_OFFSET_V175_TO_V1851), |
||||
PAUSED(0,0xC969A0), |
||||
; |
||||
|
||||
long offset; |
||||
long offset_v185; |
||||
long latest_offset; |
||||
|
||||
MemoryOffset(long offset,long offset_v185) { |
||||
this.offset=offset; |
||||
this.offset_v185=offset_v185; |
||||
|
||||
//TODO CHANGE THIS IF PUBLIC VERSION CHANGES!
|
||||
this.latest_offset = offset_v185; |
||||
} |
||||
|
||||
public long getOffset() { |
||||
return latest_offset; |
||||
} |
||||
|
||||
public long getOffsetV175() { |
||||
return offset; |
||||
} |
||||
|
||||
public long getOffsetV185() { |
||||
return offset_v185; |
||||
} |
||||
} |
||||
|
||||
class OffsetHelper{ |
||||
final static long KEY_ITEM_OFFSET_V175_TO_V185 = 0x5754D0; |
||||
final static long KEY_ITEM_OFFSET_V175_TO_V1851 = 0x5744D0; |
||||
final static long KEY_ITEM_OFFSET_V185_TO_V1851 = -0x1000; |
||||
} |
@ -0,0 +1,17 @@ |
||||
package sig.modules.RabiRibi; |
||||
|
||||
public enum MemoryType { |
||||
INTEGER(4), |
||||
FLOAT(4), |
||||
; |
||||
|
||||
int bytes; |
||||
|
||||
MemoryType(int bytes) { |
||||
this.bytes=bytes; |
||||
} |
||||
|
||||
public int getSize() { |
||||
return bytes; |
||||
} |
||||
} |
@ -0,0 +1,163 @@ |
||||
package sig.modules.RabiRibi; |
||||
|
||||
import com.sun.jna.Memory; |
||||
import com.sun.jna.Pointer; |
||||
import com.sun.jna.platform.win32.Kernel32; |
||||
|
||||
import sig.modules.RabiRibiModule; |
||||
import sig.utils.DebugUtils; |
||||
|
||||
public class MemoryValue { |
||||
RabiRibiModule parent; |
||||
MemoryValueType type; |
||||
long offset=-1; |
||||
long pointer=-1; |
||||
public boolean needsUpdating=false; |
||||
int lastIntValue; |
||||
float lastFloatValue; |
||||
|
||||
public MemoryValue(MemoryValueType type, long offset, RabiRibiModule parent) { |
||||
this.type=type; |
||||
this.offset=offset; |
||||
this.parent=parent; |
||||
} |
||||
|
||||
public MemoryValue(long offset, long pointer, RabiRibiModule parent) { |
||||
this(MemoryValueType.POINTER,offset, parent); |
||||
this.pointer=pointer; |
||||
} |
||||
|
||||
public MemoryValue(MemoryValueType type, MemoryOffset offset, RabiRibiModule parent) { |
||||
this(type,offset.getOffset(),parent); |
||||
} |
||||
|
||||
public MemoryValue(MemoryOffset offset, MemoryOffset pointer, RabiRibiModule parent) { |
||||
this(offset.getOffset(),pointer.getOffset(),parent); |
||||
} |
||||
|
||||
public int getInt() { |
||||
if (needsUpdating) { |
||||
switch (type) { |
||||
case ABSOLUTE: |
||||
lastIntValue = readDirectIntFromMemoryLocation(offset); |
||||
break; |
||||
case LOCAL: |
||||
lastIntValue = readIntFromMemory(offset); |
||||
break; |
||||
case POINTER: |
||||
lastIntValue = readIntFromPointer(offset,pointer); |
||||
break; |
||||
} |
||||
needsUpdating=false; |
||||
} |
||||
return lastIntValue; |
||||
} |
||||
|
||||
public float getFloat() { |
||||
if (needsUpdating) { |
||||
switch (type) { |
||||
case ABSOLUTE: |
||||
lastFloatValue = readDirectFloatFromMemoryLocation(offset); |
||||
break; |
||||
case LOCAL: |
||||
lastFloatValue = readFloatFromMemory(offset); |
||||
break; |
||||
case POINTER: |
||||
lastFloatValue = readFloatFromPointer(offset,pointer); |
||||
break; |
||||
} |
||||
needsUpdating=false; |
||||
} |
||||
return lastFloatValue; |
||||
} |
||||
|
||||
int readIntFromErinaData(MemoryOffset val) { |
||||
return readIntFromPointer(val,MemoryOffset.ENTITY_ARRAY); |
||||
} |
||||
|
||||
float readFloatFromErinaData(MemoryOffset val) { |
||||
return readFloatFromPointer(val,MemoryOffset.ENTITY_ARRAY); |
||||
} |
||||
|
||||
int readIntFromMemory(long offset) { |
||||
Memory mem = new Memory(4); |
||||
Kernel32.INSTANCE.ReadProcessMemory(parent.rabiribiProcess, new Pointer(parent.rabiRibiMemOffset+offset), mem, 4, null); |
||||
return mem.getInt(0); |
||||
} |
||||
|
||||
float readFloatFromMemory(long offset) { |
||||
Memory mem = new Memory(4); |
||||
Kernel32.INSTANCE.ReadProcessMemory(parent.rabiribiProcess, new Pointer(parent.rabiRibiMemOffset+offset), mem, 4, null); |
||||
return mem.getFloat(0); |
||||
} |
||||
|
||||
float readFloatFromMemoryOffset(MemoryOffset val, long pointer) { |
||||
Memory mem = new Memory(4); |
||||
Kernel32.INSTANCE.ReadProcessMemory(parent.rabiribiProcess, new Pointer(pointer+val.getOffset()), mem, 4, null); |
||||
return mem.getFloat(0); |
||||
} |
||||
|
||||
int readIntFromMemoryOffset(MemoryOffset val, long pointer) { |
||||
Memory mem = new Memory(4); |
||||
Kernel32.INSTANCE.ReadProcessMemory(parent.rabiribiProcess, new Pointer(pointer+val.getOffset()), mem, 4, null); |
||||
return mem.getInt(0); |
||||
} |
||||
|
||||
float readDirectFloatFromMemoryLocation(long pointer) { |
||||
Memory mem = new Memory(4); |
||||
Kernel32.INSTANCE.ReadProcessMemory(parent.rabiribiProcess, new Pointer(pointer), mem, 4, null); |
||||
return mem.getFloat(0); |
||||
} |
||||
|
||||
int readDirectIntFromMemoryLocation(long pointer) { |
||||
Memory mem = new Memory(4); |
||||
Kernel32.INSTANCE.ReadProcessMemory(parent.rabiribiProcess, new Pointer(pointer), mem, 4, null); |
||||
return mem.getInt(0); |
||||
} |
||||
|
||||
int readIntFromPointer(MemoryOffset val, MemoryOffset pointer) { |
||||
Memory mem = new Memory(4); |
||||
Kernel32.INSTANCE.ReadProcessMemory(parent.rabiribiProcess, new Pointer(readIntFromMemory(pointer.getOffset())+val.getOffset()), mem, 4, null); |
||||
return mem.getInt(0); |
||||
} |
||||
|
||||
int readIntFromPointer(long val, long pointer) { |
||||
Memory mem = new Memory(4); |
||||
Kernel32.INSTANCE.ReadProcessMemory(parent.rabiribiProcess, new Pointer(readIntFromMemory(pointer)+val), mem, 4, null); |
||||
return mem.getInt(0); |
||||
} |
||||
|
||||
float readFloatFromPointer(MemoryOffset val, MemoryOffset pointer) { |
||||
Memory mem = new Memory(4); |
||||
Kernel32.INSTANCE.ReadProcessMemory(parent.rabiribiProcess, new Pointer(readIntFromMemory(pointer.getOffset())+val.getOffset()), mem, 4, null); |
||||
return mem.getFloat(0); |
||||
} |
||||
|
||||
float readFloatFromPointer(long val, long pointer) { |
||||
Memory mem = new Memory(4); |
||||
Kernel32.INSTANCE.ReadProcessMemory(parent.rabiribiProcess, new Pointer(readIntFromMemory(pointer)+val), mem, 4, null); |
||||
return mem.getFloat(0); |
||||
} |
||||
|
||||
int readIntFromMemory(MemoryOffset val) { |
||||
return (int)readFromMemory(val,MemoryType.INTEGER); |
||||
} |
||||
|
||||
float readFloatFromMemory(MemoryOffset val) { |
||||
return (float)readFromMemory(val,MemoryType.FLOAT); |
||||
} |
||||
|
||||
Object readFromMemory(MemoryOffset val, MemoryType type) { |
||||
Memory mem = new Memory(type.getSize()); |
||||
Kernel32.INSTANCE.ReadProcessMemory(parent.rabiribiProcess, new Pointer(parent.rabiRibiMemOffset+val.getOffset()), mem, type.getSize(), null); |
||||
switch (type) { |
||||
case FLOAT: |
||||
return mem.getFloat(0); |
||||
case INTEGER: |
||||
return mem.getInt(0); |
||||
default: |
||||
System.out.println("WARNING! Type "+type+" does not have a defined value."); |
||||
return -1; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,7 @@ |
||||
package sig.modules.RabiRibi; |
||||
|
||||
public enum MemoryValueType { |
||||
LOCAL, //Memory offset found relative to base address.
|
||||
ABSOLUTE, //Memory found absolute in the memory table.
|
||||
POINTER; //A value that points to a memory address.
|
||||
} |
@ -0,0 +1,155 @@ |
||||
package sig.modules.RabiRibi; |
||||
|
||||
import java.awt.Graphics; |
||||
import java.awt.Point; |
||||
import java.awt.geom.Point2D; |
||||
import java.util.ArrayList; |
||||
import java.util.ConcurrentModificationException; |
||||
import java.util.List; |
||||
|
||||
import javax.swing.SwingUtilities; |
||||
|
||||
import sig.modules.RabiRibiModule; |
||||
import sig.modules.RabiRibi.SmoothObjects.ErinaMarker; |
||||
|
||||
public class Overlay { |
||||
float xcoord=-1f,ycoord=-1f; |
||||
boolean changedRooms=false; |
||||
RabiRibiModule parent; |
||||
public float xpos,ypos,xspd,yspd; |
||||
public float camera_xpos,camera_ypos; |
||||
public List<SmoothObject> objects = new ArrayList<SmoothObject>(); |
||||
|
||||
ErinaMarker ERINA_MARKER; |
||||
|
||||
public Overlay(RabiRibiModule parent){ |
||||
this.parent = parent; |
||||
/*this.xcoord = (int)(parent.readFloatFromErinaData(MemoryOffset.ERINA_XPOS)/1280); |
||||
this.ycoord = (int)(parent.readFloatFromErinaData(MemoryOffset.ERINA_YPOS)/720);*/ |
||||
ERINA_MARKER = new ErinaMarker(0,0,0,0,parent); |
||||
|
||||
objects.add(ERINA_MARKER); |
||||
} |
||||
|
||||
public void run() { |
||||
camera_xpos = parent.readIntFromMemory(MemoryOffset.CAMERA_XPOS); |
||||
camera_ypos = parent.readIntFromMemory(MemoryOffset.CAMERA_YPOS); |
||||
|
||||
float prev_camera_xpos = camera_xpos; |
||||
float prev_camera_ypos = camera_ypos; |
||||
xpos = parent.readFloatFromErinaData(MemoryOffset.ERINA_XPOS); |
||||
ypos = parent.readFloatFromErinaData(MemoryOffset.ERINA_YPOS); |
||||
|
||||
xspd = camera_xpos-prev_camera_xpos; |
||||
yspd = camera_ypos-prev_camera_ypos; |
||||
try { |
||||
for (SmoothObject so : objects) { |
||||
so.run(); |
||||
} |
||||
} catch (ConcurrentModificationException e) { |
||||
|
||||
} |
||||
/*int new_xcoord,new_ycoord; |
||||
|
||||
float prev_xpos = xpos; |
||||
float prev_ypos = ypos; |
||||
float prev_camera_xpos = camera_xpos; |
||||
float prev_camera_ypos = camera_ypos; |
||||
|
||||
xpos = parent.readFloatFromErinaData(MemoryOffset.ERINA_XPOS)/1280; |
||||
ypos = parent.readFloatFromErinaData(MemoryOffset.ERINA_YPOS)/720; |
||||
camera_xpos = parent.readIntFromMemory(MemoryOffset.CAMERA_XPOS); |
||||
camera_ypos = parent.readIntFromMemory(MemoryOffset.CAMERA_YPOS); |
||||
|
||||
if (Math.abs(parent.readFloatFromErinaData(MemoryOffset.ERINA_XSPEED))>0.5f) { |
||||
if ((Math.abs(prev_xpos-xpos)>0.005 && xpos%1>0.01 && xpos%1<0.99) || (Math.abs(prev_ypos-ypos)>0.005 && ypos%1>0.01 && ypos%1<0.99)) { |
||||
if (Math.abs(prev_xpos-xpos)>0.005) { |
||||
if (edgeOfScreenX) { |
||||
if (prev_camera_xpos!=camera_xpos) { |
||||
edgeOfScreenX = false; |
||||
//System.out.println("Not on edge of X screen anymore.");
|
||||
} |
||||
} else { |
||||
if (prev_camera_xpos==camera_xpos) { |
||||
edgeOfScreenX = true; |
||||
//System.out.println("Now on edge of X screen.");
|
||||
} |
||||
} |
||||
} |
||||
if (Math.abs(prev_ypos-ypos)>0.005) { |
||||
if (edgeOfScreenY) { |
||||
if (prev_camera_ypos!=camera_ypos) { |
||||
edgeOfScreenY = false; |
||||
//System.out.println("Not on edge of Y screen anymore.");
|
||||
} |
||||
} else { |
||||
if (prev_camera_ypos==camera_ypos) { |
||||
edgeOfScreenY = true; |
||||
//System.out.println("Now on edge of Y screen.");
|
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
new_xcoord = (int)(xpos); |
||||
new_ycoord = (int)(ypos); |
||||
int xchange = (int)Math.signum(xcoord-new_xcoord); //-1 = Moving Right (Left edge), 1 = Moving Left(Right edge)
|
||||
int ychange = (int)Math.signum(ycoord-new_ycoord); //-1 = Moving Down(Top edge), 1 = Moving Up (Bottom edge)
|
||||
if (xchange!=0 || ychange!=0) { |
||||
//Re-orient the camera, there has been a room change.
|
||||
float pct_xroom = xpos%1 + ((edgeOfScreenX)?0:0.5f); |
||||
float pct_yroom = ypos%1 + ((edgeOfScreenY)?0:0.5f); |
||||
camera_offset_x = -(pct_xroom*20); |
||||
camera_offset_y = -(pct_yroom*11.25f); |
||||
System.out.println(pct_xroom+"%,"+pct_yroom+"%. Change detected. Camera is offset by ("+camera_offset_x+","+camera_offset_y+")"); |
||||
this.xcoord = new_xcoord; |
||||
this.ycoord = new_ycoord; |
||||
camera_x = parent.readFloatFromErinaData(MemoryOffset.ERINA_XPOS) + camera_offset_x*64; |
||||
camera_y = parent.readFloatFromErinaData(MemoryOffset.ERINA_YPOS) + camera_offset_y*64; |
||||
System.out.println("Camera position is ("+camera_x+","+camera_y+")"); |
||||
starting_camera_x = camera_xpos; |
||||
starting_camera_y = camera_ypos; |
||||
}*/ |
||||
//System.out.println("Objects: "+objects.size());
|
||||
} |
||||
|
||||
public Point.Double getScreenPosition(float xpos, float ypos) { |
||||
/*float diffx = xpos-camera_x; |
||||
float diffy = ypos-camera_y; |
||||
|
||||
double screen_blocksize_x = parent.getPosition().getWidth()/20; |
||||
double screen_blocksize_y = parent.getPosition().getHeight()/11.25; |
||||
|
||||
float camera_diffx = starting_camera_x-parent.readIntFromMemory(MemoryOffset.CAMERA_XPOS); |
||||
float camera_diffy = starting_camera_y-parent.readIntFromMemory(MemoryOffset.CAMERA_YPOS); |
||||
|
||||
//System.out.println("Block size is ("+screen_blocksize_x+","+screen_blocksize_y+"). Diff is ("+diffx+","+diffy+").");
|
||||
/*System.out.println("Starting Camera: ("+starting_camera_x+","+starting_camera_y+")"); |
||||
System.out.println("Camera: ("+camera_diffx+","+camera_diffy+")"); |
||||
System.out.println("Block Coords: ("+(camera_diffx/64)+","+(camera_diffy/64)+")");*/ |
||||
|
||||
double screen_blocksize_x = parent.getPosition().getWidth()/20; |
||||
double screen_blocksize_y = parent.getPosition().getHeight()/11.25; |
||||
|
||||
return new Point.Double(((xpos-(-camera_xpos)+xspd*2)/64)*screen_blocksize_x, |
||||
((ypos-(-camera_ypos)+yspd*2)/64)*screen_blocksize_y); |
||||
} |
||||
|
||||
public void draw(Graphics g) { |
||||
/*if (parent.readIntFromMemory(MemoryOffset.TRANSITION_COUNTER)<300) { |
||||
try { |
||||
for (SmoothObject so : objects) { |
||||
so.draw(g); |
||||
} |
||||
} catch (ConcurrentModificationException e) { |
||||
|
||||
} |
||||
}*/ |
||||
//TODO check for pausing.
|
||||
for (SmoothObject so : objects) { |
||||
so.draw(g); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,13 @@ |
||||
package sig.modules.RabiRibi; |
||||
|
||||
import sig.modules.RabiRibiModule; |
||||
|
||||
public class RabiUtils { |
||||
public static RabiRibiModule module; |
||||
|
||||
public static boolean isGamePaused() { |
||||
//return module.readIntFromMemory(MemoryOffset.TRANSITION_COUNTER)>=300;
|
||||
//TODO Detect when game is paused.
|
||||
return false; |
||||
} |
||||
} |
@ -0,0 +1,51 @@ |
||||
package sig.modules.RabiRibi; |
||||
|
||||
import java.awt.Graphics; |
||||
import java.awt.Point; |
||||
|
||||
import sig.modules.RabiRibiModule; |
||||
|
||||
public class SmoothObject { |
||||
protected int x,y; |
||||
int targetx,targety; |
||||
protected RabiRibiModule parent; |
||||
|
||||
public SmoothObject(int x, int y, int targetx, int targety, RabiRibiModule parent) { |
||||
this.x=x; |
||||
this.y=y; |
||||
this.targetx=targetx; |
||||
this.targety=targety; |
||||
this.parent=parent; |
||||
} |
||||
|
||||
public void setTarget(Point target) { |
||||
targetx = (int)target.getX(); |
||||
targety = (int)target.getY(); |
||||
} |
||||
|
||||
public void setTarget(Point.Double target) { |
||||
targetx = (int)target.getX(); |
||||
targety = (int)target.getY(); |
||||
} |
||||
|
||||
public Point getTarget() { |
||||
return new Point(targetx,targety); |
||||
} |
||||
|
||||
public void setPosition(Point.Double position) { |
||||
x = (int)position.getX(); |
||||
y = (int)position.getY(); |
||||
} |
||||
|
||||
public void run() { |
||||
int xdiff = targetx-x; |
||||
int ydiff = targety-y; |
||||
x+=xdiff/1.3; |
||||
y+=ydiff/1.3; |
||||
//System.out.println("X:"+x+", Y:"+y+" TargetX:"+targetx+" TargetY:"+targety);
|
||||
} |
||||
|
||||
public void draw(Graphics g) { |
||||
|
||||
} |
||||
} |
@ -0,0 +1,37 @@ |
||||
package sig.modules.RabiRibi.SmoothObjects; |
||||
|
||||
import java.awt.Color; |
||||
import java.awt.Graphics; |
||||
|
||||
import sig.modules.RabiRibiModule; |
||||
import sig.modules.RabiRibi.Entity; |
||||
import sig.modules.RabiRibi.MemoryOffset; |
||||
import sig.modules.RabiRibi.SmoothObject; |
||||
|
||||
public class EntityMarker extends SmoothObject{ |
||||
Entity ent; |
||||
|
||||
public EntityMarker(int x, int y, int targetx, int targety, Entity ent, RabiRibiModule parent) { |
||||
super(x, y, targetx, targety, parent); |
||||
this.ent=ent; |
||||
} |
||||
|
||||
public void draw(Graphics g) { |
||||
super.draw(g); |
||||
int alphaval = (ent.getLastHitTime()>parent.readIntFromMemory(MemoryOffset.PLAYTIME)-180)?255:110; |
||||
float pct = ent.getHealth()/(float)ent.getMaxHealth(); |
||||
if (pct>=0.66) { |
||||
g.setColor(new Color(64,255,64,alphaval)); |
||||
} else |
||||
if (pct>=0.33) { |
||||
g.setColor(new Color(255,255,64,alphaval)); |
||||
} else { |
||||
g.setColor(new Color(255,64,64,alphaval)); |
||||
} |
||||
g.fillRect(x, y-56, (int)(48*pct), 16); |
||||
g.setColor(new Color(0,0,0,alphaval)); |
||||
g.drawRect(x, y-56, 48, 16); |
||||
g.setColor(Color.BLACK); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,23 @@ |
||||
package sig.modules.RabiRibi.SmoothObjects; |
||||
|
||||
import java.awt.Graphics; |
||||
import java.awt.Point; |
||||
import java.awt.geom.Point2D; |
||||
|
||||
import sig.modules.RabiRibiModule; |
||||
import sig.modules.RabiRibi.SmoothObject; |
||||
|
||||
public class ErinaMarker extends SmoothObject{ |
||||
|
||||
|
||||
public ErinaMarker(int x, int y, int targetx, int targety, RabiRibiModule parent) { |
||||
super(x, y, targetx, targety, parent); |
||||
} |
||||
|
||||
public void draw(Graphics g) { |
||||
super.draw(g); |
||||
Point2D.Double erina_pos = parent.overlay.getScreenPosition(parent.overlay.xpos, parent.overlay.ypos); |
||||
setTarget(new Point((int)erina_pos.getX(),(int)erina_pos.getY()-72)); |
||||
g.fillOval(x, y, 16, 16); |
||||
} |
||||
} |
@ -0,0 +1,397 @@ |
||||
package sig.modules; |
||||
|
||||
import java.awt.Color; |
||||
import java.awt.Graphics; |
||||
import java.awt.Point; |
||||
import java.awt.event.KeyEvent; |
||||
import java.awt.geom.Point2D; |
||||
import java.awt.geom.Rectangle2D; |
||||
import java.util.ArrayList; |
||||
import java.util.Arrays; |
||||
import java.util.ConcurrentModificationException; |
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
import java.util.concurrent.Executors; |
||||
import java.util.concurrent.ScheduledExecutorService; |
||||
import java.util.concurrent.TimeUnit; |
||||
|
||||
import javax.swing.SwingUtilities; |
||||
|
||||
import com.sun.jna.Memory; |
||||
import com.sun.jna.Pointer; |
||||
import com.sun.jna.platform.win32.Kernel32; |
||||
import com.sun.jna.platform.win32.WinNT; |
||||
import com.sun.jna.platform.win32.WinNT.HANDLE; |
||||
|
||||
import sig.Module; |
||||
import sig.sigIRC; |
||||
import sig.modules.RabiRibi.Entity; |
||||
import sig.modules.RabiRibi.EntityLookupData; |
||||
import sig.modules.RabiRibi.MemoryOffset; |
||||
import sig.modules.RabiRibi.MemoryType; |
||||
import sig.modules.RabiRibi.Overlay; |
||||
import sig.modules.RabiRibi.RabiUtils; |
||||
import sig.modules.RabiRibi.SmoothObject; |
||||
import sig.modules.utils.PsapiTools; |
||||
import sig.utils.DrawUtils; |
||||
import sig.utils.FileUtils; |
||||
import sig.utils.TextUtils; |
||||
|
||||
public class RabiRibiModule extends Module{ |
||||
final int PROCESS_PERMISSIONS = WinNT.PROCESS_QUERY_INFORMATION | WinNT.PROCESS_VM_READ; |
||||
boolean foundRabiRibi = false; |
||||
int rabiRibiPID = -1; |
||||
public long rabiRibiMemOffset = 0; |
||||
public HANDLE rabiribiProcess = null; |
||||
HashMap<Integer,Entity> entities = new HashMap<Integer,Entity>(); |
||||
final static int MAX_ENTITIES_TO_UPDATE = 500; |
||||
final static int ENTITY_ARRAY_ELEMENT_SIZE = 0x704; |
||||
public HashMap<String,EntityLookupData> lookup_table = new HashMap<String,EntityLookupData>(); |
||||
int mapx = 0, mapy = 0; |
||||
public String statustext = ""; |
||||
public int statustime = 0; |
||||
public int moneyearned = 0; |
||||
public int moneytime = 0; |
||||
public int lastmoney = -1; |
||||
|
||||
public Overlay overlay; |
||||
|
||||
public SmoothObject en_counter = new SmoothObject(0,0,0,0,this){ |
||||
public void draw(Graphics g) { |
||||
int playtime = readIntFromMemory(MemoryOffset.PLAYTIME); |
||||
if (moneyearned>0 && moneytime>playtime) { |
||||
setTarget(overlay.getScreenPosition(readFloatFromErinaData(MemoryOffset.ERINA_XPOS), readFloatFromErinaData(MemoryOffset.ERINA_YPOS))); |
||||
//System.out.println(x+","+y);
|
||||
DrawUtils.drawCenteredOutlineText(g, sigIRC.panel.rabiRibiMoneyDisplayFont, (int)x, (int)y-96, 2, Color.ORANGE, Color.BLACK, "+"+moneyearned+"EN"); |
||||
} |
||||
} |
||||
}; |
||||
|
||||
public RabiRibiModule(Rectangle2D bounds, String moduleName) { |
||||
super(bounds, moduleName); |
||||
//Initialize();
|
||||
Initialize(); |
||||
|
||||
//System.out.println("Money value is: "+readIntFromMemory(MemoryOffset.MONEY));
|
||||
} |
||||
|
||||
public void SaveConfig() { |
||||
super.SaveConfig(); |
||||
EntityLookupData.saveEntityLookupData(lookup_table); |
||||
} |
||||
|
||||
private void Initialize() { |
||||
|
||||
RabiUtils.module = this; |
||||
|
||||
List<Integer> pids; |
||||
try { |
||||
pids = PsapiTools.getInstance().enumProcesses(); |
||||
for (Integer pid : pids) { |
||||
HANDLE process = Kernel32.INSTANCE.OpenProcess(PROCESS_PERMISSIONS, true, pid); |
||||
List<sig.modules.utils.Module> hModules; |
||||
try { |
||||
hModules = PsapiTools.getInstance().EnumProcessModules(process); |
||||
for(sig.modules.utils.Module m: hModules){ |
||||
//System.out.println(m.getFileName()+":"+m.getEntryPoint());
|
||||
if (m.getFileName().contains("rabiribi")) { |
||||
rabiRibiMemOffset = Pointer.nativeValue(m.getLpBaseOfDll().getPointer()); |
||||
System.out.println("Found an instance of Rabi-Ribi at 0x"+Long.toHexString(rabiRibiMemOffset)); |
||||
rabiRibiPID=pid; |
||||
foundRabiRibi=true; |
||||
rabiribiProcess=process; |
||||
break; |
||||
} |
||||
} |
||||
} catch (Exception e) { |
||||
e.printStackTrace(); |
||||
} |
||||
if (foundRabiRibi) { |
||||
break; |
||||
} |
||||
if (process!=null) { |
||||
Kernel32.INSTANCE.CloseHandle(process); |
||||
} |
||||
} |
||||
} catch (Exception e) { |
||||
e.printStackTrace(); |
||||
} |
||||
|
||||
this.overlay = new Overlay(this); |
||||
|
||||
EntityLookupData.parent=this; |
||||
EntityLookupData.loadEntityLookupData(lookup_table); |
||||
|
||||
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); |
||||
scheduler.scheduleWithFixedDelay(()->{ |
||||
UpdateEntities(); |
||||
//System.out.println("Called Entity creation "+callcount+" times.");
|
||||
}, 1000, 1000, TimeUnit.MILLISECONDS); |
||||
} |
||||
|
||||
public void ApplyConfigWindowProperties() { |
||||
sigIRC.rabiribimodule_X=(int)position.getX(); |
||||
sigIRC.rabiribimodule_Y=(int)position.getY(); |
||||
sigIRC.config.setInteger("RABIRIBI_module_X", sigIRC.rabiribimodule_X); |
||||
sigIRC.config.setInteger("RABIRIBI_module_Y", sigIRC.rabiribimodule_Y); |
||||
} |
||||
|
||||
public void run() { |
||||
super.run(); |
||||
updateEntities(); |
||||
overlay.run(); |
||||
|
||||
if (lastmoney==-1) { |
||||
lastmoney = readIntFromMemory(MemoryOffset.MONEY); |
||||
} else |
||||
{ |
||||
int currentmoney = readIntFromMemory(MemoryOffset.MONEY); |
||||
if (currentmoney>lastmoney) { |
||||
if (moneyearned==0) { |
||||
en_counter.setPosition(overlay.getScreenPosition(readFloatFromErinaData(MemoryOffset.ERINA_XPOS), readFloatFromErinaData(MemoryOffset.ERINA_YPOS))); |
||||
} |
||||
moneyearned+=currentmoney-lastmoney; |
||||
moneytime = readIntFromMemory(MemoryOffset.PLAYTIME)+60; |
||||
} |
||||
lastmoney = currentmoney; |
||||
} |
||||
if (moneyearned>0 && moneytime<readIntFromMemory(MemoryOffset.PLAYTIME)) { |
||||
moneyearned=0; |
||||
} |
||||
en_counter.run(); |
||||
} |
||||
|
||||
public HashMap<Integer,Entity> getEntities() { |
||||
return entities; |
||||
} |
||||
|
||||
private void updateEntities() { |
||||
|
||||
//System.out.println("Size is "+size);
|
||||
List<Integer> idsToRemove = new ArrayList<Integer>(); |
||||
try { |
||||
for (Integer i : entities.keySet()) { |
||||
Entity ent = entities.get(i); |
||||
if (!ent.run()) { |
||||
idsToRemove.add(i); |
||||
} |
||||
} |
||||
for (Integer i : idsToRemove) { |
||||
if (!overlay.objects.remove(entities.get(i).marker)) { |
||||
System.out.println("WARNING! Could not remove overlay EntityMarker. Possible memory leak occurring!"); |
||||
} |
||||
entities.remove(i); |
||||
//System.out.println("Removed entity "+i+". Entities remaining: "+entities.size());
|
||||
} |
||||
} catch (ConcurrentModificationException e) { |
||||
|
||||
} |
||||
|
||||
//System.out.println("Starting address is 0x"+Long.toHexString(readIntFromMemory(MemoryOffset.ENTITY_ARRAY)));
|
||||
//System.out.println("Array Pointer starts at 0x"+Long.toHexString(arrayPtr));
|
||||
int currentx = (int)(readFloatFromErinaData(MemoryOffset.ERINA_XPOS)/1280); |
||||
int currenty = (int)(readFloatFromErinaData(MemoryOffset.ERINA_YPOS)/720); |
||||
if (mapx!=(int)(readFloatFromErinaData(MemoryOffset.ERINA_XPOS)/1280) || |
||||
mapy!=(int)(readFloatFromErinaData(MemoryOffset.ERINA_YPOS)/720)) { |
||||
//System.out.println("Update Entities.");
|
||||
mapx=currentx; |
||||
mapy=currenty; |
||||
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); |
||||
scheduler.schedule(()->{ |
||||
UpdateEntities(); |
||||
//System.out.println("Called Entity creation "+callcount+" times.");
|
||||
}, 200, TimeUnit.MILLISECONDS); |
||||
} |
||||
} |
||||
|
||||
private void UpdateEntities() { |
||||
int callcount=0; |
||||
long arrayPtr = readIntFromMemory(MemoryOffset.ENTITY_ARRAY); |
||||
for (int i=0;i<MAX_ENTITIES_TO_UPDATE;i++) { |
||||
if (!entities.containsKey(i)) { |
||||
callcount++; |
||||
Entity ent = new Entity(arrayPtr,i,this); |
||||
if (ent.isActive()) { |
||||
//System.out.println("Found entity at index "+i);
|
||||
//entities.add(ent);
|
||||
entities.put(i, ent); |
||||
} |
||||
} |
||||
arrayPtr += ENTITY_ARRAY_ELEMENT_SIZE; |
||||
} |
||||
} |
||||
|
||||
public void draw(Graphics g) { |
||||
super.draw(g); |
||||
if (!RabiUtils.isGamePaused()) { |
||||
int i=32; |
||||
/*DrawUtils.drawOutlineText(g, sigIRC.panel.programFont, position.getX(), position.getY()+(i+=24), 3, Color.BLACK, Color.WHITE, "Money: "+readIntFromMemory(MemoryOffset.MONEY)); |
||||
DrawUtils.drawOutlineText(g, sigIRC.panel.programFont, position.getX(), position.getY()+(i+=24), 3, Color.BLACK, Color.WHITE, "H-Ups: "+readItemCountFromMemory(MemoryOffset.HEALTHUP_START,MemoryOffset.HEALTHUP_END)); |
||||
DrawUtils.drawOutlineText(g, sigIRC.panel.programFont, position.getX(), position.getY()+(i+=24), 3, Color.BLACK, Color.WHITE, "A-Ups: "+readItemCountFromMemory(MemoryOffset.ATTACKUP_START,MemoryOffset.ATTACKUP_END)); |
||||
DrawUtils.drawOutlineText(g, sigIRC.panel.programFont, position.getX(), position.getY()+(i+=24), 3, Color.BLACK, Color.WHITE, "M-Ups: "+readItemCountFromMemory(MemoryOffset.MANAUP_START,MemoryOffset.MANAUP_END)); |
||||
DrawUtils.drawOutlineText(g, sigIRC.panel.programFont, position.getX(), position.getY()+(i+=24), 3, Color.BLACK, Color.WHITE, "R-Ups: "+readItemCountFromMemory(MemoryOffset.REGENUP_START,MemoryOffset.REGENUP_END)); |
||||
DrawUtils.drawOutlineText(g, sigIRC.panel.programFont, position.getX(), position.getY()+(i+=24), 3, Color.BLACK, Color.WHITE, "P-Ups: "+readItemCountFromMemory(MemoryOffset.PACKUP_START,MemoryOffset.PACKUP_END)); |
||||
DrawUtils.drawOutlineText(g, sigIRC.panel.programFont, position.getX(), position.getY()+(i+=24), 3, Color.BLACK, Color.WHITE, "HP: "+readIntFromErinaData(MemoryOffset.ERINA_HP)+"/"+readIntFromErinaData(MemoryOffset.ERINA_MAXHP)); |
||||
DrawUtils.drawOutlineText(g, sigIRC.panel.programFont, position.getX(), position.getY()+(i+=24), 3, Color.BLACK, Color.WHITE, "POS ("+(int)readFloatFromErinaData(MemoryOffset.ERINA_XPOS)/1280+","+(int)readFloatFromErinaData(MemoryOffset.ERINA_YPOS)/720+")"); |
||||
DrawUtils.drawOutlineText(g, sigIRC.panel.programFont, position.getX(), position.getY()+(i+=24), 3, Color.BLACK, Color.WHITE, "MAP: "+readIntFromMemory(MemoryOffset.MAPID));*/ |
||||
DrawUtils.drawOutlineText(g, sigIRC.panel.programFont, position.getX(), position.getY()+(i+=24), 3, Color.BLACK, Color.WHITE, "POS ("+(readFloatFromErinaData(MemoryOffset.ERINA_XPOS))+","+(readFloatFromErinaData(MemoryOffset.ERINA_YPOS))+")"); |
||||
DrawUtils.drawOutlineText(g, sigIRC.panel.programFont, position.getX(), position.getY()+(i+=24), 3, Color.BLACK, Color.WHITE, "MONEY: ("+(readIntFromMemory(MemoryOffset.MONEY))+")"); |
||||
DrawUtils.drawOutlineText(g, sigIRC.panel.programFont, position.getX(), position.getY()+(i+=24), 3, Color.BLACK, Color.WHITE, "CAMERA ("+(readIntFromMemory(MemoryOffset.CAMERA_XPOS))+","+(readIntFromMemory(MemoryOffset.CAMERA_YPOS))+")"); |
||||
//DrawUtils.drawOutlineText(g, sigIRC.panel.programFont, position.getX(), position.getY()+(i+=24), 3, Color.BLACK, Color.WHITE, "SCREENPOS ("+overlay.getScreenPosition(readFloatFromErinaData(MemoryOffset.ERINA_XPOS), readFloatFromErinaData(MemoryOffset.ERINA_YPOS))+")");
|
||||
overlay.draw(g); |
||||
/*DrawUtils.drawOutlineText(g, sigIRC.panel.programFont, position.getX(), position.getY()+(i+=24), 3, Color.BLACK, Color.WHITE, |
||||
"Sunny Beam: "+Arrays.toString( |
||||
new int[]{ |
||||
readIntFromMemory(0xD63304), |
||||
readIntFromMemory(0xD63D0C), |
||||
})); |
||||
*/ |
||||
/* |
||||
for (String s : TextUtils.WrapText(("Entities: "+entities).replaceAll(",", ", "), sigIRC.panel.programFont, position.getWidth()-20)) { |
||||
DrawUtils.drawOutlineText(g, sigIRC.panel.programFont, position.getX()+20, position.getY()+(i+=24), 3, Color.BLACK, Color.WHITE, |
||||
s); |
||||
}*/ |
||||
try { |
||||
for (Integer numb : entities.keySet()) { |
||||
Entity ent = entities.get(numb); |
||||
if (ent.getLastHitTime()>readIntFromMemory(MemoryOffset.PLAYTIME)-180) { |
||||
for (String s : TextUtils.WrapText("Entity "+ent.getID()+": "+ent.getHealth()+"/"+ent.getMaxHealth()+" HP "+((ent.getHealth()/(float)ent.getMaxHealth())*100)+"%".replaceAll(",", ", "), sigIRC.panel.programFont, position.getWidth()-20)) { |
||||
DrawUtils.drawOutlineText(g, sigIRC.panel.programFont, position.getX()+20, position.getY()+(i+=24), 3, Color.BLACK, Color.WHITE, |
||||
s); |
||||
} |
||||
} |
||||
} |
||||
} catch (ConcurrentModificationException e) { |
||||
|
||||
} |
||||
|
||||
i+=24; |
||||
|
||||
int playtime = readIntFromMemory(MemoryOffset.PLAYTIME); |
||||
|
||||
if (statustext.length()>0 && statustime>playtime-300) { |
||||
DrawUtils.drawOutlineText(g, sigIRC.panel.programFont, position.getX(), position.getY()+(i+=48), 3, Color.GREEN, Color.LIGHT_GRAY, statustext); |
||||
} |
||||
|
||||
en_counter.draw(g); |
||||
} |
||||
} |
||||
|
||||
public void setStatusMessage(String msg) { |
||||
statustime = readIntFromMemory(MemoryOffset.PLAYTIME); |
||||
statustext = msg; |
||||
} |
||||
|
||||
public void keypressed(KeyEvent ev) { |
||||
super.keypressed(ev); |
||||
if (ev.getKeyCode()==KeyEvent.VK_HOME) { |
||||
String memFile = sigIRC.BASEDIR+"memoryDump.txt"; |
||||
FileUtils.logToFile("Memory Dump of All Loaded Entities:", memFile); |
||||
for (Integer numb : entities.keySet()) { |
||||
Entity ent = entities.get(numb); |
||||
FileUtils.logToFile(ent.toString(), memFile); |
||||
for (int i=0;i<ENTITY_ARRAY_ELEMENT_SIZE/4;i++) { |
||||
Long ptrArray = (long)(readIntFromMemory(MemoryOffset.ENTITY_ARRAY)+(numb*ENTITY_ARRAY_ELEMENT_SIZE)+i*4); |
||||
FileUtils.logToFile(" +"+Integer.toHexString(i*4)+": "+readDirectIntFromMemoryLocation(ptrArray)+" / "+readDirectFloatFromMemoryLocation(ptrArray)+"f", memFile); |
||||
} |
||||
} |
||||
} /*else |
||||
if (ev.getKeyCode()==KeyEvent.VK_END) { |
||||
String memFile = sigIRC.BASEDIR+"memoryDump.txt"; |
||||
FileUtils.logToFile("Memory Dump of All Erina Values:", memFile); |
||||
for (int i=0;i<ENTITY_ARRAY_ELEMENT_SIZE/4;i++) { |
||||
Long ptrArray = (long)(MemoryOffset.CAMERA_XPOS.getOffset()+i*4); |
||||
FileUtils.logToFile(" +"+Integer.toHexString(i*4)+": "+readIntFromMemory(ptrArray)+" / "+readFloatFromMemory(ptrArray)+"f", memFile); |
||||
} |
||||
}*/ |
||||
} |
||||
|
||||
public int readIntFromErinaData(MemoryOffset val) { |
||||
return readIntFromPointer(val,MemoryOffset.ENTITY_ARRAY); |
||||
} |
||||
|
||||
public float readFloatFromErinaData(MemoryOffset val) { |
||||
return readFloatFromPointer(val,MemoryOffset.ENTITY_ARRAY); |
||||
} |
||||
|
||||
public int readIntFromMemory(long offset) { |
||||
Memory mem = new Memory(4); |
||||
Kernel32.INSTANCE.ReadProcessMemory(rabiribiProcess, new Pointer(rabiRibiMemOffset+offset), mem, 4, null); |
||||
return mem.getInt(0); |
||||
} |
||||
|
||||
public float readFloatFromMemory(long offset) { |
||||
Memory mem = new Memory(4); |
||||
Kernel32.INSTANCE.ReadProcessMemory(rabiribiProcess, new Pointer(rabiRibiMemOffset+offset), mem, 4, null); |
||||
return mem.getFloat(0); |
||||
} |
||||
|
||||
public float readFloatFromMemoryOffset(MemoryOffset val, long pointer) { |
||||
Memory mem = new Memory(4); |
||||
Kernel32.INSTANCE.ReadProcessMemory(rabiribiProcess, new Pointer(pointer+val.getOffset()), mem, 4, null); |
||||
return mem.getFloat(0); |
||||
} |
||||
|
||||
public int readIntFromMemoryOffset(MemoryOffset val, long pointer) { |
||||
Memory mem = new Memory(4); |
||||
Kernel32.INSTANCE.ReadProcessMemory(rabiribiProcess, new Pointer(pointer+val.getOffset()), mem, 4, null); |
||||
return mem.getInt(0); |
||||
} |
||||
|
||||
public float readDirectFloatFromMemoryLocation(long pointer) { |
||||
Memory mem = new Memory(4); |
||||
Kernel32.INSTANCE.ReadProcessMemory(rabiribiProcess, new Pointer(pointer), mem, 4, null); |
||||
return mem.getFloat(0); |
||||
} |
||||
|
||||
public int readDirectIntFromMemoryLocation(long pointer) { |
||||
Memory mem = new Memory(4); |
||||
Kernel32.INSTANCE.ReadProcessMemory(rabiribiProcess, new Pointer(pointer), mem, 4, null); |
||||
return mem.getInt(0); |
||||
} |
||||
|
||||
public int readIntFromPointer(MemoryOffset val, MemoryOffset pointer) { |
||||
Memory mem = new Memory(4); |
||||
Kernel32.INSTANCE.ReadProcessMemory(rabiribiProcess, new Pointer(readIntFromMemory(pointer.getOffset())+val.getOffset()), mem, 4, null); |
||||
return mem.getInt(0); |
||||
} |
||||
|
||||
public float readFloatFromPointer(MemoryOffset val, MemoryOffset pointer) { |
||||
Memory mem = new Memory(4); |
||||
Kernel32.INSTANCE.ReadProcessMemory(rabiribiProcess, new Pointer(readIntFromMemory(pointer.getOffset())+val.getOffset()), mem, 4, null); |
||||
return mem.getFloat(0); |
||||
} |
||||
|
||||
public int readIntFromMemory(MemoryOffset val) { |
||||
return (int)readFromMemory(val,MemoryType.INTEGER); |
||||
} |
||||
|
||||
public float readFloatFromMemory(MemoryOffset val) { |
||||
return (float)readFromMemory(val,MemoryType.FLOAT); |
||||
} |
||||
|
||||
Object readFromMemory(MemoryOffset val, MemoryType type) { |
||||
Memory mem = new Memory(type.getSize()); |
||||
Kernel32.INSTANCE.ReadProcessMemory(rabiribiProcess, new Pointer(rabiRibiMemOffset+val.getOffset()), mem, type.getSize(), null); |
||||
switch (type) { |
||||
case FLOAT: |
||||
return mem.getFloat(0); |
||||
case INTEGER: |
||||
return mem.getInt(0); |
||||
default: |
||||
System.out.println("WARNING! Type "+type+" does not have a defined value."); |
||||
return -1; |
||||
} |
||||
} |
||||
|
||||
int readItemCountFromMemory(MemoryOffset start_range, |
||||
MemoryOffset end_range) { |
||||
int count=0; |
||||
for (long i=start_range.getOffset();i<=end_range.getOffset();i++) { |
||||
if (readIntFromMemory(i)==1) { |
||||
count++; |
||||
} |
||||
} |
||||
return count; |
||||
} |
||||
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue