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