Changes in Q2Java 0.9.5

Three big changes this time: the grappling hook code has been split from CTF, the code responsible for changing levels has been split from BaseQ2, and the code responsible for generating the DOM documents describing a level has been generalized and made more flexible.

The GrapplingHook code still resides in the q2java.ctf package, but is not tied directly to the CTFPlayer class anymore. A new gamelet named q2java.ctf.GrapplingHook can stick a grappling hook in the inventory of any instance or q2java.baseq2.Player - which means you can use the GH in plain DM, Paranoia, BountyHunters, and hopefully in any future Q2Java game.

The basic level changing code, which watches the timelimit and fraglimit, initiates intermission, and chooses which map comes next has been placed in a new gamelet named q2java.baseq2.LevelChanger. This gamelet can easily be extended to use some other method of choosing maps or deciding when to change. However, if this gamelet or something similar to it isn't loaded, the server will never change maps.

The Game class now creates a barebones DOM document when a level first starts, and fires off a GameStatusEvent.GAME_BUILD_DOCUMENT event to give interested objects (such as barryp.map.XMLMaps gamelets) a chance to place map info into the document. It then checks to see if the gamelets have supplied any entity info, and if they either haven't at all or have included the <include-default-entities/> tag, the Game will cause the string passed up from the .bsp file by the Engine to be parsed so that default entity info is included in the document before firing GameStatusEvent.GAME_PRESPAWN. This new scheme makes it easy for multiple sources to contribute to the initial level document.

Changes in Java Classes
q2java.baseq2.BaseQ2
Removed Barry | Everything related to changing levels - from watching the fraglimit and timelimit to deciding what the next map will be. This has all been split off into a new gamelet q2java.baseq2.LevelChanger. If that gamelet or one similar to it isn't loaded, the map will never change now.
q2java.baseq2.GenericWeapon
Added Barry | getOwner() method - to complement setOwner()
q2java.baseq2.LevelChanger
Added Barry | New gamelet responsible for deciding when to change levels, initiating the intermission mode, and choosing the next map. Can easily be extended or replaced with other gamelets that choose maps in a different way.
q2java.baseq2.Player
Change Barry | Class now implements GameStatusListener so it can listen for notifications of when to begin intermission.
Change Barry | The two variations of addWeapon() are now public (was needed to support the new GrapplingHook gamelet).
Added Barry | getIntermissionSpot() for choosing where a player should be placed during intermission.
Change CheezHankrn | playerThink() now avoids calling fWeapon.weaponThink() if fWeapon is null - in preparation for future code that might have players wielding no weapons at some points. More work needs to be done though, since there's no real easy way to put the player in a no-weapon state - the game currently assumes you at least have a handblaster.
Change Barry | print() method updated to pay better attention to the destination field of a PrintEvent, and display messages on the new PRINT_TALK_PRIVATE channel slightly differently than plain PRINT_TALK messages.
Change Barry | spawn() now fires a PlayerStateEvent.STATE_SPAWNED event to let interested objects know the player has spawned (the GrapplingHook gamelet is interested in this so it can slip a grappling hook weapon into the player's inventory)
Change Barry | startIntermission() now calls getIntermissionSpot() to find an intermission spot - rather than being passed that info as a parameter. This means that different players may now see different intermission spots (unlike stock Q2), but that should just make life more interesting.
Change Barry | teleport() now fires a PlayerStateEvent.STATE_TELEPORTED event to let interested objects know the Player has made a -drastic- change in position. (The grappling hook is interested in this - since it needs to reset if a player teleports).
q2java.baseq2.event.PlayerStateEvent
Added Barry | STATE_TELEPORTED constant for events signalling that the player has stepped through a teleporter.
Removed Barry | STATE_SUSPENDEDSTOP constant wasn't being used, and had the same value as STATE_INVALID.
q2java.baseq2.spawn.item_breather
Change Barry | stateChanged() altered to only reset on death or disconnection, didn't want to reset when the player goes through a teleporter
q2java.baseq2.spawn.item_enviro
Change Barry | stateChanged() altered to only reset on death or disconnection, didn't want to reset when the player goes through a teleporter
q2java.baseq2.spawn.item_health_mega
Change Barry | stateChanged() altered to only reset on death or disconnection, didn't want to reset when the player goes through a teleporter
q2java.baseq2.spawn.item_invulnerability
Change Barry | stateChanged() altered to only reset on death or disconnection, didn't want to reset when the player goes through a teleporter
q2java.baseq2.spawn.item_quad
Change Barry | stateChanged() altered to only reset on death or disconnection, didn't want to reset when the player goes through a teleporter
q2java.baseq2.spawn.worldspawn
Removed Barry | worldspawn no longer does anything with the "nextmap" spawn parameter. Anything interested in that info (such as the new LevelChanger gamelet) can examine the level document to find it.
q2java.core.DefaultLevelDocumentFactory
Removed Barry | Class removed, most code now moved to q2java.core.GameUtil
q2java.core.Game
Removed Barry | Everything related to the obsolete LevelDocumentFactory interface including setLevelDocumentFactory() and getLevelDocumentFactory().
Fix Barry | bprint() was causing double messages to be displayed on the console. Now it -only- fires off a PrintEvent, so it'll be up to some other code, probably some type of gamelet, to relay the message down to the console.
Added Barry | getCurrentMapName() for finding out the current map name (duh). This info -could- be gotten from the level document, but the level document could also be screwed with, so the Game class now keeps a copy of the info that can be relied on.
Added Barry | getOccupancySupport() to get access to the object the Game class uses to fire off OccupancyEvents.
Added Barry | startIntermission() to fire off a new GameStatusEvent to let objects know that they should go into intermission mode. The new LevelChanger gamelet calls this when it decides it's time to move on.
Change Barry | startLevel() reworked to allow multiple objects to contribute to building the DOM document describing the level, by creating a mostly-empty level document and firing off a GameStatusEvent.GAME_BUILD_DOCUMENT event when the level is first starting. startLevel() also fills in the document with the info passed up from the .bsp file by the Q2 engine if necessary.
q2java.core.Gamelet
Change Barry | grabPlayers() now fires off a OccupancyEvent.PLAYER_CLASSCHANGE to let interested objects know that player classes are changing. (Was necessary for the grappling hook gamelet, so it could register itself with the new player objects).
q2java.core.GameUtil
Added Barry | buildLevelDocument() can either build a mostly-empty level document that can be filled in by various sources, of a full one if a map entString is passed.
Added Barry | parseAngle3f() and parsePoint3f() moved back here from the obsolete q2java.core.DefaultLevelDocumentFactory
Added Barry | parseEntString() can parse a map's entString and insert the data into an existing DOM document. Used by buildLevelDocument() and Game.startLevel().
q2java.core.LevelDocumentFactory
Removed Barry | This interface is no longer needed due to the new level document building system.
q2java.core.XMLTools
Added Barry | copy() method can copy nodes from one document to another - handy for merging multiple map data sources together.
q2java.core.event.GameStatusEvent
Added Barry | GAME_INTERMISSION constant for events that signal when intermission should begin
Added Barry | GAME_BUILD_DOCUMENT constant for events that signal when objects should consider contributing info to the next level's document
Added Barry | getMapEntities() and getSpawnpoint() to find out about what was specified by the engine during the GAME_BUILD_DOCUMENT event.
Removed Barry | constructor taking (int, String) parameters wasn't being used.
q2java.core.event.PrintEvent
Added Barry | PRINT_TALK_PRIVATE constant added as a channel for private messages
Change Barry | getEvent() and releaseEvent() made public.
q2java.ctf.CTFPlayer
Change Barry | clearSettings() no longer worries about giving the player a grappling hook. This means that in order to have a GH in CTF, you must load the GrapplingHook gamelet in addition to the CTF gamelet.
Change Barry | playerThink() no longer is aware of the grappling hook - the hook itself is now smart enough to register as a PlayerMoveListener and do what it needs when a PlayerMoveEvent is fired from inside q2java.baseq2.Player.playerThink().
Removed Barry | teleport() method that overrode q2java.baseq2.Player.teleport() no longer needed since the grappling hook is smart enough to listen for PlayerStateEvent.PLAYER_TELEPORTED and reset itself as necessary.
q2java.ctf.GrappleWeapon
Added Barry | This class used to be named q2java.ctf.spawn.weapon_grapple, but since that's not an item that appears in maps, it seemed cleaner to move it outside the q2java.ctf.spawn package.
Added Barry | Objects of this class register as PlayerMoveListeners when the weapon is active, and playerMoved() is called so the hook gets a chance to pull the player along.
Added Barry | Objects of this class register as PlayerStateListeners so they can watch for the player teleporting and reset the weapon if that happens..
q2java.ctf.GrapplingHook
Added Barry | New gamelet that should add the grappling hook to q2java.baseq2.Player or any subclass.
q2java.ctf.spawn.weapon_grapple
Added Barry | This class was renamed to q2java.ctf.GrappleWeapon since that's not an item that appears in maps, and seemed cleaner to move it outside the q2java.ctf.spawn package.

Q2Java homepage