Restructured the project and optimized several nodes.
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,93 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Flyff EXP Node (Final Combined Version)
|
||||
- Polls the API at http://127.0.0.1:5000/data
|
||||
- Outputs only the "exp" value as a string
|
||||
- Uses color (48, 116, 143) for its output port
|
||||
- Displays "exp" in a text field labeled "Value"
|
||||
- Retrieves the port with self.outputs().get('value')
|
||||
"""
|
||||
|
||||
import time
|
||||
import requests
|
||||
import traceback
|
||||
from OdenGraphQt import BaseNode
|
||||
|
||||
class FlyffEXPCurrentNode(BaseNode):
|
||||
__identifier__ = 'bunny-lab.io.flyff_exp_current_node'
|
||||
NODE_NAME = 'Flyff - EXP'
|
||||
|
||||
def __init__(self):
|
||||
super(FlyffEXPCurrentNode, self).__init__()
|
||||
|
||||
# 1) Text input property named "value" for UI display
|
||||
self.add_text_input('value', 'Value', text='N/A')
|
||||
|
||||
# 2) Output port also named "value"
|
||||
self.add_output('value', color=(48, 116, 143))
|
||||
|
||||
self._api_down = True
|
||||
self._last_api_attempt = 0.0
|
||||
self._retry_interval = 5.0
|
||||
self._last_error_printed = 0.0
|
||||
|
||||
self.set_name("Flyff - EXP (API Disconnected)")
|
||||
|
||||
def process_input(self):
|
||||
current_time = time.time()
|
||||
if self._api_down and (current_time - self._last_api_attempt < self._retry_interval):
|
||||
return
|
||||
|
||||
self._last_api_attempt = current_time
|
||||
|
||||
try:
|
||||
response = requests.get("http://127.0.0.1:5000/data", timeout=1)
|
||||
status_code = response.status_code
|
||||
print(f"[DEBUG] FlyffEXPCurrentNode: HTTP Status Code = {status_code}")
|
||||
|
||||
if status_code == 200:
|
||||
try:
|
||||
data = response.json() or {}
|
||||
except ValueError:
|
||||
data = {}
|
||||
|
||||
if isinstance(data, list):
|
||||
data = {}
|
||||
|
||||
self._api_down = False
|
||||
self.set_name("Flyff - EXP (API Connected)")
|
||||
|
||||
new_value = data.get("exp", "N/A")
|
||||
print(f"[DEBUG] FlyffEXPCurrentNode: exp = {new_value}")
|
||||
|
||||
new_value_str = str(new_value)
|
||||
self.set_property('value', new_value_str)
|
||||
self.transmit_data(new_value_str)
|
||||
|
||||
else:
|
||||
self._handle_api_error(f"HTTP {status_code} from FlyffEXPCurrentNode")
|
||||
self._api_down = True
|
||||
|
||||
except Exception as e:
|
||||
tb = traceback.format_exc()
|
||||
self._handle_api_error(f"Exception in FlyffEXPCurrentNode: {e}\nTraceback:\n{tb}")
|
||||
self._api_down = True
|
||||
|
||||
def transmit_data(self, data):
|
||||
output_port = self.outputs().get('value')
|
||||
if output_port and output_port.connected_ports():
|
||||
for connected_port in output_port.connected_ports():
|
||||
connected_node = connected_port.node()
|
||||
if hasattr(connected_node, 'receive_data'):
|
||||
try:
|
||||
connected_node.receive_data(data, source_port_name='value')
|
||||
except Exception as e:
|
||||
print(f"[ERROR] Error transmitting data to {connected_node}: {e}")
|
||||
|
||||
def _handle_api_error(self, msg):
|
||||
current_time = time.time()
|
||||
if (current_time - self._last_error_printed) >= self._retry_interval:
|
||||
print(f"[ERROR] {msg}")
|
||||
self._last_error_printed = current_time
|
||||
|
||||
self.set_name("Flyff - EXP (API Disconnected)")
|
||||
@@ -0,0 +1,93 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Flyff FP Current Node (Final Combined Version)
|
||||
- Polls the API at http://127.0.0.1:5000/data
|
||||
- Outputs only the "fp_current" value as a string
|
||||
- Uses color (36, 116, 32) for its output port
|
||||
- Displays "fp_current" in a text field labeled "Value"
|
||||
- Retrieves the port with self.outputs().get('value')
|
||||
"""
|
||||
|
||||
import time
|
||||
import requests
|
||||
import traceback
|
||||
from OdenGraphQt import BaseNode
|
||||
|
||||
class FlyffFPCurrentNode(BaseNode):
|
||||
__identifier__ = 'bunny-lab.io.flyff_fp_current_node'
|
||||
NODE_NAME = 'Flyff - FP Current'
|
||||
|
||||
def __init__(self):
|
||||
super(FlyffFPCurrentNode, self).__init__()
|
||||
|
||||
# 1) Text input property named "value" for UI display
|
||||
self.add_text_input('value', 'Value', text='N/A')
|
||||
|
||||
# 2) Output port also named "value"
|
||||
self.add_output('value', color=(36, 116, 32))
|
||||
|
||||
self._api_down = True
|
||||
self._last_api_attempt = 0.0
|
||||
self._retry_interval = 5.0
|
||||
self._last_error_printed = 0.0
|
||||
|
||||
self.set_name("Flyff - FP Current (API Disconnected)")
|
||||
|
||||
def process_input(self):
|
||||
current_time = time.time()
|
||||
if self._api_down and (current_time - self._last_api_attempt < self._retry_interval):
|
||||
return
|
||||
|
||||
self._last_api_attempt = current_time
|
||||
|
||||
try:
|
||||
response = requests.get("http://127.0.0.1:5000/data", timeout=1)
|
||||
status_code = response.status_code
|
||||
print(f"[DEBUG] FlyffFPCurrentNode: HTTP Status Code = {status_code}")
|
||||
|
||||
if status_code == 200:
|
||||
try:
|
||||
data = response.json() or {}
|
||||
except ValueError:
|
||||
data = {}
|
||||
|
||||
if isinstance(data, list):
|
||||
data = {}
|
||||
|
||||
self._api_down = False
|
||||
self.set_name("Flyff - FP Current (API Connected)")
|
||||
|
||||
new_value = data.get("fp_current", "N/A")
|
||||
print(f"[DEBUG] FlyffFPCurrentNode: fp_current = {new_value}")
|
||||
|
||||
new_value_str = str(new_value)
|
||||
self.set_property('value', new_value_str)
|
||||
self.transmit_data(new_value_str)
|
||||
|
||||
else:
|
||||
self._handle_api_error(f"HTTP {status_code} from FlyffFPCurrentNode")
|
||||
self._api_down = True
|
||||
|
||||
except Exception as e:
|
||||
tb = traceback.format_exc()
|
||||
self._handle_api_error(f"Exception in FlyffFPCurrentNode: {e}\nTraceback:\n{tb}")
|
||||
self._api_down = True
|
||||
|
||||
def transmit_data(self, data):
|
||||
output_port = self.outputs().get('value')
|
||||
if output_port and output_port.connected_ports():
|
||||
for connected_port in output_port.connected_ports():
|
||||
connected_node = connected_port.node()
|
||||
if hasattr(connected_node, 'receive_data'):
|
||||
try:
|
||||
connected_node.receive_data(data, source_port_name='value')
|
||||
except Exception as e:
|
||||
print(f"[ERROR] Error transmitting data to {connected_node}: {e}")
|
||||
|
||||
def _handle_api_error(self, msg):
|
||||
current_time = time.time()
|
||||
if (current_time - self._last_error_printed) >= self._retry_interval:
|
||||
print(f"[ERROR] {msg}")
|
||||
self._last_error_printed = current_time
|
||||
|
||||
self.set_name("Flyff - FP Current (API Disconnected)")
|
||||
@@ -0,0 +1,93 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Flyff FP Total Node (Final Combined Version)
|
||||
- Polls the API at http://127.0.0.1:5000/data
|
||||
- Outputs only the "fp_total" value as a string
|
||||
- Uses color (36, 116, 32) for its output port
|
||||
- Displays "fp_total" in a text field labeled "Value"
|
||||
- Retrieves the port with self.outputs().get('value')
|
||||
"""
|
||||
|
||||
import time
|
||||
import requests
|
||||
import traceback
|
||||
from OdenGraphQt import BaseNode
|
||||
|
||||
class FlyffFPTotalNode(BaseNode):
|
||||
__identifier__ = 'bunny-lab.io.flyff_fp_total_node'
|
||||
NODE_NAME = 'Flyff - FP Total'
|
||||
|
||||
def __init__(self):
|
||||
super(FlyffFPTotalNode, self).__init__()
|
||||
|
||||
# 1) Text input property named "value" for UI display
|
||||
self.add_text_input('value', 'Value', text='N/A')
|
||||
|
||||
# 2) Output port also named "value"
|
||||
self.add_output('value', color=(36, 116, 32))
|
||||
|
||||
self._api_down = True
|
||||
self._last_api_attempt = 0.0
|
||||
self._retry_interval = 5.0
|
||||
self._last_error_printed = 0.0
|
||||
|
||||
self.set_name("Flyff - FP Total (API Disconnected)")
|
||||
|
||||
def process_input(self):
|
||||
current_time = time.time()
|
||||
if self._api_down and (current_time - self._last_api_attempt < self._retry_interval):
|
||||
return
|
||||
|
||||
self._last_api_attempt = current_time
|
||||
|
||||
try:
|
||||
response = requests.get("http://127.0.0.1:5000/data", timeout=1)
|
||||
status_code = response.status_code
|
||||
print(f"[DEBUG] FlyffFPTotalNode: HTTP Status Code = {status_code}")
|
||||
|
||||
if status_code == 200:
|
||||
try:
|
||||
data = response.json() or {}
|
||||
except ValueError:
|
||||
data = {}
|
||||
|
||||
if isinstance(data, list):
|
||||
data = {}
|
||||
|
||||
self._api_down = False
|
||||
self.set_name("Flyff - FP Total (API Connected)")
|
||||
|
||||
new_value = data.get("fp_total", "N/A")
|
||||
print(f"[DEBUG] FlyffFPTotalNode: fp_total = {new_value}")
|
||||
|
||||
new_value_str = str(new_value)
|
||||
self.set_property('value', new_value_str)
|
||||
self.transmit_data(new_value_str)
|
||||
|
||||
else:
|
||||
self._handle_api_error(f"HTTP {status_code} from FlyffFPTotalNode")
|
||||
self._api_down = True
|
||||
|
||||
except Exception as e:
|
||||
tb = traceback.format_exc()
|
||||
self._handle_api_error(f"Exception in FlyffFPTotalNode: {e}\nTraceback:\n{tb}")
|
||||
self._api_down = True
|
||||
|
||||
def transmit_data(self, data):
|
||||
output_port = self.outputs().get('value')
|
||||
if output_port and output_port.connected_ports():
|
||||
for connected_port in output_port.connected_ports():
|
||||
connected_node = connected_port.node()
|
||||
if hasattr(connected_node, 'receive_data'):
|
||||
try:
|
||||
connected_node.receive_data(data, source_port_name='value')
|
||||
except Exception as e:
|
||||
print(f"[ERROR] Error transmitting data to {connected_node}: {e}")
|
||||
|
||||
def _handle_api_error(self, msg):
|
||||
current_time = time.time()
|
||||
if (current_time - self._last_error_printed) >= self._retry_interval:
|
||||
print(f"[ERROR] {msg}")
|
||||
self._last_error_printed = current_time
|
||||
|
||||
self.set_name("Flyff - FP Total (API Disconnected)")
|
||||
@@ -0,0 +1,112 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Flyff HP Current Node (Final Combined Version)
|
||||
- Polls the API at http://127.0.0.1:5000/data
|
||||
- Outputs only the "hp_current" value as a string
|
||||
- Uses color (126, 36, 57) for its output port
|
||||
- Displays "hp_current" in a text field labeled "Value"
|
||||
- Avoids "list indices must be integers" by retrieving the port with self.outputs().get('value')
|
||||
"""
|
||||
|
||||
import time
|
||||
import requests
|
||||
import traceback
|
||||
from OdenGraphQt import BaseNode
|
||||
|
||||
class FlyffHPCurrentNode(BaseNode):
|
||||
__identifier__ = 'bunny-lab.io.flyff_hp_current_node'
|
||||
NODE_NAME = 'Flyff - HP Current'
|
||||
|
||||
def __init__(self):
|
||||
super(FlyffHPCurrentNode, self).__init__()
|
||||
|
||||
# 1) Add a text input property named "value" for UI display
|
||||
self.add_text_input('value', 'Value', text='N/A')
|
||||
|
||||
# 2) Add an output port also named "value"
|
||||
self.add_output('value', color=(126, 36, 57))
|
||||
|
||||
# Start in "disconnected" state
|
||||
self._api_down = True
|
||||
self._last_api_attempt = 0.0
|
||||
self._retry_interval = 5.0
|
||||
self._last_error_printed = 0.0
|
||||
|
||||
# Default node title
|
||||
self.set_name("Flyff - HP Current (API Disconnected)")
|
||||
|
||||
def process_input(self):
|
||||
"""
|
||||
Called periodically by the global timer in borealis.py
|
||||
"""
|
||||
current_time = time.time()
|
||||
if self._api_down and (current_time - self._last_api_attempt < self._retry_interval):
|
||||
return
|
||||
|
||||
self._last_api_attempt = current_time
|
||||
|
||||
try:
|
||||
response = requests.get("http://127.0.0.1:5000/data", timeout=1)
|
||||
status_code = response.status_code
|
||||
print(f"[DEBUG] FlyffHPCurrentNode: HTTP Status Code = {status_code}")
|
||||
|
||||
if status_code == 200:
|
||||
# Attempt to parse JSON
|
||||
try:
|
||||
data = response.json() or {}
|
||||
except ValueError:
|
||||
data = {}
|
||||
|
||||
# If data is a list, ignore or convert to {}
|
||||
if isinstance(data, list):
|
||||
data = {}
|
||||
|
||||
# Mark node as connected
|
||||
self._api_down = False
|
||||
self.set_name("Flyff - HP Current (API Connected)")
|
||||
|
||||
# Retrieve hp_current (default "N/A" if missing)
|
||||
new_value = data.get("hp_current", "N/A")
|
||||
print(f"[DEBUG] FlyffHPCurrentNode: hp_current = {new_value}")
|
||||
|
||||
# Convert to string
|
||||
new_value_str = str(new_value)
|
||||
|
||||
# 3) Update the text input property so the user sees it
|
||||
self.set_property('value', new_value_str)
|
||||
|
||||
# 4) Transmit to downstream nodes
|
||||
self.transmit_data(new_value_str)
|
||||
|
||||
else:
|
||||
# Non-200 => disconnected
|
||||
self._handle_api_error(f"HTTP {status_code} from FlyffHPCurrentNode")
|
||||
self._api_down = True
|
||||
|
||||
except Exception as e:
|
||||
tb = traceback.format_exc()
|
||||
self._handle_api_error(f"Exception in FlyffHPCurrentNode: {e}\nTraceback:\n{tb}")
|
||||
self._api_down = True
|
||||
|
||||
def transmit_data(self, data):
|
||||
"""
|
||||
Sends 'data' to any connected node via the "value" port.
|
||||
(Uses self.outputs().get('value') instead of self.output('value'))
|
||||
"""
|
||||
output_port = self.outputs().get('value')
|
||||
if output_port and output_port.connected_ports():
|
||||
for connected_port in output_port.connected_ports():
|
||||
connected_node = connected_port.node()
|
||||
if hasattr(connected_node, 'receive_data'):
|
||||
try:
|
||||
connected_node.receive_data(data, source_port_name='value')
|
||||
except Exception as e:
|
||||
print(f"[ERROR] Error transmitting data to {connected_node}: {e}")
|
||||
|
||||
def _handle_api_error(self, msg):
|
||||
current_time = time.time()
|
||||
if (current_time - self._last_error_printed) >= self._retry_interval:
|
||||
print(f"[ERROR] {msg}")
|
||||
self._last_error_printed = current_time
|
||||
|
||||
self.set_name("Flyff - HP Current (API Disconnected)")
|
||||
@@ -0,0 +1,93 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Flyff HP Total Node (Final Combined Version)
|
||||
- Polls the API at http://127.0.0.1:5000/data
|
||||
- Outputs only the "hp_total" value as a string
|
||||
- Uses color (126, 36, 57) for its output port
|
||||
- Displays "hp_total" in a text field labeled "Value"
|
||||
- Retrieves the port with self.outputs().get('value')
|
||||
"""
|
||||
|
||||
import time
|
||||
import requests
|
||||
import traceback
|
||||
from OdenGraphQt import BaseNode
|
||||
|
||||
class FlyffHPTotalNode(BaseNode):
|
||||
__identifier__ = 'bunny-lab.io.flyff_hp_total_node'
|
||||
NODE_NAME = 'Flyff - HP Total'
|
||||
|
||||
def __init__(self):
|
||||
super(FlyffHPTotalNode, self).__init__()
|
||||
|
||||
# 1) Text input property named "value" for UI display
|
||||
self.add_text_input('value', 'Value', text='N/A')
|
||||
|
||||
# 2) Output port also named "value"
|
||||
self.add_output('value', color=(126, 36, 57))
|
||||
|
||||
self._api_down = True
|
||||
self._last_api_attempt = 0.0
|
||||
self._retry_interval = 5.0
|
||||
self._last_error_printed = 0.0
|
||||
|
||||
self.set_name("Flyff - HP Total (API Disconnected)")
|
||||
|
||||
def process_input(self):
|
||||
current_time = time.time()
|
||||
if self._api_down and (current_time - self._last_api_attempt < self._retry_interval):
|
||||
return
|
||||
|
||||
self._last_api_attempt = current_time
|
||||
|
||||
try:
|
||||
response = requests.get("http://127.0.0.1:5000/data", timeout=1)
|
||||
status_code = response.status_code
|
||||
print(f"[DEBUG] FlyffHPTotalNode: HTTP Status Code = {status_code}")
|
||||
|
||||
if status_code == 200:
|
||||
try:
|
||||
data = response.json() or {}
|
||||
except ValueError:
|
||||
data = {}
|
||||
|
||||
if isinstance(data, list):
|
||||
data = {}
|
||||
|
||||
self._api_down = False
|
||||
self.set_name("Flyff - HP Total (API Connected)")
|
||||
|
||||
new_value = data.get("hp_total", "N/A")
|
||||
print(f"[DEBUG] FlyffHPTotalNode: hp_total = {new_value}")
|
||||
|
||||
new_value_str = str(new_value)
|
||||
self.set_property('value', new_value_str)
|
||||
self.transmit_data(new_value_str)
|
||||
|
||||
else:
|
||||
self._handle_api_error(f"HTTP {status_code} from FlyffHPTotalNode")
|
||||
self._api_down = True
|
||||
|
||||
except Exception as e:
|
||||
tb = traceback.format_exc()
|
||||
self._handle_api_error(f"Exception in FlyffHPTotalNode: {e}\nTraceback:\n{tb}")
|
||||
self._api_down = True
|
||||
|
||||
def transmit_data(self, data):
|
||||
output_port = self.outputs().get('value')
|
||||
if output_port and output_port.connected_ports():
|
||||
for connected_port in output_port.connected_ports():
|
||||
connected_node = connected_port.node()
|
||||
if hasattr(connected_node, 'receive_data'):
|
||||
try:
|
||||
connected_node.receive_data(data, source_port_name='value')
|
||||
except Exception as e:
|
||||
print(f"[ERROR] Error transmitting data to {connected_node}: {e}")
|
||||
|
||||
def _handle_api_error(self, msg):
|
||||
current_time = time.time()
|
||||
if (current_time - self._last_error_printed) >= self._retry_interval:
|
||||
print(f"[ERROR] {msg}")
|
||||
self._last_error_printed = current_time
|
||||
|
||||
self.set_name("Flyff - HP Total (API Disconnected)")
|
||||
@@ -0,0 +1,93 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Flyff MP Current Node (Final Combined Version)
|
||||
- Polls the API at http://127.0.0.1:5000/data
|
||||
- Outputs only the "mp_current" value as a string
|
||||
- Uses color (35, 89, 144) for its output port
|
||||
- Displays "mp_current" in a text field labeled "Value"
|
||||
- Retrieves the port with self.outputs().get('value')
|
||||
"""
|
||||
|
||||
import time
|
||||
import requests
|
||||
import traceback
|
||||
from OdenGraphQt import BaseNode
|
||||
|
||||
class FlyffMPCurrentNode(BaseNode):
|
||||
__identifier__ = 'bunny-lab.io.flyff_mp_current_node'
|
||||
NODE_NAME = 'Flyff - MP Current'
|
||||
|
||||
def __init__(self):
|
||||
super(FlyffMPCurrentNode, self).__init__()
|
||||
|
||||
# 1) Text input property named "value" for UI display
|
||||
self.add_text_input('value', 'Value', text='N/A')
|
||||
|
||||
# 2) Output port also named "value"
|
||||
self.add_output('value', color=(35, 89, 144))
|
||||
|
||||
self._api_down = True
|
||||
self._last_api_attempt = 0.0
|
||||
self._retry_interval = 5.0
|
||||
self._last_error_printed = 0.0
|
||||
|
||||
self.set_name("Flyff - MP Current (API Disconnected)")
|
||||
|
||||
def process_input(self):
|
||||
current_time = time.time()
|
||||
if self._api_down and (current_time - self._last_api_attempt < self._retry_interval):
|
||||
return
|
||||
|
||||
self._last_api_attempt = current_time
|
||||
|
||||
try:
|
||||
response = requests.get("http://127.0.0.1:5000/data", timeout=1)
|
||||
status_code = response.status_code
|
||||
print(f"[DEBUG] FlyffMPCurrentNode: HTTP Status Code = {status_code}")
|
||||
|
||||
if status_code == 200:
|
||||
try:
|
||||
data = response.json() or {}
|
||||
except ValueError:
|
||||
data = {}
|
||||
|
||||
if isinstance(data, list):
|
||||
data = {}
|
||||
|
||||
self._api_down = False
|
||||
self.set_name("Flyff - MP Current (API Connected)")
|
||||
|
||||
new_value = data.get("mp_current", "N/A")
|
||||
print(f"[DEBUG] FlyffMPCurrentNode: mp_current = {new_value}")
|
||||
|
||||
new_value_str = str(new_value)
|
||||
self.set_property('value', new_value_str)
|
||||
self.transmit_data(new_value_str)
|
||||
|
||||
else:
|
||||
self._handle_api_error(f"HTTP {status_code} from FlyffMPCurrentNode")
|
||||
self._api_down = True
|
||||
|
||||
except Exception as e:
|
||||
tb = traceback.format_exc()
|
||||
self._handle_api_error(f"Exception in FlyffMPCurrentNode: {e}\nTraceback:\n{tb}")
|
||||
self._api_down = True
|
||||
|
||||
def transmit_data(self, data):
|
||||
output_port = self.outputs().get('value')
|
||||
if output_port and output_port.connected_ports():
|
||||
for connected_port in output_port.connected_ports():
|
||||
connected_node = connected_port.node()
|
||||
if hasattr(connected_node, 'receive_data'):
|
||||
try:
|
||||
connected_node.receive_data(data, source_port_name='value')
|
||||
except Exception as e:
|
||||
print(f"[ERROR] Error transmitting data to {connected_node}: {e}")
|
||||
|
||||
def _handle_api_error(self, msg):
|
||||
current_time = time.time()
|
||||
if (current_time - self._last_error_printed) >= self._retry_interval:
|
||||
print(f"[ERROR] {msg}")
|
||||
self._last_error_printed = current_time
|
||||
|
||||
self.set_name("Flyff - MP Current (API Disconnected)")
|
||||
@@ -0,0 +1,93 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Flyff MP Total Node (Final Combined Version)
|
||||
- Polls the API at http://127.0.0.1:5000/data
|
||||
- Outputs only the "mp_total" value as a string
|
||||
- Uses color (35, 89, 144) for its output port
|
||||
- Displays "mp_total" in a text field labeled "Value"
|
||||
- Retrieves the port with self.outputs().get('value')
|
||||
"""
|
||||
|
||||
import time
|
||||
import requests
|
||||
import traceback
|
||||
from OdenGraphQt import BaseNode
|
||||
|
||||
class FlyffMPTotalNode(BaseNode):
|
||||
__identifier__ = 'bunny-lab.io.flyff_mp_total_node'
|
||||
NODE_NAME = 'Flyff - MP Total'
|
||||
|
||||
def __init__(self):
|
||||
super(FlyffMPTotalNode, self).__init__()
|
||||
|
||||
# 1) Text input property named "value" for UI display
|
||||
self.add_text_input('value', 'Value', text='N/A')
|
||||
|
||||
# 2) Output port also named "value"
|
||||
self.add_output('value', color=(35, 89, 144))
|
||||
|
||||
self._api_down = True
|
||||
self._last_api_attempt = 0.0
|
||||
self._retry_interval = 5.0
|
||||
self._last_error_printed = 0.0
|
||||
|
||||
self.set_name("Flyff - MP Total (API Disconnected)")
|
||||
|
||||
def process_input(self):
|
||||
current_time = time.time()
|
||||
if self._api_down and (current_time - self._last_api_attempt < self._retry_interval):
|
||||
return
|
||||
|
||||
self._last_api_attempt = current_time
|
||||
|
||||
try:
|
||||
response = requests.get("http://127.0.0.1:5000/data", timeout=1)
|
||||
status_code = response.status_code
|
||||
print(f"[DEBUG] FlyffMPTotalNode: HTTP Status Code = {status_code}")
|
||||
|
||||
if status_code == 200:
|
||||
try:
|
||||
data = response.json() or {}
|
||||
except ValueError:
|
||||
data = {}
|
||||
|
||||
if isinstance(data, list):
|
||||
data = {}
|
||||
|
||||
self._api_down = False
|
||||
self.set_name("Flyff - MP Total (API Connected)")
|
||||
|
||||
new_value = data.get("mp_total", "N/A")
|
||||
print(f"[DEBUG] FlyffMPTotalNode: mp_total = {new_value}")
|
||||
|
||||
new_value_str = str(new_value)
|
||||
self.set_property('value', new_value_str)
|
||||
self.transmit_data(new_value_str)
|
||||
|
||||
else:
|
||||
self._handle_api_error(f"HTTP {status_code} from FlyffMPTotalNode")
|
||||
self._api_down = True
|
||||
|
||||
except Exception as e:
|
||||
tb = traceback.format_exc()
|
||||
self._handle_api_error(f"Exception in FlyffMPTotalNode: {e}\nTraceback:\n{tb}")
|
||||
self._api_down = True
|
||||
|
||||
def transmit_data(self, data):
|
||||
output_port = self.outputs().get('value')
|
||||
if output_port and output_port.connected_ports():
|
||||
for connected_port in output_port.connected_ports():
|
||||
connected_node = connected_port.node()
|
||||
if hasattr(connected_node, 'receive_data'):
|
||||
try:
|
||||
connected_node.receive_data(data, source_port_name='value')
|
||||
except Exception as e:
|
||||
print(f"[ERROR] Error transmitting data to {connected_node}: {e}")
|
||||
|
||||
def _handle_api_error(self, msg):
|
||||
current_time = time.time()
|
||||
if (current_time - self._last_error_printed) >= self._retry_interval:
|
||||
print(f"[ERROR] {msg}")
|
||||
self._last_error_printed = current_time
|
||||
|
||||
self.set_name("Flyff - MP Total (API Disconnected)")
|
||||
@@ -0,0 +1,108 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Flyff Character Status Node (New Version):
|
||||
- Has no inputs/outputs.
|
||||
- Creates an OCR region in data_collector.
|
||||
- Periodically grabs raw text from that region, parses it here in the node,
|
||||
and sets data_manager's HP, MP, FP, EXP accordingly.
|
||||
- Also updates its own text fields with the parsed values.
|
||||
"""
|
||||
|
||||
import re
|
||||
from OdenGraphQt import BaseNode
|
||||
from PyQt5.QtWidgets import QMessageBox
|
||||
from Modules import data_manager, data_collector
|
||||
|
||||
class FlyffCharacterStatusNode(BaseNode):
|
||||
__identifier__ = 'bunny-lab.io.flyff_character_status_node'
|
||||
NODE_NAME = 'Flyff - Character Status'
|
||||
|
||||
def __init__(self):
|
||||
super(FlyffCharacterStatusNode, self).__init__()
|
||||
# Prevent duplicates
|
||||
if data_manager.character_status_collector_exists:
|
||||
QMessageBox.critical(None, "Error", "Only one Flyff Character Status Collector node is allowed.")
|
||||
raise Exception("Duplicate Character Status Node.")
|
||||
data_manager.character_status_collector_exists = True
|
||||
|
||||
# Add text fields for display
|
||||
self.add_text_input('hp', 'HP', text="HP: 0/0")
|
||||
self.add_text_input('mp', 'MP', text="MP: 0/0")
|
||||
self.add_text_input('fp', 'FP', text="FP: 0/0")
|
||||
self.add_text_input('exp', 'EXP', text="EXP: 0%")
|
||||
|
||||
# Create a unique region id for this node (or just "character_status")
|
||||
self.region_id = "character_status"
|
||||
data_collector.create_ocr_region(self.region_id, x=250, y=50, w=180, h=130)
|
||||
|
||||
# Start the data_collector background thread (if not already started)
|
||||
data_collector.start_collector()
|
||||
|
||||
# Set the node name
|
||||
self.set_name("Flyff - Character Status")
|
||||
|
||||
def parse_character_stats(self, raw_text):
|
||||
"""
|
||||
Extract HP, MP, FP, EXP from the raw OCR text lines.
|
||||
"""
|
||||
lines = [l.strip() for l in raw_text.splitlines() if l.strip()]
|
||||
hp_current, hp_total = 0, 0
|
||||
mp_current, mp_total = 0, 0
|
||||
fp_current, fp_total = 0, 0
|
||||
exp_value = 0.0
|
||||
|
||||
if len(lines) >= 4:
|
||||
# line 1: HP
|
||||
hp_match = re.search(r"(\d+)\s*/\s*(\d+)", lines[0])
|
||||
if hp_match:
|
||||
hp_current = int(hp_match.group(1))
|
||||
hp_total = int(hp_match.group(2))
|
||||
|
||||
# line 2: MP
|
||||
mp_match = re.search(r"(\d+)\s*/\s*(\d+)", lines[1])
|
||||
if mp_match:
|
||||
mp_current = int(mp_match.group(1))
|
||||
mp_total = int(mp_match.group(2))
|
||||
|
||||
# line 3: FP
|
||||
fp_match = re.search(r"(\d+)\s*/\s*(\d+)", lines[2])
|
||||
if fp_match:
|
||||
fp_current = int(fp_match.group(1))
|
||||
fp_total = int(fp_match.group(2))
|
||||
|
||||
# line 4: EXP
|
||||
exp_match = re.search(r"(\d+(?:\.\d+)?)", lines[3])
|
||||
if exp_match:
|
||||
val = float(exp_match.group(1))
|
||||
if val < 0: val = 0
|
||||
if val > 100: val = 100
|
||||
exp_value = val
|
||||
|
||||
return hp_current, hp_total, mp_current, mp_total, fp_current, fp_total, exp_value
|
||||
|
||||
def process_input(self):
|
||||
"""
|
||||
Called periodically by the global timer in your main application (borealis.py).
|
||||
"""
|
||||
# Grab raw text from data_collector
|
||||
raw_text = data_collector.get_raw_text(self.region_id)
|
||||
|
||||
# Parse it
|
||||
hp_c, hp_t, mp_c, mp_t, fp_c, fp_t, exp_v = self.parse_character_stats(raw_text)
|
||||
|
||||
# Update data_manager
|
||||
data_manager.set_data_bulk({
|
||||
"hp_current": hp_c,
|
||||
"hp_total": hp_t,
|
||||
"mp_current": mp_c,
|
||||
"mp_total": mp_t,
|
||||
"fp_current": fp_c,
|
||||
"fp_total": fp_t,
|
||||
"exp": exp_v
|
||||
})
|
||||
|
||||
# Update the node's text fields
|
||||
self.set_property('hp', f"HP: {hp_c}/{hp_t}")
|
||||
self.set_property('mp', f"MP: {mp_c}/{mp_t}")
|
||||
self.set_property('fp', f"FP: {fp_c}/{fp_t}")
|
||||
self.set_property('exp', f"EXP: {exp_v}%")
|
||||
@@ -0,0 +1,133 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
"""
|
||||
Standardized Flyff Low Health Alert Node:
|
||||
- Monitors an input value (1 = health alert, 0 = normal).
|
||||
- Displays a visual alert and plays a sound if enabled.
|
||||
- Uses a global update timer for processing.
|
||||
- Automatically processes float, int, and string values.
|
||||
"""
|
||||
|
||||
import time
|
||||
from OdenGraphQt import BaseNode
|
||||
from Qt import QtCore, QtWidgets, QtGui
|
||||
|
||||
try:
|
||||
import winsound
|
||||
HAS_WINSOUND = True
|
||||
except ImportError:
|
||||
HAS_WINSOUND = False
|
||||
|
||||
class OverlayCanvas(QtWidgets.QWidget):
|
||||
"""
|
||||
UI overlay for displaying a red warning box, which can be repositioned by dragging.
|
||||
"""
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
screen_geo = QtWidgets.QApplication.primaryScreen().geometry()
|
||||
self.setGeometry(screen_geo)
|
||||
self.setWindowFlags(QtCore.Qt.FramelessWindowHint | QtCore.Qt.WindowStaysOnTopHint)
|
||||
self.setAttribute(QtCore.Qt.WA_TranslucentBackground, True)
|
||||
self.setVisible(False)
|
||||
self.helper_LowHealthAlert = QtCore.QRect(250, 300, 900, 35)
|
||||
self.dragging = False
|
||||
self.drag_offset = None
|
||||
|
||||
def paintEvent(self, event):
|
||||
if not self.isVisible():
|
||||
return
|
||||
painter = QtGui.QPainter(self)
|
||||
painter.setPen(QtCore.Qt.NoPen)
|
||||
painter.setBrush(QtGui.QColor(255, 0, 0))
|
||||
painter.drawRect(self.helper_LowHealthAlert)
|
||||
font = QtGui.QFont("Arial", 14, QtGui.QFont.Bold)
|
||||
painter.setFont(font)
|
||||
painter.setPen(QtGui.QColor(255, 255, 255))
|
||||
text_x = self.helper_LowHealthAlert.center().x() - 50
|
||||
text_y = self.helper_LowHealthAlert.center().y() + 5
|
||||
painter.drawText(text_x, text_y, "LOW HEALTH")
|
||||
|
||||
def toggle_alert(self, state):
|
||||
self.setVisible(state == 1)
|
||||
self.update()
|
||||
|
||||
def mousePressEvent(self, event):
|
||||
if event.button() == QtCore.Qt.LeftButton:
|
||||
if self.helper_LowHealthAlert.contains(event.pos()):
|
||||
self.dragging = True
|
||||
self.drag_offset = event.pos() - self.helper_LowHealthAlert.topLeft()
|
||||
super().mousePressEvent(event)
|
||||
|
||||
def mouseMoveEvent(self, event):
|
||||
if self.dragging:
|
||||
new_top_left = event.pos() - self.drag_offset
|
||||
self.helper_LowHealthAlert.moveTo(new_top_left)
|
||||
self.update()
|
||||
super().mouseMoveEvent(event)
|
||||
|
||||
def mouseReleaseEvent(self, event):
|
||||
if event.button() == QtCore.Qt.LeftButton:
|
||||
self.dragging = False
|
||||
super().mouseReleaseEvent(event)
|
||||
|
||||
class FlyffLowHealthAlertNode(BaseNode):
|
||||
__identifier__ = 'bunny-lab.io.flyff_low_health_alert_node'
|
||||
NODE_NAME = 'Flyff - Low Health Alert'
|
||||
|
||||
overlay_instance = None
|
||||
last_beep_time = 0
|
||||
BEEP_INTERVAL_SECONDS = 2
|
||||
|
||||
def __init__(self):
|
||||
super(FlyffLowHealthAlertNode, self).__init__()
|
||||
self.add_checkbox('cb_1', '', 'Sound Alert', True)
|
||||
self.add_checkbox('cb_2', '', 'Visual Alert', True)
|
||||
self.add_input('Toggle (1 = On | 0 = Off)', color=(200, 100, 0))
|
||||
self.add_text_input('value', 'Current Value', text='0')
|
||||
self.add_combo_menu('beep_interval', 'Beep Interval', items=["0.5s", "1.0s", "2.0s"])
|
||||
|
||||
if not FlyffLowHealthAlertNode.overlay_instance:
|
||||
FlyffLowHealthAlertNode.overlay_instance = OverlayCanvas()
|
||||
FlyffLowHealthAlertNode.overlay_instance.show()
|
||||
|
||||
def process_input(self):
|
||||
input_port = self.input(0)
|
||||
value = input_port.connected_ports()[0].node().get_property('value') if input_port.connected_ports() else "0"
|
||||
self.receive_data(value)
|
||||
|
||||
def receive_data(self, data, source_port_name=None):
|
||||
try:
|
||||
if isinstance(data, str):
|
||||
data = float(data) if '.' in data else int(data)
|
||||
if isinstance(data, (float, int)):
|
||||
data = 1 if data > 1 else 0 if data <= 0 else int(data)
|
||||
else:
|
||||
data = 0
|
||||
except ValueError:
|
||||
data = 0
|
||||
|
||||
self.set_property('value', str(data))
|
||||
if self.get_property('cb_2'):
|
||||
FlyffLowHealthAlertNode.overlay_instance.toggle_alert(data)
|
||||
self.handle_beep(data)
|
||||
|
||||
def handle_beep(self, input_value):
|
||||
# Update beep interval from the dropdown property
|
||||
interval_str = self.get_property('beep_interval')
|
||||
if interval_str.endswith("s"):
|
||||
interval_seconds = float(interval_str[:-1])
|
||||
else:
|
||||
interval_seconds = float(interval_str)
|
||||
self.BEEP_INTERVAL_SECONDS = interval_seconds
|
||||
|
||||
if input_value == 1 and self.get_property('cb_1'):
|
||||
current_time = time.time()
|
||||
if (current_time - FlyffLowHealthAlertNode.last_beep_time) >= self.BEEP_INTERVAL_SECONDS:
|
||||
FlyffLowHealthAlertNode.last_beep_time = current_time
|
||||
self.play_beep()
|
||||
|
||||
def play_beep(self):
|
||||
if HAS_WINSOUND:
|
||||
winsound.Beep(376, 100)
|
||||
else:
|
||||
print('\a', end='')
|
||||
Reference in New Issue
Block a user