mirror of
https://github.com/LmeSzinc/StarRailCopilot.git
synced 2024-11-25 10:01:10 +00:00
commit
6ea848ca51
@ -338,6 +338,8 @@ class Connection(ConnectionAttr):
|
|||||||
which has nemud.app_keep_alive and always be a vertical device
|
which has nemud.app_keep_alive and always be a vertical device
|
||||||
MuMu PRO on mac has the same feature
|
MuMu PRO on mac has the same feature
|
||||||
"""
|
"""
|
||||||
|
if not self.is_mumu_family:
|
||||||
|
return False
|
||||||
if self.nemud_app_keep_alive != '':
|
if self.nemud_app_keep_alive != '':
|
||||||
return True
|
return True
|
||||||
if IS_MACINTOSH:
|
if IS_MACINTOSH:
|
||||||
|
@ -419,26 +419,28 @@ class NemuIpcImpl:
|
|||||||
if ret > 0:
|
if ret > 0:
|
||||||
raise NemuIpcError('nemu_input_event_touch_up failed')
|
raise NemuIpcError('nemu_input_event_touch_up failed')
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def serial_to_id(serial: str):
|
||||||
|
"""
|
||||||
|
Predict instance ID from serial
|
||||||
|
E.g.
|
||||||
|
"127.0.0.1:16384" -> 0
|
||||||
|
"127.0.0.1:16416" -> 1
|
||||||
|
Port from 16414 to 16418 -> 1
|
||||||
|
|
||||||
def serial_to_id(serial: str):
|
Returns:
|
||||||
"""
|
int: instance_id, or None if failed to predict
|
||||||
Predict instance ID from serial
|
"""
|
||||||
E.g.
|
try:
|
||||||
"127.0.0.1:16384" -> 0
|
port = int(serial.split(':')[1])
|
||||||
"127.0.0.1:16416" -> 1
|
except (IndexError, ValueError):
|
||||||
|
return None
|
||||||
Returns:
|
index, offset = divmod(port - 16384 + 16, 32)
|
||||||
int: instance_id, or None if failed to predict
|
offset -= 16
|
||||||
"""
|
if 0 <= index < 32 and offset in [-2, -1, 0, 1, 2]:
|
||||||
try:
|
return index
|
||||||
port = int(serial.split(':')[1])
|
else:
|
||||||
except (IndexError, ValueError):
|
return None
|
||||||
return None
|
|
||||||
index, offset = divmod(port - 16384, 32)
|
|
||||||
if 0 <= index < 32 and offset in [0, 1, 2]:
|
|
||||||
return index
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
class NemuIpc(Platform):
|
class NemuIpc(Platform):
|
||||||
@ -452,7 +454,7 @@ class NemuIpc(Platform):
|
|||||||
# Try existing settings first
|
# Try existing settings first
|
||||||
if self.config.EmulatorInfo_path:
|
if self.config.EmulatorInfo_path:
|
||||||
folder = os.path.abspath(os.path.join(self.config.EmulatorInfo_path, '../../'))
|
folder = os.path.abspath(os.path.join(self.config.EmulatorInfo_path, '../../'))
|
||||||
index = serial_to_id(self.serial)
|
index = NemuIpcImpl.serial_to_id(self.serial)
|
||||||
if index is not None:
|
if index is not None:
|
||||||
try:
|
try:
|
||||||
return NemuIpcImpl(
|
return NemuIpcImpl(
|
||||||
|
@ -114,6 +114,23 @@ class EmulatorInstanceBase:
|
|||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def LDPlayer_id(self):
|
||||||
|
"""
|
||||||
|
Convert LDPlayer instance name to instance id.
|
||||||
|
Example names:
|
||||||
|
leidian0
|
||||||
|
leidian1
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
int: Instance ID, or None if this is not a LDPlayer instance
|
||||||
|
"""
|
||||||
|
res = re.search(r'leidian(\d+)', self.name)
|
||||||
|
if res:
|
||||||
|
return int(res.group(1))
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
class EmulatorBase:
|
class EmulatorBase:
|
||||||
# Values here must match those in argument.yaml EmulatorInfo.Emulator.option
|
# Values here must match those in argument.yaml EmulatorInfo.Emulator.option
|
||||||
|
@ -155,6 +155,30 @@ class Emulator(EmulatorBase):
|
|||||||
else:
|
else:
|
||||||
yield exe
|
yield exe
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def single_to_console(exe: str):
|
||||||
|
"""
|
||||||
|
Convert a string that might be a single instance executable to its console.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
exe (str): Path to emulator executable
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: Path to emulator console
|
||||||
|
"""
|
||||||
|
if 'MuMuPlayer.exe' in exe:
|
||||||
|
return exe.replace('MuMuPlayer.exe', 'MuMuManager.exe')
|
||||||
|
elif 'LDPlayer.exe' in exe:
|
||||||
|
return exe.replace('LDPlayer.exe', 'ldconsole.exe')
|
||||||
|
elif 'dnplayer.exe' in exe:
|
||||||
|
return exe.replace('dnplayer.exe', 'ldconsole.exe')
|
||||||
|
elif 'Bluestacks.exe' in exe:
|
||||||
|
return exe.replace('Bluestacks.exe', 'bsconsole.exe')
|
||||||
|
elif 'MEmu.exe' in exe:
|
||||||
|
return exe.replace('MEmu.exe', 'memuc.exe')
|
||||||
|
else:
|
||||||
|
return exe
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def vbox_file_to_serial(file: str) -> str:
|
def vbox_file_to_serial(file: str) -> str:
|
||||||
"""
|
"""
|
||||||
|
@ -82,7 +82,7 @@ class PlatformWindows(PlatformBase, EmulatorManager):
|
|||||||
"""
|
"""
|
||||||
Start a emulator without error handling
|
Start a emulator without error handling
|
||||||
"""
|
"""
|
||||||
exe = instance.emulator.path
|
exe: str = instance.emulator.path
|
||||||
if instance == Emulator.MuMuPlayer:
|
if instance == Emulator.MuMuPlayer:
|
||||||
# NemuPlayer.exe
|
# NemuPlayer.exe
|
||||||
self.execute(exe)
|
self.execute(exe)
|
||||||
@ -94,6 +94,9 @@ class PlatformWindows(PlatformBase, EmulatorManager):
|
|||||||
if instance.MuMuPlayer12_id is None:
|
if instance.MuMuPlayer12_id is None:
|
||||||
logger.warning(f'Cannot get MuMu instance index from name {instance.name}')
|
logger.warning(f'Cannot get MuMu instance index from name {instance.name}')
|
||||||
self.execute(f'"{exe}" -v {instance.MuMuPlayer12_id}')
|
self.execute(f'"{exe}" -v {instance.MuMuPlayer12_id}')
|
||||||
|
elif instance == Emulator.LDPlayerFamily:
|
||||||
|
# ldconsole.exe launch --index 0
|
||||||
|
self.execute(f'"{Emulator.single_to_console(exe)}" launch --index {instance.LDPlayer_id}')
|
||||||
elif instance == Emulator.NoxPlayerFamily:
|
elif instance == Emulator.NoxPlayerFamily:
|
||||||
# Nox.exe -clone:Nox_1
|
# Nox.exe -clone:Nox_1
|
||||||
self.execute(f'"{exe}" -clone:{instance.name}')
|
self.execute(f'"{exe}" -clone:{instance.name}')
|
||||||
@ -101,8 +104,11 @@ class PlatformWindows(PlatformBase, EmulatorManager):
|
|||||||
# HD-Player.exe --instance Pie64
|
# HD-Player.exe --instance Pie64
|
||||||
self.execute(f'"{exe}" --instance {instance.name}')
|
self.execute(f'"{exe}" --instance {instance.name}')
|
||||||
elif instance == Emulator.BlueStacks4:
|
elif instance == Emulator.BlueStacks4:
|
||||||
# BlueStacks\Client\Bluestacks.exe -vmname Android_1
|
# Bluestacks.exe -vmname Android_1
|
||||||
self.execute(f'"{exe}" -vmname {instance.name}')
|
self.execute(f'"{exe}" -vmname {instance.name}')
|
||||||
|
elif instance == Emulator.MEmuPlayer:
|
||||||
|
# MEmu.exe MEmu_0
|
||||||
|
self.execute(f'"{exe}" {instance.name}')
|
||||||
else:
|
else:
|
||||||
raise EmulatorUnknown(f'Cannot start an unknown emulator instance: {instance}')
|
raise EmulatorUnknown(f'Cannot start an unknown emulator instance: {instance}')
|
||||||
|
|
||||||
@ -110,8 +116,7 @@ class PlatformWindows(PlatformBase, EmulatorManager):
|
|||||||
"""
|
"""
|
||||||
Stop a emulator without error handling
|
Stop a emulator without error handling
|
||||||
"""
|
"""
|
||||||
logger.hr('Emulator stop', level=2)
|
exe: str = instance.emulator.path
|
||||||
exe = instance.emulator.path
|
|
||||||
if instance == Emulator.MuMuPlayer:
|
if instance == Emulator.MuMuPlayer:
|
||||||
# MuMu6 does not have multi instance, kill one means kill all
|
# MuMu6 does not have multi instance, kill one means kill all
|
||||||
# Has 4 processes
|
# Has 4 processes
|
||||||
@ -141,26 +146,35 @@ class PlatformWindows(PlatformBase, EmulatorManager):
|
|||||||
rf')'
|
rf')'
|
||||||
)
|
)
|
||||||
elif instance == Emulator.MuMuPlayer12:
|
elif instance == Emulator.MuMuPlayer12:
|
||||||
# MuMu 12 has 2 processes:
|
# MuMuManager.exe api -v 1 shutdown_player
|
||||||
# E:\ProgramFiles\Netease\MuMuPlayer-12.0\shell\MuMuPlayer.exe -v 0
|
|
||||||
# "C:\Program Files\MuMuVMMVbox\Hypervisor\MuMuVMMHeadless.exe" --comment MuMuPlayer-12.0-0 --startvm xxx
|
|
||||||
if instance.MuMuPlayer12_id is None:
|
if instance.MuMuPlayer12_id is None:
|
||||||
logger.warning(f'Cannot get MuMu instance index from name {instance.name}')
|
logger.warning(f'Cannot get MuMu instance index from name {instance.name}')
|
||||||
self.kill_process_by_regex(
|
self.execute(f'"{Emulator.single_to_console(exe)}" api -v {instance.MuMuPlayer12_id} shutdown_player')
|
||||||
rf'('
|
elif instance == Emulator.LDPlayerFamily:
|
||||||
rf'MuMuVMMHeadless.exe.*--comment {instance.name}'
|
# ldconsole.exe quit --index 0
|
||||||
rf'|MuMuPlayer.exe.*-v {instance.MuMuPlayer12_id}'
|
self.execute(f'"{Emulator.single_to_console(exe)}" quit --index {instance.LDPlayer_id}')
|
||||||
rf')'
|
|
||||||
)
|
|
||||||
# There is also a shared service, no need to kill it
|
|
||||||
# "C:\Program Files\MuMuVMMVbox\Hypervisor\MuMuVMMSVC.exe" --Embedding
|
|
||||||
elif instance == Emulator.NoxPlayerFamily:
|
elif instance == Emulator.NoxPlayerFamily:
|
||||||
# Nox.exe -clone:Nox_1 -quit
|
# Nox.exe -clone:Nox_1 -quit
|
||||||
self.execute(f'"{exe}" -clone:{instance.name} -quit')
|
self.execute(f'"{exe}" -clone:{instance.name} -quit')
|
||||||
|
elif instance == Emulator.BlueStacks5:
|
||||||
|
# BlueStack has 2 processes
|
||||||
|
# C:\Program Files\BlueStacks_nxt_cn\HD-Player.exe --instance Pie64
|
||||||
|
# C:\Program Files\BlueStacks_nxt_cn\BstkSVC.exe -Embedding
|
||||||
|
self.kill_process_by_regex(
|
||||||
|
rf'('
|
||||||
|
rf'HD-Player.exe.*"--instance" "{instance.name}"'
|
||||||
|
rf')'
|
||||||
|
)
|
||||||
|
elif instance == Emulator.BlueStacks4:
|
||||||
|
# E:\Program Files (x86)\BluestacksCN\bsconsole.exe quit --name Android
|
||||||
|
self.execute(f'"{Emulator.single_to_console(exe)}" quit --name {instance.name}')
|
||||||
|
elif instance == Emulator.MEmuPlayer:
|
||||||
|
# F:\Program Files\Microvirt\MEmu\memuc.exe stop -n MEmu_0
|
||||||
|
self.execute(f'"{Emulator.single_to_console(exe)}" stop -n {instance.name}')
|
||||||
else:
|
else:
|
||||||
raise EmulatorUnknown(f'Cannot stop an unknown emulator instance: {instance}')
|
raise EmulatorUnknown(f'Cannot stop an unknown emulator instance: {instance}')
|
||||||
|
|
||||||
def _emulator_function_wrapper(self, func):
|
def _emulator_function_wrapper(self, func: callable):
|
||||||
"""
|
"""
|
||||||
Args:
|
Args:
|
||||||
func (callable): _emulator_start or _emulator_stop
|
func (callable): _emulator_start or _emulator_stop
|
||||||
@ -312,7 +326,20 @@ class PlatformWindows(PlatformBase, EmulatorManager):
|
|||||||
|
|
||||||
def emulator_stop(self):
|
def emulator_stop(self):
|
||||||
logger.hr('Emulator stop', level=1)
|
logger.hr('Emulator stop', level=1)
|
||||||
return self._emulator_function_wrapper(self._emulator_stop)
|
for _ in range(3):
|
||||||
|
# Stop
|
||||||
|
if self._emulator_function_wrapper(self._emulator_stop):
|
||||||
|
# Success
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
# Failed to stop, start and stop again
|
||||||
|
if self._emulator_function_wrapper(self._emulator_start):
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
logger.error('Failed to stop emulator 3 times, stopped')
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
@ -147,6 +147,10 @@ class Fuel(UI):
|
|||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
bool: If used
|
bool: If used
|
||||||
|
|
||||||
|
Pages:
|
||||||
|
in: COMBAT_AGAIN
|
||||||
|
out: COMBAT_AGAIN
|
||||||
"""
|
"""
|
||||||
limit = self.config.stored.TrailblazePower.FIXED_TOTAL
|
limit = self.config.stored.TrailblazePower.FIXED_TOTAL
|
||||||
use = (limit - current) // self.fuel_trailblaze_power
|
use = (limit - current) // self.fuel_trailblaze_power
|
||||||
@ -173,6 +177,7 @@ class Fuel(UI):
|
|||||||
has_fuel = True
|
has_fuel = True
|
||||||
if not has_fuel and timeout.reached():
|
if not has_fuel and timeout.reached():
|
||||||
logger.info("No fuel found")
|
logger.info("No fuel found")
|
||||||
|
self._fuel_cancel()
|
||||||
return False
|
return False
|
||||||
if self.appear_then_click(FUEL):
|
if self.appear_then_click(FUEL):
|
||||||
has_fuel = True
|
has_fuel = True
|
||||||
|
Loading…
Reference in New Issue
Block a user