reversiplugin.java.svn-base
来自「开源项目openfire的完整源程序」· SVN-BASE 代码 · 共 296 行
SVN-BASE
296 行
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006 Jive Software. All rights reserved.
* This software is the proprietary information of Jive Software. Use is subject to license terms.
*/
package org.jivesoftware.game.reversi;
import org.jivesoftware.smack.provider.ProviderManager;
import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.filter.PacketTypeFilter;
import org.jivesoftware.smack.filter.PacketIDFilter;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.spark.plugin.Plugin;
import org.jivesoftware.spark.ui.ChatRoomListener;
import org.jivesoftware.spark.ui.ChatRoom;
import org.jivesoftware.spark.ui.ChatRoomListenerAdapter;
import org.jivesoftware.spark.ui.ChatRoomButton;
import org.jivesoftware.spark.ui.rooms.ChatRoomImpl;
import org.jivesoftware.spark.SparkManager;
import org.jivesoftware.spark.ChatManager;
import org.jivesoftware.spark.component.BackgroundPanel;
import javax.swing.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.*;
import java.util.Map;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Collections;
/**
* Reversi plugin. Reversi is a two-player, turn-based game. See {@link ReversiModel} for more details
* on how the game works.
*
* @author Matt Tucker
* @author Bill Lynch
*/
public class ReversiPlugin implements Plugin {
private ChatRoomListener chatRoomListener;
private PacketListener gameOfferListener;
private Map gameOffers;
private Map gameInvitations;
public void initialize() {
// Offers and invitations hold all pending game offers we've sent to other users or incoming
// invitations. The map key is always the opponent's JID. The map value is a transcript alert
// UI component.
gameOffers = Collections.synchronizedMap(new HashMap());
gameInvitations = Collections.synchronizedMap(new HashMap());
// Add Reversi item to chat toolbar.
addToolbarButton();
// Add Smack providers. The plugin uses custom XMPP extensions to communicate game offers
// and current game state. Adding the Smack providers lets us use the custom protocol.
ProviderManager.addIQProvider(GameOffer.ELEMENT_NAME, GameOffer.NAMESPACE, GameOffer.class);
ProviderManager.addExtensionProvider(GameMove.ELEMENT_NAME, GameMove.NAMESPACE, GameMove.class);
ProviderManager.addExtensionProvider(GameForfeit.ELEMENT_NAME, GameForfeit.NAMESPACE, GameForfeit.class);
// Add IQ listener to listen for incoming game invitations.
gameOfferListener = new PacketListener() {
public void processPacket(Packet packet) {
GameOffer invitation = (GameOffer)packet;
if (invitation.getType() == IQ.Type.GET) {
showInvitationAlert(invitation);
}
}
};
SparkManager.getConnection().addPacketListener(gameOfferListener, new PacketTypeFilter(GameOffer.class));
}
public void shutdown() {
// Remove Reversi button from chat toolbar.
removeToolbarButton();
// Remove IQ listener
SparkManager.getConnection().removePacketListener(gameOfferListener);
// See if there are any pending offers or invitations. If so, cancel them.
for (Iterator i=gameOffers.keySet().iterator(); i.hasNext(); ) {
String opponentJID = (String)i.next();
// TODO: cancel game offer.
}
for (Iterator i=gameInvitations.keySet().iterator(); i.hasNext(); ) {
String opponentJID = (String)i.next();
// TODO: reject game invitation.
}
gameOffers.clear();
gameInvitations.clear();
// Remove Smack providers.
ProviderManager.removeIQProvider(GameOffer.ELEMENT_NAME, GameOffer.NAMESPACE);
ProviderManager.removeExtensionProvider(GameMove.ELEMENT_NAME, GameMove.NAMESPACE);
ProviderManager.removeExtensionProvider(GameForfeit.ELEMENT_NAME, GameForfeit.NAMESPACE);
}
public boolean canShutDown() {
// The plugin is able to fully clean itself up, so return true.
return true;
}
public void uninstall() {
// Do nothing. Reversi has no permanent resources so shutdown can already do a full cleanup.
}
/**
* Display an alert that allows the user to accept or reject a game invitation.
*
* @param invitation the game invitation.
*/
private void showInvitationAlert(final GameOffer invitation) {
// Got an offer to start a new game. So, make sure that a chat is started with the other
// user and show an invite panel.
final ChatRoom room = SparkManager.getChatManager().getChatRoom(invitation.getFrom());
final JPanel inviteAlert = new JPanel();
inviteAlert.setLayout(new BorderLayout());
JPanel invitePanel = new JPanel() {
protected void paintComponent(Graphics g) {
ImageIcon imageIcon = new ImageIcon(getClass().getResource("images/reversi-icon.png"));
Image image = imageIcon.getImage();
g.drawImage(image, 0, 0, null);
}
};
invitePanel.setPreferredSize(new Dimension(24,24));
inviteAlert.add(invitePanel, BorderLayout.WEST);
JPanel content = new JPanel(new BorderLayout());
String opponentName = invitation.getFrom(); // TODO: convert to more readable name.
content.add(new JLabel(opponentName + " is requesting a Reversi game ..."), BorderLayout.CENTER);
JPanel buttonPanel = new JPanel();
// The accept button. When clicked, accept the game offer.
JButton acceptButton = new JButton("Accept");
acceptButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// Accept the game offer by sending a positive reply packet.
GameOffer reply = new GameOffer();
reply.setTo(invitation.getFrom());
reply.setPacketID(invitation.getPacketID());
reply.setType(IQ.Type.RESULT);
SparkManager.getConnection().sendPacket(reply);
// Hide the response panel. TODO: make this work.
room.getTranscriptWindow().remove(inviteAlert);
// Remove the invitation from the map.
gameInvitations.remove(invitation.getFrom());
// Show the game board.
showReversiBoard(invitation.getGameID(), room, !invitation.isStartingPlayer(), invitation.getFrom());
}
});
buttonPanel.add(acceptButton);
// The decline button. When clicked, reject the game offer.
JButton declineButton = new JButton("Decline");
declineButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// Reject the game offer by sending an error packet.
GameOffer reply = new GameOffer();
reply.setTo(invitation.getFrom());
reply.setPacketID(invitation.getPacketID());
reply.setType(IQ.Type.ERROR);
SparkManager.getConnection().sendPacket(reply);
// Hide the response panel. TODO: make this work.
room.getTranscriptWindow().remove(inviteAlert);
// Remove the invitation from the map.
gameInvitations.remove(invitation.getFrom());
}
});
buttonPanel.add(declineButton);
content.add(buttonPanel, BorderLayout.SOUTH);
inviteAlert.add(content, BorderLayout.CENTER);
// Add the invitation to the Map of invites. If there's a pending invite, remove it
// before adding the new one (possible if the opponent sends two invites in a row).
Object oldInvitation = gameInvitations.put(invitation.getFrom(), inviteAlert);
if (oldInvitation != null) {
// TODO: clean it up by removing it from the transcript window.
}
// Add the response panel to the transcript window.
room.getTranscriptWindow().addComponent(inviteAlert);
}
/**
* Adds the Reversi toolbar button.
*/
private void addToolbarButton() {
ChatManager manager = SparkManager.getChatManager();
chatRoomListener = new ChatRoomListenerAdapter() {
ImageIcon icon = new ImageIcon(getClass().getResource("images/reversi-icon.png"));
public void chatRoomOpened(final ChatRoom room) {
ChatRoomButton button = new ChatRoomButton("Reversi", icon);
room.getToolBar().addChatRoomButton(button);
// Add a button listener that sends out a game invite on a user click.
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// Show "requesting a game panel"
final JPanel request = new JPanel();
request.setLayout(new BorderLayout());
JPanel requestPanel = new JPanel() {
protected void paintComponent(Graphics g) {
g.drawImage(icon.getImage(), 0, 0, null);
}
};
requestPanel.setPreferredSize(new Dimension(24,24));
request.add(requestPanel, BorderLayout.WEST);
String opponentJID = ((ChatRoomImpl)room).getJID();
String opponentName = opponentJID; // TODO: convert to more readable name.
JPanel content = new JPanel(new BorderLayout());
content.add(new JLabel("Requesting a Reversi game with " + opponentName + ", please wait..."), BorderLayout.CENTER);
JPanel buttonPanel = new JPanel();
buttonPanel.add(new JButton("Cancel"), BorderLayout.SOUTH);
content.add(buttonPanel, BorderLayout.SOUTH);
request.add(content, BorderLayout.CENTER);
room.getTranscriptWindow().addComponent(request);
final GameOffer offer = new GameOffer();
offer.setTo(opponentJID);
// Add a listener for a reply to our offer.
SparkManager.getConnection().addPacketListener(new PacketListener() {
public void processPacket(Packet packet) {
GameOffer offerReply = ((GameOffer)packet);
if (offerReply.getType() == IQ.Type.RESULT) {
// Remove the offer panel
room.getTranscriptWindow().remove(request);
// Show game board (using original offer!).
showReversiBoard(offer.getGameID(), room, offer.isStartingPlayer(),
offerReply.getFrom());
}
else {
// TODO: show they declined
}
// TODO: Handle error case
}
}, new PacketIDFilter(offer.getPacketID()));
SparkManager.getConnection().sendPacket(offer);
}
});
}
public void chatRoomClosed(ChatRoom room) {
super.chatRoomClosed(room);
// TODO: if game is in progress, close it down. What we need is an API that lets us see
// TODO: if there's a transcript alert currently there.
}
};
manager.addChatRoomListener(chatRoomListener);
}
/**
* Displays the game board. This is called after an offer has been accepted or after accepting an
* invitation.
*
* @param gameID the game ID.
* @param room the chat room to display the game board in.
* @param startingPlayer true if this player is the starting player (black).
* @param opponentJID the opponent's JID.
*/
private void showReversiBoard(int gameID, ChatRoom room, boolean startingPlayer, String opponentJID) {
JSplitPane pane = room.getSplitPane();
pane.setResizeWeight(1.0);
BackgroundPanel reversiBackground = new BackgroundPanel();
reversiBackground.setLayout(new BorderLayout());
reversiBackground.setOpaque(false);
ReversiPanel reversi = new ReversiPanel(SparkManager.getConnection(), gameID,
startingPlayer, opponentJID);
reversiBackground.add(reversi, BorderLayout.CENTER);
pane.setRightComponent(reversiBackground);
reversi.setMinimumSize(new Dimension(ReversiPanel.TOTAL_WIDTH, ReversiPanel.TOTAL_HEIGHT));
}
/**
* Removes the Reversi toolbar button.
*/
private void removeToolbarButton() {
ChatManager manager = SparkManager.getChatManager();
manager.removeChatRoomListener(chatRoomListener);
// TODO: remove actual buttons from toolbar.
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?