mirror of
https://github.com/guilhermewerner/site-pi
synced 2025-06-16 22:04:22 +00:00
385 lines
18 KiB
Java
Vendored
385 lines
18 KiB
Java
Vendored
|
|
package com.mycompany.mavenproject1;
|
|
|
|
import cz.cuni.amis.pogamut.base.communication.worldview.IWorldView;
|
|
import cz.cuni.amis.pogamut.base.communication.worldview.event.IWorldEvent;
|
|
import cz.cuni.amis.pogamut.base.communication.worldview.event.IWorldEventListener;
|
|
import cz.cuni.amis.pogamut.base.communication.worldview.listener.annotation.AnnotationListenerRegistrator;
|
|
import cz.cuni.amis.pogamut.base.communication.worldview.listener.annotation.EventListener;
|
|
import cz.cuni.amis.pogamut.base.communication.worldview.listener.annotation.ObjectClassEventListener;
|
|
import cz.cuni.amis.pogamut.base.communication.worldview.listener.annotation.ObjectClassListener;
|
|
import cz.cuni.amis.pogamut.base.communication.worldview.listener.annotation.ObjectEventListener;
|
|
import cz.cuni.amis.pogamut.base.communication.worldview.listener.annotation.ObjectListener;
|
|
import cz.cuni.amis.pogamut.base.communication.worldview.object.IWorldObject;
|
|
import cz.cuni.amis.pogamut.base.communication.worldview.object.IWorldObjectEvent;
|
|
import cz.cuni.amis.pogamut.base.communication.worldview.object.event.WorldObjectDestroyedEvent;
|
|
import cz.cuni.amis.pogamut.base.communication.worldview.object.event.WorldObjectFirstEncounteredEvent;
|
|
import cz.cuni.amis.pogamut.base.communication.worldview.object.event.WorldObjectUpdatedEvent;
|
|
import cz.cuni.amis.pogamut.base.utils.guice.AgentScoped;
|
|
import cz.cuni.amis.pogamut.base.utils.math.DistanceUtils;
|
|
import cz.cuni.amis.pogamut.base3d.worldview.object.Location;
|
|
import cz.cuni.amis.pogamut.base3d.worldview.object.event.WorldObjectAppearedEvent;
|
|
import cz.cuni.amis.pogamut.base3d.worldview.object.event.WorldObjectDisappearedEvent;
|
|
import cz.cuni.amis.pogamut.unreal.communication.messages.UnrealId;
|
|
import cz.cuni.amis.pogamut.ut2004.bot.impl.UT2004Bot;
|
|
import cz.cuni.amis.pogamut.ut2004.bot.impl.UT2004BotModuleController;
|
|
import cz.cuni.amis.pogamut.ut2004.communication.messages.gbcommands.Initialize;
|
|
import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.BotDamaged;
|
|
import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.BotKilled;
|
|
import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.Bumped;
|
|
import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.ConfigChange;
|
|
import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.EndMessage;
|
|
import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.GameInfo;
|
|
import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.InitedMessage;
|
|
import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.NavPoint;
|
|
import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.Player;
|
|
import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.Self;
|
|
import cz.cuni.amis.pogamut.ut2004.utils.UT2004BotRunner;
|
|
import cz.cuni.amis.pogamut.ut2004.utils.UnrealUtils;
|
|
import cz.cuni.amis.utils.exception.PogamutException;
|
|
|
|
/**
|
|
* Example of Simple Pogamut bot, that can listen to some events coming from
|
|
* the game engine and respond to them appropriately. The logic of the bot is
|
|
* completely event driven.
|
|
*
|
|
* <p><p>
|
|
* Notice that we're using a special annotations
|
|
* for various methods, i.e., for the method {@link ResponsiveBot${symbol_pound}bumped(Bumped)}
|
|
* the annotation {@link EventListener}, for the method {@link ResponsiveBot${symbol_pound}playerAppeared(WorldObjectAppearedEvent)}
|
|
* we're using {@link ObjectClassEventListener}, etc. You may perceive is as a bit magic as
|
|
* some methods are called as a response to some event, e.g., the method {@link ResponsiveBot${symbol_pound}bumped(Bumped)}
|
|
* is called whenever GameBots2004 sends a message {@link Bumped} to the bot.
|
|
*
|
|
* <p><p>
|
|
* How is this possible?
|
|
*
|
|
* <p><p>
|
|
* Well, the {@link UT2004BotModuleController}
|
|
* is using {@link AnnotationListenerRegistrator} that introspects (via Java
|
|
* Reflection API) the methods declared by the {@link ResponsiveBot} looking for
|
|
* annotations: {@link EventListener}, {@link ObjectClassEventListener},
|
|
* {@link ObjectClassListener}, {@link ObjectEventListener} or {@link ObjectListener}
|
|
* (I recommend you to read javadoc for all of them) automatically registering a
|
|
* listener inside {@link ResponsiveBot${symbol_pound}getWorldView()} using one of the
|
|
* "addListener" methods (e.g. {@link EventListener} annotated method is recalled
|
|
* from listener added via {@link IWorldView${symbol_pound}addEventListener(java.lang.Class, cz.cuni.amis.pogamut.base.communication.worldview.event.IWorldEventListener)}.
|
|
* It provides you with a simple way how to create methods that reacts on certain events inside the game.
|
|
*
|
|
* <p><p>
|
|
* WARNING: these annotations works only in THIS class only. If you want other of your classes to have the
|
|
* same option, you will have to instantiate {@link AnnotationListenerRegistrator} for yourself
|
|
* within that class.
|
|
*
|
|
* <p><p>
|
|
* We advise you to read through all comments carefully and try to understand
|
|
* when {@link EventListener} suffices and when you need to use one
|
|
* of {@link ObjectClassEventListener} /
|
|
* {@link ObjectClassListener} / {@link ObjectEventListener} / {@link ObjectListener}s.
|
|
*
|
|
* <p><p>
|
|
* The trick is that some messages from GB2004 are {@link IWorldEvent}s only and some of them are {@link IWorldObject}s as well.
|
|
* For listening {@link IWorldEvent}s only you must use {@link EventListener}, for listening to object updates,
|
|
* you must use one of {@link ObjectClassEventListener} / {@link ObjectClassListener} / {@link ObjectEventListener} / {@link ObjectListener}s.
|
|
*
|
|
* <p><p>
|
|
* We recommend you to run the bot on DM-TrainingDay map.
|
|
*
|
|
* <p><p>
|
|
* Start the bot and run to it. Note that whenever the bot sees you (you enter bot's field of view}
|
|
* {@link ResponsiveBot${symbol_pound}playerAppeared(cz.cuni.amis.pogamut.base3d.worldview.object.event.WorldObjectAppearedEvent)} will be triggered
|
|
* and the bot will greet you.
|
|
*
|
|
* <p><p>
|
|
* Then try to approach very close to the bot and it will ask you "what do you want". See {@link ResponsiveBot${symbol_pound}playerUpdated(cz.cuni.amis.pogamut.base.communication.worldview.object.event.WorldObjectUpdatedEvent) }
|
|
* event listener method.
|
|
*
|
|
* <p><p>
|
|
* Check out comments inside {@link ResponsiveBot${symbol_pound}gb2004BatchEnd(cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.EndMessage)} message.
|
|
*
|
|
* @author Rudolf Kadlec aka ik
|
|
* @author Jakub Gemrot aka Jimmy
|
|
*/
|
|
@AgentScoped
|
|
public class ResponsiveBot extends UT2004BotModuleController {
|
|
|
|
/**
|
|
* Listener called when someone/something bumps into the bot. The bot
|
|
* responds by moving in the opposite direction than the bump come from.
|
|
*
|
|
* <p><p>
|
|
* We're using {@link EventListener} here that is registered by the {@link AnnotationListenerRegistrator}
|
|
* to listen for {@link Bumped} events.
|
|
*
|
|
* <p><p>
|
|
* Notice that {@link Bumped} is {@link IWorldEvent} only, it's not {@link IWorldObject},
|
|
* thus we're using {@link EventListener}.
|
|
*/
|
|
@EventListener(eventClass = Bumped.class)
|
|
protected void bumped(Bumped event) {
|
|
// schema of the vector computations
|
|
//
|
|
// e<->a<------>t
|
|
// | | v |
|
|
// | | target - bot will be heading there
|
|
// | getLocation()
|
|
// event.getLocation()
|
|
|
|
Location v = event.getLocation().sub(bot.getLocation()).scale(5);
|
|
Location target = bot.getLocation().sub(v);
|
|
|
|
// make the bot to go to the computed location while facing the bump source
|
|
move.strafeTo(target, event.getLocation());
|
|
}
|
|
|
|
/**
|
|
* Listener called when a player appears.
|
|
*
|
|
* <p><p>
|
|
* We're using {@link ObjectClassEventListener} here that is registered by the {@link AnnotationListenerRegistrator} to
|
|
* listen on all {@link WorldObjectAppearedEvent} that happens on any object
|
|
* of the class {@link Player}.
|
|
*
|
|
* <p><p>
|
|
* I.e., whenever the GameBots2004 sends an
|
|
* update about arbitrary {@link Player} object in the game notifying us that the
|
|
* player has become visible (it's {@link Player${symbol_pound}isVisible()} is switched to
|
|
* true and the {@link WorldObjectAppearedEvent} is generated), this method
|
|
* is called.
|
|
*
|
|
* <p><p>
|
|
* Notice that {@link Player} implements {@link IWorldObject} thus you CANNOT use
|
|
* {@link EventListener} to catch events that updates {@link Player} objects.
|
|
*/
|
|
@ObjectClassEventListener(eventClass = WorldObjectAppearedEvent.class, objectClass = Player.class)
|
|
protected void playerAppeared(WorldObjectAppearedEvent<Player> event) {
|
|
// greet player when he appears
|
|
body.getCommunication().sendGlobalTextMessage("Hello " + event.getObject().getName() + "!");
|
|
}
|
|
/**
|
|
* Flag indicating whether the player was also close to the bot last time it
|
|
* was updated.
|
|
*/
|
|
protected boolean wasCloseBefore = false;
|
|
|
|
/**
|
|
* Listener called each time a player is updated.
|
|
*
|
|
* <p><p>
|
|
* Again, we're using {@link ObjectClassEventListener}
|
|
* that is registered by the {@link AnnotationListenerRegistrator} to listen
|
|
* on all {@link WorldObjectUpdatedEvent} that happens on any object of the
|
|
* class {@link Player}.
|
|
*
|
|
* <p><p>
|
|
* I.e., whenever the GameBots2004 sends an update
|
|
* about arbitrary {@link Player} in the game notifying us that some
|
|
* information about the player has changed (the {@link WorldObjectUpdatedEvent}
|
|
* is generated), this method is called.
|
|
*
|
|
* <p><p>
|
|
* Again, {@link Player} implements {@link IWorldObject}, thus you CANNOT use
|
|
* {@link EventListener} annotation to check for events regarding {@link Player}
|
|
* objects.
|
|
*/
|
|
@ObjectClassEventListener(eventClass = WorldObjectUpdatedEvent.class, objectClass = Player.class)
|
|
protected void playerUpdated(WorldObjectUpdatedEvent<Player> event) {
|
|
// Check whether the player is closer than 5 bot diameters.
|
|
// Notice the use of the UnrealUtils class.
|
|
// It contains many auxiliary constants and methods.
|
|
Player player = event.getObject();
|
|
// First player objects are received in HandShake - at that time we don't have Self message yet or players location!!
|
|
if (player.getLocation() == null || info.getLocation() == null) {
|
|
return;
|
|
}
|
|
if (player.getLocation().getDistance(info.getLocation()) < (UnrealUtils.CHARACTER_COLLISION_RADIUS * 10)) {
|
|
// If the player wasn't close enough the last time this listener was called,
|
|
// then ask him what does he want.
|
|
if (!wasCloseBefore) {
|
|
body.getCommunication().sendGlobalTextMessage("What do you want " + player.getName() + "?");
|
|
// Set proximity flag to true.
|
|
wasCloseBefore = true;
|
|
}
|
|
} else {
|
|
// Otherwise set the proximity flag to false.
|
|
wasCloseBefore = false;
|
|
}
|
|
}
|
|
/**
|
|
* Listener that is manually created and manually hooked to the {@link ResponsiveBot${symbol_pound}getWorldView()}
|
|
* via {@link IWorldView${symbol_pound}addEventListener(Class, IWorldEventListener)}
|
|
* method inside {@link ResponsiveBot${symbol_pound}prepareBot(UT2004Bot)}.
|
|
*
|
|
* <p><p>
|
|
* Note, that this is old/manual way how to add listeners on various events that are rised
|
|
* within the {@link IWorldView} (obtainable from {@link UT2004Bot${symbol_pound}getWorldView()} via
|
|
* <code>bot.getWorldView()</code> or simply accessing {@link UT2004BotModuleController${symbol_pound}world} field).
|
|
*
|
|
* <p><p>
|
|
* Such event listener MUST BE registered via some method of {@link IWorldView} offers.
|
|
* This particular listener is registered inside {@link ResponsiveBot${symbol_pound}prepareBot(cz.cuni.amis.pogamut.ut2004.bot.impl.UT2004Bot)}.
|
|
* Note that you can add/remove any listener during runtime.
|
|
*/
|
|
IWorldEventListener<BotDamaged> botDamagedListener = new IWorldEventListener<BotDamaged>() {
|
|
|
|
@Override
|
|
public void notify(BotDamaged event) {
|
|
// the bot was injured - let's move around the level and hope that we will find a health pack
|
|
// note that we have to acquire "SECOND" nearest navpoint, as the first one is the navpoint we're standing at
|
|
NavPoint secondNav = DistanceUtils.getSecondNearest(getWorldView().getAll(NavPoint.class).values(), info.getLocation());
|
|
// always check even for improbable conditions
|
|
if (secondNav == null) {
|
|
// try to locate some navpoint
|
|
move.turnVertical(30);
|
|
} else {
|
|
// move to it
|
|
move.moveTo(secondNav);
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Example usage of {@link ObjectListener} that will listen on every change
|
|
* / event that will be raised on the concrete {@link IWorldObject}, in this
|
|
* case on the {@link GameInfo}.
|
|
*
|
|
* <p><p>
|
|
* Notice that we have to specify which ID
|
|
* class the world object is using and have explicit representation of it's
|
|
* id - note that this is totally unsuitable for any dynamic IDs, such as
|
|
* NavPoint ids, etc... you will probably never use this annotation.
|
|
*
|
|
* <p><p>
|
|
* See implementations of {@link IWorldObjectEvent}, which are
|
|
* {@link WorldObjectFirstEncounteredEvent}, {@link WorldObjectAppearedEvent},
|
|
* {@link WorldObjectUpdatedEvent}, {@link WorldObjectDisappearedEvent}
|
|
* and {@link WorldObjectDestroyedEvent}. All such events may be possibly
|
|
* caught by this {@link ObjectListener} annotated method.
|
|
*
|
|
* @param info
|
|
*/
|
|
@ObjectListener(idClass = UnrealId.class, objectId = "GameInfoId")
|
|
public void gameInfo1(IWorldObjectEvent<GameInfo> gameInfoEvent) {
|
|
log.warning("GAME INFO EVENT =1=: " + gameInfoEvent);
|
|
}
|
|
|
|
/**
|
|
* Example usage of {@link ObjectEventListener} that will listen on SPECIFIC
|
|
* event that is raised on the concrete {@link IWorldObject}. As is the case
|
|
* of {@link ResponsiveBot${symbol_pound}gameInfo1(IWorldObjectEvent)}, you will probably
|
|
* never use this.
|
|
*
|
|
* @param gameInfoEvent
|
|
*/
|
|
@ObjectEventListener(idClass = UnrealId.class, objectId = "GameInfoId", eventClass = WorldObjectUpdatedEvent.class)
|
|
public void gameInfo2(WorldObjectUpdatedEvent<GameInfo> gameInfoEvent) {
|
|
log.warning("GAME INFO EVENT =2=: " + gameInfoEvent);
|
|
}
|
|
|
|
/**
|
|
* Example usage of {@link ObjectClassListener} notice the difference
|
|
* between this listener and {@link ObjectClassEventListener} that is used
|
|
* on {@link ResponsiveBot${symbol_pound}playerAppeared(WorldObjectAppearedEvent)}.
|
|
*
|
|
* <p><p>
|
|
* This method will receive ALL events that are raised on any {@link Player}
|
|
* object whereas {@link ResponsiveBot${symbol_pound}playerAppeared(WorldObjectAppearedEvent)}
|
|
* will receive only {@link WorldObjectAppearedEvent}.
|
|
*
|
|
* <p><p>
|
|
* See implementations of {@link IWorldObjectEvent}, which are
|
|
* {@link WorldObjectFirstEncounteredEvent}, {@link WorldObjectAppearedEvent},
|
|
* {@link WorldObjectUpdatedEvent}, {@link WorldObjectDisappearedEvent}
|
|
* and {@link WorldObjectDestroyedEvent}. All such events may be possibly
|
|
* caught by this {@link ObjectListener} annotated method.
|
|
*
|
|
* @param playerEvent
|
|
*/
|
|
@ObjectClassListener(objectClass = Player.class)
|
|
public void playerEvent(IWorldObjectEvent<Player> playerEvent) {
|
|
log.warning("PLAYER EVENT: " + playerEvent);
|
|
}
|
|
|
|
/**
|
|
* If you uncomment {@link EventListener} annotation below this comment, this message
|
|
* will be triggered every time the GB2004 sends EndMessage to you. It will (more-less)
|
|
* act the same way as {@link ResponsiveBot${symbol_pound}logic()} method.
|
|
* @param event
|
|
*/
|
|
//@EventListener(eventClass=EndMessage.class)
|
|
public void gb2004BatchEnd(EndMessage event) {
|
|
log.info("EndMessage received!");
|
|
}
|
|
|
|
/**
|
|
* Initialize all necessary variables here, before the bot actually receives
|
|
* anything from the environment + hook up your custom listener.
|
|
*/
|
|
@Override
|
|
public void prepareBot(UT2004Bot bot) {
|
|
// register the botDamagedListener that we have previously created
|
|
getWorldView().addEventListener(BotDamaged.class, botDamagedListener);
|
|
}
|
|
|
|
/**
|
|
* Here we can modify initialize command for our bot if we want to.
|
|
*
|
|
* @return
|
|
*/
|
|
@Override
|
|
public Initialize getInitializeCommand() {
|
|
return new Initialize();
|
|
}
|
|
|
|
/**
|
|
* The bot is initialized in the environment - a physical representation of
|
|
* the bot is present in the game.
|
|
*
|
|
* @param config information about configuration
|
|
* @param init information about configuration
|
|
*/
|
|
@Override
|
|
public void botFirstSpawn(GameInfo gameInfo, ConfigChange config, InitedMessage init, Self self) {
|
|
// notify the world (i.e., send message to UT2004) that the bot is up and running
|
|
body.getCommunication().sendGlobalTextMessage("I am alive!");
|
|
}
|
|
|
|
/**
|
|
* This method is called only once right before actual logic() method is
|
|
* called for the first time. Similar to {@link ResponsiveBot${symbol_pound}botFirstSpawn(cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.GameInfo, cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.ConfigChange, cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.InitedMessage, cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.Self)}.
|
|
*/
|
|
@Override
|
|
public void beforeFirstLogic() {
|
|
}
|
|
|
|
/**
|
|
* Main method that controls the bot - makes decisions what to do next.
|
|
* <p><p> Notice that the method is empty as this bot is completely
|
|
* event-driven.
|
|
*/
|
|
@Override
|
|
public void logic() throws PogamutException {
|
|
}
|
|
|
|
/**
|
|
* Called each time our bot die. Good for reseting all bot state dependent
|
|
* variables.
|
|
*
|
|
* @param event
|
|
*/
|
|
@Override
|
|
public void botKilled(BotKilled event) {
|
|
}
|
|
|
|
/**
|
|
* This method is called when the bot is started either from IDE or from
|
|
* command line.
|
|
*
|
|
* @param args
|
|
*/
|
|
public static void main(String args[]) throws PogamutException {
|
|
// wrapped logic for bots executions, suitable to run single bot in single JVM
|
|
new UT2004BotRunner(ResponsiveBot.class, "ResponsiveBot").setMain(true).startAgent();
|
|
}
|
|
}
|