001package com.fs.starfarer.api.impl.campaign.shared;
002
003import java.util.ArrayList;
004import java.util.Collections;
005import java.util.Comparator;
006import java.util.List;
007
008import org.json.JSONException;
009import org.json.JSONObject;
010
011import com.fs.starfarer.api.Global;
012import com.fs.starfarer.api.campaign.CargoAPI.CargoItemType;
013import com.fs.starfarer.api.campaign.InteractionDialogAPI;
014import com.fs.starfarer.api.campaign.JumpPointAPI;
015import com.fs.starfarer.api.campaign.JumpPointAPI.JumpDestination;
016import com.fs.starfarer.api.campaign.LocationAPI;
017import com.fs.starfarer.api.campaign.SectorEntityToken;
018import com.fs.starfarer.api.campaign.SpecialItemData;
019import com.fs.starfarer.api.impl.campaign.JumpPointInteractionDialogPluginImpl;
020import com.fs.starfarer.api.impl.campaign.ids.Entities;
021import com.fs.starfarer.api.impl.campaign.ids.Factions;
022import com.fs.starfarer.api.impl.campaign.ids.Items;
023import com.fs.starfarer.api.impl.campaign.rulecmd.AddRemoveCommodity;
024
025public class WormholeManager {
026        
027        public static String KEY = "$core_wormholeManager";
028        
029        public static String WORMHOLE = "$wormhole";
030        public static String LIMBO_STABLE_LOCATION = "$limboStableLocation";
031        public static String GOT_WORMHOLE_CALIBRATION_DATA = "$gotWormholeCalibrationData";
032        
033        
034//      public static float UNSTABLE_DURATION_MIN = 365f * 0.75f;
035//      public static float UNSTABLE_DURATION_MAX = 365 * 1.25f;
036        public static float UNSTABLE_DURATION_MIN = 180f * 0.75f;
037        public static float UNSTABLE_DURATION_MAX = 180f * 1.25f;
038        
039        public static WormholeManager get() {
040                Object obj = Global.getSector().getMemoryWithoutUpdate().get(KEY);
041                if (obj != null) return (WormholeManager) obj;
042                
043                WormholeManager data = new WormholeManager();
044                Global.getSector().getMemoryWithoutUpdate().set(KEY, data);
045                return data;
046        }
047        
048        public static class WormholeItemData {
049                public String category;
050                public String id;
051                public String name;
052                public WormholeItemData(String jsonStr) {
053                        try {
054                                JSONObject json = new JSONObject(jsonStr);
055                                category = json.getString("cat");
056                                id = json.getString("id");
057                                name = json.getString("name");
058                        } catch (JSONException e) {
059                                throw new RuntimeException("Unable to parse Wormhole Anchor data [" + jsonStr + "]", e);
060                        }
061                }
062                public WormholeItemData(String category, String id, String name) {
063                        this.category = category;
064                        this.id = id;
065                        this.name = name;
066                }
067                
068                public String toJsonStr() {
069                        try {
070                                JSONObject json = new JSONObject();
071                                json.put("cat", category);
072                                json.put("id", id);
073                                json.put("name", name);
074                                return json.toString();
075                        } catch (JSONException e) {
076                                return null;
077                        }
078                }
079        }
080        
081        public static class WormholeData {
082                public SpecialItemData item;
083                public JumpPointAPI jumpPoint;
084                public WormholeItemData itemData;
085                public WormholeData(SpecialItemData item, JumpPointAPI jumpPoint, WormholeItemData itemData) {
086                        this.item = item;
087                        this.jumpPoint = jumpPoint;
088                        this.itemData = itemData;
089                }
090        }
091        
092        public static boolean willWormholeBecomeUnstable(SectorEntityToken stableLocation) {
093                boolean makeUnstable = true;
094                if (stableLocation.getMemoryWithoutUpdate().getBoolean(LIMBO_STABLE_LOCATION) &&
095                                Global.getSector().getPlayerMemoryWithoutUpdate().getBoolean(GOT_WORMHOLE_CALIBRATION_DATA)) {
096                        makeUnstable = false;
097                }
098                return makeUnstable;
099        }
100        
101        
102        protected List<WormholeData> deployed = new ArrayList<WormholeData>();
103        
104
105        public void updateWormholeDestinations() {
106                List<WormholeData> sorted = new ArrayList<WormholeData>(deployed);
107                Collections.sort(sorted, new Comparator<WormholeData>() {
108                        public int compare(WormholeData o1, WormholeData o2) {
109                                return o1.itemData.name.compareTo(o2.itemData.name);
110                        }
111                });
112                
113                for (WormholeData data : deployed) {
114                        JumpPointAPI jp = data.jumpPoint;
115                        jp.clearDestinations();
116                        boolean added = false;
117                        for (WormholeData other : sorted) {
118                                if (other == data) continue;
119                                if (!data.itemData.category.equals(other.itemData.category)) continue;
120
121                                jp.addDestination(new JumpDestination(other.jumpPoint, "wormhole terminus " + other.itemData.name));
122                                added = true;
123                        }
124                        if (added) {
125                                jp.setStandardWormholeToStarfieldVisual();
126                        } else {
127                                jp.setStandardWormholeToNothingVisual();
128                        }
129                }
130        }
131        
132        public JumpPointAPI addWormhole(SpecialItemData item, SectorEntityToken stableLocation, InteractionDialogAPI dialog) {
133                WormholeItemData itemData = new WormholeItemData(item.getData());
134                
135                WormholeData data = getDeployed(itemData.id);
136                if (data != null) return data.jumpPoint;
137                
138                boolean makeUnstable = willWormholeBecomeUnstable(stableLocation);
139                
140                LocationAPI loc = stableLocation.getContainingLocation();
141                JumpPointAPI wormhole = Global.getFactory().createJumpPoint(null, "Wormhole Terminus " + itemData.name);
142                wormhole.setRadius(75f);
143                //wormhole.setStandardWormholeToStarfieldVisual();
144                
145                wormhole.getMemoryWithoutUpdate().set(WORMHOLE, true);
146                if (makeUnstable) {
147                        float dur = UNSTABLE_DURATION_MIN + (UNSTABLE_DURATION_MAX - UNSTABLE_DURATION_MIN) * (float) Math.random();
148                        if (Global.getSettings().isDevMode() && !Global.getSettings().getBoolean("playtestingMode")) {
149                                dur *= 0.01f;
150                        }
151                        wormhole.getMemoryWithoutUpdate().set(JumpPointInteractionDialogPluginImpl.UNSTABLE_KEY, true, dur);
152                }
153                
154                loc.addEntity(wormhole);
155                if (stableLocation.getOrbit() != null) {
156                        wormhole.setOrbit(stableLocation.getOrbit().makeCopy());
157                }
158                wormhole.setLocation(stableLocation.getLocation().x, stableLocation.getLocation().y);
159                loc.removeEntity(stableLocation);
160                //Misc.fadeAndExpire(stableLocation);
161                
162                // DO NOT set this, it causes the original stable location to be shown on the map
163                // when the player is not in-system
164                //wormhole.getMemoryWithoutUpdate().set("$originalStableLocation", stableLocation);
165                
166                deployed.add(new WormholeData(item, wormhole, itemData));
167                
168                if (dialog != null && dialog.getTextPanel() != null) {
169                        Global.getSector().getPlayerFleet().getCargo().removeItems(CargoItemType.SPECIAL, item, 1);
170                        AddRemoveCommodity.addItemLossText(item, 1, dialog.getTextPanel());
171                }
172                
173                updateWormholeDestinations();
174                
175                return wormhole;
176        }
177        
178        public void removeWormhole(JumpPointAPI jp, InteractionDialogAPI dialog) {
179                for (WormholeData data : deployed) {
180                        if (data.jumpPoint == jp) {
181                                LocationAPI loc = jp.getContainingLocation();
182                                SectorEntityToken stableLocation = loc.addCustomEntity(null,
183                                                                                                                         null,
184                                                 Entities.STABLE_LOCATION, // type of object, defined in custom_entities.json
185                                                 Factions.NEUTRAL); // faction
186                                if (jp.getOrbit() != null) {
187                                        stableLocation.setOrbit(jp.getOrbit().makeCopy());
188                                }
189                                //Misc.fadeAndExpire(jp);
190                                loc.removeEntity(jp);
191                                
192                                if (dialog != null && dialog.getTextPanel() != null) {
193                                        Global.getSector().getPlayerFleet().getCargo().addItems(CargoItemType.SPECIAL, data.item, 1);
194                                        AddRemoveCommodity.addItemGainText(data.item, 1, dialog.getTextPanel());
195                                }
196                                
197                                deployed.remove(data);
198                                
199                                updateWormholeDestinations();
200                                break;
201                        }
202                }
203        }
204        
205        public boolean isDeployed(String id) {
206                if (id == null) return false;
207                for (WormholeData data : deployed) {
208                        if (id.equals(data.itemData.id)) return true;
209                }
210                return false;
211        }
212        public WormholeData getDeployed(String id) {
213                if (id == null) return null;
214                for (WormholeData data : deployed) {
215                        if (id.equals(data.itemData.id)) return data;
216                }
217                return null;
218        }
219        
220        public static SpecialItemData createWormholeAnchor(String id, String name) {
221                return createWormholeAnchor("standard", id, name);
222        }
223        public static SpecialItemData createWormholeAnchor(String category, String id, String name) {
224                WormholeItemData itemData = new WormholeItemData(category, id, name);
225                SpecialItemData item = new SpecialItemData(Items.WORMHOLE_ANCHOR, itemData.toJsonStr());
226                return item;
227        }
228        
229}
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248