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