Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ public enum Brackets {
VASSAL_TAX("Vassal Tax"),
DIVIDEND_TAX("Dividend Tax"),
TARIFFS("Tariffs"),
HUB_TAX("Hub Tax"),
VEHICLE_TAX("Vehicle Tax (% of upkeep)"),
REGISTRATION_FEE("Registration Fee (x upkeep)"),
TRANSFER_FEE("Transfer Fee (x upkeep)");
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/net/tfminecraft/simplefactions/enums/Rules.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ public enum Rules {
GUILD_TAX("Can Collect Guild Taxes", true), //Implemented
DIVIDEND_TAX("Can Collect Dividend Taxes", true), //Implemented
TARIFFS("Can Impose Tariffs", true), //Implemented
HUB_TAX("Can Collect Hub Taxes", true), //Implemented
SUPPLY_HUBS("Can Build Supply Hubs", true), //Implemented
VEHICLE_TAX("Can Collect Vehicle Tax", true), //Implemented
REGISTRATION_FEE("Can Charge Vehicle Registration Fees", true), //Implemented
TRANSFER_FEE("Can Charge Vehicle Transfer Fees", true), //Implemented
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ public static List<Link> linksFor(Guild guild) {
if (guild == null || guild.getId() == null) {
return List.of();
}
return links.getOrDefault(guild.getId(), List.of());
List<Link> cached = links.getOrDefault(guild.getId(), List.of());
return cached.isEmpty() || SupplyHubService.allowsSupplyHubs(guild) ? cached : List.of();
}

/** Rebuilds every guild's connections. Server thread only. */
Expand Down Expand Up @@ -179,9 +180,6 @@ private static List<Installation> activeSites(Guild guild, List<Guild> guilds) {
List<Installation> sites = new ArrayList<>();
String guildFactionId = guild.getFaction() == null ? null : guild.getFaction().getId();
for (SupplyHub hub : guild.getSupplyHubs()) {
if (SupplyHubService.beyondGuildLimit(guild, hub)) {
continue;
}
Installation installation =
SupplyHubService.findInstallation(hub.ownerFactionId(), hub.installationId());
if (installation == null) {
Expand All @@ -190,7 +188,7 @@ private static List<Installation> activeSites(Guild guild, List<Guild> guilds) {
Faction owner = FactionManager.getByString(hub.ownerFactionId());
boolean permit = owner != null && owner.hasHubPermit(guild.getId());
HubStanding standing = SupplyHubService.standing(
hub,
guild, hub,
true,
SupplyHubService.ownerAllows(guildFactionId, hub.ownerFactionId(), permit),
InstallationConfigLoader.getHubSlots(installation.getKind(), installation.getLevel()),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public static HubTaxBreakdown assess(ProvinceManager provinces, Guild guild, Lis
boolean allowed = SupplyHubService.ownerAllows(
guild.getFaction().getId(), host.getId(), host.hasHubPermit(guild.getId()));
if (!SupplyHubService.standing(
hub, true, allowed,
guild, hub, true, allowed,
InstallationConfigLoader.getHubSlots(installation.getKind(), installation.getLevel()),
SupplyHubService.atInstallation(host.getId(), installation.getId(), guilds)).active()) {
continue;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,10 @@ private static boolean build(Player player) {
player.sendMessage("搂cOnly the guild leader can build a supply hub");
return true;
}
if (!SupplyHubService.allowsSupplyHubs(guild)) {
player.sendMessage(SupplyHubService.buildFailureMessage(BuildFailure.ECONOMY_DISALLOWS, null, 0));
return true;
}
List<PlacedCandidate> covering = covering(player.getLocation());
if (covering.isEmpty()) {
player.sendMessage("搂cYou are not standing inside an installation");
Expand Down Expand Up @@ -305,10 +309,6 @@ private static void listPermits(Player player, Faction faction) {
}

private static String statusOf(Guild guild, SupplyHub hub, Installation installation) {
if (SupplyHubService.beyondGuildLimit(guild, hub)) {
return SupplyHubService.statusText(new HubStanding(
false, SupplyHubService.DormantReason.BEYOND_GUILD_LIMIT));
}
String guildFactionId = guild.getFaction() == null ? null : guild.getFaction().getId();
Faction owner = FactionManager.getByString(hub.ownerFactionId());
boolean permit = owner != null && owner.hasHubPermit(guild.getId());
Expand All @@ -319,7 +319,7 @@ private static String statusOf(Guild guild, SupplyHub hub, Installation installa
List<SupplyHub> atInstallation = SupplyHubService.atInstallation(
hub.ownerFactionId(), hub.installationId(), SupplyHubService.allGuilds());
HubStanding standing = SupplyHubService.standing(
hub,
guild, hub,
installation != null,
SupplyHubService.ownerAllows(guildFactionId, hub.ownerFactionId(), permit),
slots,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
import net.tfminecraft.simplefactions.guild.Guild;
import net.tfminecraft.simplefactions.guild.GuildModifierOverride;
import net.tfminecraft.simplefactions.enums.GuildModifier;
import net.tfminecraft.simplefactions.enums.Rules;
import net.tfminecraft.simplefactions.guild.income.IncomePreviewContext;
import net.tfminecraft.simplefactions.installation.Installation;
import net.tfminecraft.simplefactions.installation.InstallationKind;
import net.tfminecraft.simplefactions.managers.FactionManager;
Expand All @@ -39,6 +41,7 @@ private SupplyHubService() {
}

public enum BuildFailure {
ECONOMY_DISALLOWS,
KIND_DISALLOWS,
ALREADY_HAS_HUB,
HUB_LIMIT,
Expand All @@ -48,6 +51,7 @@ public enum BuildFailure {
}

public enum DormantReason {
ECONOMY_DISALLOWS,
INSTALLATION_GONE,
NO_PERMIT,
BEYOND_HUB_SLOTS,
Expand Down Expand Up @@ -195,6 +199,8 @@ public static BuildFailure checkBuild(
public static String buildFailureMessage(BuildFailure failure, String kindDisplayName, int limit) {
String kind = kindDisplayName == null || kindDisplayName.isBlank() ? "installation" : kindDisplayName;
switch (failure) {
case ECONOMY_DISALLOWS:
return "搂cYour faction's economy does not allow supply hubs";
case KIND_DISALLOWS:
return "搂cA " + kind + " cannot host a supply hub";
case ALREADY_HAS_HUB:
Expand Down Expand Up @@ -246,6 +252,32 @@ public static boolean togglePermit(List<String> permits, String guildId) {
return true;
}

public static boolean allowsSupplyHubs(Guild guild) {
Faction faction = guild == null ? null : guild.getFaction();
if (faction == null) {
return true;
}
IncomePreviewContext context = IncomePreviewContext.current();
return context != null ? context.allowsHubRule(faction, Rules.SUPPLY_HUBS)
: faction.hasFactionRule(Rules.SUPPLY_HUBS);
}

public static HubStanding standing(
Guild guild,
SupplyHub hub,
boolean installationExists,
boolean allowed,
int hubSlots,
List<SupplyHub> atInstallationOldestFirst) {
if (!allowsSupplyHubs(guild)) {
return new HubStanding(false, DormantReason.ECONOMY_DISALLOWS);
}
if (beyondGuildLimit(guild, hub)) {
return new HubStanding(false, DormantReason.BEYOND_GUILD_LIMIT);
}
return standing(hub, installationExists, allowed, hubSlots, atInstallationOldestFirst);
}

public static HubStanding standing(
SupplyHub hub,
boolean installationExists,
Expand Down Expand Up @@ -278,6 +310,8 @@ public static String dormantReasonText(DormantReason reason) {
return "dormant";
}
switch (reason) {
case ECONOMY_DISALLOWS:
return "your faction's economy does not allow supply hubs";
case INSTALLATION_GONE:
return "its installation no longer exists";
case NO_PERMIT:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,54 @@ private boolean replaces(TaxHandler handler, TaxTarget query, String id) {
return true;
}

public boolean allowsHubRule(Faction owner, Rules rule) {
if (!previewsLaw(owner)) {
return owner.hasFactionRule(rule);
}
LawEffect proposed = law.getScopedEffects().get(Scope.FACTION);
if (proposed != null && Boolean.FALSE.equals(proposed.getRules().get(rule))) {
return false;
}
boolean foundTrue = proposed != null && Boolean.TRUE.equals(proposed.getRules().get(rule));
if (owner.getLawHandler() != null) {
for (Law current : owner.getLawHandler().getCurrentLaws()) {
if (current.getGroup().equals(law.getGroup())) continue;
LawEffect effect = current.getScopedEffects().get(Scope.FACTION);
if (effect != null && effect.getRules().containsKey(rule)) {
if (!effect.getRules().get(rule)) return false;
foundTrue = true;
}
}
}
if (foundTrue) return true;
Faction overlord = owner.getOverlord();
return overlord == null || !Boolean.FALSE.equals(overlord.getExplicitRule(Scope.VASSALS, rule));
}

private Bracket hubTaxBracket() {
Bracket bracket = TaxHandler.DEFAULT_HUB_TAX_BRACKET;
boolean foundGroup = false;
if (faction.getLawHandler() != null) {
for (Law current : faction.getLawHandler().getCurrentLaws()) {
if (current.getGroup().equals(law.getGroup())) {
current = law;
foundGroup = true;
}
LawEffect effect = current.getScopedEffects().get(Scope.FACTION);
if (effect != null && effect.getBrackets().containsKey(Brackets.HUB_TAX)) {
bracket = effect.getBrackets().get(Brackets.HUB_TAX);
}
}
}
LawEffect proposed = law.getScopedEffects().get(Scope.FACTION);
return !foundGroup && proposed != null
? proposed.getBrackets().getOrDefault(Brackets.HUB_TAX, bracket) : bracket;
}

private double clampForLaw(TaxTarget target, double rate) {
if (target == TaxTarget.HUB_TAX) {
return allowsHubRule(faction, Rules.HUB_TAX) ? clamp(rate, hubTaxBracket()) : 0;
}
LawEffect effect = law.getScopedEffects().get(Scope.FACTION);
if (effect == null) {
return rate;
Expand All @@ -261,8 +308,7 @@ private double clampForLaw(TaxTarget target, double rate) {
}
if (effect.hasBrackets()) {
for (Map.Entry<Brackets, Bracket> entry : effect.getBrackets().entrySet()) {
if ((BracketToTaxTarget.convert(entry.getKey()) == family
|| (family == TaxTarget.HUB_TAX && entry.getKey() == Brackets.TARIFFS))
if (BracketToTaxTarget.convert(entry.getKey()) == family
&& entry.getValue() != null) {
rate = clamp(rate, entry.getValue());
}
Expand Down Expand Up @@ -309,7 +355,8 @@ private static Rules ruleFor(TaxTarget target) {
case GUILDS, GUILD_ID -> Rules.GUILD_TAX;
case VASSALS, VASSAL_ID -> Rules.VASSAL_TAX;
case DIVIDENDS -> Rules.DIVIDEND_TAX;
case TARIFFS, TARIFF_ID, HUB_TAX -> Rules.TARIFFS;
case TARIFFS, TARIFF_ID -> Rules.TARIFFS;
case HUB_TAX -> Rules.HUB_TAX;
default -> null;
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import net.tfminecraft.simplefactions.utils.Formatter;
import net.tfminecraft.simplefactions.utils.PostSettlementPayouts.PlayerUuidLookup;
import net.tfminecraft.simplefactions.enums.FactionModifiers;
import net.tfminecraft.simplefactions.enums.Rules;
import net.tfminecraft.simplefactions.government.proposal.TaxTarget;
import net.tfminecraft.simplefactions.mercenary.company.MercenaryCompany;
import net.tfminecraft.simplefactions.mercenary.contract.MercenaryEngagements;
Expand Down Expand Up @@ -425,8 +426,17 @@ public Map<Faction, Double> getPayableHubTaxes() {
if (hubTax == null || guild.getFaction() == null || skipsMoneyMovement()) {
return Map.of();
}
IncomePreviewContext context = IncomePreviewContext.current();
if (context != null && context.previewsLaw(guild.getFaction())
&& !context.allowsHubRule(guild.getFaction(), Rules.SUPPLY_HUBS)) {
return Map.of();
}
Map<Faction, Double> payable = new HashMap<>();
for (Map.Entry<Faction, Double> entry : hubTax.getTaxesByFaction().entrySet()) {
boolean allowed = context != null
? context.allowsHubRule(entry.getKey(), Rules.HUB_TAX)
: entry.getKey().hasFactionRule(Rules.HUB_TAX);
if (!allowed) continue;
Guild receiver = entry.getKey().getOrCreateMainGuild();
if (entry.getValue() > 0 && receiver != null && receiver.getLedger() != null
&& !receiver.getLedger().skipsMoneyMovement()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,9 @@ public boolean affectsEconomy() {
for(Rules r : rules.keySet()) {
if(r == Rules.VASSAL_TAX
|| r == Rules.GUILD_TAX
|| r == Rules.TARIFFS) {
|| r == Rules.TARIFFS
|| r == Rules.HUB_TAX
|| r == Rules.SUPPLY_HUBS) {
return true;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -268,9 +268,6 @@ private static boolean isLeader(Guild guild, Player player) {
}

private static HubStanding standing(Guild guild, SupplyHub hub) {
if (SupplyHubService.beyondGuildLimit(guild, hub)) {
return new HubStanding(false, SupplyHubService.DormantReason.BEYOND_GUILD_LIMIT);
}
Installation installation = SupplyHubService.findInstallation(
hub.ownerFactionId(), hub.installationId());
Faction owner = FactionManager.getByString(hub.ownerFactionId());
Expand All @@ -280,7 +277,7 @@ private static HubStanding standing(Guild guild, SupplyHub hub) {
int slots = installation == null
? 0
: InstallationConfigLoader.getHubSlots(installation.getKind(), installation.getLevel());
return SupplyHubService.standing(hub, installation != null, allowed, slots,
return SupplyHubService.standing(guild, hub, installation != null, allowed, slots,
SupplyHubService.atInstallation(
hub.ownerFactionId(), hub.installationId(), SupplyHubService.allGuilds()));
}
Expand Down
19 changes: 19 additions & 0 deletions src/main/java/net/tfminecraft/simplefactions/objects/Faction.java
Original file line number Diff line number Diff line change
Expand Up @@ -1042,6 +1042,7 @@ public void applyLaw(Law law, LawGroup group) {

LawEffect effect = law.getScopedEffects().get(Scope.FACTION);
if (effect == null) {
refreshHubTaxBracket();
cancelInvalidElections();
return;
}
Expand Down Expand Up @@ -1087,6 +1088,10 @@ public void applyLaw(Law law, LawGroup group) {
if (!value)
taxHandler.applyBracket(TaxTarget.TARIFFS, new Bracket(0, 0));
break;
case HUB_TAX:
if (!value)
taxHandler.applyBracket(TaxTarget.HUB_TAX, new Bracket(0, 0));
break;
case VEHICLE_TAX:
case REGISTRATION_FEE:
case TRANSFER_FEE:
Expand All @@ -1099,6 +1104,8 @@ public void applyLaw(Law law, LawGroup group) {
}
}

refreshHubTaxBracket();

// --- council structure ---
if (effect.affectsCouncilSize() || effect.affectsCouncilType()) {
government.getCouncil().reorganize();
Expand All @@ -1118,6 +1125,18 @@ public void applyLaw(Law law, LawGroup group) {
}
}

private void refreshHubTaxBracket() {
Bracket bracket = TaxHandler.DEFAULT_HUB_TAX_BRACKET;
for (Law current : lawHandler.getCurrentLaws()) {
LawEffect effect = current.getScopedEffects().get(Scope.FACTION);
if (effect != null && effect.getBrackets().containsKey(Brackets.HUB_TAX)) {
bracket = effect.getBrackets().get(Brackets.HUB_TAX);
}
}
taxHandler.applyBracket(TaxTarget.HUB_TAX,
hasFactionRule(Rules.HUB_TAX) ? bracket : new Bracket(0, 0));
}

public void applyPoliticalAction(Cause cause, Proposal proposal) {
if(!proposal.isPoliticalActionProposal()) return;
PoliticalAction politicalAction = proposal.getPoliticalAction();
Expand Down
Loading
Loading