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