diff --git a/.classpath b/.classpath index c49f98b..0a0f0b6 100644 --- a/.classpath +++ b/.classpath @@ -13,5 +13,7 @@ + + diff --git a/.gitignore b/.gitignore index 03a74bf..3748367 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ /jinput-raw.dll /jinput-raw_64.dll /jinput-wintab.dll +/memoryDump.txt diff --git a/lib/jna-4.5.0.jar b/lib/jna-4.5.0.jar new file mode 100644 index 0000000..2e4eaeb Binary files /dev/null and b/lib/jna-4.5.0.jar differ diff --git a/lib/jna-platform-4.5.0.jar b/lib/jna-platform-4.5.0.jar new file mode 100644 index 0000000..e1063a6 Binary files /dev/null and b/lib/jna-platform-4.5.0.jar differ diff --git a/projectBuilder.xml b/projectBuilder.xml index 99d06c1..96a4e1b 100644 --- a/projectBuilder.xml +++ b/projectBuilder.xml @@ -23,6 +23,8 @@ + + diff --git a/sigIRCv2.jar b/sigIRCv2.jar index d74d928..f826ebd 100644 Binary files a/sigIRCv2.jar and b/sigIRCv2.jar differ diff --git a/src/sig/ConfigFile.java b/src/sig/ConfigFile.java index 9e735a2..fe851e1 100644 --- a/src/sig/ConfigFile.java +++ b/src/sig/ConfigFile.java @@ -10,6 +10,7 @@ import java.util.Arrays; import java.util.HashMap; import java.util.Properties; +import sig.modules.RabiRibi.EntityLookupData; import sig.utils.FileUtils; public class ConfigFile { @@ -94,6 +95,9 @@ public class ConfigFile { 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(); diff --git a/src/sig/FileManager.java b/src/sig/FileManager.java index 462d848..8fe3605 100644 --- a/src/sig/FileManager.java +++ b/src/sig/FileManager.java @@ -5,6 +5,8 @@ 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/"; @@ -12,6 +14,13 @@ public class FileManager { 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; } diff --git a/src/sig/Module.java b/src/sig/Module.java index 26e6cbe..abfd447 100644 --- a/src/sig/Module.java +++ b/src/sig/Module.java @@ -18,7 +18,7 @@ import sig.utils.DrawUtils; import sig.utils.TextUtils; public class Module { - protected Rectangle2D position; + public Rectangle2D position; protected boolean enabled; protected String name; public static BufferedImage IMG_DRAGBAR; @@ -71,6 +71,10 @@ public class Module { public void ApplyConfigWindowProperties() { } + + public void SaveConfig() { + + } public void mouseReleased(MouseEvent ev) { if (dragging) { diff --git a/src/sig/MyPanel.java b/src/sig/MyPanel.java index e907573..a3c885a 100644 --- a/src/sig/MyPanel.java +++ b/src/sig/MyPanel.java @@ -39,6 +39,8 @@ public class MyPanel extends JPanel implements MouseListener, ActionListener, Mo 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; diff --git a/src/sig/ScrollingText.java b/src/sig/ScrollingText.java index 3d82889..7c3f048 100644 --- a/src/sig/ScrollingText.java +++ b/src/sig/ScrollingText.java @@ -121,9 +121,9 @@ public class ScrollingText { 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); } - private Color GetUserNameColor(String username) { + public static Color GetUserNameColor(String username) { Random r = new Random(); - r.setSeed(username.hashCode()); + r.setSeed(username.toLowerCase().hashCode()); int randomnumb = r.nextInt(3); Color col; switch (randomnumb) { diff --git a/src/sig/modules/Controller/ClickableButton.java b/src/sig/modules/Controller/ClickableButton.java index 0fad1b7..a0dfdcb 100644 --- a/src/sig/modules/Controller/ClickableButton.java +++ b/src/sig/modules/Controller/ClickableButton.java @@ -5,6 +5,7 @@ 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; @@ -13,9 +14,9 @@ import sig.utils.TextUtils; public class ClickableButton { protected int x,y,width,height; protected String label; - protected ControllerModule module; + protected Module module; - public ClickableButton(Rectangle position, String button_label, ControllerModule parent_module) { + public ClickableButton(Rectangle position, String button_label, Module parent_module) { this.x = (int)position.getX(); this.y = (int)position.getY(); this.width = (int)position.getWidth(); @@ -29,8 +30,12 @@ public class ClickableButton { //System.out.println("Click performed!"); }*/ } + + public void setButtonLabel(String text) { + this.label = text; + } - protected boolean mouseInsideBounds(MouseEvent ev) { + 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; } diff --git a/src/sig/modules/Controller/ControlConfigurationWindow.java b/src/sig/modules/Controller/ControlConfigurationWindow.java index e4e23e5..919cc1a 100644 --- a/src/sig/modules/Controller/ControlConfigurationWindow.java +++ b/src/sig/modules/Controller/ControlConfigurationWindow.java @@ -252,11 +252,7 @@ public class ControlConfigurationWindow extends JFrame implements WindowListener this.twowayAxis_range1 = new LinkedTextField(twowayAxis_range1); this.twowayAxis_range2 = new LinkedTextField(twowayAxis_range2); this.setTitle("Axis Configuration Window"); - try { - this.setIconImage(ImageIO.read(new File(sigIRC.BASEDIR+"/sigIRC/sigIRCicon.png"))); - } catch (IOException e1) { - e1.printStackTrace(); - } + this.setIconImage(sigIRC.programIcon); switch (dialog) { case AXIS_OPTIONS: diff --git a/src/sig/modules/RabiRace/ColorCycler.java b/src/sig/modules/RabiRace/ColorCycler.java new file mode 100644 index 0000000..7058b1f --- /dev/null +++ b/src/sig/modules/RabiRace/ColorCycler.java @@ -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); + } +} diff --git a/src/sig/modules/RabiRace/CreateButton.java b/src/sig/modules/RabiRace/CreateButton.java new file mode 100644 index 0000000..89a5cbd --- /dev/null +++ b/src/sig/modules/RabiRace/CreateButton.java @@ -0,0 +1,19 @@ +package sig.modules.RabiRace; + +import java.awt.Rectangle; +import java.awt.event.MouseEvent; + +import sig.Module; +import sig.modules.RabiRaceModule; +import sig.modules.Controller.ClickableButton; + +public class CreateButton extends ClickableButton{ + + public CreateButton(Rectangle position, String button_label, Module parent_module) { + super(position, button_label, parent_module); + } + + public void onClickEvent(MouseEvent ev) { + RabiRaceModule.createwindow.setVisible(true); + } +} diff --git a/src/sig/modules/RabiRace/JoinButton.java b/src/sig/modules/RabiRace/JoinButton.java new file mode 100644 index 0000000..907abcf --- /dev/null +++ b/src/sig/modules/RabiRace/JoinButton.java @@ -0,0 +1,36 @@ +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; +import sig.modules.Controller.ClickableButton; + +public class JoinButton extends ClickableButton{ + + public JoinButton(Rectangle position, String button_label, Module parent_module) { + super(position, button_label, parent_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(); + } + } + } +} diff --git a/src/sig/modules/RabiRace/MemoryData.java b/src/sig/modules/RabiRace/MemoryData.java new file mode 100644 index 0000000..754b18f --- /dev/null +++ b/src/sig/modules/RabiRace/MemoryData.java @@ -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"; + } +} diff --git a/src/sig/modules/RabiRace/Player.java b/src/sig/modules/RabiRace/Player.java new file mode 100644 index 0000000..7ebbcb5 --- /dev/null +++ b/src/sig/modules/RabiRace/Player.java @@ -0,0 +1,5 @@ +package sig.modules.RabiRace; + +public class Player { + +} diff --git a/src/sig/modules/RabiRace/Profile.java b/src/sig/modules/RabiRace/Profile.java new file mode 100644 index 0000000..4777c19 --- /dev/null +++ b/src/sig/modules/RabiRace/Profile.java @@ -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 key_items = new HashMap(); + public HashMap badges = new HashMap(); + public List updates = new ArrayList(); + 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)key_items.clone(); + oldProfile.badges = (HashMap)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"); + 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"); + //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 (difficulty0)?" 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 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 players = new ArrayList(); + + 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 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(); + } +} diff --git a/src/sig/modules/RabiRace/SessionCreateWindow.java b/src/sig/modules/RabiRace/SessionCreateWindow.java new file mode 100644 index 0000000..a2af55f --- /dev/null +++ b/src/sig/modules/RabiRace/SessionCreateWindow.java @@ -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; + } + } +} diff --git a/src/sig/modules/RabiRace/SessionListData.java b/src/sig/modules/RabiRace/SessionListData.java new file mode 100644 index 0000000..a0783f8 --- /dev/null +++ b/src/sig/modules/RabiRace/SessionListData.java @@ -0,0 +1,28 @@ +package sig.modules.RabiRace; + +import java.util.HashMap; + +public class SessionListData { + HashMap data = new HashMap(); + + 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]); + this.data.put(sessionID, new Session(session)); + } + } + //System.out.println(this.data); + } + + public HashMap getSessions() { + return data; + } +} diff --git a/src/sig/modules/RabiRace/SessionListWindow.java b/src/sig/modules/RabiRace/SessionListWindow.java new file mode 100644 index 0000000..be29110 --- /dev/null +++ b/src/sig/modules/RabiRace/SessionListWindow.java @@ -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 sessionlist = new JList(); + public DefaultListModel sessionlist_model = new DefaultListModel(); + 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.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.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(""); + } + } +} diff --git a/src/sig/modules/RabiRaceModule.java b/src/sig/modules/RabiRaceModule.java new file mode 100644 index 0000000..0f7f719 --- /dev/null +++ b/src/sig/modules/RabiRaceModule.java @@ -0,0 +1,462 @@ +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.Controller.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 image_map = new HashMap(); + 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 messages = new ArrayList(); + public static int lastScrollX = 0; + boolean firstUpdate=true; + + public SessionListData session_listing = new SessionListData(); + + ClickableButton join_button,create_button; + + public static List key_items_list = new ArrayList(); + public static List badges_list = new ArrayList(); + + 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 filtered_images = new ArrayList(); + 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 pids; + try { + pids = PsapiTools.getInstance().enumProcesses(); + boolean found=false; + for (Integer pid : pids) { + HANDLE process = Kernel32.INSTANCE.OpenProcess(PROCESS_PERMISSIONS, true, pid); + List 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;i0) { + 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 sessionPlayers = new ArrayList(); + for (Profile p : mySession.getPlayers()) { + if (!p.username.equalsIgnoreCase(myProfile.username)) { + sessionPlayers.add(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;i5)) { + //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(); + } + } + + } +} diff --git a/src/sig/modules/RabiRibi/EntityLookupData.java b/src/sig/modules/RabiRibi/EntityLookupData.java new file mode 100644 index 0000000..4599469 --- /dev/null +++ b/src/sig/modules/RabiRibi/EntityLookupData.java @@ -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 vals) { + File dir = new File(RABIRIBI_DIR); + if (!dir.exists()) { + dir.mkdirs(); + } + List data = new ArrayList(); + 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 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(); + } +} diff --git a/src/sig/modules/RabiRibi/MemoryOffset.java b/src/sig/modules/RabiRibi/MemoryOffset.java new file mode 100644 index 0000000..c1a9ba4 --- /dev/null +++ b/src/sig/modules/RabiRibi/MemoryOffset.java @@ -0,0 +1,176 @@ +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), //Erina Data Pointer. + ERINA_HP(0x4D8), + ERINA_MAXHP(0x4E8), + ERINA_XPOS(0xC), + ERINA_YPOS(0x10), + ERINA_XSPEED(0x470), //Relative to Entity Array. + ERINA_YSPEED(0x474), //Relative to Entity Array. + MAPID(0xA600AC), + CAMERA_XPOS(0x991AF4), + CAMERA_YPOS(0xABD0A4), + //ENTITY_SIZE(0x704), + ENTITY_ID(0x4F4), + ENTITY_HP(0x4D8), + ENTITY_MAXHP(0x4E8), + ENTITY_ISACTIVE(0x674), + ENTITY_ANIMATION(0x678), + ENTITY_XPOS(0xC), + ENTITY_YPOS(0x10), + ENTITY_COLOR(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; +} diff --git a/src/sig/modules/RabiRibi/MemoryType.java b/src/sig/modules/RabiRibi/MemoryType.java new file mode 100644 index 0000000..48ad2bd --- /dev/null +++ b/src/sig/modules/RabiRibi/MemoryType.java @@ -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; + } +} diff --git a/src/sig/modules/RabiRibi/MemoryValue.java b/src/sig/modules/RabiRibi/MemoryValue.java new file mode 100644 index 0000000..c68d5b3 --- /dev/null +++ b/src/sig/modules/RabiRibi/MemoryValue.java @@ -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; + } + } +} diff --git a/src/sig/modules/RabiRibi/MemoryValueType.java b/src/sig/modules/RabiRibi/MemoryValueType.java new file mode 100644 index 0000000..99c5bb9 --- /dev/null +++ b/src/sig/modules/RabiRibi/MemoryValueType.java @@ -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. +} diff --git a/src/sig/modules/RabiRibi/Overlay.java b/src/sig/modules/RabiRibi/Overlay.java new file mode 100644 index 0000000..3299f67 --- /dev/null +++ b/src/sig/modules/RabiRibi/Overlay.java @@ -0,0 +1,151 @@ +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 objects = new ArrayList(); + + 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) { + + } + } + } +} diff --git a/src/sig/modules/RabiRibi/RabiUtils.java b/src/sig/modules/RabiRibi/RabiUtils.java new file mode 100644 index 0000000..e42b4aa --- /dev/null +++ b/src/sig/modules/RabiRibi/RabiUtils.java @@ -0,0 +1,11 @@ +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; + } +} diff --git a/src/sig/modules/RabiRibi/SmoothObject.java b/src/sig/modules/RabiRibi/SmoothObject.java new file mode 100644 index 0000000..077fdd5 --- /dev/null +++ b/src/sig/modules/RabiRibi/SmoothObject.java @@ -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) { + + } +} diff --git a/src/sig/modules/RabiRibi/SmoothObjects/EntityMarker.java b/src/sig/modules/RabiRibi/SmoothObjects/EntityMarker.java new file mode 100644 index 0000000..e0d4aaa --- /dev/null +++ b/src/sig/modules/RabiRibi/SmoothObjects/EntityMarker.java @@ -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); + } + +} diff --git a/src/sig/modules/RabiRibi/SmoothObjects/ErinaMarker.java b/src/sig/modules/RabiRibi/SmoothObjects/ErinaMarker.java new file mode 100644 index 0000000..3f8b783 --- /dev/null +++ b/src/sig/modules/RabiRibi/SmoothObjects/ErinaMarker.java @@ -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); + } +} diff --git a/src/sig/modules/RabiRibiModule.java b/src/sig/modules/RabiRibiModule.java new file mode 100644 index 0000000..1348bf4 --- /dev/null +++ b/src/sig/modules/RabiRibiModule.java @@ -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; + long rabiRibiMemOffset = 0; + public HANDLE rabiribiProcess = null; + HashMap entities = new HashMap(); + final static int MAX_ENTITIES_TO_UPDATE = 500; + final static int ENTITY_ARRAY_ELEMENT_SIZE = 0x704; + public HashMap lookup_table = new HashMap(); + 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 pids; + try { + pids = PsapiTools.getInstance().enumProcesses(); + for (Integer pid : pids) { + HANDLE process = Kernel32.INSTANCE.OpenProcess(PROCESS_PERMISSIONS, true, pid); + List 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 getEntities() { + return entities; + } + + private void updateEntities() { + + //System.out.println("Size is "+size); + List idsToRemove = new ArrayList(); + 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;ireadIntFromMemory(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 enumProcesses() throws Exception{ + List list = new LinkedList(); + + int[] pProcessIds = new int[1024]; + IntByReference pBytesReturned = new IntByReference(); + boolean success = psapi.EnumProcesses(pProcessIds, pProcessIds.length*Integer.SIZE/8, pBytesReturned); + if (!success){ + int err=k32.GetLastError(); + throw new Exception("EnumProcesses failed. Error: "+err); + } + + int size = (pBytesReturned.getValue()/(Integer.SIZE/8)); + for (int i=0;i EnumProcessModules(HANDLE hProcess) throws Exception{ + List list = new LinkedList(); + + HMODULE[] lphModule = new HMODULE[1024]; + IntByReference lpcbNeededs= new IntByReference(); + boolean success = psapi.EnumProcessModules(hProcess, lphModule, lphModule.length, lpcbNeededs); + if (!success){ + int err=k32.GetLastError(); + if (err!=6) { + throw new Exception("EnumProcessModules failed. Error: "+err); + } + } + for (int i = 0; i < lpcbNeededs.getValue()/4; i++) { + list.add(new Module(hProcess, lphModule[i])); + } + + return list; + } + + public List EnumProcessModulesEx(HANDLE hProcess, int flags) throws Exception{ + List list = new LinkedList(); + + HMODULE[] lphModule = new HMODULE[1024]; + IntByReference lpcbNeededs= new IntByReference(); + boolean success = psapi.EnumProcessModulesEx(hProcess, lphModule, lphModule.length, lpcbNeededs, flags); + if (!success){ + int err=k32.GetLastError(); + throw new Exception("EnumProcessModules failed. Error: "+err); + } + for (int i = 0; i < lpcbNeededs.getValue()/4; i++) { + list.add(new Module(hProcess, lphModule[i])); + } + + return list; +} + + public String GetModuleFileNameExA(HANDLE hProcess, HMODULE hModule){ + byte[] lpImageFileName= new byte[256]; + psapi.GetModuleFileNameExA(hProcess, hModule, lpImageFileName, 256); + return Native.toString(lpImageFileName); + } + + public String GetModuleBaseNameA(HANDLE hProcess, HMODULE hModule){ + byte[] lpImageFileName= new byte[256]; + psapi.GetModuleBaseNameA(hProcess, hModule, lpImageFileName, 256); + return Native.toString(lpImageFileName); +} + + public LPMODULEINFO GetModuleInformation(HANDLE hProcess, HMODULE hModule) throws Exception{ + LPMODULEINFO lpmodinfo = new LPMODULEINFO(); + + boolean success = psapi.GetModuleInformation(hProcess, hModule, lpmodinfo, lpmodinfo.size()); + if (!success){ + int err=k32.GetLastError(); + throw new Exception("GetModuleInformation failed. Error: "+err); + } + return lpmodinfo; + } + +} diff --git a/src/sig/sigIRC.java b/src/sig/sigIRC.java index 0b6bcaf..0fed04b 100644 --- a/src/sig/sigIRC.java +++ b/src/sig/sigIRC.java @@ -12,15 +12,29 @@ import com.mb3364.twitch.api.handlers.ChannelResponseHandler; import com.mb3364.twitch.api.handlers.StreamResponseHandler; import com.mb3364.twitch.api.models.Channel; import com.mb3364.twitch.api.models.Stream; +import com.sun.jna.Memory; +import com.sun.jna.Native; +import com.sun.jna.Pointer; +import com.sun.jna.platform.win32.Advapi32; +import com.sun.jna.platform.win32.Kernel32; +import com.sun.jna.platform.win32.WinDef.DWORD; +import com.sun.jna.platform.win32.WinNT; +import com.sun.jna.platform.win32.WinNT.HANDLE; +import com.sun.jna.platform.win32.WinNT.HANDLEByReference; import sig.modules.ChatLogModule; import sig.modules.ControllerModule; +import sig.modules.RabiRaceModule; +import sig.modules.RabiRibiModule; import sig.modules.TouhouMotherModule; import sig.modules.TwitchModule; import sig.modules.ChatLog.ChatLogMessage; import sig.modules.ChatLog.ChatLogTwitchEmote; +import sig.modules.utils.MyKernel32; +import sig.modules.utils.PsapiTools; import sig.utils.FileUtils; import sig.utils.GithubUtils; +import sig.utils.MemoryUtils; import sig.utils.TextUtils; import java.awt.Color; @@ -29,6 +43,7 @@ import java.awt.Font; import java.awt.Graphics; import java.awt.GraphicsDevice; import java.awt.GraphicsEnvironment; +import java.awt.Image; import java.awt.Rectangle; import java.awt.event.WindowEvent; import java.awt.event.WindowListener; @@ -72,7 +87,7 @@ public class sigIRC{ public final static String PROGRAM_EXECUTABLE_URL = "https://github.com/sigonasr2/sigIRCv2/raw/master/sigIRCv2.jar"; public static ConfigFile config; static String server; - static String nickname; + public static String nickname; public static String channel; public static boolean authenticated=false; public static int lastPlayedDing=0; @@ -116,6 +131,16 @@ public class sigIRC{ public static int chatlogmodule_height=312; public static int chatlogmodule_X=0; public static int chatlogmodule_Y=312; + public static int rabiribimodule_width=320; + public static int rabiribimodule_height=312; + public static int rabiribimodule_X=0; + public static int rabiribimodule_Y=312; + public static boolean rabiribimodule_enabled=false; + public static int rabiracemodule_width=320; + public static int rabiracemodule_height=312; + public static int rabiracemodule_X=0; + public static int rabiracemodule_Y=312; + public static boolean rabiracemodule_enabled=false; public static int chatlogMessageHistory=50; public static boolean controllermodule_enabled=true; public static int controllermodule_width=320; @@ -133,6 +158,7 @@ public class sigIRC{ public static long channel_id = -1; public static int lastSubEmoteUpdate = -1; public static boolean autoUpdateProgram = true; + public static Image programIcon; public static int subchannelCount = 0; public static HashMap subchannelIds = new HashMap(); @@ -163,7 +189,7 @@ public class sigIRC{ dingThreshold = Integer.parseInt(config.getProperty("dingThreshold")); backgroundcol = new Color(Integer.parseInt(config.getProperty("backgroundColor"))); messageFont = config.getProperty("messageFont","Gill Sans Ultra Bold Condensed"); - usernameFont = config.getProperty("usernameFont","Gill Sans"); + usernameFont = config.getProperty("usernameFont","Segoe UI Semibold"); touhoumotherConsoleFont = config.getProperty("touhoumotherConsoleFont","Agency FB Bold"); touhoumothermodule_enabled = config.getBoolean("Module_touhoumother_Enabled",false); controllermodule_enabled = config.getBoolean("Module_controller_Enabled",false); @@ -186,6 +212,16 @@ public class sigIRC{ touhoumothermodule_Y = config.getInteger("TOUHOUMOTHER_module_Y",312); touhoumothermodule_width = config.getInteger("TOUHOUMOTHER_module_width",320); touhoumothermodule_height = config.getInteger("TOUHOUMOTHER_module_height",312); + /*rabiribimodule_X = config.getInteger("RABIRIBI_module_X",0); + rabiribimodule_Y = config.getInteger("RABIRIBI_module_Y",312); + rabiribimodule_width = config.getInteger("RABIRIBI_module_width",320); + rabiribimodule_height = config.getInteger("RABIRIBI_module_height",312); + rabiribimodule_enabled = config.getBoolean("Module_rabiribi_Enabled", false);*/ + rabiracemodule_X = config.getInteger("RABIRACE_module_X",0); + rabiracemodule_Y = config.getInteger("RABIRACE_module_Y",312); + rabiracemodule_width = config.getInteger("RABIRACE_module_width",320); + rabiracemodule_height = config.getInteger("RABIRACE_module_height",312); + rabiracemodule_enabled = config.getBoolean("Module_rabirace_Enabled", false); chatlogmodule_X = config.getInteger("CHATLOG_module_X",0); chatlogmodule_Y = config.getInteger("CHATLOG_module_Y",312); chatlogmodule_width = config.getInteger("CHATLOG_module_width",320); @@ -208,6 +244,8 @@ public class sigIRC{ final String oauth = filedata[0]; + Initialize(); + WriteBreakToLogFile(); programClock.start(); @@ -227,6 +265,14 @@ public class sigIRC{ InitializeIRCConnection(server, nickname, channel, oauth); } + private static void Initialize() { + try { + programIcon = ImageIO.read(new File(sigIRC.BASEDIR+"/sigIRC/sigIRCicon.png")); + } catch (IOException e) { + e.printStackTrace(); + } + } + private static ConfigFile InitializeConfigurationFile() { ConfigFile.configureDefaultConfiguration(); final String configname = "sigIRCv2.conf"; @@ -245,6 +291,9 @@ public class sigIRC{ manager = new FileManager("sigIRC/subscribers.txt"); manager.verifyAndFetchFileFromServer(); manager = new FileManager("sigIRC/logs/",true); manager.verifyAndFetchFileFromServer(); manager = new FileManager("sigIRC/sounds/",true); manager.verifyAndFetchFileFromServer(); + manager = new FileManager("sigIRC/rabi-ribi/",true); manager.verifyAndFetchFileFromServer(); + manager = new FileManager("sigIRC/rabi-ribi/characters",true); manager.verifyAndFetchFileFromServer(); + manager = new FileManager("sigIRC/rabi-ribi/items",true); manager.verifyAndFetchFileFromServer(); //manager = new FileManager("sigIRC/sounds/Glaceon_cry.wav"); manager.verifyAndFetchFileFromServer(); File follower_sounds_folder = new File(BASEDIR+"sigIRC/follower_sounds"); if (!follower_sounds_folder.exists()) { @@ -265,6 +314,7 @@ public class sigIRC{ manager = new FileManager("sigIRC/controller/4-way_axis.png"); manager.verifyAndFetchFileFromServer(); manager = new FileManager("sigIRC/controller/controller_overlay.png"); manager.verifyAndFetchFileFromServer(); manager = new FileManager("sigIRC/controller/controller_template.png"); manager.verifyAndFetchFileFromServer(); + manager = new FileManager("sigIRC/CP_Font.ttf"); manager.verifyAndFetchFileFromServer(); manager = new FileManager("kill.png"); manager.verifyAndFetchFileFromServer(); manager = new FileManager("memory"); manager.verifyAndFetchFileFromServer(); manager = new FileManager("swap.png"); manager.verifyAndFetchFileFromServer(); @@ -332,6 +382,18 @@ public class sigIRC{ "Controller" )); } + if (rabiribimodule_enabled) { + modules.add(new RabiRibiModule( + new Rectangle(rabiribimodule_X,rabiribimodule_Y,rabiribimodule_width,rabiribimodule_height), + "Rabi-Ribi" + )); + } + if (rabiracemodule_enabled) { + modules.add(new RabiRaceModule( + new Rectangle(rabiracemodule_X,rabiracemodule_Y,rabiracemodule_width,rabiracemodule_height), + "Rabi-Race" + )); + } } private static void InitializeCustomSounds() { @@ -557,11 +619,7 @@ public class sigIRC{ f.setLocation(windowX, windowY); f.setSize(windowWidth, windowHeight); - try { - f.setIconImage(ImageIO.read(new File(sigIRC.BASEDIR+"/sigIRC/sigIRCicon.png"))); - } catch (IOException e) { - e.printStackTrace(); - } + f.setIconImage(programIcon); button = new BackgroundColorButton(new File(sigIRC.BASEDIR+"backcolor.png"),panel.getX()+panel.getWidth()-96,64+rowobj.size()*rowSpacing); if (sigIRC.overlayMode) { diff --git a/src/sig/utils/DebugUtils.java b/src/sig/utils/DebugUtils.java new file mode 100644 index 0000000..fcf2bd7 --- /dev/null +++ b/src/sig/utils/DebugUtils.java @@ -0,0 +1,17 @@ +package sig.utils; + + +public class DebugUtils { + public static void showStackTrace() { + System.out.println("Trace:"+getStackTrace()); + } + + public static String getStackTrace() { + StackTraceElement[] stacktrace = new Throwable().getStackTrace(); + StringBuilder stack = new StringBuilder("Mini stack tracer:"); + for (int i=0;i200) { g2.setColor(shadow_color); - g2.drawString(as.getIterator(),(int)x+outline_size,(int)y+outline_size); + g2.drawString(as.getIterator(),(int)(x+outline_size+xoffset),(int)(y+outline_size+yoffset)); } else { FontRenderContext frc = g2.getFontMetrics(font).getFontRenderContext(); GlyphVector gv = font.createGlyphVector(frc, message); Rectangle2D box = gv.getVisualBounds(); - Shape shape = gv.getOutline((int)x,(int)y); + Shape shape = gv.getOutline((int)(x+xoffset),(int)(y+yoffset)); g2.setClip(shape); - g2.drawString(as.getIterator(),(int)x,(int)y); + g2.drawString(as.getIterator(),(int)(x+xoffset),(int)(y+yoffset)); g2.setClip(null); g2.setStroke(new BasicStroke(outline_size*2)); g2.setColor(shadow_color); @@ -40,7 +47,11 @@ public class DrawUtils { g2.draw(shape); } g2.setColor(text_color); - g2.drawString(as.getIterator(),(int)x,(int)y); + g2.drawString(as.getIterator(),(int)(x+xoffset),(int)(y+yoffset)); + } + public static void drawCenteredOutlineText(Graphics g, Font font, double x, double y, int outline_size, Color text_color, Color shadow_color, String message) { + Rectangle2D textBounds = TextUtils.calculateStringBoundsFont(message, font); + drawOutlineText(g,font,x,y,-textBounds.getWidth()/2,-textBounds.getHeight()/2,outline_size,text_color,shadow_color,message); } public static void drawText(Graphics g, double x, double y, Color color, String message) { if (message.length()>0) { @@ -95,6 +106,17 @@ public class DrawUtils { } } + public static void drawImage(Graphics g, Image img, double x, double y, Color blend_col, ImageObserver source) { + BufferedImage tmp = new BufferedImage(img.getWidth(source),img.getHeight(source),BufferedImage.TYPE_INT_ARGB); + Graphics2D g2 = tmp.createGraphics(); + g2.drawImage(img, 0, 0, null); + g2.setComposite(AlphaComposite.SrcAtop); + g2.setColor(blend_col); + g2.fillRect(0, 0, img.getWidth(source), img.getHeight(source)); + g2.dispose(); + g.drawImage(tmp,(int)x,(int)y,source); + } + public static Color invertColor(Color c) { return new Color(255-c.getRed(),255-c.getGreen(),255-c.getBlue(),255); } diff --git a/src/sig/utils/JavaUtils.java b/src/sig/utils/JavaUtils.java new file mode 100644 index 0000000..cdc5802 --- /dev/null +++ b/src/sig/utils/JavaUtils.java @@ -0,0 +1,50 @@ +package sig.utils; + +import java.lang.reflect.Field; + +public class JavaUtils { + public JavaUtils clone() { + JavaUtils newpos = new JavaUtils(); + for (Field f : this.getClass().getDeclaredFields()) { + if (ReflectUtils.isCloneable(f)) { + try { + f.set(newpos, f.get(this)); + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + } + return newpos; + } + 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(); + } +} diff --git a/src/sig/utils/MemoryUtils.java b/src/sig/utils/MemoryUtils.java new file mode 100644 index 0000000..7138235 --- /dev/null +++ b/src/sig/utils/MemoryUtils.java @@ -0,0 +1,37 @@ +package sig.utils; + +import com.sun.jna.Native; +import com.sun.jna.platform.win32.Advapi32; +import com.sun.jna.platform.win32.Kernel32; +import com.sun.jna.platform.win32.WinNT; +import com.sun.jna.platform.win32.WinDef.DWORD; +import com.sun.jna.platform.win32.WinNT.HANDLEByReference; + +public class MemoryUtils { + /** + * Enables debug privileges for this process, required for OpenProcess() to + * get processes other than the current user + */ + public static void enableDebugPrivilege() { + HANDLEByReference hToken = new HANDLEByReference(); + boolean success = Advapi32.INSTANCE.OpenProcessToken(Kernel32.INSTANCE.GetCurrentProcess(), + WinNT.TOKEN_QUERY | WinNT.TOKEN_ADJUST_PRIVILEGES, hToken); + if (!success) { + System.out.println("OpenProcessToken failed. Error: {}" + Native.getLastError()); + return; + } + WinNT.LUID luid = new WinNT.LUID(); + success = Advapi32.INSTANCE.LookupPrivilegeValue(null, WinNT.SE_DEBUG_NAME, luid); + if (!success) { + System.out.println("LookupprivilegeValue failed. Error: {}" + Native.getLastError()); + return; + } + WinNT.TOKEN_PRIVILEGES tkp = new WinNT.TOKEN_PRIVILEGES(1); + tkp.Privileges[0] = new WinNT.LUID_AND_ATTRIBUTES(luid, new DWORD(WinNT.SE_PRIVILEGE_ENABLED)); + success = Advapi32.INSTANCE.AdjustTokenPrivileges(hToken.getValue(), false, tkp, 0, null, null); + if (!success) { + System.out.println("AdjustTokenPrivileges failed. Error: {}" + Native.getLastError()); + } + Kernel32.INSTANCE.CloseHandle(hToken.getValue()); + } +} diff --git a/src/sig/utils/ReflectUtils.java b/src/sig/utils/ReflectUtils.java new file mode 100644 index 0000000..abed4ee --- /dev/null +++ b/src/sig/utils/ReflectUtils.java @@ -0,0 +1,10 @@ +package sig.utils; + +import java.lang.reflect.Field; + +public class ReflectUtils { + public static boolean isCloneable(Field f) { + int mods = f.getModifiers(); + return mods<8; + } +} diff --git a/src/sig/utils/TextUtils.java b/src/sig/utils/TextUtils.java index 4725f83..194ffd9 100644 --- a/src/sig/utils/TextUtils.java +++ b/src/sig/utils/TextUtils.java @@ -1,8 +1,11 @@ package sig.utils; import java.awt.Color; import java.awt.Font; +import java.awt.Point; import java.awt.font.FontRenderContext; import java.awt.geom.Rectangle2D; +import java.util.ArrayList; +import java.util.List; import sig.sigIRC; @@ -24,6 +27,10 @@ public class TextUtils { return sourcestring; } + public static boolean isAlphanumeric(String str) { + return str.matches("^[a-zA-Z0-9!\\-.? ]+$"); + } + public static boolean isNumeric(String str) { return str.matches("-?\\d+(\\.\\d+)?"); //match a number with optional '-' and decimal. @@ -45,7 +52,7 @@ public class TextUtils { StringBuilder sb = new StringBuilder(); int sec = seconds%60; int min = (seconds/60)%60; - int hrs = (min/60)%60; + int hrs = (seconds/3600)%24; if (hrs>0) { if (hrs>=10) { sb.append(hrs); @@ -82,4 +89,45 @@ public class TextUtils { String[] split = col.split(","); return new Color(Integer.parseInt(split[0]),Integer.parseInt(split[1]),Integer.parseInt(split[2])); } + + public static List WrapText(String msg, Font font, double width) { + List displayMessage = new ArrayList(); + String rawmessage = msg; + int textWidth = (int)TextUtils.calculateStringBoundsFont(rawmessage, font).getWidth(); + int maxWidth = (int)width; + do { + rawmessage = BreakTextAtNextSection(rawmessage+" ",font,displayMessage,maxWidth); + textWidth = (int)TextUtils.calculateStringBoundsFont(rawmessage, font).getWidth(); + } while (textWidth>maxWidth); + if (rawmessage.length()>0) { + displayMessage.add(rawmessage); + } + return displayMessage; + //System.out.println(displayMessage+": "+messageDisplaySize); + } + + private static String BreakTextAtNextSection(String msg, Font font, List list, int maxWidth) { + int marker = 1; + int textWidth = (int)TextUtils.calculateStringBoundsFont(msg.substring(0, marker), font).getWidth(); + while (textWidth