/*
* Copyright (c) 2014 tabletoptool.com team.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Public License v3.0
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/gpl.html
*
* Contributors:
* rptools.com team - initial implementation
* tabletoptool.com team - further development
*/
package com.t3.networking;
import java.awt.EventQueue;
import java.awt.Point;
import java.awt.geom.Area;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import com.t3.MD5Key;
import com.t3.client.AppActions;
import com.t3.client.AppPreferences;
import com.t3.client.AppUtil;
import com.t3.client.ScreenPoint;
import com.t3.client.TabletopTool;
import com.t3.client.ui.T3Frame;
import com.t3.client.ui.tokenpanel.InitiativePanel;
import com.t3.client.ui.zone.FogUtil;
import com.t3.client.ui.zone.ZoneRenderer;
import com.t3.client.ui.zone.ZoneRendererFactory;
import com.t3.clientserver.handler.AbstractMethodHandler;
import com.t3.guid.GUID;
import com.t3.model.Asset;
import com.t3.model.AssetManager;
import com.t3.model.CellPoint;
import com.t3.model.ExposedAreaMetaData;
import com.t3.model.Label;
import com.t3.model.MacroButtonProperties;
import com.t3.model.Player;
import com.t3.model.Pointer;
import com.t3.model.Token;
import com.t3.model.Zone;
import com.t3.model.Zone.VisionType;
import com.t3.model.ZonePoint;
import com.t3.model.campaign.Campaign;
import com.t3.model.campaign.CampaignProperties;
import com.t3.model.chat.TextMessage;
import com.t3.model.drawing.Drawable;
import com.t3.model.drawing.DrawnElement;
import com.t3.model.drawing.Pen;
import com.t3.model.grid.Grid;
import com.t3.model.initiative.InitiativeList;
import com.t3.model.initiative.InitiativeValue;
import com.t3.model.initiative.InitiativeList.TokenInitiative;
import com.t3.transfer.AssetChunk;
import com.t3.transfer.AssetConsumer;
import com.t3.transfer.AssetHeader;
public class ClientMethodHandler extends AbstractMethodHandler<NetworkCommand> {
public ClientMethodHandler() {
}
@Override
public void handleMethod(final String id, final NetworkCommand method, final Object... parameters) {
// System.out.println("ClientMethodHandler#handleMethod: " + cmd.name());
// These commands are safe to do in the background, any events that cause model updates need
// to be on the EDT (See next section)
switch (method) {
case putAsset:
AssetManager.putAsset((Asset) parameters[0]);
TabletopTool.getFrame().getCurrentZoneRenderer().flushDrawableRenderer();
TabletopTool.getFrame().refresh();
return;
case removeAsset:
return;
case startAssetTransfer:
AssetHeader header = (AssetHeader) parameters[0];
TabletopTool.getAssetTransferManager().addConsumer(new AssetConsumer(AppUtil.getTmpDir(), header));
return;
case updateAssetTransfer:
AssetChunk chunk = (AssetChunk) parameters[0];
try {
TabletopTool.getAssetTransferManager().update(chunk);
} catch (IOException ioe) {
// TODO: do something intelligent like clear the transfer
// manager, and clear the "we're waiting for" flag so that it
// gets requested again
ioe.printStackTrace();
}
return;
}
// Model events need to update on the EDT
EventQueue.invokeLater(new Runnable() {
@Override
@SuppressWarnings("unchecked")
public void run() {
GUID zoneGUID;
Zone zone;
Set<GUID> selectedToks = null;
switch (method) {
case bootPlayer:
String playerName = (String) parameters[0];
if (TabletopTool.getPlayer().getName().equals(playerName)) {
ServerDisconnectHandler.disconnectExpected = true;
AppActions.disconnectFromServer();
TabletopTool.showInformation("You have been booted from the server.");
}
return;
case enforceZone:
zoneGUID = (GUID) parameters[0];
ZoneRenderer renderer = TabletopTool.getFrame().getZoneRenderer(zoneGUID);
if (renderer != null && renderer != TabletopTool.getFrame().getCurrentZoneRenderer() && (renderer.getZone().isVisible() || TabletopTool.getPlayer().isGM())) {
TabletopTool.getFrame().setCurrentZoneRenderer(renderer);
}
return;
case clearAllDrawings:
zoneGUID = (GUID) parameters[0];
Zone.Layer layer = (Zone.Layer) parameters[1];
zone = TabletopTool.getCampaign().getZone(zoneGUID);
zone.getDrawnElements(layer).clear();
TabletopTool.getFrame().refresh();
return;
case setZoneHasFoW:
zoneGUID = (GUID) parameters[0];
boolean hasFog = (Boolean) parameters[1];
zone = TabletopTool.getCampaign().getZone(zoneGUID);
zone.setHasFog(hasFog);
// In case we're looking at the zone
TabletopTool.getFrame().refresh();
return;
case exposeFoW:
zoneGUID = (GUID) parameters[0];
Area area = (Area) parameters[1];
if (parameters.length > 2) {
if (parameters[2] != null) {
selectedToks = (Set<GUID>) parameters[2];
}
}
zone = TabletopTool.getCampaign().getZone(zoneGUID);
zone.exposeArea(area, selectedToks);
TabletopTool.getFrame().refresh();
return;
case setFoW:
zoneGUID = (GUID) parameters[0];
area = (Area) parameters[1];
if (parameters.length > 2) {
if (parameters[2] != null) {
selectedToks = (Set<GUID>) parameters[2];
}
}
zone = TabletopTool.getCampaign().getZone(zoneGUID);
zone.setFogArea(area, selectedToks);
TabletopTool.getFrame().refresh();
return;
case hideFoW:
zoneGUID = (GUID) parameters[0];
area = (Area) parameters[1];
if (parameters.length > 2) {
if (parameters[2] != null) {
selectedToks = (Set<GUID>) parameters[2];
}
}
zone = TabletopTool.getCampaign().getZone(zoneGUID);
zone.hideArea(area, selectedToks);
TabletopTool.getFrame().refresh();
return;
case setCampaign:
Campaign campaign = (Campaign) parameters[0];
TabletopTool.setCampaign(campaign);
// Hide the "Connecting" overlay
TabletopTool.getFrame().hideGlassPane();
return;
case putZone:
zone = (Zone) parameters[0];
TabletopTool.getCampaign().putZone(zone);
// TODO: combine this with TabletopTool.addZone()
renderer = ZoneRendererFactory.newRenderer(zone);
TabletopTool.getFrame().addZoneRenderer(renderer);
if (TabletopTool.getFrame().getCurrentZoneRenderer() == null && zone.isVisible()) {
TabletopTool.getFrame().setCurrentZoneRenderer(renderer);
}
TabletopTool.getEventDispatcher().fireEvent(TabletopTool.ZoneEvent.Added, TabletopTool.getCampaign(), null, zone);
return;
case removeZone:
zoneGUID = (GUID) parameters[0];
TabletopTool.getCampaign().removeZone(zoneGUID);
TabletopTool.getFrame().removeZoneRenderer(TabletopTool.getFrame().getZoneRenderer(zoneGUID));
return;
case putToken:
zoneGUID = (GUID) parameters[0];
zone = TabletopTool.getCampaign().getZone(zoneGUID);
Token token = (Token) parameters[1];
zone.putToken(token);
TabletopTool.getFrame().refresh();
return;
case putLabel:
zoneGUID = (GUID) parameters[0];
zone = TabletopTool.getCampaign().getZone(zoneGUID);
Label label = (Label) parameters[1];
zone.putLabel(label);
TabletopTool.getFrame().refresh();
return;
case removeToken:
zoneGUID = (GUID) parameters[0];
zone = TabletopTool.getCampaign().getZone(zoneGUID);
GUID tokenGUID = (GUID) parameters[1];
zone.removeToken(tokenGUID);
TabletopTool.getFrame().refresh();
return;
case removeLabel:
zoneGUID = (GUID) parameters[0];
zone = TabletopTool.getCampaign().getZone(zoneGUID);
GUID labelGUID = (GUID) parameters[1];
zone.removeLabel(labelGUID);
TabletopTool.getFrame().refresh();
return;
case enforceZoneView:
zoneGUID = (GUID) parameters[0];
int x = (Integer) parameters[1];
int y = (Integer) parameters[2];
double scale = (Double) parameters[3];
int gmWidth = (Integer) parameters[4];
int gmHeight = (Integer) parameters[5];
renderer = TabletopTool.getFrame().getZoneRenderer(zoneGUID);
if (renderer == null) {
return;
}
if (AppPreferences.getFitGMView()) {
renderer.enforceView(x, y, scale, gmWidth, gmHeight);
} else {
renderer.setScale(scale);
renderer.centerOn(new ZonePoint(x, y));
}
return;
case draw:
zoneGUID = (GUID) parameters[0];
Pen pen = (Pen) parameters[1];
Drawable drawable = (Drawable) parameters[2];
zone = TabletopTool.getCampaign().getZone(zoneGUID);
zone.addDrawable(new DrawnElement(drawable, pen));
TabletopTool.getFrame().refresh();
return;
case undoDraw:
zoneGUID = (GUID) parameters[0];
GUID drawableId = (GUID) parameters[1];
zone = TabletopTool.getCampaign().getZone(zoneGUID);
if (zone == null) {
return;
}
zone.removeDrawable(drawableId);
if (TabletopTool.getFrame().getCurrentZoneRenderer().getZone().getId().equals(zoneGUID) && zoneGUID != null) {
TabletopTool.getFrame().refresh();
}
return;
case setZoneVisibility:
zoneGUID = (GUID) parameters[0];
boolean visible = (Boolean) parameters[1];
zone = TabletopTool.getCampaign().getZone(zoneGUID);
zone.setVisible(visible);
ZoneRenderer currentRenderer = TabletopTool.getFrame().getCurrentZoneRenderer();
if (!visible && !TabletopTool.getPlayer().isGM() && currentRenderer != null && currentRenderer.getZone().getId().equals(zoneGUID)) {
TabletopTool.getFrame().setCurrentZoneRenderer(null);
}
if (visible && currentRenderer == null) {
currentRenderer = TabletopTool.getFrame().getZoneRenderer(zoneGUID);
TabletopTool.getFrame().setCurrentZoneRenderer(currentRenderer);
}
TabletopTool.getFrame().refresh();
return;
case setZoneGridSize:
zoneGUID = (GUID) parameters[0];
int xOffset = ((Integer) parameters[1]).intValue();
int yOffset = ((Integer) parameters[2]).intValue();
int size = ((Integer) parameters[3]).intValue();
int color = ((Integer) parameters[4]).intValue();
zone = TabletopTool.getCampaign().getZone(zoneGUID);
zone.getGrid().setSize(size);
zone.getGrid().setOffset(xOffset, yOffset);
zone.setGridColor(color);
TabletopTool.getFrame().refresh();
return;
case playerConnected:
TabletopTool.addPlayer((Player) parameters[0]);
TabletopTool.getFrame().refresh();
return;
case playerDisconnected:
TabletopTool.removePlayer((Player) parameters[0]);
TabletopTool.getFrame().refresh();
return;
case message:
TextMessage message = (TextMessage) parameters[0];
TabletopTool.addServerMessage(message);
return;
case showPointer:
TabletopTool.getFrame().getPointerOverlay().addPointer((String) parameters[0], (Pointer) parameters[1]);
TabletopTool.getFrame().refresh();
return;
case hidePointer:
TabletopTool.getFrame().getPointerOverlay().removePointer((String) parameters[0]);
TabletopTool.getFrame().refresh();
return;
case startTokenMove:
String playerId = (String) parameters[0];
zoneGUID = (GUID) parameters[1];
GUID keyToken = (GUID) parameters[2];
Set<GUID> selectedSet = (Set<GUID>) parameters[3];
renderer = TabletopTool.getFrame().getZoneRenderer(zoneGUID);
renderer.addMoveSelectionSet(playerId, keyToken, selectedSet, true);
return;
case stopTokenMove:
zoneGUID = (GUID) parameters[0];
keyToken = (GUID) parameters[1];
renderer = TabletopTool.getFrame().getZoneRenderer(zoneGUID);
renderer.removeMoveSelectionSet(keyToken);
return;
case updateTokenMove:
zoneGUID = (GUID) parameters[0];
keyToken = (GUID) parameters[1];
x = ((Integer) parameters[2]).intValue();
y = ((Integer) parameters[3]).intValue();
renderer = TabletopTool.getFrame().getZoneRenderer(zoneGUID);
renderer.updateMoveSelectionSet(keyToken, new ZonePoint(x, y));
return;
case setTokenLocation:
// Only the table should process this
if (TabletopTool.getPlayer().getName().equalsIgnoreCase("Table")) {
// System.out.println("Inside ClientMethodHandler.handleMethod().setTokenLocation");
zoneGUID = (GUID) parameters[0];
keyToken = (GUID) parameters[1];
// This X,Y is the where the center of the token needs to be placed in
// relation to the screen. So 0,0 would be top left which means only 1/4
// of token would be drawn. 1024,768 would be lower right (on my table).
x = ((Integer) parameters[2]).intValue();
y = ((Integer) parameters[3]).intValue();
// Get the zone
zone = TabletopTool.getCampaign().getZone(zoneGUID);
// Get the token
token = zone.getToken(keyToken);
Grid grid = zone.getGrid();
// Convert the X/Y to the screen point
renderer = TabletopTool.getFrame().getZoneRenderer(zone);
CellPoint newPoint = renderer.getCellAt(new ScreenPoint(x, y));
ZonePoint zp2 = grid.convert(newPoint);
token.setX(zp2.x);
token.setY(zp2.y);
TabletopTool.serverCommand().putToken(zoneGUID, token);
}
return;
case toggleTokenMoveWaypoint:
zoneGUID = (GUID) parameters[0];
keyToken = (GUID) parameters[1];
ZonePoint zp = (ZonePoint) parameters[2];
renderer = TabletopTool.getFrame().getZoneRenderer(zoneGUID);
renderer.toggleMoveSelectionSetWaypoint(keyToken, zp);
return;
case setServerPolicy:
ServerPolicy policy = (ServerPolicy) parameters[0];
TabletopTool.setServerPolicy(policy);
return;
case addTopology:
zoneGUID = (GUID) parameters[0];
area = (Area) parameters[1];
zone = TabletopTool.getCampaign().getZone(zoneGUID);
zone.addTopology(area);
TabletopTool.getFrame().getZoneRenderer(zoneGUID).repaint();
return;
case removeTopology:
zoneGUID = (GUID) parameters[0];
area = (Area) parameters[1];
zone = TabletopTool.getCampaign().getZone(zoneGUID);
zone.removeTopology(area);
TabletopTool.getFrame().getZoneRenderer(zoneGUID).repaint();
return;
case renameZone:
zoneGUID = (GUID) parameters[0];
String name = (String) parameters[1];
zone = TabletopTool.getCampaign().getZone(zoneGUID);
if (zone != null) {
zone.setName(name);
}
return;
case updateCampaign:
CampaignProperties properties = (CampaignProperties) parameters[0];
TabletopTool.getCampaign().replaceCampaignProperties(properties);
T3Frame frame = TabletopTool.getFrame();
ZoneRenderer zr = frame.getCurrentZoneRenderer();
if (zr != null) {
zr.getZoneView().flush();
zr.repaint();
}
AssetManager.updateRepositoryList();
InitiativePanel ip = frame.getInitiativePanel();
ip.setOwnerPermissions(properties.isInitiativeOwnerPermissions());
ip.setMovementLock(properties.isInitiativeMovementLock());
TabletopTool.getFrame().getLookupTablePanel().updateView();
return;
case movePointer:
String player = (String) parameters[0];
x = (Integer) parameters[1];
y = (Integer) parameters[2];
Pointer pointer = TabletopTool.getFrame().getPointerOverlay().getPointer(player);
if (pointer == null) {
return;
}
pointer.setX(x);
pointer.setY(y);
TabletopTool.getFrame().refresh();
return;
case updateInitiative:
InitiativeList list = (InitiativeList) parameters[0];
Boolean ownerPermission = (Boolean) parameters[1];
if (list != null) {
zone = list.getZone();
if (zone == null)
return;
zone.setInitiativeList(list);
}
if (ownerPermission != null) {
TabletopTool.getFrame().getInitiativePanel().setOwnerPermissions(ownerPermission.booleanValue());
}
return;
case updateTokenInitiative:
zoneGUID = (GUID) parameters[0];
tokenGUID = (GUID) parameters[1];
zone = TabletopTool.getCampaign().getZone(zoneGUID);
list = zone.getInitiativeList();
TokenInitiative ti = list.getTokenInitiative((Integer) parameters[4]);
if (!ti.getId().equals(tokenGUID)) {
// Index doesn't point to same token, try to find it
token = zone.getToken(tokenGUID);
List<Integer> tokenIndex = list.indexOf(token);
// If token in list more than one time, punt
if (tokenIndex.size() != 1)
return;
ti = list.getTokenInitiative(tokenIndex.get(0));
} // endif
ti.update((Boolean) parameters[2], (InitiativeValue) parameters[3]);
return;
case setUseVision:
zoneGUID = (GUID) parameters[0];
VisionType visionType = (VisionType) parameters[1];
zone = TabletopTool.getCampaign().getZone(zoneGUID);
if (zone != null) {
zone.setVisionType(visionType);
if (TabletopTool.getFrame().getCurrentZoneRenderer() != null) {
TabletopTool.getFrame().getCurrentZoneRenderer().flushFog();
TabletopTool.getFrame().getCurrentZoneRenderer().getZoneView().flush();
}
TabletopTool.getFrame().refresh();
}
return;
case setBoard:
zoneGUID = (GUID) parameters[0];
zone = TabletopTool.getCampaign().getZone(zoneGUID);
Point boardXY = new Point((Integer) parameters[2], (Integer) parameters[3]);
zone.setBoard(boardXY, (MD5Key) parameters[1]);
return;
case updateCampaignMacros:
TabletopTool.getCampaign().setMacroButtonPropertiesArray(new ArrayList<MacroButtonProperties>((ArrayList<MacroButtonProperties>) parameters[0]));
TabletopTool.getFrame().getCampaignPanel().reset();
return;
// moved this down into the event queue section so that the threading works as expected
case setLiveTypingLabel:
if ((Boolean) parameters[1]) {
// add a typer
TabletopTool.getFrame().getChatNotificationTimers().setChatTyper(parameters[0].toString());
return;
} else {
// remove typer from list
TabletopTool.getFrame().getChatNotificationTimers().removeChatTyper(parameters[0].toString());
return;
}
case exposePCArea:
if (parameters[0] != null && parameters[0] instanceof GUID) {
ZoneRenderer currentRenderer1 = TabletopTool.getFrame().getZoneRenderer((GUID) parameters[0]);
FogUtil.exposePCArea(currentRenderer1);
}
return;
case enforceNotification:
Boolean enforce = (Boolean) parameters[0];
TabletopTool.getFrame().getCommandPanel().disableNotifyButton(enforce);
return;
case updateExposedAreaMeta:
zoneGUID = (GUID) parameters[0];
tokenGUID = (GUID) parameters[1];
ExposedAreaMetaData meta = (ExposedAreaMetaData) parameters[2];
zone = TabletopTool.getCampaign().getZone(zoneGUID);
zone.setExposedAreaMetaData(tokenGUID, meta);
return;
}
}
});
}
}