Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/refactor flags #6475

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 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
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
58 changes: 58 additions & 0 deletions megamek/src/megamek/common/AmmoTypeFlag.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* 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


@Override
public int getFlagIndex() {
return this.ordinal();
}

Scoppio marked this conversation as resolved.
Show resolved Hide resolved
}
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;
Scoppio marked this conversation as resolved.
Show resolved Hide resolved

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.getFlagIndex());
}

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.getFlagIndex());
}

/**
* 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.getFlagIndex());
}


/**
* 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