Jump to content

KeyWorld

Members
  • Posts

    379
  • Joined

  • Last visited

  • Days Won

    11

Everything posted by KeyWorld

  1. You can use the PHP function date_default_timezone_set(). I can't help you muh since you don't give any information of your website (language, panel, etc.).
  2. Some news today. Map loading I really improve my map loading : update the zlib unpacker, optimize the mesh compilation. It's now about 2-3 times faster than before. It takes ~3 seconds to load a map like Izlude or Prontera, instant loading for little map. Lighthalzen seems to be the slowest to load : ~5 seconds. I'm quite happy of the result. Sound objects I added sound objects to the map, I'm not certain of the volume to use for this objects (Audio API allow a min volume of 0.0 and max volume of 1.0; there are some sound object with a volume of 2.0 so not sure yet what the max volume is here). You can see the sound visualization of aldebaran (all porings are a sound object): Lub files Since Renewal, a big part of servers use lub files to store data info, so it should be normal for robrowser to load this files at runtime to build its DB. So I wrote a Lub decompiler (PHP, and converted the code to JS), it don't support all opcode but is enough to extract tables (I don't care of extracting functions). Here the PHP code in action: http://www.robrowser.com/prototype/lub/ For now I'm only able to extract lub version 0x51 but it seems some client use the 0x50 version (why ? ), so I will have to extend the code later. Sprite Rendering I re-wrote the whole Entity Manager code, as the old one it support all actions/animations. I added some setter to update automatically the sprites/act/palettes when modifying/setting a new visual look, ex: you change the sex, it will automaticaly reload all sprites/actions (head, hat, weapon, ...). Palettes are applying on the pixel shader to avoid having to re-build each sprite image (faster and easier). I also face the same problem as Shinryo in his topic and used the same way to fix it, but it's definitively not the way to go : collision with roof, weird result when sprite is on the water. The better way is to project the top vertices to the up vector of the bottom part and modifying UVs to match the new form in the screen, but it's more complicate and I lack knowledge on 3D maths. Weather I just add sky and clouds to some maps (yuno, gonryun, thana_boss, 5@tower, ...) using a config file in the DB, it's funny how the client manage it. The result looks good: Other news IE11 will support webgl Web API Device Storage will allow to use local GRF without needed to select it each time at runtime (I hope this standard will be accept...). Firefox added ASM.js in the latest nighty build. It allow to run some js (at this time just arithmetic code) script at 2 times slower than native speed (comparable as Java and C#), by doing some low typage on variables.
  3. I wrote an online tool some months ago : http://www.robrowser.com/prototype/vdk/ (required a recent browser). It's not a complete tool (only work with version 1.1 and not sure it work with all vdk files), but if you don't want to install a software in your computer or don't want to extract the whole archive, it do the job.
  4. First thing I see, you add item to a shop "Emistry_shop", I guess you forget to update the shop name (should be "Cloud_Machine"). npcshopadditem "Emistry_Shop",@ItemListscloud[.@i],@ItemCostcloud[.@i];
  5. Replace .share_date with .share_date$ The value is truncate because of the conversion to int.
  6. Add a "end;" before "OnHour24:".
  7. v - value (string, int or reference) s - string i - int r - reference (variable) l - label ? - optional parameter * - as you want optionals parameters
  8. It's hardcoded in the executable. The client now the sprite type using the view id (or the sprite id - since each type is related to a range id) and define for each class the action based on this type.
  9. It's not a lossless compression. It's safe.
  10. It will be released this year even if it's not totally finished, it will be a good thing to open the source Same here, I try to do my best to work on this project but sometimes it's hard to manage it and all others things (like my girlfriend lol). It can be a good thing to have a GRF history/diff/tracking tool to see what Gravity add/remove/change in its files, keep it up ! (I know some others guys had the same idea ) Nice js1k entry, I asked myself "why 'ninja' ?" the first time I saw it, nice done @project, No news, have problems with one of my computer, so I will try all I did in "bind mode" (rewrote the whole Entity manager) when I will switch to my girlfriend's home this week end
  11. Feel secured doesn't mean be secured. Https don't protect from SQL injection and some hacks methods. Maybe because he doesn't want to cheat but just want to annoyed your server. As everyone said, it can come from any tool you add to your CP (forum, control panel, bug tracker) or in game npc (check for query_sql) or even from the hoster or your own team.
  12. Yeah I rewrote the whole core as I said before. The old one wasn't really well optimized and organized, and pretty hard to update, now it's much better and user-friendly About your way to do, it missing some structure at my point of view and will be maybe hard to maintain in future (and it seems you generate the password hash even if not used), but yeah it's fun the way you did it, to merge packet and just define the header to build the correct one. Hmm maybe I will remove the packet_id from the Network.bindPacket() and move it to the packet structure instead, I don't think we have to care about it at this step... About js1k yeah it was fun to do lol but very hard to compact to 1024bytes, but I'm really satisfied about the result. Nice to see you here curiosity What about your project ? @Project Now support 0x200 GRF version with DES encryption.
  13. I just add the network core in roBrowser. I search a way to make it organized and user-friendly to use. So basically, all packets are converted from http://rathena.org/wiki/index.php?title=Packets using tools/packet-builder/. Example to parse: Network.bindPacket( 0x69, PACKET.AC.ACCEPT_LOGIN, function(data){ // data.AuthCode, data.AID, data.userLevel, data.ServerList, ... // do whatever you want with "data" });Example to send:var pkt = new PACKET.CA.LOGIN(); pkt.ID = "Test"; pkt.Passwd = "Test"; pkt.Version = 20; Network.sendPacket(pkt);If you have a better idea, let's talk about it There will be three differents ways to connect to server: Using JAVA. Using Chrome Socket API. Using WebSocket to connect to a Proxy server. For moment I am focus on JAVA.
  14. It depend of the OS and graphic card, but yeah for now the canvas should be hardware accelerated. I will drop you a PM, not enough time right now Keep it up.
  15. I'm here just because I see "HTML5" in the title The result is nice, great work but some things can be change in the code (in my own opinion), it can be good also to check for the support of css3 so you will just use the GPU
  16. Read the entire post, or the comments below please.
  17. Do you really need to modify the model ? I think just change the texture is enough in your case.
  18. You can integrate it in whatever you want: fluxcp, cerescp, triton, custom CP, or without CP.
  19. Thank you As I said in the main post, it's a design integrated to an index.html page. There is no CP in the archive, you are free to integrate it yourself to your favorite one.
  20. File Name: CeresCP Default Theme File Submitter: KeyWorld File Submitted: 26 Feb 2013 File Category: Web Resources Content Author: KeyWorld If you remember this topic there was a contest for the upcoming Cerescp default theme. For now, I don't know if developers stopped to work on the new CeresCP version, but a lot of time passed since the last update/announce and some members asked me to release the default theme I made. I hope the best to CeresCP developers, the theme can always be used if they continue the project. So in this archive, an index.html page with css/javascript and images. Compatible (the last time I checked) with: IE6, IE7, IE8, IE9, IE10 Safari Chrome Opera Firefox You can check the online version: http://upload.robrowser.com/templates/ceres/ There is no CP in the archive, you will have to integrate it to your favorite one yourself (hey don't pay someone to do it, all the work is already done seriously...). Have fun Click here to download this file
  21. You can find it by reversing the client, or by searching in some source tools as Actor. But in the past we just have reverse engineering and trying to search by finding redundant informations in the hex. But your current function is not really good, some bugs on some versions, not really good name convention... If you want mine: <?php /** * @fileoverview Action - Loader for the Gravity .act file * @author Vincent Thibault (alias KeyWorld - Twitter: @robrowser) * @version 2.3.0 */ class Action { private $fp, $version; public $actions = array(), $sounds = array(); /// Loader on construct public function __construct($filename=false) { if ( $filename ) $this->open($filename); } /// Open a Action file /// Do some check before. public function open($filename) { if ( substr( $filename, 0, 7 ) !== "data://" ) { if ( ! file_exists($filename) ) throw new Exception("ACT::open() - Can't find file '{$filename}'."); if ( ! is_readable($filename) ) throw new Exception("ACT::open() - Can't read file '{$filename}'."); $this->size = filesize($filename); if ( $this->size < 0x08 ) throw new Exception("ACT::open() - Incorrect file size, shoulnot be a ACT file"); } $this->fp = fopen($filename,'r'); $this->load(); } /// Load an Action file private function load() { extract( unpack( "a2head/C2ver", fread($this->fp, 0x4 ) ) ); if ( $head !== 'AC' ) throw new Exception("ACT::load() - Incorrect act header, is '{$head}' - should be 'AC'"); $this->version = $ver1/10 + $ver2; $this->readActions(); if ( $this->version >= 2.1 ) { // Sound extract( unpack("Vcount", fread( $this->fp, 0x04 ) ) ); for ( $i=0; $i<$count; ++$i ) $this->sounds[$i] = current( unpack('a40', fread( $this->fp, 40 ) ) ); // Delay if ( $this->version >= 2.2 ) foreach( $this->actions as &$action ) $action->delay = current( unpack("f", fread($this->fp, 0x04) ) ) * 25; } } /// Load ACT actions private function readActions() { extract( unpack("vcount/x10", fread( $this->fp, 12 ) ) ); for ( $i=0; $i<$count; ++$i ) { $this->actions[$i] = (object) array( "animations" => $this->readAnimations(), "delay" => 150 ); } } /// Load ACT animations private function readAnimations() { extract( unpack("Vcount", fread( $this->fp, 0x04 ) ) ); $animations = array(); for ( $i=0; $i<$count; ++$i ) { fseek( $this->fp, 32, SEEK_CUR ); $animations[$i] = $this->readLayers(); } return $animations; } /// Load ACT layers private function readLayers() { extract( unpack("Vcount", fread( $this->fp, 0x04 ) ) ); $layers = array(); if ( $this->version < 2.0 ) { $size = 0; $struct = ""; } else if ( $this->version < 2.4 ) { $size = 16; $struct = "C4color/f1scale/Vangle/Vspr_type"; } else if ( $this->version === 2.4 ) { $size = 20; $struct = "C4color/f2scale/Vangle/Vspr_type"; } else { $size = 28; $struct = "C4color/f2scale/Vangle/Vspr_type/Vwidth/Vheight"; } for ( $i=0; $i<$count; ++$i ) { $param = unpack( "Vx/Vy/Vindex/Vis_mirror/" . $struct, fread($this->fp, $size + 16) ); $layers[$i] = (object) array( "pos" => array( $param['x'], $param['y'] ), "index" => $param['index'], "is_mirror" => $param['is_mirror'], "scale" => array( 1.0, 1.0 ), "color" => array( 255, 255, 255, 255 ), "angle" => 0, "spr_type" => 0, "width" => 0, "height" => 0 ); $layer = &$layers[$i]; $layer->color[0] = $param['color1']/255; $layer->color[1] = $param['color2']/255; $layer->color[2] = $param['color3']/255; $layer->color[3] = $param['color4']/255; $layer->scale[0] = isset($param['scale1']) ? $param['scale1'] : 1.0; $layer->scale[1] = isset($param['scale2']) ? $param['scale2'] : $layer->scale[0]; if ( isset($param['angle']) ) $layer->angle = $param['angle']; if ( isset($param['spr_type']) ) $layer->spr_type = $param['spr_type']; if ( isset($param['width']) ) $layer->width = $param['width']; if ( isset($param['height']) ) $layer->height = $param['height']; } $sound = -1; if ( $this->version >= 2.0 ) extract( unpack("Vsound", fread($this->fp,0x04) ) ); $pos= array(); if ( $this->version >= 2.3 ) { extract( unpack("Vcount", fread($this->fp,0x04) ) ); for ( $i=0; $i<$count; ++$i ) { $pos[$i] = (object) unpack( "Vunk/Vx/Vy/Vattr", fread($this->fp,16) ); } } return (object) array( "layers" => $layers, "sound" => $sound, "pos" => $pos ); } /// Compile a ACT file public function compile() { // Header $result = pack('a2C2', 'AC', $this->version * 10 % 10, floor($this->version * 10)/10 ); // Action count $result .= pack( 'vx10', count($this->actions) ); // Compile each actions foreach( $this->actions as $action ) { // Number of animations $result .= pack( 'V', count($action->animations) ); // Compile animations foreach( $action->animations as $animation ) { // 32 uknown offset + layers count $result .= pack( 'x32V', count($animation->layers) ); // Compile layers foreach( $animation->layers as $layer ) { $result .= pack('V4', $layer->pos[0], $layer->pos[1], $layer->index, $layer->is_mirror); if ( $this->version < 2.0 ) continue; else if ( $this->version < 2.4 ) $result .= pack( 'C4fV2', $layer->color[0]*255, $layer->color[1]*255, $layer->color[2]*255, $layer->color[3]*255, $layer->scale[0], $layer->angle, $layer->spr_type ); else if ( $this->version === 2.4 ) $result .= pack( 'C4f2V2', $layer->color[0]*255, $layer->color[1]*255, $layer->color[2]*255, $layer->color[3]*255, $layer->scale[0], $layer->scale[1], $layer->angle, $layer->spr_type ); else $result .= pack( 'C4f2V4', $layer->color[0]*255, $layer->color[1]*255, $layer->color[2]*255, $layer->color[3]*255, $layer->scale[0], $layer->scale[1], $layer->angle, $layer->spr_type, $layer->width, $layer->height ); } // Animation sound if ( $this->version >= 2.0 ) { $result .= pack('V', $animation->sound ); } // Animation imf (head pos) if ( $this->version >= 2.3 ) { $result .= pack('V', count($animation->pos) ); foreach( $animation->pos as $pos ) { $result .= pack( 'V4', $pos->unk, $pos->x, $pos->y, $pos->attr ); } } } } if ( $this->version >= 2.1 ) { // Comple sounds $result .= pack( 'V', count($this->sounds) ); foreach( $this->sounds as $sound ) { $result .= pack( 'a40', $sound ); } // Comple delay if ( $this->version >= 2.2 ) { foreach( $this->actions as $action ) { $result .= pack( 'f', $action->delay / 25 ); } } } return $result; } } ?>Maybe should I release my character-viewer...Have fun~
  22. Well test this: public function readAct($act,$save,$output,$code) { // Open the act file. $this->act = fopen($act, "rb"); // Just like on the sprites we read some infos: ident=ACT, version, number of frames $this->aHeader = unpack('H4ident/Sversion/SnumFrames', fread($this->act, 0x06)); // Get the filesize (used this for sql database etc.) $this->aSize = filesize($act); // The total amount of animations used $this->aAnimations = $this->aHeader['numFrames']; // The number of actions is the num of animations divided by 8. // So what are the "actions"? I just named them like this. They're basicly the directions you can look at. Just like in actOR. // \ | / } // -- o -- }-> 8 in total // / | \ } $this->aActions = ($this->aAnimations / 8); // The version $this->aVersion = dechex($this->aHeader['version']); // Format the version nicely $this->aVersion = (double)preg_replace('{([0-9])(.*?)([0-9])}', '$1.$2', $this->aVersion); // Skip some useless data on one needs fseek($this->act, 0xA, SEEK_CUR); // We're currently at action 0 $currentAction = 0; // Our index for the while loop $anim = 0; // Arrays we save our informations in $pointerMemoryANIM = array(); $pointerMemoryNF = array(); $pointerMemoryPAT = array(); // Lets go through the animations, shall we? while($anim < $this->aAnimations) { // First how many Frames does the action have? // On a normal headgear this would be 3. Because when you are sitting downwards you can look down with your head, left and right. So 3 in total. // Ff you have an animated sprite its more obviously $this->aAnimData[$anim] = unpack('lnumFrames', fread($this->act, 0x04)); // So lets loop through those Frames, cuz they all got individual informations for us for($nf = 0; $nf < $this->aAnimData[$anim]['numFrames']; $nf++) { // Skip useless data fseek($this->act, 0x20, SEEK_CUR); // And now we check how many subFrames this frame got. Or better said Patterns (like in actOR) // For example, if you have a monster sprite and some special effects as seperates sprite frames in the .spr file. // You'll have to paste them onto the stage right? Thats where the patters are being created. Like layers in photoshop. $this->aAnimData[$anim][$nf] = unpack('lnumSubFrames', fread($this->act, 0x04)); // Loop through the patterns or layers for more info about them for($patNo = 0; $patNo < $this->aAnimData[$anim][$nf]['numSubFrames']; $patNo++) { $this->aAnimData[$anim][$nf][$patNo] = unpack('lxOffset/lyOffset/lsprNo/lmirrored/Cred/Cgreen/Cblue/Calpha', fread($this->act, 0x14)); if($this->aVersion < 2.0 ); else if($this->aVersion < 2.4 ) $this->aAnimData[$anim][$nf][$patNo] += unpack('fxyScale/lrotation/lsprType', fread($this->act, 12)); else if($this->aVersion == 2.4 ) $this->aAnimData[$anim][$nf][$patNo] += unpack('fxScale/fyScale/lrotation/lspr_type', fread($this->act, 16)); else $this->aAnimData[$anim][$nf][$patNo] += unpack('fxScale/fyScale/lrotation/lsprType/lsprWidth/lsprHeight', fread($this->act, 24)); } // The end of the Patterns/Layers on the Frame. // So lets see if it has some kind of sound attached to it? (To the frame) fseek( $this->act, 4, SEEK_CUR ); // sound id, store it in a variable if you want extract( unpack("lnumExtraInfo", fread($this->act,0x04) ) ); $extraInfos = array(); for ( $i=0; $i<$numExtraInfo; ++$i ) { $extraInfos[$i] = unpack( "x4/VExtXOffsetX/VExtXOffsetY/x4", fread($this->act,16) ); } } // Increase our Action and loop through the next frames and patterns^^ $anim++; } // After reading all infos we are at the end of the act file where the sound informations are stored. $this->aSoundData = unpack('lnumSounds', fread($this->act, 0x04)); // It has some sounds? if($this->aSoundData['numSounds'] > 0) { // We loop through number of sounds to grab it. for($nSnd = 0; $nSnd < $this->aSoundData['numSounds']; $nSnd++) { // Now because the sound file is a string (directs to some .wav file in the grf), saved in hex and for our advantage always exactly 40 bytes long // we read the string as hex values and save it like that $this->aSoundData[$nSnd] = unpack('H80file', fread($this->act, 0x28)); } } // Oh we also got the interval a frame is played at? That info is ours! > for($intv = 0; $intv < $this->aAnimations; $intv++) { $this->aAnimData[$intv] += unpack('fanimSpeed', fread($this->act, 0x04)); } // Lets format our earlier saved hex string to a actual string with letters and not just numbers ^^ // Some note: If there are sounds in the act (mostly monsters) there always appears to be a sound called "atk", just like that. // It doesnt exist in the grf and I have no idea how it is being handled. Maybe some description of the sounds? foreach($this->aSoundData as $id=>$string) { if((string)$id != 'numSounds') $this->aSoundData[$id] = str_replace(pack('H2','00'),"",(pack('H*', $string['file']))); } // Lets display our results of the act file. $act = '$jact'; if (strpos($output, "head")) { $act = '$hact'; } else { echo '<pre>'; echo print_r($this->aAnimData, true); echo print_r($this->aSoundData, true); echo '</pre>'; } // Close the file, its no longer needed. =( fclose($this->act); }
  23. Oups the latest thing I wrote was wrong: fseek( $this->act, 4, SEEK_CUR ); // sound id, store it in a variable if you want extract( unpack("lnumExtraInfo", fread($this->act,0x04) ) ); $extraInfos = array(); for ( $i=0; $i<$numExtraInfo; ++$i ) { $extraInfos[$i] = unpack( "x2/VExtXOffsetX/VExtXOffsetY/x2", fread($this->act,10) ); } Now working.
  24. Did you even read what I wrote ? If you want to store extrainfo, you have to do this:fseek( $this->act, 4, SEEK_CUR ); // sound id, store it in a variable if you want extract( unpack("lnumExtraInfo", fread($this->fp,0x04) ) ); $extraInfos = array(); for ( $i=0; $i<$numExtraInfo; ++$i ) { $extraInfos[$i] = unpack( "x4/VExtXOffsetX/VExtXOffsetY/x4", fread($this->act,16) ); }Edit: Why the bbcode is buggy ?
×
×
  • Create New...