Jump to content

Salty Mike

Members
  • Posts

    123
  • Credits

  • Joined

  • Last visited

  • Days Won

    8
  • Feedback

    0%

Everything posted by Salty Mike

  1. You don't have to use the "Classic" version of the client. You could use the MAIN/LIVE version and just update the MINIMAP (textures) and the actual heightmap/UNR, some of which you can take from the Classic version. Anyway, what you have decided to do is the inferior option. The suggestion by Banshee Garnet is the betterr solution, in my humble opinion. I already have a HF core that is running on a client that is 1.5 years old and can be easily upgraded to support the latest. When you take that route, you ensure stability, as well as features working as they were supposed to. You could still introduce customs on top of them, but the base would be a real HF, not some "Classic IMPROVED/REIMAGINED" or however they call it nowadays.
  2. The picture below is source of Interface.u "class" file + its XDAT container. As such you can't copy-paste it and expect anything to happen. These file are for people who want to reproduce it on thier own custom interfaces. The one in the picture below you have to put in Textures, by default, unless you have edited your system folder to read TEXTURES from other folders as well, such as System. And this below you put within the explicitly specified "systemmsg-e.dat" or "systemmsg.dat" (or something like that, they can differ in name, I suppose) file within the system folder. You have to actually open the file (decrypt), add the lines while ensuring the proper formatting (making sure the structure is the correct one, or in other words that all of the TAB SPACES are in place, etc), and then you save the file (encrypt it with the proper encryption).
  3. In short, what you need is this: - special script (be it handler or AI or however your source handles it) that will be activated when you speak to the said NPC. - hook the script to an NPC of your choice - your multi-skills manager if you will. - a few static HTMLs and/or at least one Container HTML that will be used for the dynamic display of stuff. Now the lengthier version: You should create a special script/handler/AI (any will do initially) and assign it to an NPC of your choice (just has to be one that has no other special handler/script/ai assigned to it). Once you have that in place, you need to develop/write the actual script/handler/ai of the npc, which in actuality will handle all of the skill learning. To better illustrate it, think of the NPC as simply an empty box, in which you can put almost anything. In your case, you want to put a script/code that handles skill learning. The script itself is not very complicated. You just need to set conditions/backstops that would prevent exploits (which will be the majority of the coding/programming), and then a couple of methods that will handle the actual DYNAMIC display of skills within the container HTML that you would create. The dynamic display of skills means that you will be generating skills info and availability and populating the said Container HTML with the different data depending on who is using it and other conditions, such as learned skills/levels.
  4. All of the info is available on the forum. As such, there is no need for additional info. The provided assets are more than enough, not only to apply them to RUAcis, but also to any other pack/l2 version.
  5. Do you have a list of what the lost changes were? Additionally, how much should one expect as a compensation for the, as per your own words, "kind of complicated" job?
  6. Play with the Collision Height of the NPC itself, and good luck!
  7. Ask in the Eternity's discord server or forum and you will not only be answer but also, most likely, helped. Good luck!
  8. The author is here. No idea how you couldn't find him other than not searching for him at all. @LordWinter
  9. Nothing works on minimized clients anymore. The protection is designed to check if the game window is at the front when it is sending X, Y, or Z packet. Meanwhile, even the simplest of clickers works on the active client. I have a Logitech mouse, which comes with software that allows you to create macros and loops and what not, and I've used it on several occasions with no issues nor repercussions.
  10. You speak as if there were such magicians who could wave their magic wand and people would not only show up but also stay and donate so you can buy yourself a new car or a house. If you find such a unicorn, please do tell! We all would like to catch one for ourself too. ^.^
  11. You are not parsing the HTML, or at least that's what the error states. I assume the issue might lie here: return HTMLTemplateParser.fromCache(Path.of("/data/scripts/" + SCRIPT_SUBFOLDER + "/data/html/" + dialogType.toString().toLowerCase(Locale.ENGLISH) + "/" + path).toString(), player, placeholders, IncludeFunc.INSTANCE, IfFunc.INSTANCE, ForeachFunc.INSTANCE, ExistsFunc.INSTANCE, IfChildsFunc.INSTANCE, ChildsCountFunc.INSTANCE)
  12. If you hover over the weapon and you can see the augment, then it is client side, indeed. Else, it is server side, most definitely. Fact of the matter is, there is a whole chain of packets that are responsible for handling the new Augmentation system. The easiest way to keep track of them is by activating the NETCHAT packet debugger from ALT+G. It is not a debugger per-se, but it would help you see the packet exchange between client and server, which should then show you where the issue lies, namely the client->server packet, whose trail you should follow until you find your issue. If the other weapons are working, then it is quite possible that you have missed adding the new custom weapons somewhere in the datapack (in some xml or wherever your server pack keeps such data).
  13. One of the main issues with HTML on Interlude is that you can only have a few very specific basic colors and nothing in-between. However, there is an approach you can take to make it so that you have custom colors for your table background. To do this, you would have to stack a bunch of tables with different background colors up. Here is an example of the code: <table width="274" cellpadding="0" cellspacing="0" height="32" border="0" bgcolor="FF0000"> <tr> <td width="242"> <table width="242" cellpadding="0" cellspacing="0" height="33" bgcolor="FAFAFA"> <tr> <td> <!-- FF0000 = RED --> <!-- 000400 = GREEN --> <table width="242" cellpadding="0" cellspacing="0" height="33" bgcolor="FF0000"> <tr> <td> <table width="242" cellpadding="0" cellspacing="0" height="33" bgcolor="FAFAFA"> <tr> <td> <table width="242" cellpadding="0" cellspacing="0" height="33" bgcolor="000000"> <tr> <td> <table width="242" cellpadding="0" cellspacing="0" height="33" bgcolor="000000"> <tr> <td width="90"> <table width="242" cellpadding="0" cellspacing="0" height="33" > <tr> <td height="5"> </td> <td height="5"> </td> <td height="11"> </td> </tr> </table> </td> </tr> </table> </td> </tr> </table> </td> </tr> </table> </td> </tr> </table> </td> </tr> </table> </td> </tr> </table> The end result will be this nice dark-red or red-brownish background color (disregard the buttons and text): PLEASE NOTE! This will make your HTML explode in length/size! To help with the increased size, you can follow this guide to reduce it by about 30-35%.
  14. One of the two major issues with HTML on Interlude has been the absence of `background` option for tables. However, there is a way to manipulate the HTML code so that you can achieve the same effect as `<table background=" "` on newer chronicles. A little known fact is that the <img /> tag does not necessarily has to have an `src` element. On top of that, we can set a negaive value for height, which would bring the next <img /> element up in the Z direction by the height we have set. Here is an example of how we do that: <img height=-34> <img src=L2UI_CH3.multisell_plusicon height=32 width=32> It is important to note that this code has to be placed outside of the table that you want to set the image as background. This is how the code would look like, if we are to add an <img /> as background to a button: <td width=36> <table cellpadding=0 cellspacing=0> <tr> <td> <button value=\" \" action=\" \" height=35 width=35 back=L2UI_CH3.inventory_outline_down fore=L2UI_CH3.inventory_outline> </td> </tr> </table> <img height=-34> <img src=L2UI_CH3.multisell_plusicon height=32 width=32> </td> Here is the resulting button with its background being the + sign and the OVER being taken from the inventory_outline. This is another example of utilizing this exact same code with different images/textures: And this is what it would look like if we were to stack a bunch of TDs in the same table:
  15. I have, as evident from the posted screenshot, see a copy below. The bottom-most line is No White-Spaces, at all. However, the 5% gain is not worth the risk, in my personal opinion. The Tab-Spaces and New Rows reduces the overall length by quite a lot as is. Here is a list of all four methods that I used in the screenshot. public static String removeTabSpaces(String text) { return text.replaceAll("\\t", ""); } public static String removeNewRows(String text) { return text.replaceAll("\\n", ""); } public static String removeTabSpacesAndNewRows(String text) { return text.replaceAll("[\\t\\n]", ""); } public static String removeAllWhiteSpacing(String text) { return text.replaceAll("\\s+", ""); }
  16. Greetings, folks! Here is a way to optimise the HTML length by up to 30%, depending on the nesting. The examples I give are taken from an old Interlude core, but the general idea is applicable to all java-based cores. Proof of concept! The two important bits in the screenshot below are the (1) Original HTML size row and the (4) No Tabs/Rows size row, which represent the before and after, respectively. STEPS: 1. locate the `setHtml(String text)` method inside `NpcHtmlMessage.java`. 2. add the following bit of code as a standalone method: /** * Replaces all occurrences of New Rows and Tab spaces in the string. * @param text the string that may contain invalid characters * @return the string with invalid character replaced by underscores */ public static String removeTabSpacesAndNewRows(String text) { return text.replaceAll("[\\t\\n]", ""); } 3. find the last ocurence of the `text` String variable in the `setHtml()` method, and push it through this newly created method like so: `removeTabSpacesAndNewRows(text);`. 4. example of the final result. /** * Sets the html. * @param text the new html */ public void setHtml(String text) { if (text == null) { LOGGER.warning("Html is null! this will crash the client!"); _html = "<html><body></body></html>"; return; } if (text.length() > 8192) { LOGGER.warning("Html is too long! this will crash the client!"); _html = "<html><body>Html was too long,<br>Try to use DB for this action</body></html>"; return; } _html = removeTabSpacesAndNewRows(text); // html code must not exceed 8192 bytes } /** * Replaces all occurrences of New Rows and Tab spaces in the string. * @param text the string that may contain invalid characters * @return the string with invalid character replaced by underscores */ public static String removeTabSpacesAndNewRows(String text) { return text.replaceAll("[\\t\\n]", ""); } 5. You could further refine it by processing the `text` variable between the two IF clauses by creating a new local variable, assigning it a value of `text` and then replacing the subsequent `text` mentions in the `setHtml()` method with this new local var. Here's what it would look like: /** * Sets the html. * @param text the new html */ public void setHtml(String text) { if (text == null) { LOGGER.warning("Html is null! this will crash the client!"); _html = "<html><body></body></html>"; return; } String refinedText = removeTabSpacesAndNewRows(text); if (refinedText.length() > 8192) { LOGGER.warning("Html is too long! this will crash the client!"); _html = "<html><body>Html was too long,<br>Try to use DB for this action</body></html>"; return; } _html = refinedText; // html code must not exceed 8192 bytes } UPDATE: (thanks to @xdem for pointing it out) You can instead apply the same logic/method to the HTMCache.java. To do so, locate the loadFile() method and recycle the String/Text/Content through the removeTabSpacesAndNewRows method. KEEP IN MIND that you might want to move the removeTabSpacesAndNewRows method in another java class, preferrably in some UTILITY class. Here is an example: public String loadFile(File file) { final HtmFilter filter = new HtmFilter(); String content = null; if (file.exists() && filter.accept(file) && !file.isDirectory()) { FileInputStream fis = null; BufferedInputStream bis = null; try { fis = new FileInputStream(file); bis = new BufferedInputStream(fis); final int bytes = bis.available(); final byte[] raw = new byte[bytes]; bis.read(raw); content = new String(raw, StandardCharsets.UTF_8); content = content.replaceAll("\r\n", "\n"); content = content.replaceAll("(?s)<!--.*?-->", ""); // Remove html comments content = NpcHtmlMessage.removeTabSpacesAndNewRows(content); final String relpath = Util.getRelativePath(Config.DATAPACK_ROOT, file); final int hashcode = relpath.hashCode(); if (Config.CHECK_HTML_ENCODING && !StandardCharsets.US_ASCII.newEncoder().canEncode(content)) { LOGGER.warning("HTML encoding check: File " + relpath + " contains non ASCII content."); } final String oldContent = _cache.get(hashcode); if (oldContent == null) { _bytesBuffLen += bytes; _loadedFiles++; } else { _bytesBuffLen = (_bytesBuffLen - oldContent.length()) + bytes; } _cache.put(hashcode, content); } catch (Exception e) { LOGGER.warning("Problem with htm file " + e); } finally { if (bis != null) { try { bis.close(); } catch (Exception e1) { LOGGER.warning("Problem with HtmCache: " + e1.getMessage()); } } if (fis != null) { try { fis.close(); } catch (Exception e1) { LOGGER.warning("Problem with HtmCache: " + e1.getMessage()); } } } } return content; }
  17. If your source is java-based, then it is quite easy. Each source comes with a ReceivablePacket.java whose read() function is being overwritten by its sub-classes, one of which is something related to Game Client. This class, let's call it GameClientPacket.java, also has sub-classes, the actual client->server packets, which extend its secondary read method. From here, you have 2 options. 1 - Enable the Net Stats(Chat) feature in the client to see the name of the sendable/receivable packets (Client <-> Server, where C_ = sent by the client and S_ = sent by the server). 2 - Rely on the source's exception-handler, which will show the ID of the packet, if it is unknown, or the IDE's (IntelliJ/Eclipse) debug feature to figure out which packet is being sent. Then, you also have multiple options, with the easiest one being to search for the packet structure in the client itself, or brute-force the incoming data from the server-side by utilising the aforementioned IDE debug feature with breakpoints.
  18. I'm fairly certain I can help. But which protocol version are we talking about?
  19. There isn't one, in terms of dimensions. You gotta run around and write down /loc coordinates.
  20. You have to create the "voiced" handler in the core too, or at the very least make sure that the delimiter is underscore and not an empty space. Alternatively, you can try changing all references of the strings below to start with "voiced_", or remove the "voiced_" portion from the button bypass. private static final String[] VOICED_COMMANDS = { "siege", "siege_gludio", "siege_dion", "siege_giran", "siege_oren", "siege_aden", "siege_innadril", "siege_goddard", "siege_rune", "siege_schuttgart" };
  21. Аз ще ти свърша по-добра работа. :Р Ако усетиш, че тоя иска да ти подлива вода - дискорд инфото ми е на профила.
  22. And how does this account for a genuine, legit player who is just holding down the keyboard key with the marco?
  23. I'm interested in the solution too, out of pure curiosity. The flood protector will work only if the macro is being sent non-stop, which I don't think any Client Dev would be stupid enough to do. Instead, I'd expect that it is being sent every X ms, which would mean you wouldn't be able to reasonably differentiate between genuine MacroSpamming and auto-macroing. One rather reasonable assumption would be to monitor and record the difference between UseMacro requests for each individual player and to disconnect them based on certain criteria. Example - (MarcoUseRequestTime_1 - MacroUseRequestTime_2) != (MarcoUseRequestTime_3 - MarcoUseRequestTime_4) + X_miliseconds_to_account_for_network_delay. [note]: Just note that a skilled client dev could simply add a random delay to macro-looping to bypass the above method. As far as my knowledge goes, the ultimate solution should be in the client. Maybe you can add something to your interface, some check that will be done through a packet every X seconds, similarly to how pinging works, but this one will just make sure that the player is using your interface and not another modified version.
×
×
  • Create New...