VIP Member
  • Content count

  • Joined

  • Last visited

  • Days Won

  • Feedback


eressea last won the day on October 5

eressea had the most liked content!

Community Reputation

12 Good


About eressea

  • Rank

Contact Methods

  • Website URL

Profile Information

  • Current Mood
  • Gender
  • Country
    Czech Republic

Recent Profile Visitors

1,478 profile views
  1. Are you sure you’re asking in right section? This is for l2off. If you want to change it in l2j, comment out lines 2231-2235 in Please someone move it to proper section :)
  2. Hi, 1. First I need to get it running without items - just pure mail, then add items and then maybe sending via SQL or Cached admin socket 2. Probably yes (and if not, I would gladly accept a patch for it :D) 3. Of course, you will be able to send only items that are tradeable and usable in private store 4. Thanks :)
  3. Hi, this depends on whether you're speaking about extender compiler or AI compiler. Extenders* are written in ASM, C++ or combination of both and usually it's compiled with Visual Studio. AI is written in NASC language (made by NCsoft) and there are multiple compilers available - some of them based on NCsoft binaries, some of them written from scratch. * explanation about extenders: There are some files from NCsoft that leaked out. We know at least about C0 files, C4 PTS files and GF PTS files. All these contain EXE files that you can use - but they're full of bugs etc. Here comes the extender - it's some DLL file that attaches to server EXE file and does some changes and fixes. Usually it's very difficult to find out how to change something so I won't recommend trying this if you're beginner and don't have good experience with ASM and C++. Probably decompiler for AI - in L2OFF there are leaked obj files (compiled AI), if you want to work with it, you need to get decompiled AI somewhere or decompile it yourself. If you're beginner, you should find already decompiled AI. As for server itself - it can't be decompiled, programmers have to reverse engineer it (see explanation about extenders in previous answer) The original servers are written in C++ and AI is written in NASC language Only C0 server was 32bit, all newer versions are 64bit so they require 64bit system. GF-based servers run fine on all Windows Servers 2008+ (64bit). You definitely don't want to use C0 based server if you're a beginner. I would guess it's again about compiled AI (obj files using simple stack language, hard to read and update) and source AI (NASC files, easy to read and update, have to be compiled before use on server) but I'm not sure. You don't have server source, you have only extender source. You probably want to compile it (in Visual Studio) and use it with your server files. Pay attention to picking right binaries (EXE files) as it must match extender base version (C4/GF) - extender for GF won't work with C4 EXE files and vice versa. You would have to add handling for all bypasses for community board into the extender. Maybe few days of work for someone who is experienced with L2OFF core development - there are not many people who can do this. You can try to learn it slowly (get IDA Pro, create database for your l2server.exe and try to comprehend what your extender is doing there) but you stand no chance if you're not ASM/C++ programmer. You should get decopiled AI somewhere and try to learn from it. There are AI classes defined and NPCs can use them. For TvT event you would probably create some NPC (manager who would manage the event) and write an AI class for it to handle everything. If it will need some core support, you'll have to implement it in your extender. If you're ok with features that are already there, you need just to write the AI class (in NASC language), create NPC(s) for it, write HTML dialogs etc. You can run it on W10 64bit so you don't need any VM. As for Visual Studio, you'll probably need exactly Visual Studio 2005 SP1 64bit. As for clean GF - google for l2server_l2off_gracia_final_83, that's the original leak. Don't run live server (with players) on it as it's full of dupes and other security bugs (and many other bugs). As for some extender source - you can get my opensource extender or download Vanganth's extender somewhere, if I remember correctly, someone has shared it here on this forum.
  4. [L2Off] L2 Shrine

    We've managed to get Christmas event Raising Rudolph running - if you ever wanted to try it, it's perfect time now :)
  5. Hi everyone, apart of L2, I also work on many different things and I'd like to share one example I wrote (because it's not so easy finding out how to do it properly). When you need to render some text that requires more complex rendering than Latin - for example Hebrew, Arabic and Devanagari (Hindi) - you'll have to do some text shaping. It's not so difficult for Hebrew and Arabic (if you don't mind sometimes wrong niqqud, you can implement subset of OpenType and use fribidi) but for Devanagari it's almost impossible to implement again (too much work). If you're on Windows platform only, you can use Microsoft's Uniscribe which works perfectly, on OS X/iOS you can use Apple's Coretext which works very well too. But what if you need it to be platform agnostic? Then you can use FreeType and HarfBuzz :) Also, HarfBuzz can use native (Uniscribe/Coretext) shapers on given platform (depends how you compile it) instead of it's own shaper. So the example here, as for fonts, you can download them from Google, if you want to see output without compiling, scroll down. #include <iostream> #include <harfbuzz/hb.h> #include <harfbuzz/hb-ft.h> #include <ft2build.h> #include <freetype.h> // Input texts in UTF-8 (without Byte Order Mask) static const char *texts[] = { "\xd7\xa9\xd7\x9c\xd7\x95\xd7\x9d \xd7\xa2\xd7\x95\xd7\x9c\xd7\x9d", "\xd9\x85\xd8\xb1\xd8\xad\xd8\xa8\xd8\xa7 \xd8\xa8\xd8\xa7\xd9\x84\xd8\xb9\xd8\xa7\xd9\x84\xd9\x85", "\xe0\xa4\xa8\xe0\xa4\xae\xe0\xa4\xb8\xe0\xa5\x8d\xe0\xa4\xa4\xe0\xa5\x87 \xe0\xa4\xa6\xe0\xa5\x81\xe0\xa4\xa8\xe0\xa4\xbf\xe0\xa4\xaf\xe0\xa4\xbe" }; // Font sizes in points static const size_t fontSizes[] = { 16, 16, 16 }; // Font filenames static const char *fontFiles[] = { "NotoSansHebrew-Regular.ttf", "NotoSansArabic-Regular.ttf", "NotoSansDevanagari-Regular.ttf" }; int main(int argc, char **argv) { // Freetype library handle FT_Library library; // Initialize FreeType if (FT_Init_FreeType(&library)) { std::cerr << "Can't initialize FreeType" << std::endl; return 1; } // Go through all input texts for (size_t textIndex = 0 ; textIndex < sizeof(texts) / sizeof(texts[0]) ; ++textIndex) { // Current input text const char *text = texts[textIndex]; const size_t fontSize = fontSizes[textIndex]; const char *fontFile = fontFiles[textIndex]; // FreeType font face handle FT_Face face; // Load font if (FT_New_Face(library, fontFile, 0, &face)) { std::cerr << "Can't load font " << fontFile << std::endl; return 1; } // Set character size if (FT_Set_Char_Size(face, fontSize << 6, fontSize << 6, 0, 0)) { std::cerr << "Can't set character size" << std::endl; return 1; } // Set no transform (identity) FT_Set_Transform(face, 0, 0); // Load font into HarfBuzz hb_font_t *hbFont = hb_ft_font_create(face, 0); // Create buffer for our text hb_buffer_t *hbBuffer = hb_buffer_create(); // Add our text to buffer hb_buffer_add_utf8(hbBuffer, text, -1, 0, -1); // Detect direction etc hb_buffer_guess_segment_properties(hbBuffer); // Shape our text hb_shape(hbFont, hbBuffer, 0, 0); // Shaped text info unsigned int len = hb_buffer_get_length(hbBuffer); hb_glyph_info_t *info = hb_buffer_get_glyph_infos(hbBuffer, 0); hb_glyph_position_t *pos = hb_buffer_get_glyph_positions(hbBuffer, 0); // Compute text width and origin (from min and max X and Y drawing coordinate) int originX = 0, originY = 0; int minX = INT_MAX, maxX = INT_MIN, minY = INT_MAX, maxY = INT_MIN; // Go through all glyphs and find minimum and maximum X and Y coordinate for (size_t i = 0 ; i < len ; ++i) { // Load glyph if (FT_Load_Glyph(face, info[i].codepoint, FT_LOAD_RENDER)) { std::cerr << "Can't load glyph " << info[i].codepoint << std::endl; return 1; } // Glyph data FT_GlyphSlot slot = face->glyph; // Get X and Y offset int offsetX = ((pos[i].x_offset + slot->metrics.horiBearingX) >> 6); int offsetY = ((pos[i].y_offset + slot->metrics.horiBearingY) >> 6); // Compute minimum and maximum X and Y for this glyph int glyphMinX = originX + offsetX; int glyphMaxX = originX + slot->bitmap.width + offsetX; int glyphMinY = originY - slot->bitmap.rows + offsetY; int glyphMaxY = originY + offsetY; // Update minimum and maximum X and Y for text if (glyphMinX < minX) minX = glyphMinX; if (glyphMaxX > maxX) maxX = glyphMaxX; if (glyphMinY < minY) minY = glyphMinY; if (glyphMaxY > maxY) maxY = glyphMaxY; // Advance originX += pos[i].x_advance >> 6; } // Text will start on 0 originX = -minX; originY = -minY; // Compute width and height size_t width = maxX - minX + 1; size_t height = maxY - minY + 1; // Allocate buffer for image unsigned char *image = new unsigned char[width * height]; // Clear image bufer memset(image, 0, width * height); // Go through glyphs and draw them for (size_t i = 0 ; i < len ; ++i) { // Load glyph if (FT_Load_Glyph(face, info[i].codepoint, FT_LOAD_RENDER)) { std::cerr << "Can't load glyph " << info[i].codepoint << std::endl; return 1; } // Glyph data FT_GlyphSlot slot = face->glyph; // Pointer to bitmap data unsigned char *ptr = slot->bitmap.buffer; // Get real offset int drawX = originX + ((pos[i].x_offset + slot->metrics.horiBearingX) >> 6); int drawY = originY + ((pos[i].y_offset + slot->metrics.horiBearingY) >> 6); // Copy bitmap for (size_t y = 0 ; y < slot->bitmap.rows ; ++y) { // Copy row for (size_t x = 0 ; x < slot->bitmap.width ; ++x) { if (drawX + x < 0) { std::cerr << "drawX (" << drawX << ") + x (" << x << ") < 0" << std::endl; abort(); } if (drawX + x >= width) { std::cerr << "drawX (" << drawX << ") + x (" << x << ") > width (" << width << ")" << std::endl; abort(); } if (drawY - y < 0) { std::cerr << "drawY (" << drawY << ") - y (" << y << ") < 0" << std::endl; abort(); } if (drawY - y >= height) { std::cerr << "drawY (" << drawY << ") - y (" << y << ") > height (" << height << ")" << std::endl; abort(); } image[(drawY - y) * width + drawX + x] = ptr[x]; } // Advance pointer ptr += slot->bitmap.pitch; } // Advance originX += pos[i].x_advance >> 6; } // Output rendered text for (size_t y = 0 ; y < height ; ++y) { for (size_t x = 0 ; x < width ; ++x) { unsigned char value = image[(height - y - 1) * width + x]; if (value >= 0x80) { std::cout << "XX"; // if it's 128+ } else if (value >= 0x40) { std::cout << ".."; // if it's 64+ } else { std::cout << " "; // if its under 64 } } std::cout << std::endl; } std::cout << std::endl; // Delete image buffer delete [] image; // Destroy buffer for text hb_buffer_destroy(hbBuffer); // Destroy HarfBuzz font hb_font_destroy(hbFont); // Destroy FreeType font FT_Done_Face(face); } // Destroy FreeType FT_Done_FreeType(library); return 0; } XXXX XXXX XXXX XXXX XXXX XXXX XXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXX XXXX XX XXXXXXXXXXXXXX XXXX XXXXXXXXXXXXXXXX..XX XXXX XXXX XXXX........XXXX ............XX.. XXXX XXXX ..XX XXXX........XXXX XXXX ............XX.. XX XXXX XXXX XXXX ..XX ..XX XXXX ..XX ..XX XXXX ..XX XXXX ..XX XX.. XX.. XXXX XXXX ..XX XXXX XXXX XX.. XXXX XXXX ..XX XXXX XXXX XX.. ..XX XX.. XXXX ..XX XX.. XXXX XXXX XXXX XXXX ..XX XXXX XX.. XXXXXXXXXX XX.. XXXX ..XX XXXX XXXX XXXX XXXX XXXX ..XX XXXX XXXX XXXXXX XXXX XXXX ..XX XXXX XXXX ..XX XXXX XXXX ..XX XXXX XXXX XXXX ..XXXX XXXX........XXXX ..XX XXXX ....XXXXXXXX.. XXXX........XXXX XXXX ..XX XXXX......XXXXXX XXXXXXXXXXXXXXXX XXXX XXXX XXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXX XXXX XXXXXXXXXXXX.. ..XX XX.. ..XX XX.. XX.. ..XX XXXX ..XX XXXX XXXX ..XX XXXX ..XX XXXX XXXX ..XX XXXX ..XX XXXX XXXX ..XX XXXX XXXXXXXX.. ..XX XXXX .. XXXX ..XXXX.. XX XXXX XXXX....XXXX XX XXXX ..XX XXXX XXXXXXXX.. .. XXXXXX XXXX..XXXX XX XXXX XX.. XX XX XXXX XX.. XXXX .... ......XXXXXX ..XX ..XX..XXXX XXXX XX.. XX XXXX ..XX.. XXXX XX XXXX XX.. XXXX XXXX XX XXXX XX.. XX.. XXXXXX XXXX XX XXXX ..XXXXXX XX XXXX XX.. XXXX XX.. ..XXXX ..XX ..XX XX.. XXXX XXXX..XXXX..XXXX ..XXXX....XXXXXXXXXX....XXXX ..XXXX....XX ..XXXX..XXXXXX......XXXXXX.. ..XXXX..XXXXXX....XX XXXX XXXXXXXXXXXX.. XXXXXXXXXX.. XXXXXXXXXX.. XXXXXXXX.. XXXXXXXX..XXXXXXXXXX.. XXXXXXXXXX XXXXXXXX XX.. ..XX XXXX ..XX.. XXXX ..XX ..XX XXXX.. ..XX .. XX XX.. ..XXXXXX XXXXXXXXXX.. XX.. XXXX.. ..XXXXXX ..XX XX XXXX XX XX.. XXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX .. XX.. XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.. XXXX XX.. ..XX.. XXXX XXXX ..XX XXXX XXXX XXXX XXXX XXXX XX.. XX.. XX XXXX XXXX ..XX XXXX XX.. ..XX ..XX XXXX XX.. XX.. XX XXXX XXXX XXXXXXXX XXXX XX.. XXXX ..XX XXXX ..XXXXXXXXXXXX.. XX.. XX ..XXXXXX.. ..XXXXXXXXXXXX XXXX.. XXXX ..XXXXXXXXXXXX.. XXXX.. ..XX XXXX XXXX.. XX....XXXXXXXXXXXXXX XXXXXXXXXX XXXX XXXX XX XXXX XXXX.. XX.. XX.. XXXX XXXX ..XX XX.. XXXX.. XX ..XX XX XXXX XX XXXX XXXX ..XX XX.. XXXX ..XXXX XXXX XX.. XX XX XXXX XX.. XXXX XXXX XXXX.. XXXX XX.. XXXXXXXXXXXX XXXX XX.. XX XXXX ..XX.. XXXX XXXXXXXXXX XXXX XX.. ..XX XXXX XX.. XX XXXX ..XX XXXX XX XXXX XX.. ..XX XXXX XXXXXX.. ..XX ..XX XXXX.. XXXX ..XXXXXXXX
  6. How about install VirtualBox (or use Hyper-V but I don't have any experience with it) create virtual machine with 1 core, 512 MB RAM and 10 GB disk image install Debian Stretch with just only ssh server configure networking so host (windows) will have no IP address set on the primary NIC guest (linux) will have eth0 bridged with windows primary NIC and will have IP address that your windows server had guest (linux) will have eth1 just between host and guest and set some internal address on it ( host (windows) virtual NIC (linux eth1) will have internal address in the same segment ( and default gateway set to linux IP ( Then you would have real linux router so you can do all the stuff needed (policy-based routing). But you need to find some way how to start that VM when windows start.
  7. Discussion Game time [Day-Night] Ticks

    Sorry, I wrote it wrong, time info is sent on login (not sunset/sunrise), it's part of CharSelected packet
  8. You can't do it without Linux router - Windows can't do policy-based routing. You would have to set default gateway on Windows Server to and make all packets out go through it (but you would lose connectivity to it from internet, so you would have to create static route via previous default gateway to your proxy; even that would be very inconvenient because you would have to access your server only from proxy or via the proxy - because there would be no other way to it). Without right default gateway your only option is to use MASQUERADE or SNAT (it's the same, masquerade just automatically assumes new source IP address) which changes sender IP address to proxy IP - that you then see on Windows server.
  9. HOWTO - L2 server with (transparent) proxies DISCLAIMER: I wrote this HOWTO without really testing it (I've configured it for my server more than year ago), so if you find any mistake, feel free to comment/ask, I'll try to update this HOWTO appropriately. Purpose of using proxies The standard old way of setting up L2off server involves one Windows Server that is connected directly to internet and players connect directly to it's IP address. While it's enough for a small server, it may bring few problems: If someone wants to DDoS your server, he just pays for some attack to your IP address. You're screwed. There may be players who experience lags because route from their network to your server isn't perfect (because of bad peering between player's ISP and your datacenter etc). You can't just tell those players "Try better ISP". Players from foreign countries may have good ping to datacenters in their country but not to your data center. Some of these problems can be mitigated by using proxies for your server: When someone buys DDoS attack to your login server on first proxy, you can just change IP address in your DNS and let your players login on your second proxy (you need to have domain name instead of IP address in your l2.ini). When someone buys DDoS attack to your game server on first proxy, players can still play on second proxy. When player has bad ping on first proxy, login will be bit slower but player can select second proxy with better ping and play on it You can also do the same with your website, just replace ports 2106 and 7777 with 80 and 443... What will you need Some basic knowledge about L2off, Linux and networking. Also you'll have to read few manuals. Linux router between your L2 server and internet, you can do it two ways (of course it must be configured to forward IPv4 traffic): real physical Linux router between them Linux as main operating system on your server hardware + L2 server in virtual machine (kvm-qemu). Linux servers (1 core & 512 MB RAM is usually enough) for proxies Copy of patched hauthd - READ INSTRUCTIONS THERE Script that will be able to restart hauthd when L2 server crashes/exits How to do it I will use following IP networks and addresses in this example: Networks: Local network between Linux router and Windows VM Virtual network between Linux router and proxies Addresses: on Linux router eth0 on first proxy eth0 on second proxy eth0 on third proxy eth0 on Linux router eth1 (for physical router) or tap0 (for kvm-qemu variant) on Windows server Local network interface on Linux router tun0 (OpenVPN server 1) on Linux router tun1 (OpenVPN server 2) on Linux router tun2 (OpenVPN server 3) on first proxy tun0 (OpenVPN client) on second proxy tun0 (OpenVPN client) on third proxy tun0 (OpenVPN client) Physical network: Logical network: Now proceed with installation and configuration: ROUTER + PROXIES: Install OpenVPN ROUTER: For each proxy, configure one instance of OpenVPN server with static key (it will have to run on different ports, for example 1194, 1195, 1196) PROXY: Copy static key from router, configure OpenVPN client WINDOWS: Make sure windows server can ping linux router (ping PROXY: Make sure proxies can ping server (ping / ping / ping PROXY: Setup NAT (find some way how to run it on every start!) iptables -t nat -A PREROUTING -m tcp -p tcp --dport 2106 -j DNAT --to-destination iptables -t nat -A PREROUTING -m tcp -p tcp --dport 7777 -j DNAT --to-destination You need this to make proxies forward traffic on ports 2106 and 7777 to windows server. ROUTER: Setup connmark (find some way how to run it on every start! If it's physical router, use eth1 instead of tap0!): iptables -t mangle -A PREROUTING -i tun0 -p tcp -m tcp --dport 7777 -j CONNMARK --set-mark 100 iptables -t mangle -A PREROUTING -i tun1 -p tcp -m tcp --dport 2106 -j CONNMARK --set-mark 101 iptables -t mangle -A PREROUTING -i tun1 -p tcp -m tcp --dport 7777 -j CONNMARK --set-mark 101 iptables -t mangle -A PREROUTING -i tun2 -p tcp -m tcp --dport 2106 -j CONNMARK --set-mark 101 iptables -t mangle -A PREROUTING -i tun2 -p tcp -m tcp --dport 7777 -j CONNMARK --set-mark 101 iptables -t mangle -i tap0 -p tcp -m tcp --sport 2106 -j CONNMARK --restore-mark iptables -t mangle -i tap0 -p tcp -m tcp --sport 7777 -j CONNMARK --restore-mark You need this to mark connections so you know where they came from. ROUTER: Setup policy-based routing (find some way how to run it on every start!): ip rule add fwmark 100 table 100 ip route add default via table 100 ip rule add fwmark 101 table 101 ip route add default via table 101 ip rule add fwmark 102 table 102 ip route add default via table 102 You need this to make packets go back through the right proxy. Otherwise you'll send those packets out via your router public interface which won't work. WINDOWS: Setup hauthd to use multiple proxies and add servers appropriately to dbo.server table WINDOWS: Make sure hauthd restarts every time L2 server restarts Useful resources Patched hauthd with basic instructions OpenVPN Static Key Mini-HOWTO Linux Advanced Routing & Traffic Control HOWTO - Rules - routing policy database Linux Advanced Routing & Traffic Control HOWTO - Netfilter & iproute - marking packets
  10. Discussion Game time [Day-Night] Ticks

    Hi, in l2off (at least in leaked Gracia Final) it works this way: there's class CL2Time that manages this, game time runs 6 times faster than real time so each game day is 3 hours long and night 1 hour long it runs a timer each 10 seconds and checks whether day or night started, day starts at 6:00 game time, night starts at 0:00 game time when that 10 second timer expires and night changes to day or vice versa, server broadcasts SunRise packet (0x12) or SunSet packet (0x13) these packets are sent to player upon login as well
  11. When they inform you about it and don't do it in such stupid way (you can use only idle CPU, throttle it somehow etc) and give you something as reward - then it's OK.
  12. Probably yes, but it's VERY unethical.
  13. Thanks for tip, adblock does not detect/block it so maybe it's time to try something different... :)
  14. Now with that line in hosts file (see my first post) it doesn't eat more than 0.1 % CPU :) BTW I won't mind them computing few hashes on my CPU, but it seems it would run forever!
  15. Hi everyone, did you notice that whole HopZone site recently started to run some kind of miner that eats up to 100 % CPU? Shame! EDIT: If you don't want HopZone to steal your CPU, add this to C:\Windows\System32\Drivers\etc\hosts file