Skip to content

Commit

Permalink
Merge pull request #6475 from Scoppio/feat/refactor-flags
Browse files Browse the repository at this point in the history
Feat/refactor flags
  • Loading branch information
HammerGS authored Feb 6, 2025
2 parents 4cc98ff + 17a88fa commit beeac38
Show file tree
Hide file tree
Showing 21 changed files with 1,024 additions and 377 deletions.
3 changes: 1 addition & 2 deletions megamek/src/megamek/client/ui/swing/MapMenu.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
import java.awt.event.ActionEvent;
import java.awt.event.InputEvent;
import java.awt.event.MouseEvent;
import java.math.BigInteger;
import java.util.*;

import javax.swing.*;
Expand Down Expand Up @@ -1612,7 +1611,7 @@ private boolean hasAmmoType(int ammoType) {
return false;
}

private boolean hasWeaponFlag(BigInteger weaponFlag) {
private boolean hasWeaponFlag(EquipmentFlag weaponFlag) {
if (myEntity.getWeaponList().isEmpty()) {
return false;
}
Expand Down
45 changes: 22 additions & 23 deletions megamek/src/megamek/common/AmmoType.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
*/
package megamek.common;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.Enumeration;
Expand Down Expand Up @@ -182,42 +181,42 @@ public class AmmoType extends EquipmentType {
public static final Set<Integer> ALLOWED_BY_TYPE = Set.of(ALLOWED_BY_TYPE_ARRAY);

// ammo flags
public static final BigInteger F_MG = BigInteger.valueOf(1).shiftLeft(0);
public static final BigInteger F_BATTLEARMOR = BigInteger.valueOf(1).shiftLeft(1); // only used by BA squads
public static final BigInteger F_PROTOMEK = BigInteger.valueOf(1).shiftLeft(2); // only used by ProtoMeks
public static final BigInteger F_HOTLOAD = BigInteger.valueOf(1).shiftLeft(3); // Ammo can be hotloaded
public static final AmmoTypeFlag F_MG = AmmoTypeFlag.F_MG;
public static final AmmoTypeFlag F_BATTLEARMOR = AmmoTypeFlag.F_BATTLEARMOR; // only used by BA squads
public static final AmmoTypeFlag F_PROTOMEK = AmmoTypeFlag.F_PROTOMEK; // only used by ProtoMeks
public static final AmmoTypeFlag F_HOTLOAD = AmmoTypeFlag.F_HOTLOAD; // Ammo can be hotloaded

// BA can't jump or make anti-mek until dumped
public static final BigInteger F_ENCUMBERING = BigInteger.valueOf(1).shiftLeft(4);

public static final BigInteger F_MML_LRM = BigInteger.valueOf(1).shiftLeft(5); // LRM type
public static final BigInteger F_AR10_WHITE_SHARK = BigInteger.valueOf(1).shiftLeft(6); // White shark type
public static final BigInteger F_AR10_KILLER_WHALE = BigInteger.valueOf(1).shiftLeft(7); // Killer Whale type
public static final BigInteger F_AR10_BARRACUDA = BigInteger.valueOf(1).shiftLeft(8); // barracuda type
public static final BigInteger F_NUCLEAR = BigInteger.valueOf(1).shiftLeft(9); // Nuclear missile
public static final BigInteger F_SANTA_ANNA = BigInteger.valueOf(1).shiftLeft(14); // Santa Anna Missile
public static final BigInteger F_PEACEMAKER = BigInteger.valueOf(1).shiftLeft(15); // Peacemaker Missile
public static final BigInteger F_TELE_MISSILE = BigInteger.valueOf(1).shiftLeft(10); // Tele-Missile
public static final BigInteger F_CAP_MISSILE = BigInteger.valueOf(1).shiftLeft(11); // Other Capital-Missile
public static final BigInteger F_SPACE_BOMB = BigInteger.valueOf(1).shiftLeft(12); // can be used to space bomb
public static final AmmoTypeFlag F_ENCUMBERING = AmmoTypeFlag.F_ENCUMBERING;

public static final AmmoTypeFlag F_MML_LRM = AmmoTypeFlag.F_MML_LRM; // LRM type
public static final AmmoTypeFlag F_AR10_WHITE_SHARK = AmmoTypeFlag.F_AR10_WHITE_SHARK; // White shark type
public static final AmmoTypeFlag F_AR10_KILLER_WHALE = AmmoTypeFlag.F_AR10_KILLER_WHALE; // Killer Whale type
public static final AmmoTypeFlag F_AR10_BARRACUDA = AmmoTypeFlag.F_AR10_BARRACUDA; // barracuda type
public static final AmmoTypeFlag F_NUCLEAR = AmmoTypeFlag.F_NUCLEAR; // Nuclear missile
public static final AmmoTypeFlag F_SANTA_ANNA = AmmoTypeFlag.F_SANTA_ANNA; // Santa Anna Missile
public static final AmmoTypeFlag F_PEACEMAKER = AmmoTypeFlag.F_PEACEMAKER; // Peacemaker Missile
public static final AmmoTypeFlag F_TELE_MISSILE = AmmoTypeFlag.F_TELE_MISSILE; // Tele-Missile
public static final AmmoTypeFlag F_CAP_MISSILE = AmmoTypeFlag.F_CAP_MISSILE; // Other Capital-Missile
public static final AmmoTypeFlag F_SPACE_BOMB = AmmoTypeFlag.F_SPACE_BOMB; // can be used to space bomb

// can be used to ground bomb
public static final BigInteger F_GROUND_BOMB = BigInteger.valueOf(1).shiftLeft(13);
public static final BigInteger F_MML_SRM = BigInteger.valueOf(1).shiftLeft(14); // SRM type
public static final AmmoTypeFlag F_GROUND_BOMB = AmmoTypeFlag.F_GROUND_BOMB;
public static final AmmoTypeFlag F_MML_SRM = AmmoTypeFlag.F_MML_SRM; // SRM type

// Numbers 14-15 out of order. See nuclear missiles, above

// For tag, rl pods, missiles and the like
public static final BigInteger F_OTHER_BOMB = BigInteger.valueOf(1).shiftLeft(16);
public static final AmmoTypeFlag F_OTHER_BOMB = AmmoTypeFlag.F_OTHER_BOMB;

// Used by MHQ for loading ammo bins
public static final BigInteger F_CRUISE_MISSILE = BigInteger.valueOf(1).shiftLeft(17);
public static final AmmoTypeFlag F_CRUISE_MISSILE = AmmoTypeFlag.F_CRUISE_MISSILE;

// Used by MHQ for loading ammo bins
public static final BigInteger F_SCREEN = BigInteger.valueOf(1).shiftLeft(18);
public static final AmmoTypeFlag F_SCREEN = AmmoTypeFlag.F_SCREEN;

// Used for Internal Bomb Bay bombs; to differentiate them from
public static final BigInteger F_INTERNAL_BOMB = BigInteger.valueOf(1).shiftLeft(19);
public static final AmmoTypeFlag F_INTERNAL_BOMB = AmmoTypeFlag.F_INTERNAL_BOMB;

// ammo munitions, used for custom load outs
// N.B. We use EnumSet<Munitions> allow "incendiary"
Expand Down
52 changes: 52 additions & 0 deletions megamek/src/megamek/common/AmmoTypeFlag.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright (c) 2025 - The MegaMek Team. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
package megamek.common;

/**
* Set of flags that can be used to determine how the ammo is used and its
* special properties
* @author Luana Coppio
*/
public enum AmmoTypeFlag implements EquipmentFlag {

F_BATTLEARMOR, // only used by BA squads
F_PROTOMEK, // only used by ProtoMeks

F_ENCUMBERING, // Encumbering ammo - if loaded on a BA it cant jump or make anti-mek attacks until dumped

F_MG, // Machinegun ammo
F_MML_LRM, // LRM type
F_MML_SRM, // SRM type

F_HOTLOAD, // Ammo can be hotloaded

F_SCREEN, // Used by MHQ for loading ammo bins

F_INTERNAL_BOMB, // Used for Internal Bomb Bay bombs; to differentiate them from other bombs
F_GROUND_BOMB, // the ammo can be used to ground bomb
F_OTHER_BOMB, // For tag, rl pods, missiles and the like
F_SPACE_BOMB, // defines that the ammo can be used to space bomb

F_AR10_BARRACUDA, // barracuda type
F_AR10_KILLER_WHALE, // Killer Whale type
F_AR10_WHITE_SHARK, // White shark type
F_CAP_MISSILE, // Other Capital-Missile
F_CRUISE_MISSILE, // Used by MHQ for loading ammo bins
F_TELE_MISSILE, // Tele-Missile

F_NUCLEAR, // Nuclear missile
F_SANTA_ANNA, // Nuke Santa Anna Missile
F_PEACEMAKER, // Nuke Peacemaker Missile

}
17 changes: 8 additions & 9 deletions megamek/src/megamek/common/Entity.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@
import megamek.utilities.xml.MMXMLUtility;

import java.awt.*;
import java.math.BigInteger;
import java.util.List;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
Expand Down Expand Up @@ -4470,7 +4469,7 @@ public List<BombMounted> getBombs() {
* @return The list of found bombs
* @see Mounted#isOperable()
*/
public List<BombMounted> getBombs(BigInteger flag) {
public List<BombMounted> getBombs(EquipmentFlag flag) {
return getBombs().stream()
.filter(b -> b.getType().hasFlag(flag))
.filter(Mounted::isOperable)
Expand Down Expand Up @@ -4632,7 +4631,7 @@ public List<MiscMounted> getClubs() {
* @param flag A MiscType.F_XXX
* @return true if at least one ready item.
*/
public boolean hasWorkingMisc(BigInteger flag) {
public boolean hasWorkingMisc(EquipmentFlag flag) {
return hasWorkingMisc(flag, -1);
}

Expand All @@ -4643,7 +4642,7 @@ public boolean hasWorkingMisc(BigInteger flag) {
* @param secondary A MiscType.S_XXX or -1 for don't care
* @return true if at least one ready item.
*/
public boolean hasWorkingMisc(BigInteger flag, long secondary) {
public boolean hasWorkingMisc(EquipmentFlag flag, long secondary) {
for (MiscMounted m : miscList) {
if (m.isReady() && m.getType().hasFlag(flag)
&& ((secondary == -1) || m.getType().hasSubType(secondary))) {
Expand All @@ -4653,11 +4652,11 @@ public boolean hasWorkingMisc(BigInteger flag, long secondary) {
return false;
}

public boolean hasMisc(BigInteger flag) {
public boolean hasMisc(EquipmentFlag flag) {
return miscList.stream().anyMatch(misc -> misc.getType().hasFlag(flag));
}

public List<MiscMounted> getMiscEquipment(BigInteger flag) {
public List<MiscMounted> getMiscEquipment(EquipmentFlag flag) {
return miscList.stream()
.filter(item -> item.getType().hasFlag(flag))
.collect(Collectors.toList());
Expand All @@ -4682,11 +4681,11 @@ public long countEquipment(String internalName) {
* @param flag
* @return
*/
public int countWorkingMisc(BigInteger flag) {
public int countWorkingMisc(EquipmentFlag flag) {
return countWorkingMisc(flag, -1);
}

public int countWorkingMisc(BigInteger flag, int location) {
public int countWorkingMisc(EquipmentFlag flag, int location) {
int count = 0;
OUTER: for (MiscMounted m : getMisc()) {
if (!m.isInoperable() && m.getType().hasFlag(flag)
Expand Down Expand Up @@ -4745,7 +4744,7 @@ public boolean hasWorkingMisc(String name) {
* @param location The location to check e.g. Mek.LOC_LARM
* @return true if at least one ready item.
*/
public boolean hasWorkingMisc(BigInteger flag, long secondary, int location) {
public boolean hasWorkingMisc(EquipmentFlag flag, long secondary, int location) {
// go through the location slot by slot, because of misc equipment that
// is spreadable
for (int slot = 0; slot < getNumberOfCriticals(location); slot++) {
Expand Down
148 changes: 148 additions & 0 deletions megamek/src/megamek/common/EquipmentBitSet.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
/*
* Copyright (c) 2025 - The MegaMek Team. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
package megamek.common;

import java.util.BitSet;
import java.util.Objects;

/**
* Represents a set of flags that can be used to represent the type and
* special properties of the equipment.
* @author Luana Coppio
*/
public class EquipmentBitSet {

private final BitSet bitSet;

/**
* Default constructor.
*/
public EquipmentBitSet() {
// This value is currently a bit above the double of what we need, but it's a power of 2, and it's a good
// starting point since it will give a lot of runaway for new types of equipments, ammo and weapons to be added
// Whenever we surpass this number, the bitset will increase on its own as needed, so its more of a performance
// matter than a limitation.
this.bitSet = new BitSet(512);
}

/**
* Copy constructor.
* @param other the EquipmentBitSet to copy
*/
public EquipmentBitSet(EquipmentBitSet other) {
this.bitSet = (BitSet) other.bitSet.clone();
}

/**
* Returns true if the flag is set in the EquipmentBitSet.
* @param flag the flag to check
* @return true if the flag is set in the EquipmentBitSet
*/
public boolean get(EquipmentFlag flag) {
return bitSet.get(flag.ordinal());
}

public boolean contains(EquipmentBitSet other) {
var checker = new EquipmentBitSet(this);
checker.bitSet.and(other.bitSet);
return checker.equals(other);
}

/**
* Clears the flag in the EquipmentBitSet.
* @param flag the flag to clear
*/
public void clear(EquipmentFlag flag) {
bitSet.clear(flag.ordinal());
}

/**
* Clears all flags in the EquipmentBitSet.
*/
public void clear() {
bitSet.clear();
}

/**
* Sets the flag in the EquipmentBitSet.
* @param flag the flag to set
*/
public void set(EquipmentFlag flag) {
bitSet.set(flag.ordinal());
}


/**
* Returns a copy of this EquipmentBitSet with the flag set.
* @param flag the flag to set
* @return a copy of this EquipmentBitSet with the flag set
*/
public EquipmentBitSet or(EquipmentFlag flag) {
var newBitSet = new EquipmentBitSet(this);
newBitSet.set(flag);
return newBitSet;
}

/**
* Returns a copy of this EquipmentBitSet with the flag cleared.
* @param flag the flag to clear
* @return a copy of this EquipmentBitSet with the flag cleared
*/
public EquipmentBitSet andNot(EquipmentFlag flag) {
var newBitSet = new EquipmentBitSet(this);
newBitSet.clear(flag);
return newBitSet;
}

/**
* Returns a new empty EquipmentBitSet and the flag set if it is set in this EquipmentBitSet.
* Example:
* EquipmentBitSet a = new EquipmentBitSet();
* a.set(F_HEAT_SINK);
* a.set(F_DOUBLE_HEATSINK);
* a.and(F_HEAT_SINK) // EquipmentBitSet with only F_HEAT_SINK set if it was originally set
* a.has(F_HEAT_SINK); // true
* a.has(F_DOUBLE_HEATSINK); // false
* @param flag the flag to check
* @return a new empty EquipmentBitSet and the flag set if it is set in this EquipmentBitSet
*/
public EquipmentBitSet and(EquipmentFlag flag) {
var newBitSet = new EquipmentBitSet();
if (this.get(flag)) {
newBitSet.set(flag);
}
return newBitSet;
}

@Override
public String toString() {
return "EntityBitSet{" +
"bitSet=" + bitSet +
'}';
}

@Override
public boolean equals(Object o) {
if (o instanceof EquipmentBitSet that) {
return Objects.equals(bitSet, that.bitSet);
}

return false;
}

@Override
public int hashCode() {
return Objects.hashCode(bitSet);
}
}
Loading

0 comments on commit beeac38

Please sign in to comment.