de.rpgframework.genericrpg.chargen.CharacterControllerImpl Maven / Gradle / Ivy
The newest version!
package de.rpgframework.genericrpg.chargen;
import java.io.IOException;
import java.lang.System.Logger;
import java.lang.System.Logger.Level;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
import de.rpgframework.character.Attachment;
import de.rpgframework.character.Attachment.Format;
import de.rpgframework.character.Attachment.Type;
import de.rpgframework.character.CharacterHandle;
import de.rpgframework.character.CharacterProvider;
import de.rpgframework.character.CharacterProviderLoader;
import de.rpgframework.character.ProcessingStep;
import de.rpgframework.character.RuleSpecificCharacterObject;
import de.rpgframework.core.BabylonEventBus;
import de.rpgframework.core.BabylonEventType;
import de.rpgframework.genericrpg.ToDoElement;
import de.rpgframework.genericrpg.data.CommonCharacter;
import de.rpgframework.genericrpg.data.CommonCharacter.DataSetControl;
import de.rpgframework.genericrpg.data.DataItem;
import de.rpgframework.genericrpg.data.DataSet;
import de.rpgframework.genericrpg.data.IAttribute;
import de.rpgframework.genericrpg.data.RuleController;
import de.rpgframework.genericrpg.modification.Modification;
/**
* @author Stefan
*
*/
public abstract class CharacterControllerImpl> implements CharacterController {
private final static Logger logger = System.getLogger(CharacterControllerImpl.class.getPackageName()+".main");
protected M model;
protected CharacterHandle handle;
protected RuleController ruleCtrl;
protected LevellingProfileController profileCtrl;
protected Optional> recommender;
protected Locale locale = Locale.getDefault();
private Collection listener;
protected List processChain;
protected boolean dontProcess;
private List unitTestModifications;
protected boolean allowRunProcessor = true;
//-------------------------------------------------------------------
protected CharacterControllerImpl() {
listener = new ArrayList();
processChain = new ArrayList();
unitTestModifications = new ArrayList();
recommender = Optional.empty();
}
//-------------------------------------------------------------------
protected CharacterControllerImpl(M model, CharacterHandle handle) {
this();
this.model = model;
this.handle= handle;
recommender = Optional.empty();
}
//-------------------------------------------------------------------
public Locale getLocale() {
return locale;
}
public void setLocale(Locale locale) {
this.locale = locale;
}
//-------------------------------------------------------------------
public boolean showDataItem(DataItem item) {
// If the item is restricted to a language and that doesn't match, hide it
if (item.getLanguage()!=null && !locale.getLanguage().equals(item.getLanguage()))
return false;
// If this is the default item, but there is one specific to the chosen language, hide it
if (item.getLanguage()==null && item.hasLanguageAlternative(locale.getLanguage()))
return false;
if (model instanceof CommonCharacter) {
DataSetControl dsCtrl = ((CommonCharacter)model).getDataSets();
if (dsCtrl.mode==DataSetMode.SELECTED) {
boolean found = false;
for (DataSet set : item.getAssignedDataSets()) {
if (dsCtrl.selected.contains(set.getID()) || set.getID().equalsIgnoreCase("CORE"))
found= true;
}
if (!found)
return false;
}
}
return true;
}
//-------------------------------------------------------------------
public void addUnitTestModification(Modification mod) {
unitTestModifications.add(mod);
runProcessors();
}
//-------------------------------------------------------------------
public void removeUnitTestModification(Modification mod) {
unitTestModifications.remove(mod);
runProcessors();
}
//-------------------------------------------------------------------
@Override
public M getModel() {
return model;
}
//-------------------------------------------------------------------
@Override
public void setModel(M data) {
this.model = data;
}
//-------------------------------------------------------------------
/**
* @see de.rpgframework.genericrpg.chargen.CharacterController#addListener(de.rpgframework.genericrpg.chargen.ControllerListener)
*/
@Override
public void addListener(ControllerListener callback) {
if (!listener.contains(callback)) {
listener.add(callback);
}
}
//-------------------------------------------------------------------
@Override
public void removeListener(ControllerListener callback) {
listener.remove(callback);
}
//-------------------------------------------------------------------
/**
* @see de.rpgframework.genericrpg.chargen.CharacterController#hasListener(de.rpgframework.genericrpg.chargen.ControllerListener)
*/
@Override
public boolean hasListener(ControllerListener callback) {
return listener.contains(callback);
}
//-------------------------------------------------------------------
@Override
public Collection getListener() {
return listener;
}
//-------------------------------------------------------------------
@Override
public void fireEvent(ControllerEvent type, Object...param) {
logger.log(Level.WARNING, "########"+type+" to "+listener.size()+" listeners of "+this.getClass());
System.err.println("CharacterControllerImpl########"+type+" to "+listener.size()+" listeners of "+this.getClass());
if (listener.size()==0) {
logger.log(Level.ERROR, "No listeners for character controller - that can only be an error");
System.err.println( "CharacterControllerImpl: No listeners for character controller - that can only be an error");
}
for (ControllerListener callback : new ArrayList<>(listener)) {
try {
callback.handleControllerEvent(type, param);
} catch (Exception e) {
logger.log(Level.ERROR, "Error delivering generation event",e);
}
}
if (type==BasicControllerEvents.CHARACTER_PROFILES_CHANGED) {
recommender.ifPresent(r -> r.update());
}
}
//-------------------------------------------------------------------
/**
* @see de.rpgframework.genericrpg.chargen.CharacterController#getRuleController()
*/
@Override
public RuleController getRuleController() {
return ruleCtrl;
}
//-------------------------------------------------------------------
/**
* @see de.rpgframework.genericrpg.chargen.CharacterController#getProfileController()
*/
@Override
public LevellingProfileController getProfileController() {
return profileCtrl;
}
//-------------------------------------------------------------------
@Override
public List getToDos() {
List ret = new ArrayList();
if (model==null)
return ret;
for (ProcessingStep step : processChain) {
if (step instanceof PartialController) {
ret.addAll( ((PartialController>)step).getToDos());
}
}
Collections.sort(ret, new Comparator() {
public int compare(ToDoElement o1, ToDoElement o2) {
return Integer.compare(o1.getSeverity().ordinal(), o2.getSeverity().ordinal());
}
});
return ret;
}
//-------------------------------------------------------------------
/**
* @see de.rpgframework.genericrpg.chargen.CharacterController#setAllowRunProcessor(boolean)
*/
@Override
public void setAllowRunProcessor(boolean value) {
this.allowRunProcessor = value;
}
//-------------------------------------------------------------------
@Override
public void runProcessors() {
if (dontProcess || !allowRunProcessor)
return;
try {
dontProcess = true;
logger.log(Level.DEBUG, "\n\nSTART: runProcessors: "+processChain.size()+"-------------------------------------------------------");
List unprocessed = new ArrayList<>(unitTestModifications);
for (ProcessingStep processor : processChain) {
if (processor==null) {
logger.log(Level.ERROR, "Found NULL in processChain");
continue;
}
try {
unprocessed = processor.process(unprocessed);
} catch (Exception e) {
logger.log(Level.ERROR, "Exception in processor "+processor.getClass(),e);
BabylonEventBus.fireEvent(BabylonEventType.UI_MESSAGE, 2, "Error calculating character",e);
}
logger.log(Level.WARNING, "------ after {0}:\t {1}",processor.getClass().getSimpleName(),unprocessed);
}
logger.log(Level.DEBUG, "Remaining mods = "+unprocessed);
logger.log(Level.INFO, "ToDos = "+getToDos());
logger.log(Level.WARNING, "STOP : runProcessors: "+processChain.size()+"-------------------------------------------------------");
fireEvent(BasicControllerEvents.CHARACTER_CHANGED, model);
} finally {
dontProcess = false;
}
}
//-------------------------------------------------------------------
/**
* Save the current version of the character to a long time storage.
* If implemented by a CharacterGenerator, an unfinished version is
* saved so creation can be continued later.
*
* @param data Native save format (XML bytes)
* @return TRUE, if saving has been successful
* @throws IOException
* @see de.rpgframework.genericrpg.chargen.CharacterController#save()
*/
@Override
public boolean save(byte[] data) throws IOException {
logger.log(Level.DEBUG, "save called for handle {0} and char {0}", handle, model.getName());
CharacterProvider prov = CharacterProviderLoader.getCharacterProvider();
if (handle!=null) {
logger.log(Level.DEBUG, "handle already exists");
boolean modelNeedsSaving = true;
boolean imageNeedsSaving = true;
// Character has been continued and is only modified
for (Attachment attach : prov.listAttachments(handle)) {
if (attach.getType()==Type.CHARACTER && attach.getFormat()==Format.RULESPECIFIC) {
attach.setData(data);
logger.log(Level.INFO, "Update character file");
prov.modifyAttachment(handle, attach);
modelNeedsSaving = false;
}
if (attach.getType()==Type.CHARACTER && attach.getFormat()==Format.IMAGE) {
if (model.getImage()!=null) {
attach.setData(model.getImage());
logger.log(Level.INFO, "Update character image");
prov.modifyAttachment(handle, attach);
} else {
logger.log(Level.INFO, "Delete character image, since not present in model anymore");
prov.deleteAttachment(handle, attach);
}
imageNeedsSaving = false;
}
}
// See if anything must be created
if (modelNeedsSaving) {
prov.addAttachment(handle, Type.CHARACTER, Format.RULESPECIFIC, handle.getName(), data);
}
if (imageNeedsSaving && model.getImage()!=null) {
prov.addAttachment(handle, Type.CHARACTER, Format.IMAGE, handle.getName(), model.getImage());
}
return true;
}
// Character has not previously been saved
// Before creating a new handle, make sure there isn't already
// one that would be overwritten
logger.log(Level.DEBUG, "handle does not exist yet");
handle = prov.getCharacter(model.getName(), model.getRules());
if (handle!=null) {
// Would overwrite existing character.
logger.log(Level.WARNING, "Trying to overwrite existing character with this one");
return false;
}
// Create new character
handle = prov.createCharacter(model.getName(), model.getRules());
if (handle==null)
throw new IOException("Failed: No character handle");
if (handle.getUUID()==null)
throw new IOException("Failed: No UUID in character handle");
// A valid character handle exists - now create attachments
prov.addAttachment(handle, Type.CHARACTER, Format.RULESPECIFIC, model.getName()+".xml", data);
if (model.getImage()!=null) {
prov.addAttachment(handle, Type.CHARACTER, Format.IMAGE, model.getName()+".img", model.getImage());
}
return true;
}
//-------------------------------------------------------------------
/**
* @see de.rpgframework.genericrpg.chargen.CharacterController#getRecommender()
*/
public Optional> getRecommender() {
return recommender;
}
//-------------------------------------------------------------------
/**
* @param recommender the recommender to set
*/
public void setRecommender(IRecommender recommender) {
this.recommender = Optional.ofNullable(recommender);
}
// //-------------------------------------------------------------------
// protected abstract void updateEffectiveRules() ;
//
// //-------------------------------------------------------------------
// public void setRule(Rule rule, Object value) {
// model.setRuleValue(rule, String.valueOf(value));
// updateEffectiveRules();
// }
//
// //-------------------------------------------------------------------
// /**
// * @see de.rpgframework.genericrpg.chargen.CharacterController#getRule(de.rpgframework.genericrpg.chargen.Rule)
// */
// @Override
// public RuleValue getRule(Rule rule) {
// for (Entry entry : effectiveRules.entrySet()) {
// if (entry.getKey()==rule) {
// return entry.getValue();
// }
// }
// return null;
// }
//
// //-------------------------------------------------------------------
// /**
// * @see de.rpgframework.genericrpg.chargen.CharacterController#getRules()
// */
// @Override
// public List getRules() {
// return new ArrayList<>(effectiveRules.values());
// }
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy