mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
Create a checked, releasable type for laser codes.
The release behavior isn't used yet, but I'm working on pre-allocating laser codes for front lines and flights to make it easier for players to pick the laser codes for their weapons.
This commit is contained in:
@@ -1 +1,3 @@
|
||||
from .ilasercoderegistry import ILaserCodeRegistry
|
||||
from .lasercode import LaserCode
|
||||
from .lasercoderegistry import LaserCodeRegistry
|
||||
|
||||
17
game/lasercodes/ilasercoderegistry.py
Normal file
17
game/lasercodes/ilasercoderegistry.py
Normal file
@@ -0,0 +1,17 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .lasercode import LaserCode
|
||||
|
||||
|
||||
class ILaserCodeRegistry(ABC):
|
||||
@abstractmethod
|
||||
def alloc_laser_code(self) -> LaserCode:
|
||||
...
|
||||
|
||||
@abstractmethod
|
||||
def release_code(self, code: LaserCode) -> None:
|
||||
...
|
||||
56
game/lasercodes/lasercode.py
Normal file
56
game/lasercodes/lasercode.py
Normal file
@@ -0,0 +1,56 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .ilasercoderegistry import ILaserCodeRegistry
|
||||
|
||||
|
||||
class LaserCode:
|
||||
def __init__(self, code: int, registry: ILaserCodeRegistry) -> None:
|
||||
self.verify_laser_code(code)
|
||||
self.code = code
|
||||
self.registry = registry
|
||||
|
||||
def release(self) -> None:
|
||||
self.registry.release_code(self)
|
||||
|
||||
@staticmethod
|
||||
def verify_laser_code(code: int) -> None:
|
||||
# https://forum.dcs.world/topic/211574-valid-laser-codes/
|
||||
# Valid laser codes are as follows
|
||||
# First digit is always 1
|
||||
# Second digit is 5-7
|
||||
# Third and fourth digits are 1 - 8
|
||||
# We iterate backward (reversed()) so that 1687 follows 1688
|
||||
|
||||
# Special case used by FC3 aircraft like the A-10A that is not valid for other
|
||||
# aircraft.
|
||||
if code == 1113:
|
||||
return
|
||||
|
||||
# Must be 4 digits with no leading 0
|
||||
if code < 1000 or code >= 2000:
|
||||
raise ValueError
|
||||
|
||||
# The first digit was already verified above. Isolate the remaining three
|
||||
# digits. The resulting list is ordered by significance, not printed position.
|
||||
digits = [code // 10**i % 10 for i in range(3)]
|
||||
|
||||
if digits[0] < 1 or digits[0] > 8:
|
||||
raise ValueError
|
||||
if digits[1] < 1 or digits[1] > 8:
|
||||
raise ValueError
|
||||
if digits[2] < 5 or digits[2] > 7:
|
||||
raise ValueError
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"{self.code}"
|
||||
|
||||
def __eq__(self, other: object) -> bool:
|
||||
if not isinstance(other, LaserCode):
|
||||
return False
|
||||
return self.code == other.code
|
||||
|
||||
def __hash__(self) -> int:
|
||||
return hash(self.code)
|
||||
@@ -1,19 +1,33 @@
|
||||
import logging
|
||||
from collections import deque
|
||||
|
||||
from .ilasercoderegistry import ILaserCodeRegistry
|
||||
from .lasercode import LaserCode
|
||||
|
||||
class LaserCodeRegistry:
|
||||
|
||||
class LaserCodeRegistry(ILaserCodeRegistry):
|
||||
def __init__(self) -> None:
|
||||
self.allocated_codes: set[int] = set()
|
||||
self.available_codes = LaserCodeRegistry._all_valid_laser_codes()
|
||||
self.fc3_code = LaserCode(1113, self)
|
||||
|
||||
def alloc_laser_code(self) -> int:
|
||||
def alloc_laser_code(self) -> LaserCode:
|
||||
try:
|
||||
code = self.available_codes.popleft()
|
||||
self.allocated_codes.add(code)
|
||||
return code
|
||||
return LaserCode(code, self)
|
||||
except IndexError:
|
||||
raise RuntimeError("All laser codes have been allocated")
|
||||
|
||||
def release_code(self, code: LaserCode) -> None:
|
||||
if code.code in self.allocated_codes:
|
||||
self.allocated_codes.remove(code.code)
|
||||
self.available_codes.appendleft(code.code)
|
||||
else:
|
||||
logging.error(
|
||||
"attempted to release laser code %d which was not allocated", code.code
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def _all_valid_laser_codes() -> deque[int]:
|
||||
# Valid laser codes are as follows
|
||||
|
||||
Reference in New Issue
Block a user