Package com.jcloisterzone.ui.plugin

Source Code of com.jcloisterzone.ui.plugin.ResourcePlugin

package com.jcloisterzone.ui.plugin;

import java.awt.Image;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.geom.AffineTransform;
import java.awt.geom.Area;
import java.io.IOException;
import java.net.URL;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import javax.swing.ImageIcon;
import javax.xml.parsers.ParserConfigurationException;

import org.slf4j.LoggerFactory;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import com.jcloisterzone.Expansion;
import com.jcloisterzone.board.Location;
import com.jcloisterzone.board.Tile;
import com.jcloisterzone.feature.Bridge;
import com.jcloisterzone.feature.Castle;
import com.jcloisterzone.feature.City;
import com.jcloisterzone.feature.Farm;
import com.jcloisterzone.feature.Feature;
import com.jcloisterzone.feature.Road;
import com.jcloisterzone.feature.Tower;
import com.jcloisterzone.figure.Barn;
import com.jcloisterzone.figure.Meeple;
import com.jcloisterzone.ui.ImmutablePoint;
import com.jcloisterzone.ui.resources.ResourceManager;
import com.jcloisterzone.ui.theme.FeatureDescriptor;
import com.jcloisterzone.ui.theme.ThemeGeometry;

public class ResourcePlugin extends Plugin implements ResourceManager {

    public static final int NORMALIZED_SIZE = 1000;

    private static ThemeGeometry defaultGeometry;
    private ThemeGeometry pluginGeometry;

    private Set<String> supportedExpansions = new HashSet<>(); //expansion codes

    static {
        try {
            defaultGeometry = new ThemeGeometry(ResourcePlugin.class.getClassLoader(), "defaults");
        } catch (IOException | SAXException | ParserConfigurationException e) {
            LoggerFactory.getLogger(ThemeGeometry.class).error(e.getMessage(), e);
        }
    }

    public ResourcePlugin(URL url) throws Exception {
        super(url);
        pluginGeometry = new ThemeGeometry(getLoader(), "tiles");
    }

    @Override
    protected void parseMetadata(Element rootElement) throws Exception {
        super.parseMetadata(rootElement);
        NodeList nl = rootElement.getElementsByTagName("expansions");
        if (nl.getLength() == 0) throw new Exception("Supported expansions missing in plugin.xml for " + getId());
        Element expansion = (Element) nl.item(0);
        nl = expansion.getElementsByTagName("expansion");
        if (nl.getLength() == 0) throw new Exception("No expansion is supported by " + getId());
        for (int i = 0; i < nl.getLength(); i++) {
            String expName = nl.item(i).getFirstChild().getNodeValue().trim();
            Expansion exp = Expansion.valueOf(expName);
            supportedExpansions.add(exp.getCode());
        }
    }


    protected Image getImageResource(String path) {
        logger.debug("Trying to load image resource {}:{}", getTitle(), path);
        URL url = getLoader().getResource(path);
        if (url == null) return null;
        return Toolkit.getDefaultToolkit().getImage(url);
    }

    protected boolean containsTile(String tileId) {
        String expCode = tileId.substring(0, 2);
        return supportedExpansions.contains(expCode);
    }

    @Override
    public Image getTileImage(Tile tile) {
        return getTileImage(tile.getId());
    }

    @Override
    public Image getAbbeyImage() {
        return getTileImage(Tile.ABBEY_TILE_ID);
    }

    private Image getTileImage(String tileId) {
        //return null;
        if (!containsTile(tileId)) return null;
        String fileName = "tiles/"+tileId.substring(0, 2) + "/" + tileId.substring(3) + ".jpg";
        Image img = getImageResource(fileName);
        if (img == null) return null;
        return (new ImageIcon(img)).getImage();
    }


    @Override
    public ImmutablePoint getMeeplePlacement(Tile tile, Class<? extends Meeple> type, Location loc) {
        if (!containsTile(tile.getId())) return null;
        if (type.equals(Barn.class)) return null;
        Feature piece = tile.getFeature(loc);
        ImmutablePoint point = pluginGeometry.getMeeplePlacement(tile, piece.getClass(), loc);
        if (point == null) {
            point = defaultGeometry.getMeeplePlacement(tile, piece.getClass(), piece.getLocation());
        }
        if (point == null) {
            logger.warn("No point defined for <" + (new FeatureDescriptor(tile, piece.getClass(), loc)) + ">");
            point =  new ImmutablePoint(0, 0);
        }
        return point;
    }

    private Area getArea(Tile tile, Class<? extends Feature> featureClass, Location loc) {
        if (loc == Location.ABBOT) loc = Location.CLOISTER;
        if (Castle.class.equals(featureClass)) {
            featureClass = City.class;
        }
        Area area = pluginGeometry.getArea(tile, featureClass, loc);
        if (area == null) {
            area  = defaultGeometry.getArea(tile, featureClass, loc);
        }
        if (area == null) {
            logger.error("No shape defined for <" + (new FeatureDescriptor(tile, featureClass, loc)) + ">");
            area = new Area();
        }
        return area;
    }

    private Area getSubstractionArea(Tile tile, boolean farm) {
        Area d = defaultGeometry.getSubstractionArea(tile, farm),
             p = pluginGeometry.getSubstractionArea(tile, farm),
             area = new Area();

        if (d != null) area.add(d);
        if (p != null) area.add(p);
        return area;
    }

    private boolean isFarmComplement(Tile tile, Location loc) {
        if (pluginGeometry.isFarmComplement(tile, loc)) return true;
        if (defaultGeometry.isFarmComplement(tile, loc)) return true;
        return false;
    }

    @Override
    public Map<Location, Area> getFeatureAreas(Tile tile, int size, Set<Location> locations) {
        if (!containsTile(tile.getId())) return null;

        Map<Location, Area> areas = new HashMap<>();
        Area subsBridge = getBaseRoadAndCitySubstractions(tile);
        Area subsRoadCity = new Area(subsBridge);
        substractBridge(subsRoadCity, tile);
        Area subsFarm = getFarmSubstractions(tile);

        for (Feature piece : tile.getFeatures()) {
            boolean aliasAbbot = false;
            Location loc = piece.getLocation();
            if (loc == Location.CLOISTER && locations.contains(Location.ABBOT)) {
                aliasAbbot = true;
            }
            if (!aliasAbbot && !locations.contains(loc)) {
                continue;
            }

            if (piece instanceof Farm) {
                areas.put(loc, getFarmArea(loc, tile, subsFarm));
                continue;
            }
            Area a = getArea(tile, piece.getClass(), loc);
            if (piece instanceof City || piece instanceof Road) {
                Area subs = subsRoadCity;
                if (piece instanceof Bridge) {
                    subs = subsBridge;
                }
                if (!subs.isEmpty()) {
                    a = new Area(a); //copy to preserve original
                    a.subtract(subs);
                }
            }
            areas.put(aliasAbbot ? Location.ABBOT : loc, a);
        }
        if (locations.contains(Location.FLIER)) {
            areas.put(Location.FLIER, getArea(tile, null, Location.FLIER));
        }

        Map<Location, Area> transformed = new HashMap<>();

        AffineTransform transform1;
        if (size == NORMALIZED_SIZE) {
            transform1 = new AffineTransform();
        } else {
            double ratio = size/(double)NORMALIZED_SIZE;
            transform1 = AffineTransform.getScaleInstance(ratio,ratio);
        }
        //TODO rotation - 3 rotations are done - Location rotation, getArea and this affine
        AffineTransform transform2 = tile.getRotation().getAffineTransform(size);

        for (Entry<Location, Area> entry : areas.entrySet()) {
            Area a = entry.getValue();
            a = a.createTransformedArea(transform1);
            a = a.createTransformedArea(transform2);
            transformed.put(entry.getKey(), a);
        }
        return transformed;
    }

    @Override
    public Map<Location, Area> getBarnTileAreas(Tile tile, int size, Set<Location> corners) {
        return null;
    }

    //TODO Move to default provider ???
    public Map<Location, Area> getBridgeAreas(Tile tile, int size, Set<Location> locations) {
        Map<Location, Area> result = new HashMap<>();
        for (Location loc : locations) {
            result.put(loc, getBridgeArea(size, loc));
        }
        return result;
    }

    //TODO move to Area Provider ???
    private Area getBridgeArea(int size, Location loc) {
        AffineTransform transform1;
        if (size == NORMALIZED_SIZE) {
            transform1 = new AffineTransform();
        } else {
            double ratio = size/(double)NORMALIZED_SIZE;
            transform1 = AffineTransform.getScaleInstance(ratio,ratio);
        }
        return pluginGeometry.getBridgeArea(loc).createTransformedArea(transform1);
    }

    private void substractBridge(Area substractions, Tile tile) {
        Bridge bridge = tile.getBridge();
        if (bridge != null) {
            Area area;
            area = getArea(tile, Bridge.class, bridge.getLocation());
            substractions.add(area);
        }
    }

    private Area getBaseRoadAndCitySubstractions(Tile tile) {
        Area sub = new Area();
        if (tile.getTower() != null) {
            sub.add(getArea(tile, Tower.class, Location.TOWER));
        }
        if (tile.getFlier() != null) {
            sub.add(getArea(tile, null, Location.FLIER));
        }
        sub.add(getSubstractionArea(tile, false));
        return sub;
    }

    private Area getFarmSubstractions(Tile tile) {
        Area sub = new Area();
        for (Feature piece : tile.getFeatures()) {
            if (!(piece instanceof Farm)) {
                Area area = getArea(tile, piece.getClass(), piece.getLocation());
                sub.add(area);
            }
        }
        if (tile.getFlier() != null) {
            sub.add(getArea(tile, null, Location.FLIER));
        }
        sub.add(getSubstractionArea(tile, true));
        return sub;
    }


    private Area getFarmArea(Location farm, Tile tile, Area sub) {
        Area base;
        if (isFarmComplement(tile, farm)) { //is complement farm
            base = new Area(new Rectangle(0,0, NORMALIZED_SIZE, NORMALIZED_SIZE));
            for (Feature piece : tile.getFeatures()) {
                if (piece instanceof Farm && piece.getLocation() != farm) {
                    Area area = getArea(tile, Farm.class, piece.getLocation());
                    base.subtract(area);
                }
            }
        } else {
            base = getArea(tile, Farm.class, farm);
            base = new Area(base); //copy area to not substract from original
        }
        if (!sub.isEmpty()) {
            base.subtract(sub);
        }
        return base;
    }



}
TOP

Related Classes of com.jcloisterzone.ui.plugin.ResourcePlugin

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.