001package com.fs.starfarer.api.impl.campaign; 002 003import java.util.ArrayList; 004import java.util.List; 005 006import com.fs.starfarer.api.GameState; 007import com.fs.starfarer.api.Global; 008import com.fs.starfarer.api.campaign.CampaignFleetAPI; 009import com.fs.starfarer.api.campaign.CargoAPI; 010import com.fs.starfarer.api.campaign.CargoStackAPI; 011import com.fs.starfarer.api.campaign.econ.MarketAPI; 012import com.fs.starfarer.api.campaign.listeners.RefitScreenListener; 013import com.fs.starfarer.api.combat.ShipVariantAPI; 014import com.fs.starfarer.api.fleet.FleetMemberAPI; 015import com.fs.starfarer.api.loading.HullModSpecAPI; 016import com.fs.starfarer.api.util.ListMap; 017import com.fs.starfarer.api.util.Misc; 018 019public class HullModItemManager implements RefitScreenListener { 020 021 public static class HullModInstallData { 022 public String modId; 023 public CargoStackAPI item; 024 } 025 026 public static class HullModDiff { 027 public List<String> needItems = new ArrayList<>(); 028 public List<String> noLongerNeedItems = new ArrayList<>(); 029 } 030 031 public static HullModItemManager getInstance() { 032 String key = "$hullModItemManager"; 033 HullModItemManager manager = (HullModItemManager) Global.getSector().getMemoryWithoutUpdate().get(key); 034 if (manager == null) { 035 manager = new HullModItemManager(); 036 Global.getSector().getMemoryWithoutUpdate().set(key, manager); 037 } 038 return manager; 039 } 040 041 protected ListMap<HullModInstallData> map = new ListMap<>(); 042 043 public HullModItemManager() { 044 Global.getSector().getListenerManager().addListener(this); 045 } 046 047 protected Object readResolve() { 048 return this; 049 } 050 051 public boolean isRequiredItemAvailable(String modId, FleetMemberAPI member, ShipVariantAPI currentVariant, MarketAPI dockedAt) { 052 if (Global.getCurrentState() == GameState.TITLE) return true; 053 054 if (member == null || currentVariant == null) return true; 055 056 HullModSpecAPI mod = Global.getSettings().getHullModSpec(modId); 057 CargoStackAPI req = mod.getEffect().getRequiredItem(); 058 if (req == null) return true; 059 060 CampaignFleetAPI fleet = Global.getSector().getPlayerFleet(); 061 if (fleet == null) return true; 062 063 String memberId = member.getId(); 064 List<HullModInstallData> installed = map.getList(memberId); 065 List<String> installedIds = new ArrayList<>(); 066 for (HullModInstallData data : installed) { 067 installedIds.add(data.modId); 068 } 069 070 if (installedIds.contains(modId)) return true; 071 072 int available = getNumAvailableMinusUnconfirmed(req, member, currentVariant, dockedAt); 073 return available >= 1; 074 } 075 076 public int getNumAvailableMinusUnconfirmed(CargoStackAPI req, FleetMemberAPI member, ShipVariantAPI currentVariant, MarketAPI dockedAt) { 077 int requiredAlreadyByUnconfirmed = getNumUnconfirmed(req, member, currentVariant); 078 int available = getNumAvailable(req, dockedAt); 079 return available - requiredAlreadyByUnconfirmed; 080 } 081 public int getNumUnconfirmed(CargoStackAPI req, FleetMemberAPI member, ShipVariantAPI currentVariant) { 082 if (member == null || currentVariant == null) return 0; 083 084 HullModDiff diff = getHullmodDiff(member, currentVariant); 085 int requiredAlreadyByUnconfirmed = 0; 086 for (String otherModId : diff.needItems) { 087 HullModSpecAPI otherMod = Global.getSettings().getHullModSpec(otherModId); 088 CargoStackAPI otherReq = otherMod.getEffect().getRequiredItem(); 089 if (otherReq == null) continue; 090 091 if (req.getType() == otherReq.getType() && req.getData() != null && 092 req.getData().equals(otherReq.getData())) { 093 requiredAlreadyByUnconfirmed++; 094 } 095 } 096 for (String otherModId : diff.noLongerNeedItems) { 097 HullModSpecAPI otherMod = Global.getSettings().getHullModSpec(otherModId); 098 CargoStackAPI otherReq = otherMod.getEffect().getRequiredItem(); 099 if (otherReq == null) continue; 100 101 if (req.getType() == otherReq.getType() && req.getData() != null && 102 req.getData().equals(otherReq.getData())) { 103 requiredAlreadyByUnconfirmed--; 104 } 105 } 106 return requiredAlreadyByUnconfirmed; 107 } 108 109 public int getNumAvailable(CargoStackAPI req, MarketAPI dockedAt) { 110 CampaignFleetAPI fleet = Global.getSector().getPlayerFleet(); 111 if (fleet == null) return 0; 112 113 CargoAPI cargo = fleet.getCargo(); 114 115 float quantity = (int) Math.round(cargo.getQuantity(req.getType(), req.getData())); 116 if (dockedAt != null) { 117 cargo = Misc.getStorageCargo(dockedAt); 118 if (cargo != null) { 119 quantity += (int) Math.round(cargo.getQuantity(req.getType(), req.getData())); 120 } 121 } 122 return (int) Math.round(quantity); 123 } 124 125 public CargoAPI getItemsInUseBy(FleetMemberAPI member) { 126 CargoAPI cargo = Global.getFactory().createCargo(true); 127 128 String memberId = member.getId(); 129 List<HullModInstallData> installed = map.getList(memberId); 130 for (HullModInstallData data : installed) { 131 cargo.addItems(data.item.getType(), data.item.getData(), 1f); 132 } 133 134// cargo.addSpecial(new SpecialItemData(Items.SYNCHROTRON, null), 1); 135// cargo.addSpecial(new SpecialItemData(Items.CATALYTIC_CORE, null), 1); 136// cargo.addSpecial(new SpecialItemData(Items.BIOFACTORY_EMBRYO, null), 1); 137// cargo.addSpecial(new SpecialItemData(Items.ORBITAL_FUSION_LAMP, null), 1); 138// cargo.addSpecial(new SpecialItemData(Items.CRYOARITHMETIC_ENGINE, null), 1); 139// cargo.addSpecial(new SpecialItemData(Items.DEALMAKER_HOLOSUITE, null), 1); 140 141 cargo.sort(); 142 return cargo; 143 } 144 145 public void giveBackAllItems(FleetMemberAPI member) { 146 giveBackAllItems(member, null); 147 } 148 149 public void giveBackAllItems(FleetMemberAPI member, CargoAPI cargo) { 150 String memberId = member.getId(); 151 List<HullModInstallData> installed = map.getList(memberId); 152 List<String> installedIds = new ArrayList<>(); 153 for (HullModInstallData data : installed) { 154 installedIds.add(data.modId); 155 } 156 for (String modId : installedIds) { 157 giveBackRequiredItems(modId, member, cargo); 158 } 159 160 map.cleanupEmptyLists(); 161 } 162 163 @Override 164 public void reportFleetMemberVariantSaved(FleetMemberAPI member, MarketAPI dockedAt) { 165 HullModDiff diff = getHullmodDiff(member, member.getVariant()); 166 for (String modId : diff.needItems) { 167 takeRequiredItems(modId, member, dockedAt); 168 } 169 for (String modId : diff.noLongerNeedItems) { 170 giveBackRequiredItems(modId, member, null); 171 } 172 173 map.cleanupEmptyLists(); 174 } 175 176 public HullModDiff getHullmodDiff(FleetMemberAPI member, ShipVariantAPI currentVariant) { 177 HullModDiff diff = new HullModDiff(); 178 179 String memberId = member.getId(); 180 List<HullModInstallData> installed = map.getList(memberId); 181 List<String> installedIds = new ArrayList<>(); 182 for (HullModInstallData data : installed) { 183 installedIds.add(data.modId); 184 } 185 186 for (String modId : currentVariant.getHullMods()) { 187 if (member.getHullSpec().isBuiltInMod(modId)) continue; 188 HullModSpecAPI mod = Global.getSettings().getHullModSpec(modId); 189 CargoStackAPI req = mod.getEffect().getRequiredItem(); 190 if (req == null) continue; 191 192 if (!installedIds.contains(modId)) { 193 diff.needItems.add(modId); 194 } 195 installedIds.remove(modId); 196 } 197 198 diff.noLongerNeedItems.addAll(installedIds); 199 200 return diff; 201 } 202 203 public void takeRequiredItems(String modId, FleetMemberAPI member, MarketAPI dockedAt) { 204 HullModSpecAPI mod = Global.getSettings().getHullModSpec(modId); 205 CargoStackAPI req = mod.getEffect().getRequiredItem(); 206 if (req == null) return; 207 208 String memberId = member.getId(); 209 List<HullModInstallData> installed = map.getList(memberId); 210 for (HullModInstallData data : installed) { 211 if (data.modId.equals(modId)) return; 212 } 213 214 215 CampaignFleetAPI fleet = Global.getSector().getPlayerFleet(); 216 if (fleet == null) return; 217 CargoAPI cargo = fleet.getCargo(); 218 219 boolean removed = false; 220 if (cargo.getQuantity(req.getType(), req.getData()) >= 1f) { 221 cargo.removeItems(req.getType(), req.getData(), 1); 222 removed = true; 223 } 224 225 if (!removed && dockedAt != null) { 226 cargo = Misc.getStorageCargo(dockedAt); 227 if (cargo != null && cargo.getQuantity(req.getType(), req.getData()) >= 1f) { 228 cargo.removeItems(req.getType(), req.getData(), 1); 229 removed = true; 230 } 231 } 232 233 if (!removed) return; 234 235 HullModInstallData data = new HullModInstallData(); 236 data.modId = modId; 237 data.item = req; 238 map.add(memberId, data); 239 } 240 241 public void giveBackRequiredItems(String modId, FleetMemberAPI member, CargoAPI cargo) { 242 HullModSpecAPI mod = Global.getSettings().getHullModSpec(modId); 243 CargoStackAPI req = mod.getEffect().getRequiredItem(); 244 if (req == null) return; 245 246 if (cargo == null) { 247 CampaignFleetAPI fleet = Global.getSector().getPlayerFleet(); 248 if (fleet == null) return; 249 cargo = fleet.getCargo(); 250 } 251 252 String memberId = member.getId(); 253 List<HullModInstallData> installed = map.getList(memberId); 254 for (HullModInstallData data : installed) { 255 if (data.modId.equals(modId)) { 256 map.remove(memberId, data); 257 cargo.addItems(data.item.getType(), data.item.getData(), 1); 258 break; 259 } 260 } 261 } 262} 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278