mirror of https://github.com/FreeCol/freecol.git
Areas can now be edited in the map editor. Areas can now be used for defining the locations a given native nation can have settlements (when generating settlements semi-randomly).
This commit is contained in:
parent
c6ed870630
commit
06dcf01df9
|
@ -78,6 +78,7 @@ image.icon.coin=resources/images/misc/coin.png
|
|||
image.icon.Colopedia.openSection=resources/images/ui/open_section_120pct.png
|
||||
image.icon.Colopedia.closedSection=resources/images/ui/closed_section_125pct.png
|
||||
image.icon.Colopedia.idea=resources/images/ui/idea.png
|
||||
image.icon.mapEditor.selectArea=resources/images/ui/select-area.png
|
||||
|
||||
# User Interface Images
|
||||
image.flavor.Declaration=resources/images/ui/doi.png
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 4.5 KiB |
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
|
@ -392,6 +392,7 @@ loadAction.accelerator=L
|
|||
loadAction.name=Load
|
||||
mapControlsAction.accelerator=control M
|
||||
mapControlsAction.name=Map Controls
|
||||
mapEditorToolboxPanelAction.name=Toolbox
|
||||
mapEditorTransformPanelAction.name=Tile Transform
|
||||
mapEditorAction.name=Map Editor
|
||||
mapGeneratorOptionsAction.accelerator=shift F12
|
||||
|
@ -3611,7 +3612,11 @@ loadingSavegameDialog.serverName=Server Name:
|
|||
loadingSavegameDialog.singlePlayer=Single player
|
||||
loadingSavegameDialog.name=Loading Save game
|
||||
|
||||
# Map Editor
|
||||
mapEditor.loadedWithMods=You have started the map editor with active mods that contain specification changes. Please note that the same mods need to be manually activated by every user that loads maps that are using anything new from a mod.\n\nYou can go back to the main menu and deactivate any mods through the Preferences if this was not intentional.
|
||||
mapEditor.chooseAreaModificationPanel.title=Choose Area
|
||||
mapEditor.toolBoxPanel.title=Toolbox
|
||||
mapEditor.tool.paintBrush.name=Paint
|
||||
|
||||
# MapEditorTransformPanel
|
||||
mapEditorTransformPanel.title=Tile Transform
|
||||
|
@ -3621,6 +3626,7 @@ mapEditorTransformPanel.minorRiver=Minor river
|
|||
mapEditorTransformPanel.changeRiverConnections=Add/remove river connections
|
||||
mapEditorTransformPanel.setRiverStyle=Set river style
|
||||
mapEditorTransformPanel.resource=Change/remove resource
|
||||
mapEditorTransformPanel.selectArea=Add/remove tiles from area
|
||||
|
||||
# MapGeneratorOptionsDialog
|
||||
freecol.map.L_America_JsTheDude=<html>L America<br><font size="-2">By JsTheDude</font></html>
|
||||
|
|
|
@ -41,6 +41,7 @@ import net.sf.freecol.common.i18n.Messages;
|
|||
import net.sf.freecol.common.io.FreeColDirectories;
|
||||
import net.sf.freecol.common.io.FreeColModFile;
|
||||
import net.sf.freecol.common.io.FreeColSavegameFile;
|
||||
import net.sf.freecol.common.model.Area;
|
||||
import net.sf.freecol.common.model.Game;
|
||||
import net.sf.freecol.common.model.Map;
|
||||
import net.sf.freecol.common.model.Nation;
|
||||
|
@ -68,11 +69,15 @@ public final class MapEditorController extends FreeColClientHolder {
|
|||
/** Map height in MapGeneratorOptionsDialog. */
|
||||
private static final int MINI_MAP_THUMBNAIL_FINAL_HEIGHT = 64;
|
||||
|
||||
private MapEditorTool currentTool = MapEditorTool.PAINTBRUSH;
|
||||
|
||||
/**
|
||||
* The transform that should be applied to a {@code Tile}
|
||||
* that is clicked on the map.
|
||||
*/
|
||||
private MapTransform currentMapTransform = null;
|
||||
|
||||
private Area currentArea = null;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -213,6 +218,18 @@ public final class MapEditorController extends FreeColClientHolder {
|
|||
public MapTransform getMapTransform() {
|
||||
return currentMapTransform;
|
||||
}
|
||||
|
||||
public MapEditorTool getCurrentTool() {
|
||||
return currentTool;
|
||||
}
|
||||
|
||||
public void setCurrentArea(Area currentArea) {
|
||||
this.currentArea = currentArea;
|
||||
}
|
||||
|
||||
public Area getCurrentArea() {
|
||||
return currentArea;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms the given {@code Tile} using the
|
||||
|
@ -330,6 +347,7 @@ public final class MapEditorController extends FreeColClientHolder {
|
|||
Specification spec = getDefaultSpecification();
|
||||
Game game = FreeColServer.readGame(new FreeColSavegameFile(theFile),
|
||||
spec, freeColServer);
|
||||
game.generateDefaultAreas();
|
||||
fcc.setGame(game);
|
||||
requireNativeNations(game);
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
/**
|
||||
* Copyright (C) 2002-2024 The FreeCol Team
|
||||
*
|
||||
* This file is part of FreeCol.
|
||||
*
|
||||
* FreeCol is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* FreeCol is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with FreeCol. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.sf.freecol.client.control;
|
||||
|
||||
/**
|
||||
* Possible tools to use in the map editor.
|
||||
*/
|
||||
public enum MapEditorTool {
|
||||
|
||||
//CURSOR("mapEditor.tool.cursor"),
|
||||
//SELECTION("mapEditor.tool.selection"),
|
||||
PAINTBRUSH("mapEditor.tool.paintBrush"),
|
||||
//FILL("mapEditor.tool.fill"),
|
||||
;
|
||||
|
||||
private final String id;
|
||||
|
||||
private MapEditorTool(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
}
|
|
@ -75,6 +75,7 @@ import net.sf.freecol.client.gui.panel.FreeColPanel;
|
|||
import net.sf.freecol.client.gui.panel.InfoPanel;
|
||||
import net.sf.freecol.client.gui.panel.MainPanel;
|
||||
import net.sf.freecol.client.gui.panel.MapControls;
|
||||
import net.sf.freecol.client.gui.panel.MapEditorToolboxPanel;
|
||||
import net.sf.freecol.client.gui.panel.MapEditorTransformPanel;
|
||||
import net.sf.freecol.client.gui.panel.MiniMapFreeColPanel;
|
||||
import net.sf.freecol.client.gui.panel.Utility;
|
||||
|
@ -693,6 +694,10 @@ public final class Canvas extends JDesktopPane {
|
|||
x = ((getWidth() - width) * 3) / 4;
|
||||
y = (getHeight() - height) / 2;
|
||||
break;
|
||||
case LEFT:
|
||||
x = 0;
|
||||
y = (getHeight() - height) / 2;
|
||||
break;
|
||||
case LOWER_LEFT:
|
||||
x = 0;
|
||||
y = getHeight() - height;
|
||||
|
@ -705,6 +710,10 @@ public final class Canvas extends JDesktopPane {
|
|||
x = getWidth() - width;
|
||||
y = 0;
|
||||
break;
|
||||
case RIGHT:
|
||||
x = getWidth() - width;
|
||||
y = (getHeight() - height) / 2;
|
||||
break;
|
||||
case UPPER_LEFT:
|
||||
case ORIGIN:
|
||||
x = y = 0;
|
||||
|
@ -1316,7 +1325,7 @@ public final class Canvas extends JDesktopPane {
|
|||
dialogRemove(dialog);
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Displays a {@code FreeColPanel} at a generalized position.
|
||||
*
|
||||
|
@ -1327,10 +1336,29 @@ public final class Canvas extends JDesktopPane {
|
|||
* @return The panel.
|
||||
*/
|
||||
public FreeColPanel showFreeColPanel(FreeColPanel panel,
|
||||
PopupPosition popupPosition,
|
||||
boolean resizable) {
|
||||
PopupPosition popupPosition,
|
||||
boolean resizable) {
|
||||
return showFreeColPanel(panel, false, popupPosition, resizable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a {@code FreeColPanel} at a generalized position.
|
||||
*
|
||||
* @param panel {@code FreeColPanel}, panel to show
|
||||
* @param toolBox Should be set to true if the resulting frame is
|
||||
* used as a toolbox (that is: it should not be counted as a
|
||||
* frame).
|
||||
* @param popupPosition {@code PopupPosition} The generalized
|
||||
* position to place the panel.
|
||||
* @param resizable Should the panel be resizable?
|
||||
* @return The panel.
|
||||
*/
|
||||
public FreeColPanel showFreeColPanel(FreeColPanel panel,
|
||||
boolean toolBox,
|
||||
PopupPosition popupPosition,
|
||||
boolean resizable) {
|
||||
repaint();
|
||||
addAsFrame(panel, false, popupPosition, resizable);
|
||||
addAsFrame(panel, toolBox, popupPosition, resizable);
|
||||
panel.requestFocus();
|
||||
freeColClient.getActionManager().update();
|
||||
return panel;
|
||||
|
@ -1666,7 +1694,15 @@ public final class Canvas extends JDesktopPane {
|
|||
addAsFrame(panel, true, null, true);
|
||||
repaint();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Display the map editor toolbox panel.
|
||||
*/
|
||||
public void showMapEditorToolboxPanel() {
|
||||
final MapEditorToolboxPanel panel = new MapEditorToolboxPanel(this.freeColClient);
|
||||
addAsFrame(panel, true, null, true);
|
||||
repaint();
|
||||
}
|
||||
|
||||
// Override JComponent
|
||||
public void paintJustTheMapImmediately() {
|
||||
|
|
|
@ -41,6 +41,7 @@ import net.sf.freecol.client.ClientOptions;
|
|||
import net.sf.freecol.client.FreeColClient;
|
||||
import net.sf.freecol.client.control.FreeColClientHolder;
|
||||
import net.sf.freecol.client.control.MapTransform;
|
||||
import net.sf.freecol.client.gui.SwingGUI.PopupPosition;
|
||||
import net.sf.freecol.client.gui.dialog.FreeColDialog;
|
||||
import net.sf.freecol.client.gui.dialog.Parameters;
|
||||
import net.sf.freecol.client.gui.mapviewer.MapAsyncPainter;
|
||||
|
@ -1158,6 +1159,18 @@ public class GUI extends FreeColClientHolder {
|
|||
*/
|
||||
public void startMapEditorGUI() {}
|
||||
|
||||
/**
|
||||
* Shows the map editor toolbox panel.
|
||||
*/
|
||||
public void enableEditorToolboxPanel(boolean shouldDisplayPanel) {}
|
||||
|
||||
/**
|
||||
* Checks if the map editor toolbox panel is being displayed.
|
||||
*/
|
||||
public boolean isShowingMapEditorToolboxPanel() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the map editor transform panel.
|
||||
*/
|
||||
|
@ -1961,6 +1974,19 @@ public class GUI extends FreeColClientHolder {
|
|||
* @return The panel shown.
|
||||
*/
|
||||
public FreeColPanel showColonyPanel(Colony colony, Unit unit) { return null; }
|
||||
|
||||
/**
|
||||
* Displays a {@code FreeColPanel} at a generalized position.
|
||||
*
|
||||
* @param panel {@code FreeColPanel}, panel to show
|
||||
* @param toolBox Should be set to true if the resulting frame is
|
||||
* used as a toolbox (that is: it should not be counted as a
|
||||
* frame).
|
||||
* @param popupPosition {@code PopupPosition} The generalized
|
||||
* position to place the panel.
|
||||
* @param resizable Should the panel be resizable?
|
||||
*/
|
||||
public void showFreeColPanel(FreeColPanel panel, boolean toolBox, PopupPosition popupPosition, boolean resizable) { }
|
||||
|
||||
/**
|
||||
* Show a colopedia panel.
|
||||
|
|
|
@ -42,7 +42,6 @@ import java.util.Collection;
|
|||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.logging.Level;
|
||||
import java.util.stream.Collectors;
|
||||
|
@ -60,7 +59,7 @@ import net.sf.freecol.client.ClientOptions;
|
|||
import net.sf.freecol.client.FreeColClient;
|
||||
import net.sf.freecol.client.control.MapTransform;
|
||||
import net.sf.freecol.client.control.SoundController;
|
||||
import net.sf.freecol.client.gui.action.MapEditorTransformPanelAction;
|
||||
import net.sf.freecol.client.gui.SwingGUI.PopupPosition;
|
||||
import net.sf.freecol.client.gui.animation.Animation;
|
||||
import net.sf.freecol.client.gui.animation.Animations;
|
||||
// Special dialogs and panels
|
||||
|
@ -72,13 +71,14 @@ import net.sf.freecol.client.gui.mapviewer.MapAsyncPainter;
|
|||
import net.sf.freecol.client.gui.mapviewer.MapViewer;
|
||||
import net.sf.freecol.client.gui.mapviewer.MapViewerState;
|
||||
import net.sf.freecol.client.gui.mapviewer.TileViewer;
|
||||
import net.sf.freecol.client.gui.panel.BuildQueuePanel;
|
||||
import net.sf.freecol.client.gui.panel.ColonyPanel;
|
||||
import net.sf.freecol.client.gui.panel.CornerMapControls;
|
||||
import net.sf.freecol.client.gui.panel.ErrorPanel;
|
||||
import net.sf.freecol.client.gui.panel.FreeColImageBorder;
|
||||
import net.sf.freecol.client.gui.panel.FreeColPanel;
|
||||
import net.sf.freecol.client.gui.panel.InformationPanel;
|
||||
import net.sf.freecol.client.gui.panel.MapControls;
|
||||
import net.sf.freecol.client.gui.panel.MapEditorToolboxPanel;
|
||||
import net.sf.freecol.client.gui.panel.MapEditorTransformPanel;
|
||||
import net.sf.freecol.client.gui.panel.PurchasePanel;
|
||||
import net.sf.freecol.client.gui.panel.RecruitPanel;
|
||||
|
@ -126,7 +126,6 @@ import net.sf.freecol.common.option.LanguageOption;
|
|||
import net.sf.freecol.common.option.LanguageOption.Language;
|
||||
import net.sf.freecol.common.option.Option;
|
||||
import net.sf.freecol.common.option.OptionGroup;
|
||||
import net.sf.freecol.common.resources.AudioResource;
|
||||
import net.sf.freecol.common.resources.ImageCache;
|
||||
import net.sf.freecol.common.resources.ImageResource;
|
||||
import net.sf.freecol.common.resources.ResourceManager;
|
||||
|
@ -149,6 +148,8 @@ public class SwingGUI extends GUI {
|
|||
LOWER_RIGHT,
|
||||
UPPER_LEFT,
|
||||
UPPER_RIGHT,
|
||||
LEFT,
|
||||
RIGHT,
|
||||
|
||||
/**
|
||||
* Places centered even this means overlapping components.
|
||||
|
@ -920,11 +921,33 @@ public class SwingGUI extends GUI {
|
|||
resetMapZoom(); // Reset zoom to the default
|
||||
mapViewer.getMapViewerState().setActiveUnit(null);
|
||||
this.canvas.startMapEditorGUI();
|
||||
enableEditorToolboxPanel(getGame() != null && getGame().getMap() != null);
|
||||
enableEditorTransformPanel(getGame() != null && getGame().getMap() != null);
|
||||
enableMapControls(getGame() != null && getGame().getMap() != null && getClientOptions().getBoolean(ClientOptions.DISPLAY_MAP_CONTROLS));
|
||||
updateMenuBar();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void enableEditorToolboxPanel(boolean shouldDisplayPanel) {
|
||||
final MapEditorToolboxPanel panel = this.canvas.getExistingFreeColPanel(MapEditorToolboxPanel.class);
|
||||
if (shouldDisplayPanel && panel == null) {
|
||||
this.canvas.showMapEditorToolboxPanel();
|
||||
} else if (!shouldDisplayPanel && panel != null) {
|
||||
this.canvas.removeFromCanvas(panel);
|
||||
} // else: ignore.
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public boolean isShowingMapEditorToolboxPanel() {
|
||||
return this.canvas.isAddedAsPanelFrameOrIcon(MapEditorToolboxPanel.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
|
@ -2095,6 +2118,18 @@ public class SwingGUI extends GUI {
|
|||
if (unit != null) panel.setSelectedUnit(unit);
|
||||
return panel;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void showFreeColPanel(FreeColPanel panel, boolean toolBox, PopupPosition popupPosition, boolean resizable) {
|
||||
if (canvas.isAddedAsPanelFrameOrIcon(panel)) {
|
||||
panel.requestFocus();
|
||||
} else {
|
||||
canvas.showFreeColPanel(panel, toolBox, popupPosition, resizable);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
|
|
|
@ -119,6 +119,7 @@ public class ActionManager extends OptionGroup {
|
|||
add(new LoadAction(freeColClient));
|
||||
add(new MapControlsAction(freeColClient));
|
||||
add(new MapEditorAction(freeColClient));
|
||||
add(new MapEditorToolboxPanelAction(freeColClient));
|
||||
add(new MapEditorTransformPanelAction(freeColClient));
|
||||
add(new MiniMapToggleViewAction(freeColClient));
|
||||
add(new MiniMapToggleViewAction(freeColClient, true));
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
/**
|
||||
* Copyright (C) 2002-2022 The FreeCol Team
|
||||
*
|
||||
* This file is part of FreeCol.
|
||||
*
|
||||
* FreeCol is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* FreeCol is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with FreeCol. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.sf.freecol.client.gui.action;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
|
||||
import javax.swing.AbstractButton;
|
||||
|
||||
import net.sf.freecol.client.ClientOptions;
|
||||
import net.sf.freecol.client.FreeColClient;
|
||||
|
||||
|
||||
/**
|
||||
* An action for displaying the map editor toolbox.
|
||||
*/
|
||||
public class MapEditorToolboxPanelAction extends SelectableAction {
|
||||
|
||||
public static final String id = "mapEditorToolboxPanelAction";
|
||||
|
||||
|
||||
/**
|
||||
* Creates this action.
|
||||
*
|
||||
* @param freeColClient The {@code FreeColClient} for the game.
|
||||
*/
|
||||
public MapEditorToolboxPanelAction(FreeColClient freeColClient) {
|
||||
super(freeColClient, id);
|
||||
setSelected(isSelected());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected boolean shouldBeEnabled() {
|
||||
return freeColClient.isMapEditor() && getGame() != null && getGame().getMap() != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldBeSelected() {
|
||||
return getGUI().isShowingMapEditorToolboxPanel();
|
||||
}
|
||||
|
||||
// Interface ActionListener
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent ae) {
|
||||
getGUI().enableEditorToolboxPanel(isEnabled() && isSelected());
|
||||
}
|
||||
}
|
|
@ -28,7 +28,7 @@ import net.sf.freecol.client.FreeColClient;
|
|||
|
||||
|
||||
/**
|
||||
* An action for displaying the map controls.
|
||||
* An action for displaying the map editor tile transform panel.
|
||||
*/
|
||||
public class MapEditorTransformPanelAction extends SelectableAction {
|
||||
|
||||
|
|
|
@ -64,6 +64,7 @@ import net.sf.freecol.client.gui.SwingGUI;
|
|||
import net.sf.freecol.common.debug.FreeColDebugger;
|
||||
import net.sf.freecol.common.i18n.Messages;
|
||||
import net.sf.freecol.common.model.Ability;
|
||||
import net.sf.freecol.common.model.Area;
|
||||
import net.sf.freecol.common.model.BuildableType;
|
||||
import net.sf.freecol.common.model.Colony;
|
||||
import net.sf.freecol.common.model.Direction;
|
||||
|
@ -390,9 +391,10 @@ public final class MapViewer extends FreeColClientHolder {
|
|||
final long animatedBaseMs = now();
|
||||
if (!dirtyClipBounds.isEmpty()) {
|
||||
displayToNonAnimationBufferImage(mapViewerBounds, dirtyClipBounds, nonAnimationG2d, map, useBuffers);
|
||||
if (useBuffers) {
|
||||
nonAnimationG2d.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
if (useBuffers) {
|
||||
nonAnimationG2d.dispose();
|
||||
}
|
||||
|
||||
final long nonAnimatedMs = now();
|
||||
|
@ -702,6 +704,10 @@ public final class MapViewer extends FreeColClientHolder {
|
|||
});
|
||||
|
||||
displayDebugAiDefensiveMap(nonAnimationG2d, tcb);
|
||||
|
||||
if (getFreeColClient().isMapEditor()) {
|
||||
displayAreasInMapEditor(nonAnimationG2d, tcb);
|
||||
}
|
||||
|
||||
// Display the colony names, if needed
|
||||
long t14 = now();
|
||||
|
@ -753,6 +759,32 @@ public final class MapViewer extends FreeColClientHolder {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private void displayAreasInMapEditor(Graphics2D nonAnimationG2d, TileClippingBounds tcb) {
|
||||
final Object oldAntialiasingHint = nonAnimationG2d.getRenderingHint(RenderingHints.KEY_ANTIALIASING);
|
||||
nonAnimationG2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
|
||||
|
||||
final Composite oldComposite = nonAnimationG2d.getComposite();
|
||||
nonAnimationG2d.setColor(Color.BLACK);
|
||||
nonAnimationG2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));
|
||||
|
||||
final Color oldColor = nonAnimationG2d.getColor();
|
||||
|
||||
paintEachTile(nonAnimationG2d, tcb, (tileG2d, tile) -> {
|
||||
// This can easily be optimized if slow on some systems.
|
||||
final List<Area> areas = getGame().getAreas();
|
||||
// TODO: Support showing multiple areas by drawing in a checkered/blinds pattern.
|
||||
final Area area = areas.stream().filter(a -> a.containsTile(tile)).findAny().orElse(null);
|
||||
if (area != null) {
|
||||
tileG2d.setColor(area.getColor());
|
||||
tileG2d.fill(mapViewerScaledUtils.getFog());
|
||||
}
|
||||
});
|
||||
nonAnimationG2d.setColor(oldColor);
|
||||
nonAnimationG2d.setComposite(oldComposite);
|
||||
nonAnimationG2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, oldAntialiasingHint);
|
||||
}
|
||||
|
||||
private void displayDebugAiDefensiveMap(Graphics2D nonAnimationG2d, TileClippingBounds tcb) {
|
||||
if (FreeColDebugger.debugShowDefenceMapForPlayer() != null
|
||||
&& getFreeColServer() != null
|
||||
|
|
|
@ -33,6 +33,7 @@ import net.sf.freecol.client.gui.action.DisplayGridAction;
|
|||
import net.sf.freecol.client.gui.action.DisplayTileTextAction;
|
||||
import net.sf.freecol.client.gui.action.DisplayTileTextAction.DisplayText;
|
||||
import net.sf.freecol.client.gui.action.MapControlsAction;
|
||||
import net.sf.freecol.client.gui.action.MapEditorToolboxPanelAction;
|
||||
import net.sf.freecol.client.gui.action.MapEditorTransformPanelAction;
|
||||
import net.sf.freecol.client.gui.action.NewAction;
|
||||
import net.sf.freecol.client.gui.action.NewEmptyMapAction;
|
||||
|
@ -131,6 +132,7 @@ public class MapEditorMenuBar extends FreeColMenuBar {
|
|||
menu.setMnemonic(KeyEvent.VK_V);
|
||||
|
||||
menu.add(getCheckBoxMenuItem(MapControlsAction.id));
|
||||
menu.add(getCheckBoxMenuItem(MapEditorToolboxPanelAction.id));
|
||||
menu.add(getCheckBoxMenuItem(MapEditorTransformPanelAction.id));
|
||||
menu.add(getCheckBoxMenuItem(DisplayGridAction.id));
|
||||
menu.add(getCheckBoxMenuItem(ChangeWindowedModeAction.id));
|
||||
|
|
|
@ -0,0 +1,138 @@
|
|||
/**
|
||||
* Copyright (C) 2002-2022 The FreeCol Team
|
||||
*
|
||||
* This file is part of FreeCol.
|
||||
*
|
||||
* FreeCol is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* FreeCol is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with FreeCol. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.sf.freecol.client.gui.panel;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.ButtonGroup;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JToggleButton;
|
||||
|
||||
import net.sf.freecol.client.FreeColClient;
|
||||
import net.sf.freecol.client.control.MapEditorController;
|
||||
import net.sf.freecol.client.control.MapEditorTool;
|
||||
import net.sf.freecol.client.gui.ImageLibrary;
|
||||
import net.sf.freecol.client.gui.SwingGUI.PopupPosition;
|
||||
import net.sf.freecol.client.gui.panel.WrapLayout.HorizontalAlignment;
|
||||
import net.sf.freecol.client.gui.panel.WrapLayout.HorizontalGap;
|
||||
import net.sf.freecol.common.i18n.Messages;
|
||||
|
||||
|
||||
/**
|
||||
* A panel for choosing the current tool in the map editor.
|
||||
*
|
||||
* This panel is only used when running in
|
||||
* {@link net.sf.freecol.client.FreeColClient#isMapEditor() map editor mode}.
|
||||
*
|
||||
* @see MapEditorTransformPanel
|
||||
*/
|
||||
public final class MapEditorToolboxPanel extends FreeColPanel {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static final Logger logger = Logger.getLogger(MapEditorToolboxPanel.class.getName());
|
||||
|
||||
private final JPanel listPanel;
|
||||
private final ButtonGroup group;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a panel for choosing the current tool in the map editor.
|
||||
*
|
||||
* @param freeColClient The {@code FreeColClient} for the game.
|
||||
*/
|
||||
public MapEditorToolboxPanel(FreeColClient freeColClient) {
|
||||
super(freeColClient, null, new BorderLayout());
|
||||
|
||||
final Dimension terrainSize = ImageLibrary.scaleDimension(getImageLibrary().scale(ImageLibrary.TILE_OVERLAY_SIZE), ImageLibrary.SMALLER_SCALE);
|
||||
listPanel = new JPanel(new WrapLayout()
|
||||
.withForceComponentSize(terrainSize)
|
||||
.withHorizontalAlignment(HorizontalAlignment.LEFT)
|
||||
.withHorizontalGap(HorizontalGap.AUTO));
|
||||
|
||||
group = new ButtonGroup();
|
||||
//Add an invisible, move button to de-select all others
|
||||
group.add(new JToggleButton());
|
||||
buildList();
|
||||
|
||||
JScrollPane sl = new JScrollPane(listPanel,
|
||||
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
|
||||
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
|
||||
sl.getViewport().setOpaque(false);
|
||||
listPanel.setSize(new Dimension(terrainSize.width * 3, 0));
|
||||
add(sl, BorderLayout.CENTER);
|
||||
setBorder(BorderFactory.createEmptyBorder());
|
||||
revalidate();
|
||||
repaint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFrameTitle() {
|
||||
return Messages.message("mapEditor.toolBoxPanel.title");
|
||||
}
|
||||
|
||||
@Override
|
||||
public PopupPosition getFramePopupPosition() {
|
||||
return PopupPosition.UPPER_RIGHT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the buttons for all the tools.
|
||||
*/
|
||||
private void buildList() {
|
||||
final MapEditorController ctlr = getFreeColClient().getMapEditorController();
|
||||
final MapEditorTool defaultTool = ctlr.getCurrentTool();
|
||||
for (MapEditorTool mapEditorTool : MapEditorTool.values()) {
|
||||
final boolean isDefaultTool = (mapEditorTool == defaultTool);
|
||||
listPanel.add(buildButton(mapEditorTool, isDefaultTool));
|
||||
}
|
||||
}
|
||||
|
||||
private JToggleButton buildButton(MapEditorTool mapEditorTool, boolean defaultTool) {
|
||||
final String text = Messages.getName(mapEditorTool.getId());
|
||||
final MapEditorController ctlr = getFreeColClient().getMapEditorController();
|
||||
/* TODO: Update description panel?
|
||||
JPanel descriptionPanel = new JPanel(new BorderLayout());
|
||||
descriptionPanel.add(new JLabel(new ImageIcon(image)),
|
||||
BorderLayout.CENTER);
|
||||
descriptionPanel.add(new JLabel(text, JLabel.CENTER),
|
||||
BorderLayout.PAGE_END);
|
||||
descriptionPanel.setBackground(Color.RED);
|
||||
mt.setDescriptionPanel(descriptionPanel);
|
||||
*/
|
||||
final Dimension riverSize = ImageLibrary.scaleDimension(getImageLibrary().scale(ImageLibrary.TILE_SIZE), ImageLibrary.SMALLER_SCALE);
|
||||
ImageIcon icon = new ImageIcon(getImageLibrary().getScaledImage("image.ui.includesSpecification")); // TODO: Add icon
|
||||
final JToggleButton button = new JToggleButton(icon);
|
||||
button.setToolTipText(text);
|
||||
button.setOpaque(false);
|
||||
button.setSelected(defaultTool);
|
||||
group.add(button);
|
||||
button.addActionListener((ActionEvent ae) -> {
|
||||
|
||||
});
|
||||
button.setBorder(null);
|
||||
return button;
|
||||
}
|
||||
}
|
|
@ -45,11 +45,14 @@ import net.sf.freecol.client.FreeColClient;
|
|||
import net.sf.freecol.client.control.MapEditorController;
|
||||
import net.sf.freecol.client.control.MapTransform;
|
||||
import net.sf.freecol.client.gui.ChoiceItem;
|
||||
import net.sf.freecol.client.gui.DialogHandler;
|
||||
import net.sf.freecol.client.gui.ImageLibrary;
|
||||
import net.sf.freecol.client.gui.SwingGUI.PopupPosition;
|
||||
import net.sf.freecol.client.gui.panel.WrapLayout.HorizontalAlignment;
|
||||
import net.sf.freecol.client.gui.panel.WrapLayout.HorizontalGap;
|
||||
import net.sf.freecol.client.gui.panel.mapeditor.ChooseAreaModificationPanel;
|
||||
import net.sf.freecol.common.i18n.Messages;
|
||||
import net.sf.freecol.common.model.Area;
|
||||
import net.sf.freecol.common.model.Direction;
|
||||
import net.sf.freecol.common.model.IndianNationType;
|
||||
import net.sf.freecol.common.model.LostCityRumour;
|
||||
|
@ -258,6 +261,37 @@ public final class MapEditorTransformPanel extends FreeColPanel {
|
|||
t.removeLostCityRumour();
|
||||
}
|
||||
}
|
||||
|
||||
public static final class AssignAreaTransform extends MapTransform {
|
||||
private Area area;
|
||||
|
||||
private AssignAreaTransform(Area area) {
|
||||
this.area = area;
|
||||
}
|
||||
|
||||
public Area getArea() {
|
||||
return area;
|
||||
}
|
||||
|
||||
public void setArea(Area area) {
|
||||
this.area = area;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void transform(Tile t) {
|
||||
if (area == null) {
|
||||
return;
|
||||
}
|
||||
if (area.containsTile(t)) {
|
||||
area.removeTile(t);
|
||||
} else {
|
||||
area.addTile(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** A native nation to use for native settlement type and skill. */
|
||||
private static Nation nativeNation;
|
||||
|
@ -265,6 +299,8 @@ public final class MapEditorTransformPanel extends FreeColPanel {
|
|||
private final JPanel listPanel;
|
||||
private JToggleButton settlementButton;
|
||||
private final ButtonGroup group;
|
||||
|
||||
private final ChooseAreaModificationPanel chooseAreaModificationPanel;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -275,6 +311,17 @@ public final class MapEditorTransformPanel extends FreeColPanel {
|
|||
public MapEditorTransformPanel(FreeColClient freeColClient) {
|
||||
super(freeColClient, null, new BorderLayout());
|
||||
|
||||
final MapEditorController ctlr = getFreeColClient().getMapEditorController();
|
||||
final DialogHandler<Area> areaModificationHandler = (area) -> {
|
||||
ctlr.setCurrentArea(area);
|
||||
final MapTransform currentMapTransform = ctlr.getMapTransform();
|
||||
if (currentMapTransform instanceof AssignAreaTransform) {
|
||||
final AssignAreaTransform assignAreaTransform = (AssignAreaTransform) currentMapTransform;
|
||||
assignAreaTransform.setArea(area);
|
||||
}
|
||||
};
|
||||
this.chooseAreaModificationPanel = new ChooseAreaModificationPanel(freeColClient, areaModificationHandler );
|
||||
|
||||
final Dimension terrainSize = ImageLibrary.scaleDimension(getImageLibrary().scale(ImageLibrary.TILE_OVERLAY_SIZE), ImageLibrary.SMALLER_SCALE);
|
||||
listPanel = new JPanel(new WrapLayout()
|
||||
.withForceComponentSize(terrainSize)
|
||||
|
@ -304,7 +351,7 @@ public final class MapEditorTransformPanel extends FreeColPanel {
|
|||
|
||||
@Override
|
||||
public PopupPosition getFramePopupPosition() {
|
||||
return PopupPosition.UPPER_RIGHT;
|
||||
return PopupPosition.RIGHT;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -375,6 +422,10 @@ public final class MapEditorTransformPanel extends FreeColPanel {
|
|||
listPanel.add(buildButton(getImageLibrary().getSettlementTypeImage(settlementType, riverSize),
|
||||
Messages.message("settlement"),
|
||||
new SettlementTransform()));
|
||||
|
||||
listPanel.add(buildButton(getImageLibrary().getScaledImage("image.icon.mapEditor.selectArea"),
|
||||
Messages.message("mapEditorTransformPanel.selectArea"),
|
||||
new AssignAreaTransform(null)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -413,6 +464,10 @@ public final class MapEditorTransformPanel extends FreeColPanel {
|
|||
.getRiverStyleKeys(all));
|
||||
if (style != null) rst.setStyle(style);
|
||||
}
|
||||
if (mt instanceof AssignAreaTransform) {
|
||||
getGUI().showFreeColPanel(chooseAreaModificationPanel, true, null, true);
|
||||
newMapTransform = null;
|
||||
}
|
||||
newMapTransform = mt;
|
||||
}
|
||||
ctlr.setMapTransform(newMapTransform);
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
/**
|
||||
* Copyright (C) 2002-2024 The FreeCol Team
|
||||
*
|
||||
* This file is part of FreeCol.
|
||||
*
|
||||
* FreeCol is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* FreeCol is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with FreeCol. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.sf.freecol.client.gui.panel.mapeditor;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.ButtonGroup;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JToggleButton;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import net.sf.freecol.client.FreeColClient;
|
||||
import net.sf.freecol.client.gui.DialogHandler;
|
||||
import net.sf.freecol.client.gui.panel.FreeColPanel;
|
||||
import net.sf.freecol.client.gui.panel.WrapLayout;
|
||||
import net.sf.freecol.client.gui.panel.WrapLayout.HorizontalAlignment;
|
||||
import net.sf.freecol.common.i18n.Messages;
|
||||
import net.sf.freecol.common.model.Area;
|
||||
|
||||
/**
|
||||
* A panel for choosing an area that tiles should be toggled in or out from.
|
||||
*/
|
||||
public final class ChooseAreaModificationPanel extends FreeColPanel {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(ChooseAreaModificationPanel.class.getName());
|
||||
|
||||
|
||||
private final DialogHandler<Area> dialogHandler;
|
||||
|
||||
/**
|
||||
* Creates a new game panel.
|
||||
*
|
||||
* @param freeColClient The {@code FreeColClient} for the game.
|
||||
*/
|
||||
public ChooseAreaModificationPanel(FreeColClient freeColClient, DialogHandler<Area> dialogHandler) {
|
||||
super(freeColClient, null, new MigLayout("fill, wrap 1", "[fill, growprio 150]", "[fill, growprio 150]"));
|
||||
|
||||
this.dialogHandler = dialogHandler;
|
||||
|
||||
final JPanel areasPanel = new JPanel(new WrapLayout()
|
||||
.withHorizontalAlignment(HorizontalAlignment.CENTER)
|
||||
) {
|
||||
@Override
|
||||
public Dimension getMinimumSize() {
|
||||
return new Dimension(1, 1);
|
||||
}
|
||||
};
|
||||
areasPanel.setOpaque(false);
|
||||
|
||||
final ButtonGroup bg = new ButtonGroup();
|
||||
for (Area a : freeColClient.getGame().getAreas()) {
|
||||
final String title = (a.getNameKey() != null) ? Messages.message(a.getNameKey()) : a.getName();
|
||||
final JToggleButton areaButton = new JToggleButton(title);
|
||||
areaButton.addActionListener((e) -> {
|
||||
dialogHandler.handle(a);
|
||||
});
|
||||
bg.add(areaButton);
|
||||
areasPanel.add(areaButton);
|
||||
}
|
||||
|
||||
add(areasPanel, "grow, shrink");
|
||||
|
||||
setBorder(BorderFactory.createEmptyBorder());
|
||||
setSize(getPreferredSize());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFrameTitle() {
|
||||
return Messages.message("mapEditor.chooseAreaModificationPanel.title");
|
||||
}
|
||||
|
||||
}
|
|
@ -19,11 +19,30 @@
|
|||
|
||||
package net.sf.freecol.server.generator;
|
||||
|
||||
import static net.sf.freecol.common.model.Constants.INFINITY;
|
||||
import static net.sf.freecol.common.util.CollectionUtils.alwaysTrue;
|
||||
import static net.sf.freecol.common.util.CollectionUtils.any;
|
||||
import static net.sf.freecol.common.util.CollectionUtils.descendingListLengthComparator;
|
||||
import static net.sf.freecol.common.util.CollectionUtils.find;
|
||||
import static net.sf.freecol.common.util.CollectionUtils.forEachMapEntry;
|
||||
import static net.sf.freecol.common.util.CollectionUtils.isNotNull;
|
||||
import static net.sf.freecol.common.util.CollectionUtils.isNull;
|
||||
import static net.sf.freecol.common.util.CollectionUtils.map;
|
||||
import static net.sf.freecol.common.util.CollectionUtils.matchKeyEquals;
|
||||
import static net.sf.freecol.common.util.CollectionUtils.minimize;
|
||||
import static net.sf.freecol.common.util.CollectionUtils.toListNoNulls;
|
||||
import static net.sf.freecol.common.util.CollectionUtils.transform;
|
||||
import static net.sf.freecol.common.util.RandomUtils.getRandomMember;
|
||||
import static net.sf.freecol.common.util.RandomUtils.randomInt;
|
||||
import static net.sf.freecol.common.util.RandomUtils.randomShuffle;
|
||||
|
||||
import java.awt.Rectangle;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
|
@ -37,10 +56,11 @@ import net.sf.freecol.common.debug.FreeColDebugger;
|
|||
import net.sf.freecol.common.i18n.Messages;
|
||||
import net.sf.freecol.common.model.Ability;
|
||||
import net.sf.freecol.common.model.AbstractUnit;
|
||||
import net.sf.freecol.common.model.Area;
|
||||
import net.sf.freecol.common.model.Building;
|
||||
import net.sf.freecol.common.model.BuildingType;
|
||||
import net.sf.freecol.common.model.Colony;
|
||||
import static net.sf.freecol.common.model.Constants.*;
|
||||
import net.sf.freecol.common.model.Direction;
|
||||
import net.sf.freecol.common.model.Europe;
|
||||
import net.sf.freecol.common.model.EuropeanNationType;
|
||||
import net.sf.freecol.common.model.Game;
|
||||
|
@ -51,8 +71,6 @@ import net.sf.freecol.common.model.IndianSettlement;
|
|||
import net.sf.freecol.common.model.LandMap;
|
||||
import net.sf.freecol.common.model.LostCityRumour;
|
||||
import net.sf.freecol.common.model.Map;
|
||||
import net.sf.freecol.common.model.Direction;
|
||||
import net.sf.freecol.common.model.Map.Position;
|
||||
import net.sf.freecol.common.model.Nation;
|
||||
import net.sf.freecol.common.model.NationType;
|
||||
import net.sf.freecol.common.model.Player;
|
||||
|
@ -69,8 +87,7 @@ import net.sf.freecol.common.option.MapGeneratorOptions;
|
|||
import net.sf.freecol.common.option.OptionGroup;
|
||||
import net.sf.freecol.common.util.LogBuilder;
|
||||
import net.sf.freecol.common.util.RandomChoice;
|
||||
import static net.sf.freecol.common.util.CollectionUtils.*;
|
||||
import static net.sf.freecol.common.util.RandomUtils.*;
|
||||
import net.sf.freecol.common.util.RandomUtils.RandomIntCache;
|
||||
import net.sf.freecol.server.model.ServerBuilding;
|
||||
import net.sf.freecol.server.model.ServerColony;
|
||||
import net.sf.freecol.server.model.ServerIndianSettlement;
|
||||
|
@ -96,41 +113,6 @@ public class SimpleMapGenerator implements MapGenerator {
|
|||
*/
|
||||
private static final float MIN_DISTANCE_FROM_POLE = 0.30f;
|
||||
|
||||
|
||||
private static class Territory {
|
||||
public ServerRegion region;
|
||||
public Tile tile;
|
||||
public final Player player;
|
||||
public int numberOfSettlements;
|
||||
|
||||
public Territory(Player player, Tile tile) {
|
||||
this.player = player;
|
||||
this.tile = tile;
|
||||
}
|
||||
|
||||
public Territory(Player player, ServerRegion region) {
|
||||
this.player = player;
|
||||
this.region = region;
|
||||
}
|
||||
|
||||
public Tile getCenterTile(Map map) {
|
||||
if (tile != null) return tile;
|
||||
int[] xy = region.getCenter();
|
||||
return map.getTile(xy[0], xy[1]);
|
||||
}
|
||||
|
||||
|
||||
// Override Object
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return player + " territory at " + region;
|
||||
}
|
||||
}
|
||||
|
||||
/** The random number source. */
|
||||
private final Random random;
|
||||
|
||||
|
@ -317,164 +299,117 @@ public class SimpleMapGenerator implements MapGenerator {
|
|||
LogBuilder lb) {
|
||||
final Game game = map.getGame();
|
||||
final Specification spec = game.getSpecification();
|
||||
final boolean importSettlements = game.getMapGeneratorOptions()
|
||||
.getBoolean(MapGeneratorOptions.IMPORT_SETTLEMENTS);
|
||||
if (importSettlements && importMap != null) {
|
||||
if (importIndianSettlements(map, importMap, lb)) return;
|
||||
// Fall through and create them
|
||||
final boolean importSettlements = game.getMapGeneratorOptions() .getBoolean(MapGeneratorOptions.IMPORT_SETTLEMENTS);
|
||||
if (importSettlements && importMap != null && importIndianSettlements(map, importMap, lb)) {
|
||||
return;
|
||||
}
|
||||
|
||||
float shares = 0f;
|
||||
List<IndianSettlement> settlements = new ArrayList<>();
|
||||
HashMap<String, Territory> territoryMap = new HashMap<>();
|
||||
|
||||
List<Player> players = game.getLiveNativePlayerList();
|
||||
List<Player> indians = new ArrayList<>(players.size());
|
||||
for (Player player : players) {
|
||||
switch (player.getNationType().getNumberOfSettlements()) {
|
||||
case HIGH:
|
||||
shares += 4;
|
||||
break;
|
||||
case AVERAGE:
|
||||
shares += 3;
|
||||
break;
|
||||
case LOW:
|
||||
shares += 2;
|
||||
break;
|
||||
}
|
||||
indians.add(player);
|
||||
List<String> regionKeys
|
||||
= ((IndianNationType)player.getNationType()).getRegions();
|
||||
Territory territory = null;
|
||||
if (regionKeys == null || regionKeys.isEmpty()) {
|
||||
territory = new Territory(player, map.getRandomLandTile(random));
|
||||
territoryMap.put(player.getId(), territory);
|
||||
} else {
|
||||
for (String key : regionKeys) {
|
||||
if (territoryMap.get(key) == null) {
|
||||
ServerRegion region = (ServerRegion)map.getRegionByKey(key);
|
||||
if (region == null) {
|
||||
territory = new Territory(player, map.getRandomLandTile(random));
|
||||
} else {
|
||||
territory = new Territory(player, region);
|
||||
}
|
||||
territoryMap.put(key, territory);
|
||||
lb.add("Allocated region ", key,
|
||||
" for ", player, ".\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (territory == null) {
|
||||
lb.add("Failed to allocate preferred region ",
|
||||
first(regionKeys), " for ", player.getNation(), "\n");
|
||||
outer: for (String key : regionKeys) {
|
||||
Territory otherTerritory = territoryMap.get(key);
|
||||
for (String otherKey : ((IndianNationType) otherTerritory.player.getNationType())
|
||||
.getRegions()) {
|
||||
if (territoryMap.get(otherKey) == null) {
|
||||
ServerRegion foundRegion = otherTerritory.region;
|
||||
otherTerritory.region = (ServerRegion)map.getRegionByKey(otherKey);
|
||||
territoryMap.put(otherKey, otherTerritory);
|
||||
territory = new Territory(player, foundRegion);
|
||||
territoryMap.put(key, territory);
|
||||
break outer;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (territory == null) {
|
||||
lb.add("Unable to find free region for ",
|
||||
player.getName(), "\n");
|
||||
territory = new Territory(player, map.getRandomLandTile(random));
|
||||
territoryMap.put(player.getId(), territory);
|
||||
}
|
||||
}
|
||||
}
|
||||
final List<Player> nativePlayers = game.getLiveNativePlayerList();
|
||||
if (nativePlayers.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (indians.isEmpty()) return;
|
||||
|
||||
|
||||
// Examine all the non-polar settleable tiles in a random
|
||||
// order picking out as many as possible suitable tiles for
|
||||
// native settlements such that can be guaranteed at least one
|
||||
// layer of surrounding tiles to own.
|
||||
List<Tile> allTiles = map.getShuffledTiles(random);
|
||||
final List<Tile> allTiles = map.getShuffledTiles(random);
|
||||
final int minDistance = spec.getRange(GameOptions.SETTLEMENT_NUMBER);
|
||||
List<Tile> settlementTiles = new ArrayList<>();
|
||||
|
||||
final Set<Tile> settlementTiles = new LinkedHashSet<>();
|
||||
for (Tile tile : allTiles) {
|
||||
if (!tile.isPolar()
|
||||
&& suitableForNativeSettlement(tile)
|
||||
&& none(settlementTiles, t -> t.getDistanceTo(tile) < minDistance))
|
||||
settlementTiles.add(tile);
|
||||
}
|
||||
randomShuffle(logger, "Settlement tiles", settlementTiles, random);
|
||||
|
||||
// Check number of settlements.
|
||||
int settlementsToPlace = settlementTiles.size();
|
||||
float share = settlementsToPlace / shares;
|
||||
if (settlementTiles.size() < indians.size()) {
|
||||
// FIXME: something drastic to boost the settlement number
|
||||
lb.add("There are only ", settlementTiles.size(),
|
||||
" settlement sites.\n",
|
||||
" This is smaller than ", indians.size(),
|
||||
" the number of tribes.\n");
|
||||
}
|
||||
|
||||
// Find the capitals
|
||||
List<Territory> territories
|
||||
= new ArrayList<>(territoryMap.values());
|
||||
int settlementsPlaced = 0;
|
||||
for (Territory territory : territories) {
|
||||
switch (territory.player.getNationType().getNumberOfSettlements()) {
|
||||
case HIGH:
|
||||
territory.numberOfSettlements = Math.round(4 * share);
|
||||
break;
|
||||
case AVERAGE:
|
||||
territory.numberOfSettlements = Math.round(3 * share);
|
||||
break;
|
||||
case LOW:
|
||||
territory.numberOfSettlements = Math.round(2 * share);
|
||||
break;
|
||||
if (tile.isPolar()) {
|
||||
continue;
|
||||
}
|
||||
int radius = territory.player.getNationType().getCapitalType()
|
||||
.getClaimableRadius();
|
||||
IndianSettlement is = placeCapital(map, territory, radius,
|
||||
new ArrayList<>(settlementTiles), lb);
|
||||
if (is != null) {
|
||||
settlements.add(is);
|
||||
settlementsPlaced++;
|
||||
settlementTiles.remove(is.getTile());
|
||||
if (!suitableForNativeSettlement(tile)) {
|
||||
continue;
|
||||
}
|
||||
if (any(settlementTiles, t -> t.getDistanceTo(tile) < minDistance)) {
|
||||
continue;
|
||||
}
|
||||
settlementTiles.add(tile);
|
||||
}
|
||||
|
||||
// Sort tiles from the edges of the map inward
|
||||
settlementTiles.sort(Tile.edgeDistanceComparator);
|
||||
|
||||
// Now place other settlements
|
||||
while (!settlementTiles.isEmpty() && !territories.isEmpty()) {
|
||||
Tile tile = settlementTiles.remove(0);
|
||||
if (tile.getOwner() != null) continue; // No close overlap
|
||||
|
||||
Territory territory = getClosestTerritory(tile, territories);
|
||||
int radius = territory.player.getNationType().getSettlementType(false)
|
||||
.getClaimableRadius();
|
||||
// Insist that the settlement can not be linear
|
||||
if (territory.player.getClaimableTiles(tile, radius).size()
|
||||
> 2 * radius + 1) {
|
||||
String name = (territory.region == null) ? "default region"
|
||||
: territory.region.toString();
|
||||
lb.add("Placing a ", territory.player,
|
||||
" camp in region: ", name,
|
||||
" at tile: ", tile, "\n");
|
||||
settlements.add(placeIndianSettlement(territory.player,
|
||||
false, tile, map, lb));
|
||||
settlementsPlaced++;
|
||||
territory.numberOfSettlements--;
|
||||
if (territory.numberOfSettlements <= 0) {
|
||||
territories.remove(territory);
|
||||
|
||||
final java.util.Map<Player, Set<Tile>> designatedArea = new HashMap<>();
|
||||
for (Player player : nativePlayers) {
|
||||
final Area area = map.getGame().getNationStartingArea(player.getNation());
|
||||
if (area != null && !area.isEmpty()) {
|
||||
final Set<Tile> settlementTilesForNation = area.getTiles().stream()
|
||||
.filter(t -> settlementTiles.contains(t))
|
||||
.collect(Collectors.toCollection(LinkedHashSet::new));
|
||||
if (settlementTilesForNation.isEmpty()) {
|
||||
logger.warning("No settlements for nationType=" + player.getNationId());
|
||||
}
|
||||
|
||||
designatedArea.put(player, settlementTilesForNation);
|
||||
}
|
||||
}
|
||||
for (Player player : nativePlayers) {
|
||||
if (designatedArea.containsKey(player)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final IndianNationType indianNationType = (IndianNationType) player.getNationType();
|
||||
final List<Rectangle> otherRegions = indianNationType.getRegions().stream()
|
||||
.map(key -> ((ServerRegion) map.getRegionByKey(key)).getBounds())
|
||||
.filter(bounds -> !bounds.isEmpty())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (otherRegions.isEmpty()) {
|
||||
logger.warning("No area or regions found for nationType=" + player.getNationId());
|
||||
continue;
|
||||
}
|
||||
|
||||
final Set<Tile> settlementTilesForNation = settlementTiles.stream()
|
||||
.filter(t -> otherRegions.stream().anyMatch(bounds -> bounds.contains(t.getX(), t.getY())))
|
||||
.collect(Collectors.toCollection(LinkedHashSet::new));
|
||||
|
||||
if (settlementTilesForNation.isEmpty()) {
|
||||
logger.warning("No settlements in region for nationType=" + player.getNationId());
|
||||
}
|
||||
designatedArea.put(player, settlementTilesForNation);
|
||||
}
|
||||
|
||||
// Place the capitals:
|
||||
for (Player player : nativePlayers) {
|
||||
final Set<Tile> allowedPlacements = designatedArea.get(player);
|
||||
if (allowedPlacements == null) {
|
||||
continue;
|
||||
}
|
||||
for (Tile settlementTile : new ArrayList<>(settlementTiles)) {
|
||||
if (!allowedPlacements.contains(settlementTile)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final IndianSettlement capital = placeIndianSettlement(player, true, settlementTile, map, lb);
|
||||
settlements.add(capital);
|
||||
settlementTiles.remove(settlementTile);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (Tile settlementTile : settlementTiles) {
|
||||
final List<Player> players = new ArrayList<>(designatedArea.keySet());
|
||||
Collections.shuffle(players, random);
|
||||
|
||||
final Player owner = players.stream().filter(p -> {
|
||||
final Set<Tile> tiles = designatedArea.get(p);
|
||||
if (tiles == null) {
|
||||
return false;
|
||||
}
|
||||
return tiles.contains(settlementTile);
|
||||
})
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
|
||||
if (owner == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final IndianSettlement settlement = placeIndianSettlement(owner, false, settlementTile, map, lb);
|
||||
settlements.add(settlement);
|
||||
}
|
||||
|
||||
// Grow some more tiles.
|
||||
// FIXME: move the magic numbers below to the spec
|
||||
// Also collect the skills provided
|
||||
|
@ -566,8 +501,6 @@ public class SimpleMapGenerator implements MapGenerator {
|
|||
" x ", iss.get(0).getLearnableSkill().getSuffix());
|
||||
}
|
||||
}
|
||||
lb.add("\nCreated ", settlementsPlaced,
|
||||
" Indian settlements of maximum ", settlementsToPlace, ".\n");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -614,58 +547,6 @@ public class SimpleMapGenerator implements MapGenerator {
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the closest territory to a given tile from a list of choices.
|
||||
*
|
||||
* @param tile The {@code Tile} to search from.
|
||||
* @param territories The list of {@code Territory}s to choose from.
|
||||
* @return The closest {@code Territory} found, or null if none.
|
||||
*/
|
||||
private Territory getClosestTerritory(final Tile tile,
|
||||
List<Territory> territories) {
|
||||
final Map map = tile.getMap();
|
||||
final Comparator<Territory> comp = Comparator.comparingInt(t ->
|
||||
map.getDistance(tile, t.getCenterTile(map)));
|
||||
return minimize(territories, comp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Place a native capital in a territory.
|
||||
*
|
||||
* @param map The {@code Map} to place the settlement in.
|
||||
* @param territory The {@code Territory} within the map.
|
||||
* @param radius The settlement radius.
|
||||
* @param tiles A list of {@code Tile}s to select from.
|
||||
* @param lb A {@code LogBuilder} to log to.
|
||||
* @return The {@code IndianSettlement} placed, or null if
|
||||
* none placed.
|
||||
*/
|
||||
private IndianSettlement placeCapital(final Map map, Territory territory,
|
||||
int radius, List<Tile> tiles,
|
||||
LogBuilder lb) {
|
||||
final Tile center = territory.getCenterTile(map);
|
||||
final Predicate<Tile> terrPred = t ->
|
||||
territory.player.getClaimableTiles(t, radius).size()
|
||||
>= (2 * radius + 1) * (2 * radius + 1) / 2;
|
||||
final Comparator<Tile> comp
|
||||
= Comparator.comparingInt(t -> t.getDistanceTo(center));
|
||||
// Choose a tile that is free and half the expected tile claims
|
||||
// can succeed, preventing capitals on small islands.
|
||||
Tile t = first(transform(tiles, terrPred, Function.<Tile>identity(),
|
||||
comp));
|
||||
if (t == null) return null;
|
||||
|
||||
String name = (territory.region == null) ? "default region"
|
||||
: territory.region.toString();
|
||||
lb.add("Placing the ", territory.player,
|
||||
" capital in region: ", name, " at tile: ", t, "\n");
|
||||
IndianSettlement is = placeIndianSettlement(territory.player,
|
||||
true, t, map, lb);
|
||||
territory.numberOfSettlements--;
|
||||
territory.tile = t;
|
||||
return is;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a {@code IndianSettlement} at the given position.
|
||||
*
|
||||
|
@ -1132,7 +1013,7 @@ public class SimpleMapGenerator implements MapGenerator {
|
|||
// Create terrain.
|
||||
Map map = new TerrainGenerator(this.random)
|
||||
.generateMap(game, importMap, landMap, lb);
|
||||
|
||||
|
||||
// Decorate the map.
|
||||
makeNativeSettlements(map, importMap, lb);
|
||||
makeLostCityRumours(map, importMap, lb);
|
||||
|
|
|
@ -30,6 +30,7 @@ import java.util.logging.Logger;
|
|||
import net.sf.freecol.common.model.Game;
|
||||
import net.sf.freecol.common.model.LandMap;
|
||||
import net.sf.freecol.common.model.Map;
|
||||
import net.sf.freecol.common.model.Area;
|
||||
import net.sf.freecol.common.model.Direction;
|
||||
import net.sf.freecol.common.model.Region;
|
||||
import net.sf.freecol.common.model.Region.RegionType;
|
||||
|
@ -931,6 +932,13 @@ public class TerrainGenerator {
|
|||
|
||||
// Probably only needed on import of old maps.
|
||||
map.fixupRegions();
|
||||
|
||||
if (importMap != null) {
|
||||
for (Area importMapArea : importMap.getGame().getAreas()) {
|
||||
game.addArea(new Area(game, importMapArea));
|
||||
}
|
||||
}
|
||||
game.generateDefaultAreas();
|
||||
|
||||
// Add the bonuses only after the map is completed.
|
||||
// Otherwise we risk creating resources on fields where they
|
||||
|
|
Loading…
Reference in New Issue