Ryley Posted October 29, 2013 Share Posted October 29, 2013 (edited) I started writing my own extension API alongside OSBots which contains helper methods that are typically used in most scripts, this is one of the classes: package org.milkcouch.script; import java.util.HashMap; import java.util.Map; /** * Represents attributes that a script uses. * * <a> * Example: for skill calculators I see a bunch of people adding a multitude of * variables to represent the initial experience before starting a script. * With this you could create constant fields: * <code> * final class MyScriptsAttributes { * private static final ScriptAttributes attributes = ScriptAttributes.getInstance(); * * public static final boolean USE_FOOD = attributes.contains("USE_FOOD"); * ... and so on ... * } * </code> * * This makes your code much more readable and you do not have * A cluster fuck of random variables everywhere representing various attributes. * This can also be used for setting the current state of your bot, I see people * All the time having a static <code>String</code> and setting it each time a state is updated. * * <code> * vars.status = "antiban"; * </code> * * That is very unappealing and ignores any convention. * * Instead we could do this: * * <code> * ScriptAttributes.getInstance().updateStatus("Antiban"); * </code> * * And to return it, I have added status helper methods, which make it simple for everyone. * * <code> * ScriptAttributes.getInstance().getCurrentStatus(); * </code> * </a> * * @author Ryley Kimmel <ryley.kimmel@live.com> */ public final class ScriptAttributes { /** * A 'lazy' singleton implementation. */ private static final ScriptAttributes INSTANCE = new ScriptAttributes(); /** * A map of strings->objects, which represent attributes. */ private final Map<String, Object> attributes = new HashMap<>(); /** * Adds an attribute to the attribute map. * @param key The attributes key. * @param value The value of the attribute. */ public void add(String key, Object value) { attributes.put(key, value); } /** * Returns the value of a specified key. * @param key The key. * @return The value of the specified key, <tt>null</tt> if the key does not exist. */ public Object getValue(String key) { return attributes.get(key); } /** * Removes an attribute from the map by its key. * @param key The key to remove. */ public void remove(String key) { attributes.remove(key); } /** * Removes a set of keys from the map. * @param keys The keys to remove. */ public void remove(String... keys) { for (String key : keys) { remove(key); } } /** * Returns whether or not the map contains the specified key. * @param key The key. * @return <code>true</code> if the key exists, otherwise </code>false</code> */ public boolean contains(String key) { return attributes.containsKey(key); } // ... status helpers /** * Updates the current status of your script. * @param newStatus The new status. */ public void updateStatus(String newStatus) { add("CURRENT_STATUS", newStatus); } /** * Returns the current status of your script. * @return The current status of your script, <tt>null</tt> if no status exists. */ public String getStatus() { return (String) getValue("CURRENT_STATUS"); } /** * Returns the singleton instance of this class. * @return The singleton instance. */ public static ScriptAttributes getInstance() { return INSTANCE; } /** * Default private constructor, used to prevent this class from being instantiated. * <a> * This constructor should not be instanced directly, use {@link #getInstance()} instead! * </a> * @see {@link #getInstance()}. */ private ScriptAttributes() { } } Edited October 29, 2013 by Ryley Link to comment Share on other sites More sharing options...
liverare Posted October 30, 2013 Share Posted October 30, 2013 (edited) Why not just extend the HashMap<String, Object> onto the class and create a static constant of the class itself? You could remove all the already-existing methods from the class, i.e., #getValue(String). Here's what I would do instead: public class ScriptAttribute extends HashMap<String, Object> { private static final ScriptAttribute INSTANCE = new ScriptAttribute(); private static final String KEY_STATUS = "CURRENT_STATUS"; static { INSTANCE.put(KEY_STATUS, "null"); } private ScriptAttribute() { } public String getStatus() { return (String) get(KEY_STATUS); } public void setStatus(String status) { put(KEY_STATUS, status); } /** * This may look weird, but: * <code> * #setStatus("Al Kharid"); * #updateStatus("Walking to Bank"); * * #getStatus() @return "Al Kharid - Walking to Bank" * </code> * * @param updateStatus * Status to concatenate onto the prior state */ public void updateStatus(String updateStatus) { put(KEY_STATUS, getStatus() + " - " + updateStatus); } public void remove(String... keys) { if (keys == null || keys.length == 0) for (String next : keys) if (next != null && next.length() > 0) remove(next); } public static ScriptAttribute getInstance() { return INSTANCE; } } ...A few changes, but in a ScriptAdapter class (A class that merely extends Script and allows script conformity) would be: public class ScriptAdapter extends Script { . . . public static ScriptAttribute getAttributeHandler() { return ScriptAttribute.getInstance(); } } I would do this so that you can direct the access to the script's attributes via the main script class. 1 second after posting and I just remembered something:: I would override the #remove(Object) to prevent the removal of important keys, i.e., CURRENT_STATUS, etc. P.S. I did kind of rush the code, so updateStatus(String) would continuously append the existing String for CURRENT_STATUS, e.g., "Al Kharid - Going to Bank - Going to Mines - ..." ..It's not too bad, especially if you wanted to keep track of the executing states in order, but it wouldn't look good in the paint, though. Edited October 30, 2013 by liverare Link to comment Share on other sites More sharing options...
Ryley Posted October 30, 2013 Author Share Posted October 30, 2013 ++ for the usage of the adapter pattern; but extending HashMap is a bit overkill, if you were to do that I would rather make my own collection for this. Link to comment Share on other sites More sharing options...
Toph Posted November 8, 2013 Share Posted November 8, 2013 This seems like a major overkill. People not skilled enough to make the errors you mentioned are not going to be skilled enough to implement this. Link to comment Share on other sites More sharing options...
LifezHatred Posted November 8, 2013 Share Posted November 8, 2013 Remember using a system exactly like this when i was on the Dementhium development team, Source was still pretty shitty Link to comment Share on other sites More sharing options...