2018-04-22 15:55:55 +00:00
|
|
|
//======== (C) Copyright 2002 Charles G. Cleveland All rights reserved. =========
|
|
|
|
//
|
|
|
|
// The copyright to the contents herein is the property of Charles G. Cleveland.
|
|
|
|
// The contents may be used and/or copied only with the written permission of
|
|
|
|
// Charles G. Cleveland, or in accordance with the terms and conditions stipulated in
|
|
|
|
// the agreement/contract under which the contents have been supplied.
|
|
|
|
//===============================================================================
|
|
|
|
|
|
|
|
#ifndef BALANCE_H
|
|
|
|
#define BALANCE_H
|
|
|
|
|
|
|
|
#include <string>
|
|
|
|
#include <map>
|
|
|
|
#include <memory>
|
|
|
|
#include "Balance.txt" //default balancing source - this used to be ../Balance.txt
|
|
|
|
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
// BalanceValueContainerFactory -- facade that creates, stores, and
|
|
|
|
// maintains BalanceValueContainer objects. Multiple calls with the
|
|
|
|
// same parameter will return the same object. The (void) function
|
|
|
|
// call is equivalent to calling for a filename with an empty string.
|
|
|
|
// Invalid filenames will still return an usable BalanceValueContainer,
|
|
|
|
// but that container will not be able to save later.
|
|
|
|
//
|
|
|
|
// The objects that this function creates should not be manually
|
|
|
|
// deleted; it is responsible for cleanup of the objects.
|
|
|
|
//
|
|
|
|
// TODO: Add another constructor for UPP::ProductInfo objects
|
|
|
|
// TODO: Make retrieval/creation of objects thread safe (it's not)
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
|
|
class BalanceValueContainer;
|
|
|
|
|
|
|
|
namespace BalanceValueContainerFactory
|
|
|
|
{
|
|
|
|
BalanceValueContainer* get(const std::string& filename);
|
|
|
|
BalanceValueContainer* get(void);
|
|
|
|
const std::string& getDefaultFilename(void);
|
|
|
|
};
|
|
|
|
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
// BalanceChangeListener -- abstract class that allows arbitrary
|
|
|
|
// items to listen for changes to the balancing system. Items can
|
|
|
|
// register for individual values or for the entire balance variable
|
|
|
|
// set. Listeners are notified in advance of each change, but don't
|
|
|
|
// have the authority to override.
|
|
|
|
//
|
|
|
|
// The shouldNotify function is a filter for items registered for
|
|
|
|
// entire sets, allowing them to select items they are actually
|
|
|
|
// interested in receiving. Items that are registered for specific
|
|
|
|
// variables skip the shouldNotify check.
|
|
|
|
//
|
|
|
|
// When a BalanceValueContainer is wiped, the balanceCleared function
|
|
|
|
// is called rather than iterating over all of the values for all of
|
|
|
|
// the attached listeners. It should be considered a signal that
|
|
|
|
// all items the listener is interested in have been removed.
|
|
|
|
//
|
|
|
|
// The BalanceStartCompoundChange and BalanceEndCompoundChange
|
|
|
|
// functions provide rough grain functionality for listeners that
|
|
|
|
// want to only operate once on a large change (such as a complete
|
|
|
|
// reset) instead of once per change. By combining these functions
|
|
|
|
// with an internal state variable, they can know when to ignore
|
|
|
|
// individual signals. The compound change functions will not be
|
|
|
|
// called for individual balance changes, so it's important to track
|
|
|
|
// these as well if you want a catch-all method of detecting changes.
|
|
|
|
//
|
|
|
|
// The compound change functions will only be called for universally
|
|
|
|
// registered listeners.
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
|
|
enum BalanceValueType {
|
|
|
|
BALANCE_TYPE_FLOAT = 1,
|
|
|
|
BALANCE_TYPE_INT = 2,
|
|
|
|
BALANCE_TYPE_STRING = 3
|
|
|
|
};
|
|
|
|
|
|
|
|
class BalanceChangeListener
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
unsigned int getBalanceChangeListenerID(void) const;
|
|
|
|
virtual ~BalanceChangeListener(void);
|
|
|
|
|
|
|
|
virtual bool shouldNotify(const std::string& name, const BalanceValueType type) const;
|
|
|
|
virtual void balanceCleared(void) const;
|
|
|
|
|
|
|
|
virtual void balanceValueInserted(const std::string& name, const float value) const;
|
|
|
|
virtual void balanceValueInserted(const std::string& name, const int value) const;
|
|
|
|
virtual void balanceValueInserted(const std::string& name, const std::string& value) const;
|
|
|
|
|
|
|
|
virtual void balanceValueChanged(const std::string& name, const float old_value, const float new_value) const;
|
|
|
|
virtual void balanceValueChanged(const std::string& name, const int old_value, const int new_value) const;
|
|
|
|
virtual void balanceValueChanged(const std::string& name, const std::string& old_value, const std::string& default_value) const;
|
|
|
|
|
|
|
|
virtual void balanceValueRemoved(const std::string& name, const float old_value) const;
|
|
|
|
virtual void balanceValueRemoved(const std::string& name, const int old_value) const;
|
|
|
|
virtual void balanceValueRemoved(const std::string& name, const std::string& old_value) const;
|
|
|
|
|
|
|
|
virtual void balanceStartCompoundChange(void) const;
|
|
|
|
virtual void balanceEndCompoundChange(void) const;
|
|
|
|
protected:
|
|
|
|
BalanceChangeListener(void);
|
|
|
|
private:
|
|
|
|
const unsigned int BCL_ID; //handle for tracking registrations; internal use only
|
|
|
|
};
|
|
|
|
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
// BalanceValueContainer -- abstract parent class for balance variable
|
|
|
|
// storage and retrieval with change notification.
|
|
|
|
//
|
|
|
|
// It is possible to actually use the same name for multiple variable
|
|
|
|
// types at runtime, but the results are undefined if the conflict
|
|
|
|
// is saved or reloaded, so it's important to be careful when using
|
|
|
|
// value types.
|
|
|
|
//
|
|
|
|
// When calling addListener, multiple registrations for the same
|
|
|
|
// variable name or multiple global registrations have no added
|
|
|
|
// effect. If a listener is registered globally and for a specific
|
|
|
|
// variable, it will still only be called once per event.
|
|
|
|
//
|
|
|
|
// When calling removeListener without a name argument, only the
|
|
|
|
// universal listener location is checked for the matching pointer.
|
|
|
|
// It is safe to leave listeners registered with a container even
|
|
|
|
// after the listeners have been deconstructed, so it is not required
|
|
|
|
// to unregister a listener from many different items.
|
|
|
|
//
|
|
|
|
// The equality and inequality checks test the equality/inequality
|
|
|
|
// of the value maps. The assignment operator performs the minimum
|
|
|
|
// number of changes required for the value maps to become equal.
|
|
|
|
// This is much more complex than simple reassignment, but it allows
|
|
|
|
// proper notification of BalanceChangeListeners.
|
|
|
|
//
|
|
|
|
// TODO: Make addition/removal of listeners thread safe (it's not)
|
|
|
|
// TODO: Make assignment thread safe (it's not)
|
|
|
|
// TODO: Make insertion/retrieval/removal of values thread safe
|
|
|
|
// TODO: Make load a minimal change operation (like assignment)
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
|
|
typedef std::map<std::string,float> BalanceFloatCollection;
|
|
|
|
typedef std::map<std::string,int> BalanceIntCollection;
|
|
|
|
typedef std::map<std::string,std::string> BalanceStringCollection;
|
|
|
|
|
|
|
|
class BalanceValueContainer
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
virtual ~BalanceValueContainer(void);
|
|
|
|
virtual BalanceValueContainer& operator=(const BalanceValueContainer& other) = 0;
|
|
|
|
virtual bool operator!=(const BalanceValueContainer& other) const = 0;
|
|
|
|
virtual bool operator==(const BalanceValueContainer& other) const = 0;
|
|
|
|
|
|
|
|
virtual bool load(void) = 0;
|
|
|
|
virtual bool save(void) = 0;
|
|
|
|
|
|
|
|
virtual const float get(const std::string& name, const float default_value) const = 0;
|
|
|
|
virtual const int get(const std::string& name, const int default_value) const = 0;
|
|
|
|
virtual const std::string get(const std::string& name, const std::string& default_value) const = 0;
|
|
|
|
|
|
|
|
virtual const BalanceFloatCollection* getFloatMap(void) const = 0;
|
|
|
|
virtual const BalanceIntCollection* getIntMap(void) const = 0;
|
|
|
|
virtual const BalanceStringCollection* getStringMap(void) const = 0;
|
|
|
|
|
|
|
|
virtual void insert(const std::string& name, const float value) = 0;
|
|
|
|
virtual void insert(const std::string& name, const int value) = 0;
|
|
|
|
virtual void insert(const std::string& name, const std::string& value) = 0;
|
|
|
|
|
|
|
|
virtual void remove(const std::string& name) = 0;
|
|
|
|
virtual void clear(void) = 0;
|
|
|
|
|
|
|
|
virtual void addListener(const BalanceChangeListener* listener) = 0;
|
|
|
|
virtual void addListener(const std::string& name, const BalanceChangeListener* listener) = 0;
|
|
|
|
virtual void removeListener(const BalanceChangeListener* listener) = 0;
|
|
|
|
virtual void removeListener(const std::string& name, const BalanceChangeListener* listener) = 0;
|
|
|
|
protected:
|
|
|
|
BalanceValueContainer(void);
|
|
|
|
};
|
|
|
|
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
// BALANCE_VAR(x) macro - the heart of the balance system, ties value
|
|
|
|
// to default balance source if PLAYTEST_BUILD is enabled, uses
|
|
|
|
// hardcoded value otherwise. Place the name of the varaible #define
|
|
|
|
// in Balance.txt as the value in the macro.
|
|
|
|
//
|
|
|
|
// BALANCE_LISTENER(x) macro - for registering global
|
|
|
|
// BalanceChangeListeners (see below), reverts to no operation
|
|
|
|
// if AVH_PLAYTEST_BUILD isn't enabled.
|
|
|
|
//
|
|
|
|
// BALANCE_FIELD_LISTENER(x,y) macro - for registering field-specific
|
|
|
|
// BalanceChangeListeners, reverts to no operation if
|
|
|
|
// BALANCE_ENABLED isn't defined
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
|
|
#ifdef BALANCE_ENABLED //use Balance.txt values on server, no-source/explicitly set values for client
|
|
|
|
#ifdef SERVER
|
|
|
|
#define BALANCE_DEFNAME BalanceValueContainerFactory::getDefaultFilename()
|
|
|
|
#else
|
|
|
|
#define BALANCE_DEFNAME ""
|
|
|
|
#endif
|
|
|
|
|
|
|
|
inline void BALANCE_LISTENER(const BalanceChangeListener* object) { BalanceValueContainerFactory::get(BALANCE_DEFNAME)->addListener(object); }
|
|
|
|
inline void BALANCE_FIELD_LISTENER(const BalanceChangeListener* object, const char* field) { BalanceValueContainerFactory::get(BALANCE_DEFNAME)->addListener(field,object); }
|
|
|
|
|
|
|
|
#define BALANCE_VAR(name) GetBalanceVar(#name,name) //requires macro for string-izing of name
|
|
|
|
inline int GetBalanceVar(const char* name, const int value) { return BalanceValueContainerFactory::get(BALANCE_DEFNAME)->get(name,value); }
|
|
|
|
inline float GetBalanceVar(const char* name, const float value) { return BalanceValueContainerFactory::get(BALANCE_DEFNAME)->get(name,value); }
|
|
|
|
inline float GetBalanceVar(const char* name, const double value) { return BalanceValueContainerFactory::get(BALANCE_DEFNAME)->get(name,(float)value); }
|
|
|
|
inline std::string GetBalanceVar(const char* name, const char* value) { return BalanceValueContainerFactory::get(BALANCE_DEFNAME)->get(name,value); }
|
|
|
|
#else
|
|
|
|
#define BALANCE_VAR(name) name //hardcodes the value at compile time
|
|
|
|
#define BALANCE_LISTENER(object)
|
|
|
|
#define BALANCE_FIELD_LISTENER(object,name)
|
|
|
|
#endif //BALANCE_ENABLED
|
|
|
|
|
|
|
|
#endif //BALANCE_H
|