Interface MapModel<G extends GameObject<G,A,R>,A extends MapArchObject<A>,R extends Archetype<G,A,R>>
-
- All Superinterfaces:
java.lang.Iterable<MapSquare<G,A,R>>
,java.io.Serializable
- All Known Implementing Classes:
DefaultMapModel
public interface MapModel<G extends GameObject<G,A,R>,A extends MapArchObject<A>,R extends Archetype<G,A,R>> extends java.lang.Iterable<MapSquare<G,A,R>>, java.io.Serializable
A MapModel reflects the data of a map. This MapModel interface covers the similarities between the current CFEditor and DaiEditor implementations.Transaction System
The purpose of the transaction system in MapModel is to allow several subsequent changes to the model to be collected as a single big change before the registered listeners (usually the user interface) gets notified. This prevents the user interface from performing hundreds of updates when a single one would be enough. The transaction system will also be used for implementing undo / redo.Concurrency
It's not purpose of the transaction system to provide concurrent transactions for concurrent threads. A MapModel will protect itself against concurrent modification.Performance
The transaction system is efficient-safe. The following operations are very cheap:
- Beginning a nested transaction
- Ending a nested transaction
- Ending an outermost transaction without having changed something
Transactions are recorded.
It is not (yet?) the purpose of the transaction system to provide real transactions (ACID). Queries to the MapModel during an ongoing transaction will reflect the intermediate state. And there is no rollback yet, but this is planned for future as it's required for undo anyway.
Future
The following features are not yet implemented but planned.Undo System
The transaction system will serve as a base for an undo / redo system. Beginning the outermost transaction stores a new undo record in the undo buffer. An undo record consists of the transaction's name plus the current map state.- Invariant:
- !isAnyTransactionActive() || getTransactionDepth() > 0
-
-
Method Summary
All Methods Instance Methods Abstract Methods Modifier and Type Method Description void
addActiveEditType(int editType)
Add edit type to the bitmask of active types.void
addGameObjectToMap(G gameObject, @NotNull java.awt.Point pos, @NotNull InsertionMode<G,A,R> insertionMode)
Add a gameObject to the map.void
addMapModelListener(@NotNull MapModelListener<G,A,R> listener)
Register a map listener.void
addMapTransactionListener(@NotNull MapTransactionListener<G,A,R> listener)
Registers a map transaction listener.void
addObjectListToMap(@NotNull java.lang.Iterable<G> objects)
Adds a list ofGameObjects
to this map.void
beginGameObjectChange(G gameObject)
Method to notify the model that a game object is about to change.void
beginSquareChange(@NotNull MapSquare<G,A,R> mapSquare)
Method to notify the model that a map square is about to change.void
beginTransaction(@NotNull java.lang.String name)
Starts a new transaction.void
clearMap()
Clears this map completely.void
endAllTransactions()
Ends all transaction.void
endGameObjectChange(G gameObject)
Method to notify the model that a game object was changed.void
endSquareChange(@NotNull MapSquare<G,A,R> mapSquare)
Method to notify the model that a map square was changed.void
endTransaction()
End a transaction.void
endTransaction(boolean fireEvent)
End a transaction.void
facesReloaded()
Will be called whenever the archetype faces have been reloaded.@NotNull java.util.List<G>
getAllGameObjects()
Returns all game objects.@NotNull ErrorCollector<G,A,R>
getErrors()
Gets the errors in this map.A
getMapArchObject()
Returns the Map Arch Object with the meta information about the map.@Nullable MapFile
getMapFile()
Returns the map file.@NotNull MapFile
getMapFile(@NotNull MapPath mapPath)
Returns the map file for a map that can be reached by following aMapPath
from this map.@NotNull MapSquare<G,A,R>
getMapSquare(@NotNull java.awt.Point pos)
Get the square at a specified location.int
getTransactionDepth()
Get the transaction depth, which is the number ofbeginTransaction(String)
invocations without matchingendTransaction()
invocations.G
insertArchToMap(@NotNull BaseObject<G,A,R,?> templateBaseObject, G nextGameObject, @NotNull java.awt.Point pos, boolean join)
Insert a game object to the map at a specified position.G
insertBaseObject(@NotNull BaseObject<G,A,R,?> baseObject, @NotNull java.awt.Point pos, boolean allowMany, boolean join, @NotNull InsertionMode<G,A,R> insertionMode)
Inserts aBaseObject
to a map.boolean
isAnyTransactionActive()
Returns whether a transaction is currently active.boolean
isAreaEmpty(int left, int top, int width, int height)
Checks whether an area of a map is completely empty.boolean
isEmpty()
Returns whether the map is empty.boolean
isModified()
Return whether the map has been modified from the on-disk state.boolean
isMultiArchFittingToMap(@NotNull Archetype<G,A,R> archetype, @NotNull java.awt.Point pos, boolean allowDouble)
Checks whether an GameObject (multi-arch) would still fit on this map.void
mapClosed()
This function must be called if this instance is freed.void
moveEnv(G gameObject, @NotNull java.awt.Point pos, G nextGameObject)
Moves aGameObject
to its environment.void
moveInv(G gameObject, @NotNull GameObject<G,A,R> prevGameObject)
Moves aGameObject
to the inventory of another game object.void
nextPoint(java.awt.Point point, int direction)
Moves the given point forward or backward one map square.void
removeGameObject(G gameObject, boolean join)
Delete an existingGameObject
from the map.void
removeMapModelListener(@NotNull MapModelListener<G,A,R> listener)
Unregister a map listener.void
removeMapTransactionListener(@NotNull MapTransactionListener<G,A,R> listener)
Unregisters a map transaction listener.void
resetModified()
Resets the modified flag to false.void
setErrors(@NotNull ErrorCollector<G,A,R> errors)
Sets the errors in this map.void
setMapFile(@Nullable MapFile mapFile)
Sets the map file.void
transientGameObjectChange(G gameObject)
Method to notify the model that a game object was changed but need not be restored by undo/redo.
-
-
-
Method Detail
-
mapClosed
void mapClosed()
This function must be called if this instance is freed.
-
clearMap
void clearMap()
Clears this map completely. After invoking this method, no objects will remain on this map.
-
isEmpty
boolean isEmpty()
Returns whether the map is empty.- Returns:
true
if the map is empty, orfalse
if the map is not empty
-
getMapArchObject
@NotNull A getMapArchObject()
Returns the Map Arch Object with the meta information about the map.- Returns:
- the map arch object with the meta information about the map
-
addMapModelListener
void addMapModelListener(@NotNull @NotNull MapModelListener<G,A,R> listener)
Register a map listener.- Parameters:
listener
- the listener to register
-
removeMapModelListener
void removeMapModelListener(@NotNull @NotNull MapModelListener<G,A,R> listener)
Unregister a map listener.- Parameters:
listener
- the listener to unregister
-
addMapTransactionListener
void addMapTransactionListener(@NotNull @NotNull MapTransactionListener<G,A,R> listener)
Registers a map transaction listener.- Parameters:
listener
- the the listener to register
-
removeMapTransactionListener
void removeMapTransactionListener(@NotNull @NotNull MapTransactionListener<G,A,R> listener)
Unregisters a map transaction listener.- Parameters:
listener
- the listener to unregister
-
beginSquareChange
void beginSquareChange(@NotNull @NotNull MapSquare<G,A,R> mapSquare)
Method to notify the model that a map square is about to change.- Parameters:
mapSquare
- the map square that is about to change
-
endSquareChange
void endSquareChange(@NotNull @NotNull MapSquare<G,A,R> mapSquare)
Method to notify the model that a map square was changed. A change to a square is atomic ifgetTransactionDepth()
returns 0, otherwise it is transactional. The model then notifies the registered listeners of the changes.- Parameters:
mapSquare
- the map square that has changed
-
beginGameObjectChange
void beginGameObjectChange(@NotNull G gameObject)
Method to notify the model that a game object is about to change.- Parameters:
gameObject
- the game object that is about to change
-
endGameObjectChange
void endGameObjectChange(@NotNull G gameObject)
Method to notify the model that a game object was changed. A change to a game object is atomic ifgetTransactionDepth()
returns 0, otherwise it is transactional. The model then notifies the registered listeners of the changes.- Parameters:
gameObject
- the game object that has changed
-
transientGameObjectChange
void transientGameObjectChange(@NotNull G gameObject)
Method to notify the model that a game object was changed but need not be restored by undo/redo. A change to a game object is atomic ifgetTransactionDepth()
returns 0, otherwise it is transactional. The model then notifies the registered listeners of the changes.- Parameters:
gameObject
- the game object that has changed
-
beginTransaction
void beginTransaction(@NotNull @NotNull java.lang.String name)
Starts a new transaction. Transactions may be nested. Transactions serve the purpose of firing events to the views when more changes are known to come before the view is really required to update. Each invocation of this function requires its own invocation ofendTransaction()
.A transaction has a name. The name of the outermost transaction is used as a String presented to the user for undoing the operation enclosed by that transaction.
Beginning a nested transaction is a cheap operation.
- Parameters:
name
- the name of the transaction- See Also:
endTransaction()
,endTransaction(boolean)
,endAllTransactions()
,getTransactionDepth()
,isAnyTransactionActive()
-
endTransaction
void endTransaction()
End a transaction. Invoking this method will reduce the transaction depth by only 1.Ending a nested operation is a cheap operation. Ending a transaction without changes also is a cheap operation.
If the last transaction is ended, the changes are committed.
Same as
endTransaction(false)
.
-
endTransaction
void endTransaction(boolean fireEvent)
End a transaction. Invoking this method will reduce the transaction depth by only 1.Ending a nested operation is a cheap operation. Ending a transaction without changes also is a cheap operation.
If the last transaction is ended, the changes are committed.
An example where setting
fireEvent
totrue
is useful even though the outermost transaction is not ended is when during painting the UI should be updated though painting is not finished.- Parameters:
fireEvent
-true
if an event should be fired even in case this doesn't end the outermost transaction.- See Also:
beginTransaction(String)
,endTransaction()
,endAllTransactions()
,getTransactionDepth()
,isAnyTransactionActive()
- Note:
- If the outermost transaction is ended,
fireEvent
is ignored and the event is always fired., An event is never fired when there were no changes, no matter whether the outermost transaction is ended orfireEvent
is set totrue
., If the event is fired, the internal change list is not cleared.
-
endAllTransactions
void endAllTransactions()
Ends all transaction. Invoking this method will reduce set the transaction depth to 0. You shouldn't invoke this method regularly. It is meant as a fallback in high level methods / exception handlers to prevent errors from causing unclosed transactions.
-
getTransactionDepth
int getTransactionDepth()
Get the transaction depth, which is the number ofbeginTransaction(String)
invocations without matchingendTransaction()
invocations. A transaction depth of 0 means there is no ongoing transaction.- Returns:
- transaction depth
- See Also:
beginTransaction(String)
,endTransaction()
,endTransaction(boolean)
,endAllTransactions()
,isAnyTransactionActive()
-
isAnyTransactionActive
boolean isAnyTransactionActive()
Returns whether a transaction is currently active. This method will returntrue
if and only ifgetTransactionDepth()
returns a value greater than zero.- Returns:
true
if there's a transaction going on, otherwisefalse
.- See Also:
beginTransaction(String)
,endTransaction()
,endTransaction(boolean)
,endAllTransactions()
,getTransactionDepth()
-
getMapSquare
@NotNull @NotNull MapSquare<G,A,R> getMapSquare(@NotNull @NotNull java.awt.Point pos)
Get the square at a specified location.- Parameters:
pos
- location to get square at- Returns:
- square at
p
- Throws:
java.lang.IndexOutOfBoundsException
- in case p specifies a location that's not valid within this map model
-
addObjectListToMap
void addObjectListToMap(@NotNull @NotNull java.lang.Iterable<G> objects)
Adds a list ofGameObjects
to this map.- Parameters:
objects
- the game objects to add
-
addGameObjectToMap
void addGameObjectToMap(@NotNull G gameObject, @NotNull @NotNull java.awt.Point pos, @NotNull @NotNull InsertionMode<G,A,R> insertionMode)
Add a gameObject to the map. Including multi square objects. This function allows to insert any given GameObject. Make sure that the givengameObject
is a new and unlinked object.- Parameters:
gameObject
- The new GameObject with set destination coordinates to be linked onto the map.pos
- the insert locationinsertionMode
- the insertion mode to use
-
moveEnv
void moveEnv(@NotNull G gameObject, @NotNull @NotNull java.awt.Point pos, @NotNull G nextGameObject)
Moves aGameObject
to its environment.- Parameters:
gameObject
- the game object to movepos
- the insertion positionnextGameObject
- the next game object
-
moveInv
void moveInv(@NotNull G gameObject, @NotNull @NotNull GameObject<G,A,R> prevGameObject)
Moves aGameObject
to the inventory of another game object.- Parameters:
gameObject
- the game object to moveprevGameObject
- the previous game object
-
insertBaseObject
@Nullable G insertBaseObject(@NotNull @NotNull BaseObject<G,A,R,?> baseObject, @NotNull @NotNull java.awt.Point pos, boolean allowMany, boolean join, @NotNull @NotNull InsertionMode<G,A,R> insertionMode)
Inserts aBaseObject
to a map. Archetypes are instantiated, game objects are cloned. The direction of the inserted game object is set to the direction of the archetype chooser. This function allows multi-square game objects.- Parameters:
baseObject
- the base objectpos
- the insert-location on this mapallowMany
- whether duplicates are allowedjoin
- whether to auto-join the inserted game objectinsertionMode
- the insertion mode to use- Returns:
- the inserted game object or
null
if nothing was inserted
-
insertArchToMap
@Nullable G insertArchToMap(@NotNull @NotNull BaseObject<G,A,R,?> templateBaseObject, @Nullable G nextGameObject, @NotNull @NotNull java.awt.Point pos, boolean join)
Insert a game object to the map at a specified position. This function allows either to choose from the archetypes or to insert a copy from an existing game object. It also works for container-inventory.- Parameters:
templateBaseObject
- a clone copy of this game object gets inserted to the map; it can be an archetype of a game objectnextGameObject
- the new game object gets inserted before this; ifnull
, the game object gets inserted at bottompos
- the map position to insert the new game objectjoin
- if set, auto-joining is supported- Returns:
- the inserted game object, or
null
if an error occurred
-
removeGameObject
void removeGameObject(@NotNull G gameObject, boolean join)
Delete an existingGameObject
from the map.- Parameters:
gameObject
- the game object to removejoin
- if set, auto-joining is supported
-
isMultiArchFittingToMap
boolean isMultiArchFittingToMap(@NotNull @NotNull Archetype<G,A,R> archetype, @NotNull @NotNull java.awt.Point pos, boolean allowDouble)
Checks whether an GameObject (multi-arch) would still fit on this map.- Parameters:
archetype
- the archetype to checkpos
- position of multi-square headallowDouble
- whether overlapping multi-square arches should be allowed (check is done using the archetype name)- Returns:
- whether the multi-arch would still fit on this map
- Return Value:
true
if the multi-square archetype would still fit on this map,false
otherwise
-
setErrors
void setErrors(@NotNull @NotNull ErrorCollector<G,A,R> errors)
Sets the errors in this map.- Parameters:
errors
- the errors
-
getErrors
@NotNull @NotNull ErrorCollector<G,A,R> getErrors()
Gets the errors in this map.- Returns:
- the errors
-
isAreaEmpty
boolean isAreaEmpty(int left, int top, int width, int height)
Checks whether an area of a map is completely empty.- Parameters:
left
- the left border of the areatop
- the top border of the areawidth
- the with of the areaheight
- the height of the area- Returns:
- whether the area is completely empty
-
addActiveEditType
void addActiveEditType(int editType)
Add edit type to the bitmask of active types. If this is a new type, it gets calculated for every arch on the map. Once it is calculated, we save that state in 'activeEditType' so we don't need to do it again.- Parameters:
editType
- new edit type
-
setMapFile
void setMapFile(@Nullable @Nullable MapFile mapFile)
Sets the map file.- Parameters:
mapFile
- the map file ornull
if the map has not yet been saved
-
getMapFile
@Nullable @Nullable MapFile getMapFile()
Returns the map file.- Returns:
- the map file or
null
if the map has not yet been saved
-
getMapFile
@NotNull @NotNull MapFile getMapFile(@NotNull @NotNull MapPath mapPath) throws SameMapException, UnsavedMapException
Returns the map file for a map that can be reached by following aMapPath
from this map.- Parameters:
mapPath
- the map path to follow- Returns:
- the map file
- Throws:
SameMapException
- of the destination map file is the same as this map fileUnsavedMapException
- if this map is not saved and therefore its map file is unknown
-
getAllGameObjects
@NotNull @NotNull java.util.List<G> getAllGameObjects()
Returns all game objects. Only top-level head parts are returned; tail parts are ignored as are objects in inventories.- Returns:
- all game objects
-
isModified
boolean isModified()
Return whether the map has been modified from the on-disk state.- Returns:
true
if the map has been modified from the on-disk state
-
resetModified
void resetModified()
Resets the modified flag to false.
-
facesReloaded
void facesReloaded()
Will be called whenever the archetype faces have been reloaded.
-
nextPoint
void nextPoint(java.awt.Point point, int direction)
Moves the given point forward or backward one map square.- Parameters:
point
- the point to start with and modifydirection
- the direction (-1
or+1
)
-
-