Thread: [EXTREMELY DETAILED][COLORCODED] How to pack multiple files in one file(Custom Cache)

Page 1 of 2 12 LastLast
Results 1 to 10 of 18
  1. #1 [EXTREMELY DETAILED][COLORCODED] How to pack multiple files in one file(Custom Cache) 
    Registered Member

    Join Date
    Oct 2009
    Posts
    149
    Thanks given
    4
    Thanks received
    20
    Rep Power
    97
    Purpose: Teach reader how to make their own simple cache writing and reading system.
    Difficulty: 6/10
    Assumed Knowledge: Standard Java Structure, I Explain everything else in-depth
    Classes Modified: CachePacker.java, CacheFile.java, CacheUnpacker.java
    Refactored/Non-Refactored?: Either

    In this tutorial I will be explaining in depth how to make a simple, yet effective system for packing multiple files into a single file. And then reading from that file to obtain the multiple files. The biggest advantage of using this for a RSPS client is that instead of having thousands of model and animation files which will bump up compressing, decompressing size and downloading time you can have a single file which contains all of files, and can be easily parsed during runtime.

    Step 1: What kind of properties are my cached files going to need?
    Well the first thing you need to do is figure out what kind of properties each file in your cache is going to need. The most common uses I could think of is the path the file would be located in within the cache. On top of these properties you will also need the byte[] Array which contains the file in byte format, which can be read by many different Java IO readers as well as a boolean which indicates whether or not to keep the file cached after loading, which may help to clear up RAM using during runtime(Always a priority)

    Step 2: Creating a class to represent a cache file.
    So know that you have decided what kind of properties you will need to hold for each file, you need to create a class which will represent each file within the cache and hold each of those properties for each file.

    Here is my template for this class: (Contains the essentials for this usage of the class)
    Code:
    import java.io.ByteArrayInputStream;
    
    public class CacheFile {
    
    	private boolean store;
    	private byte[] bytes;
    	
    	public CacheFile(boolean store, Arguments Here, byte[] bytes)
    	{
    		this.store = store;
    		this.bytes = bytes;
    	}
    
    	public boolean getStore()
    	{
    		return store;
    	}
    	
    	public byte[] getBytes()
    	{
    		return bytes;
    	}
    		
    	public ByteArrayInputStream getNewInputStream()
    	{
    		return new ByteArrayInputStream(bytes);
    	}
    }
    Here is my finished CacheFile class after I have adjusted it to support my properties of after loading storage and the path within the cache the file is located in.
    Code:
    import java.io.ByteArrayInputStream;
    
    public class CacheFile {
    	
    	private boolean store;
    	private String path;
    	private byte[] bytes;
    	
    	public CacheFile(boolean store, String path, byte[] bytes)
    	{
    		this.store = store;
    		this.path = path;
    		this.bytes = bytes;
    	}
    
    	public boolean getStore()
    	{
    		return store;
    	}
    	
    	public String getPath()
    	{
    		return path;
    	}
    	
    	public byte[] getBytes()
    	{
    		return bytes;
    	}
    		
    	public ByteArrayInputStream getNewInputStream()
    	{
    		return new ByteArrayInputStream(bytes);
    	}
    }
    Step 3: An overview of the cache packing system you will use.
    Ok so the way we are going to pack multiple files into a single cache is by first, getting the amount of files that are in the cache and writing that into the file. This way the cache unpacker can know how many files are in the cache without any troubles.

    Then, for each file we are going to write, we ill write the following:
    - ID : The id of the file being written, starting at 0 and incrementing for each file
    - Any Properties : For each custom property the CacheFile class contains
    - Bytes : The file in byte array form, which as stated earlier can be read by many of the Java IO readers.

    Then we will simply make sure all the data is saved to the file and close it off. Done! The cache will then be in a single file.

    Step 4: Tackling the structure of your cache packer
    Now that you have an idea of how the cache packer is going to operate, you are going to have to create your CachePacker class(or whatever you chose to call it). Following this you will need to set up your imports and 3 static methods: One to take in a output file, a list of files to pack and a optional boolean of whether to stop overwriting, One to take in a byte array and write both its size and contents to the file and finally One to convert any file into a byte[] array.
    Make sure to read the comments!
    Code:
    import java.io.DataOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.util.List;
    
    public class CachePacker {
    	
    	// Because it is easy to put all of this in one method,
    	// I have done so. I have also made it a static method
    	// so that you do not need to initiate an instance of
    	// this class to be able to use this method.
    	public static void createCache(String cacheFile, List<String> files,
    			 List<Boolean> stores, List<YourProperty> YourProperties, 
    			 boolean... overwrite)
    	{
    	}
    	
    	// My method for writing bytes to the stream
    	// in a way which the reader will be able to
    	// parse into a byte[] array.
    	private static void writeBytes(byte[] bytes, DataOutputStream out) throws IOException
    	{
    		out.writeShort(bytes.length);
    		out.write(bytes);
    	}
    	
    	// Simple method to read all of the bytes out of a file
    	// then return with those bytes in an array.
    	private static byte[] getBytes(String file) throws IOException
    	{
    		File f = new File(file);
    		byte[] fileBytes = new byte[(int)f.length()];
    		new FileInputStream(f).read(fileBytes);
    		return fileBytes;
    	}
    
    }
    Well you are going to notice I have highlighted a few things in this template, here are the explainations:
    1. "boolean... overwrite" - Some of you will be thinking "What is this, what does it do?", so to answer that if you are asking it. When you add "..." to the end of a Class type as an argument in Java; it can make the argument optional(If it is the last argument), but is designed to make it so that you can enter multiple arguments of that Class type when executing the method, then Java will automatically turn those arguments into a Class[] array of the given type. (i.e. the method "doSomething(int anArg, String... others)" can be executed via "doSomething(1, "string1", "string2", "string3", "etc.");"

    2. "List<YourProperty> YourProperties" - Remember back in step 1 you decided what properties you were going to need for your cached files, and in step 2 you implemented those properties into your CacheFile class? Well now you have to implement them into your Cache Packer, this is rather simple however. For each custom property you have, add a new List argument to the createCache method (i.e. List<Integer> prices, List<String> nicknames)

    3. "out.writeShort(bytes.length)" - Your probably wondering why this is highlighted, don't worry you don't have to change anything. This is simply just to give you a tip on these sorts of things if you don't already know it. When you are using bytes to store data, eventually the amount of space the bytes(even though they are small) take up will add up. So, when using bytes to store data you should always be aware of what type of variable you are using to store data in. In this example, even though "bytes.length" is an Integer, I have it being written as a short because I am not expecting the length of that array to exceed that a Short can hold. And because an Integer takes up 4 bytes, while Shorts take up two, I am saving space(Once again it adds up!) by using a Short instead of an Integer(Hope that explains that)

    Ok so now that you've hopefully read through that you should have your createCache method looking something like this:
    Code:
    	public static void createCache(String cacheFile, List<String> files,
    			 List<Boolean> stores, List<Integer> somevalue,
    			boolean... overwrite)
    	{
    	}
    Though because my extra property is the file path, it is already given in the files List and I don't need to add any extra arguments.

    Step 5: Checking and opening our cache for writing
    Now just some fairly standard procedures to add to our method here, the first bit:
    Code:
    		// Create the File class associated with the
    		// output file for the cache.
    		File file = new File(cacheFile);
    
    		// Check if our overwrite argument has been
    		// given a value by checking length, then
    		// checking if the first (presumably only)
    		// value is true. If then the file exists
    		// a new Exception will be created, traced
    		// and then the method will be stopped.
    		if (overwrite.length > 0)
    		{
    			if (overwrite[0])
    			{
    				if (file.exists())
    				{
    					new Exception("File already exists").printStackTrace();
    					return;
    				}
    			}
    		}
    
    		// Standard try catch exception with the creation of a new
    		// DataOutputStream using our previously instanced file.
    		try
    		{
    			DataOutputStream out = new DataOutputStream(new FileOutputStream(file));
    		} catch (Exception e)
    		{
    			e.printStackTrace();
    		}
    So to just summarize on all those comments, we first simply create an instance of File giving it the location of the cacheFile argument, then proceed to check if we aren't aloud to overwrite an existing file and finally create a standard TryCatch statement which opens a new DataOutputStream to write in.

    Step 5: Writing files to the DataOutputStream
    Ok so by now you should have a good idea of what's going on, so I'm not going to spend much time elabourating on the comments. Add this underneath the line creating a new DataOutputStream:
    Code:
    			// Write the amount of files going to be packed (Length of File List)
    			out.writeInt(files.size());
    			
    			// Get the base directory for all of the cache files after making sure
    			// the slashes are in sync and initialize fileID
    			cacheFile = cacheFile.replaceAll("/", "\\");
    			String cacheDirectory;
    			if (cacheFile.contains("\\"))
    			{
    				cacheDirectory = cacheFile.substring(0, cacheFile.lastIndexOf("\\"));
    			} else
    			{
    				new Exception("CacheFolder not seperate").printStackTrace();
    				out.close();
    				return;
    			}
    			int fileID = 0;
    			
    			// For each file listed in the File List,
    			// give it an ID, set it's name and whether
    			// or not it should be stored. As well as
    			// get the file contents as a byte[] and
    			// write that.
    			for (int i=0; i<files.size(); i++) {
    				out.writeInt(fileID++); // Write the file id then increment it by 1
    				// If we have a list indicating whether to store
    				// each file or not go by that, other wise go
    				// off of a default value.
    				if (stores != null)
    					out.writeBoolean(stores.get(i));
    				else
    					out.writeBoolean(false);
    				String filePath = files.get(i);
    				// BEGIN CUSTOM PROPERTIES
    				writeBytes(filePath.getBytes(), out);
    				// END CUSTOM PROPERTIES
    				if (!cacheDirectory.endsWith("\\"))
    					cacheDirectory += "\\";
    				writeBytes(getBytes(cacheDirectory + filePath), out);
    			}
    You guessed it right(I hope), after reading through the comments you should have assumed that you replace the blue code with that appropriate to the properties you decided to create.

    To help you out heres a small list of common variables you can write:
    Code:
    	out.writeInt(INTEGER);
    	out.writeBoolean(BOOLEAN);
    	out.writeShort(SHORT);
    	out.writeLong(LONG);
    	out.writeDouble(DOUBLE);
    	writeBytes((STRING).getBytes(), out); // Using my method
    If you want to add more flexibility with the extra lists you added, use this template for them. This way you can set a List to null and all files will be given a default value.

    Step 6: Flushing and Closing our cache
    Now a the easiest part of all, flushing and closing our DataOutputStream. Add this just before the end of the try brackets:
    Code:
    			// And finally we flush the stream to make sure
    			// all the data we have wrote to the stream gets
    			// put in the file and close it so that other
    			// applications may open the file for reading/writing.
    			out.flush();
    			out.close();
    And now your AlMOST THERE!!!. Now you just need to adjust my class to read your cache.
    Spoiler for Heres what your CachePacker class should look like:
    Code:
    mport java.io.DataOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.util.List;
    
    public class CachePacker {
    	
    	// Because it is easy to put all of this in one method,
    	// I have done so. I have also made it a static method
    	// so that you do not need to initiate an instance of
    	// this class to be able to use this method.
    	public static void createCache(String cacheFile, List<String> files,
    			 List<Boolean> stores, 
    			 boolean... overwrite)
    	{
    		// Create the File class associated with the
    		// output file for the cache.
    		File file = new File(cacheFile);
    
    		// Check if our overwrite argument has been
    		// given a value by checking length, then
    		// checking if the first (presumably only)
    		// value is true. If then the file exists
    		// a new Exception will be created, traced
    		// and then the method will be stopped.
    		if (overwrite.length > 0)
    		{
    			if (overwrite[0])
    			{
    				if (file.exists())
    				{
    					new Exception("File already exists").printStackTrace();
    					return;
    				}
    			}
    		}
    
    		// Standard try catch exception with the creation of a new
    		// DataOutputStream using our previously instanced file.
    		try
    		{
    			DataOutputStream out = new DataOutputStream(new FileOutputStream(file));
    			// Write the amount of files going to be packed (Length of File List)
    			out.writeInt(files.size());
    			
    			// Get the base directory for all of the cache files after making sure
    			// the slashes are in sync and initialize fileID
    			cacheFile = cacheFile.replaceAll("/", "\\");
    			String cacheDirectory;
    			if (cacheFile.contains("\\"))
    			{
    				cacheDirectory = cacheFile.substring(0, cacheFile.lastIndexOf("\\"));
    			} else
    			{
    				new Exception("CacheFolder not seperate").printStackTrace();
    				out.close();
    				return;
    			}
    			int fileID = 0;
    			
    			// For each file listed in the File List,
    			// give it an ID, set it's name and whether
    			// or not it should be stored. As well as
    			// get the file contents as a byte[] and
    			// write that.
    			for (int i=0; i<files.size(); i++) {
    				out.writeInt(fileID++); // Write the file id then increment it by 1
    				// If we have a list indicating whether to store
    				// each file or not go by that, other wise go
    				// off of a default value.
    				if (stores != null)
    					out.writeBoolean(stores.get(i));
    				else
    					out.writeBoolean(false);
    				String filePath = files.get(i);
    				// BEGIN CUSTOM PROPERTIES
    				writeBytes(filePath.getBytes(), out);
    				// END CUSTOM PROPERTIES
    				if (!cacheDirectory.endsWith("\\"))
    					cacheDirectory += "\\";
    				writeBytes(getBytes(cacheDirectory + filePath), out);
    			}
    
    			// And finally we flush the stream to make sure
    			// all the data we have wrote to the stream gets
    			// put in the file and close it so that other
    			// applications may open the file for reading/writing.
    			out.flush();
    			out.close();
    		} catch (Exception e)
    		{
    			e.printStackTrace();
    		}
    	}
    	
    	// My method for writing bytes to the stream
    	// in a way which the reader will be able to
    	// parse into a byte[] array.
    	private static void writeBytes(byte[] bytes, DataOutputStream out) throws IOException
    	{
    		out.writeShort(bytes.length);
    		out.write(bytes);
    	}
    	
    	// Simple method to read all of the bytes out of a file
    	// then return with those bytes in an array.
    	private static byte[] getBytes(String file) throws IOException
    	{
    		File f = new File(file);
    		byte[] fileBytes = new byte[(int)f.length()];
    		new FileInputStream(f).read(fileBytes);
    		return fileBytes;
    	}
    
    }
    Reply With Quote  
     

  2. Thankful users:


  3. #2  
    Registered Member

    Join Date
    Oct 2009
    Posts
    149
    Thanks given
    4
    Thanks received
    20
    Rep Power
    97
    Step 7: HashMaps
    If you already know about HashMaps, skip this step.

    (In my own words)
    HashMaps take two Classes(i.e. CachePacker, Integer, String, CacheFile etc. e.g. HashMap<String, Integer>) and act like a bunch of locks. The first Class that it takes is the key to get the value of the second class. But you can also access a HashMap like a List using .get(INT) and .size().

    Though I can't really explain it too well so here are 3 different HashMap tutorials:
    [Only registered and activated users can see links. ]
    [Only registered and activated users can see links. ]
    [Only registered and activated users can see links. ]

    Step 8: Adjusting the CacheUnpacker class
    Ok so now you should know about HashMaps irregardless, in the CacheUnpacker class I've made a HashMap is used with properties <Integer, CacheFile> to store each file as its loaded in the form of our CacheFile class and with the key as the ID written in the CachePacker (See note-able places to edit down the bottom). This class is already setup for you and all you need to do is change the reading methods like you just did in the cachePacker: (Nobody gains anything from me explaining the same stuff in detail again)
    Code:
    import java.io.DataInputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.util.HashMap;
    import java.util.Set;
    
    public class CacheUnpacker {
    	
    	// Two variables needed for this class.
    	// A HashMap to hold file information
    	// and a boolean to state whether or not
    	// a cache load has been called.
    	private HashMap<Integer, CacheFile> files;
    	private boolean loaded;
    	
    	public CacheUnpacker()
    	{
    		loaded = false;
    	}
    	
    	// Attempt to load the contents of a cache created
    	// using the same format, and parsing all files
    	// that are included within.
    	public void loadCache(String filePath)
    	{
    		files = new HashMap<Integer, CacheFile>();
    		loaded = true;
    		try
    		{
    			// Just checking if the file exists, I've made it
    			// manually throw an exception in case any of you
    			// have the need to do something special if the
    			// file doesn't exist. (i.e. Scan for similar files)
    			File file = new File(filePath);
    			if (!file.exists())
    				throw new FileNotFoundException();
    			
    			// I doub't the file size is going to exceed the
    			// Integer max, which just about 2GB
    			DataInputStream in = new DataInputStream(new FileInputStream(file));
    			int packedFiles = in.readInt();
    			for (int i=0; i<packedFiles; i++)
    			{
    				// For each file, read the following and put in HashMap
    				// Integer - The files id
    				// Boolean - Whether or not to keep file in cache
    				//			(If a file only needs to be used once)
    				// String via byte[] - The "file path" for the file
    				//			(If you want to get the "directory" the
    				//			file would have been in)
    				// byte[] - The file contents in byte form
    				files.put(in.readInt(), new CacheFile(
    						in.readBoolean(),
    						new String(getBytes(in)),
    						getBytes(in)));
    			}
    			
    			// Finally closing the stream as it is no longer
    			// being used, so that other applications may
    			// open and read/write to it.
    			in.close();
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    	
    	public boolean isLoaded()
    	{
    		return loaded;
    	}
    	
    	private byte[] getBytes(DataInputStream in) throws IOException {
    		// This is the method I use to obtain the
    		// size that is needed for a byte array
    		// and then return one with the given data.
    		byte[] bytes = new byte[in.readShort()];
    		in.read(bytes);
    		return bytes;
    	}
    
    }
    Note: Remember to double check that the order you're reading variables in corresponds with your CacheFile() constructor!
    As you will notice I marked the comments irrelevant to you in blue as well so you know how they match up. Once again heres a list of the common DataInputStream methods to replace code with:
    Code:
    	in.readInt();
    	in.readBoolean();
    	in.readShort();
    	in.readLong();
    	in.readDouble();
    	new String(getBytes(in)); // My Method
    Step 9: Once we have used the files we needed...
    Remember how in step 1 I mentioned that the store valuable was required, but we haven't really done anything with it yet? Well now I'm going to explain the method used in CacheUnpacker to make use of that property.

    So the way the following method works is, first makes sure a cache has been loaded, and will stop the method if one hasn't. Then it uses the HashMap getKeys() method to obtain a list of all the Key objects that have been placed in the HashMap, this way when using a cache with file id's that don't go up in increments of 1(e.g. select model cache). It then goes through that list of Key objects, checking and removing HashMap entries if they are set to be removed when this method is called(Not stored after loading) Here is the method:
    Code:
    	// Clean out HashMap once loading has
    	// completed, ridding of any entries in
    	// the HashMap of which are no longer
    	// needed.
    	public void cleanFileMap()
    	{
    		// If nothing has been loaded yet
    		if (!loaded)
    			return;
    		// Gets all the "Key" objects that are in
    		// the files HashMap. Doing it this way
    		// allows there to be keys that do not
    		// go up from 0 in increments of 1.
    		Set<Integer> keys = files.keySet();
    		for (int i : keys)
    			if (!files.get(i).getStore())
    				files.remove(i);
    	}
    Place that in your CacheUnpacker class, no editing of this method is required.

    Step 10: Obtaining loaded files from outside of the CacheUnpacker class
    As you may/may not have noticed(doesn't really matter), the HashMap instance "files" in CacheUnpacker is private. So we need to make a method to get that HashMap externally, making sure that it has been initialized before we try to give it:
    Code:
    	public HashMap<Integer, CacheFile> getFileMap()
    	{
    		// If the loadCache() method hasn't been
    		// called, the HashMap will not have
    		// been initialized. (Exception prevention)
    		if (!loaded)
    			return null;
    		return files;
    	}
    Once again, just add it to your CacheUnpacker class.

    AND VIOLA YOUR FINISHED (To an extent)

    Extra: Notable places for editing
    At the moment the only place you may need to edit is the fileID in the CachePacker class.
    Remove this line:
    Code:
    			int fileID = 0;
    Modify this line to your liking:
    Code:
    				out.writeInt(fileID++);
    Extra: (Advanced)(Corruption Protection) FailSafe'ing Lists that aren't Synchronized
    Well theres a chance that when you make up the List's to pack your cache with that sometimes one or more wont match up to the main(File) List, so heres a simple method that will cycle all lists and unless null, return false if any of them don't match up with the File List: (Add in CachePacker)
    Code:
    	// For flexibility of the cache packing method,
    	// this method takes in a main List of type
    	// <?> which enables it to be any List. Then
    	// a Array of List<?>'s. It then loops through
    	// the Array of Lists, and unless the Array is
    	// null; if it's size does not match that of the
    	// main Arrays it will return false as the List's
    	// are not in synchronization.
    	private static boolean isSynchronized(List<?> main, List<?>... lists)
    	{
    		for (List<?> l : lists)
    			if (l != null && main.size() != l.size())
    				return false;
    		return true;
    	}
    And to implement it just add this and adjust the third++ arguments to your custom List's somewhere before the TryCatch in the createCache method of CachePacker:
    Code:
    		// Check if File List and Store List are in sync,
    		// if they aren't throw a new exception.
    		// HOWEVER, if you do not wish to utilize the
    		// storage feature you may set the store list to
    		// null and this check will be ignored. Leaving all
    		// store variables to be set to the default true;
    		if (!isSynchronized(files, stores, yourList1, yourList2, etc.))
    		{
    			new Exception("Lists arent synchronized").printStackTrace();
    			return;
    		}
    Extra: Modify CachePacker.createCache to be more flexible
    Whilst in the making of a tutorial to implement this Cache system into Model Preloading it occured to me that it would be alot easier to have the createCache method accept 2 Strings first, One for where the cache file will be output and one for the input directory. So here is how to do so.

    First off here:
    Code:
    	public static void createCache(String cacheFile, List<String> files,
    Add this new argument:
    Code:
    	public static void createCache(String cacheFile, String cacheDirectory, List<String> files,
    Now delete this:
    Code:
    			cacheFile = cacheFile.replaceAll("/", "\\");
    			String cacheDirectory;
    			if (cacheFile.contains("\\"))
    			{
    				cacheDirectory = cacheFile.substring(0, cacheFile.lastIndexOf("\\"));
    			} else
    			{
    				new Exception("CacheFolder not seperate").printStackTrace();
    				out.close();
    				return;
    			}
    Now your modified method will create the cache in the file cachePath specifies, while receiving files to place in the cache from cacheDirectory.


    Sources: (I've used this before but I can't remember it all off by heart)
    [Only registered and activated users can see links. ] (To check how much 2147483647 bytes is)
    [Only registered and activated users can see links. ]

    FINISHED!!!! Who knows why I spent 3 hours writing this tutorial... IT BETTER HELP SOMEONE!!!

    Cheers,
    Ninjastylz(az)
    Reply With Quote  
     

  4. Thankful users:


  5. #3  
    Registered Member
    Addiction's Avatar
    Join Date
    Mar 2011
    Posts
    959
    Thanks given
    1,875
    Thanks received
    136
    Rep Power
    311
    Awesome! Repped!
    Reply With Quote  
     

  6. #4  
    Registered Member

    Join Date
    Oct 2009
    Posts
    149
    Thanks given
    4
    Thanks received
    20
    Rep Power
    97
    Nevermind will add to second post iPlasma
    Reply With Quote  
     

  7. #5  
    I'm Back

    Stewie's Avatar
    Join Date
    Jul 2008
    Age
    26
    Posts
    7,989
    Thanks given
    1,877
    Thanks received
    1,491
    Rep Power
    5000
    Quote Originally Posted by iPlasma View Post
    Awesome! Repped!
    Because you totally read this in 2 minutes..


    But Jeez. You really put some detail into this. Ill have to bring myself to read it one day. bookmarked.


    [Only registered and activated users can see links. ]
    Reply With Quote  
     

  8. Thankful users:


  9. #6  
    Registered Member
    Slay No More's Avatar
    Join Date
    Oct 2008
    Age
    25
    Posts
    2,334
    Thanks given
    695
    Thanks received
    170
    Rep Power
    554
    Some how doubt you did this..
    Add me on skype if you wish to contact me.
    slaynomore
    My Steam Profile (from [Only registered and activated users can see links. ])
    • Worth: $719 ($245 with sales)
    • Games owned: 86
    • Games not played: 27 (31%)
    • Hours on record: 1,851.8h
    Reply With Quote  
     

  10. #7  
    Registered Member

    Join Date
    Dec 2007
    Age
    28
    Posts
    1,954
    Thanks given
    114
    Thanks received
    608
    Rep Power
    1094
    so you're basically creating your own cache?
    Reply With Quote  
     

  11. #8  
    なぜこのテキストは日本語で書かれている ?

    Kenneh's Avatar
    Join Date
    Dec 2009
    Age
    27
    Posts
    2,754
    Thanks given
    63
    Thanks received
    296
    Rep Power
    478
    Its basically the same thing we do with custom sprite caches and stuff, just more confusing.


    Reply With Quote  
     

  12. #9  
    Registered Member

    Join Date
    Oct 2009
    Posts
    149
    Thanks given
    4
    Thanks received
    20
    Rep Power
    97
    Quote Originally Posted by Slay No More View Post
    Some how doubt you did this..
    Find this tutorial elsewhere posted before me, I'll pay you if you do because this was 100% me and I spent 2-3 hours on this. I also have a dodgier version of this when I first created the idea(Surely done by someone else before though) of putting files in a single file using a byte array when I was to make 2d games using Applets.

    Quote Originally Posted by Kenneh View Post
    Its basically the same thing we do with custom sprite caches and stuff, just more confusing.
    This is the simplest form of cache creating I can think of, it just comes off as confusing until you read it because it's written in a tutorial. If you are capable of it and you just read the code(With/without comments) you would be able to understand it a whole lot more easily
    Reply With Quote  
     

  13. #10  
    Banned

    Join Date
    Jun 2010
    Age
    33
    Posts
    4,337
    Thanks given
    4
    Thanks received
    274
    Rep Power
    0
    Niceee, decent. Won't use though.
    Reply With Quote  
     

Page 1 of 2 12 LastLast

Thread Information
Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)


User Tag List

Similar Threads

  1. Replies: 49
    Last Post: 06-08-2011, 01:24 AM
  2. Replies: 10
    Last Post: 12-05-2010, 12:31 AM
  3. Renaming Multiple Files
    By NICKname in forum Snippets
    Replies: 4
    Last Post: 06-13-2010, 02:19 AM
  4. Replies: 3
    Last Post: 12-08-2009, 12:42 AM
Posting Permissions
  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •