Power grid works!
This commit is contained in:
parent
db74d4135d
commit
2283afbf51
11 changed files with 245 additions and 42 deletions
|
@ -12,11 +12,21 @@ var wired setget , get_wired
|
|||
export var power_usage = 0.0
|
||||
export var power_source = 0.0
|
||||
|
||||
const DEBUG = true
|
||||
var power_load = 0.0
|
||||
var available = 0.0
|
||||
var powered = false setget set_powered
|
||||
|
||||
func get_wired() -> bool:
|
||||
return socket != null
|
||||
|
||||
func _physics_process(_delta):
|
||||
func set_powered(val: bool) -> void:
|
||||
var current = powered
|
||||
powered = val
|
||||
if current and not val:
|
||||
emit_signal("power_disconnected")
|
||||
elif not current and val:
|
||||
emit_signal("power_connected")
|
||||
|
||||
func _physics_process(_delta: float) -> void:
|
||||
if wired:
|
||||
pass
|
||||
|
|
|
@ -14,6 +14,7 @@ var screen_region_offset = Vector2.ZERO
|
|||
var open = false
|
||||
|
||||
onready var activationRange = $ActivationRange as ActivationRange
|
||||
onready var manager = $PowerManager as PowerManager
|
||||
|
||||
func _ready():
|
||||
if not Engine.editor_hint:
|
||||
|
@ -77,7 +78,7 @@ func _input_event(_viewport, event, _shape_idx):
|
|||
return
|
||||
if event is InputEventMouseButton and event.pressed and not open:
|
||||
# Must be in range
|
||||
if activationRange.in_range():
|
||||
if activationRange.in_range() and manager.powered:
|
||||
open = true
|
||||
manage_controls(true)
|
||||
$UIAnimation.play("fadein")
|
||||
|
@ -94,3 +95,10 @@ func _force_close_ui():
|
|||
if open:
|
||||
open = false
|
||||
$UIAnimation.play("fadeout")
|
||||
|
||||
func _power_status_changed(powered: bool) -> void:
|
||||
activationRange.visible = powered
|
||||
if powered:
|
||||
$ScreenAnimation.play("on")
|
||||
else:
|
||||
$ScreenAnimation.play("off")
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
[gd_scene load_steps=14 format=2]
|
||||
[gd_scene load_steps=15 format=2]
|
||||
|
||||
[ext_resource path="res://Graphics/tgstation/computer-screens.png" type="Texture" id=1]
|
||||
[ext_resource path="res://Graphics/tgstation/computer.png" type="Texture" id=2]
|
||||
|
@ -6,6 +6,7 @@
|
|||
[ext_resource path="res://Actors/Objects/Computer/UI/ControlComp.tscn" type="PackedScene" id=4]
|
||||
[ext_resource path="res://Graphics/light_shadow_light.png" type="Texture" id=5]
|
||||
[ext_resource path="res://Actors/Components/ActivationRange.gd" type="Script" id=6]
|
||||
[ext_resource path="res://Actors/Components/PowerManager.gd" type="Script" id=7]
|
||||
|
||||
[sub_resource type="RectangleShape2D" id=1]
|
||||
extents = Vector2( 16, 16 )
|
||||
|
@ -14,6 +15,7 @@ extents = Vector2( 16, 16 )
|
|||
blend_mode = 1
|
||||
|
||||
[sub_resource type="Animation" id=3]
|
||||
loop = true
|
||||
tracks/0/type = "value"
|
||||
tracks/0/path = NodePath("computer/screen:modulate")
|
||||
tracks/0/interp = 1
|
||||
|
@ -127,7 +129,7 @@ texture_scale = 0.5
|
|||
energy = 0.5
|
||||
|
||||
[node name="ScreenAnimation" type="AnimationPlayer" parent="."]
|
||||
autoplay = "on"
|
||||
autoplay = "off"
|
||||
anims/off = SubResource( 3 )
|
||||
anims/on = SubResource( 4 )
|
||||
|
||||
|
@ -155,7 +157,13 @@ script = ExtResource( 6 )
|
|||
[node name="CollisionShape2D" type="CollisionShape2D" parent="ActivationRange"]
|
||||
position = Vector2( 16, 16 )
|
||||
shape = SubResource( 7 )
|
||||
|
||||
[node name="PowerManager" type="Node" parent="."]
|
||||
script = ExtResource( 7 )
|
||||
power_usage = 20.0
|
||||
[connection signal="animation_finished" from="UIAnimation" to="." method="_ui_fade_completed"]
|
||||
[connection signal="mouse_entered" from="Control/ControlComp" to="." method="_ui_focus_changed" binds= [ true ]]
|
||||
[connection signal="mouse_exited" from="Control/ControlComp" to="." method="_ui_focus_changed" binds= [ false ]]
|
||||
[connection signal="player_left" from="ActivationRange" to="." method="_force_close_ui"]
|
||||
[connection signal="power_connected" from="PowerManager" to="." method="_power_status_changed" binds= [ true ]]
|
||||
[connection signal="power_disconnected" from="PowerManager" to="." method="_power_status_changed" binds= [ false ]]
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
tool
|
||||
|
||||
class_name ElectricSocket
|
||||
|
||||
extends Area2D
|
||||
|
||||
class_name ElectricSocket
|
||||
|
||||
enum Direction { LEFT, RIGHT, UP, DOWN }
|
||||
enum Flow { SOURCE, SINK, BIDIRECTIONAL }
|
||||
|
||||
|
@ -22,25 +22,28 @@ onready var socket = $socket
|
|||
|
||||
var network = null
|
||||
|
||||
func _ready():
|
||||
func _ready() -> void:
|
||||
socket.material = socket.material.duplicate()
|
||||
refresh_sprite()
|
||||
if Engine.editor_hint:
|
||||
return
|
||||
for connection in connectionPaths:
|
||||
add_connection(get_node(connection))
|
||||
|
||||
func add_connection(node: Node):
|
||||
func add_connection(node: Node) -> void:
|
||||
var manager = node.get_node("PowerManager") as PowerManager
|
||||
manager.socket = self
|
||||
connections.append(manager)
|
||||
|
||||
func set_direction(dir):
|
||||
func set_direction(dir) -> void:
|
||||
direction = dir
|
||||
refresh_sprite()
|
||||
|
||||
func set_flow(val):
|
||||
func set_flow(val) -> void:
|
||||
flow = val
|
||||
refresh_sprite()
|
||||
|
||||
func refresh_sprite():
|
||||
func refresh_sprite() -> void:
|
||||
if socket == null:
|
||||
return
|
||||
match direction:
|
||||
|
|
|
@ -2,22 +2,29 @@ extends StaticBody2D
|
|||
|
||||
class_name GameObjectPowerStorage
|
||||
|
||||
const MAX_CHARGE = 5000.0
|
||||
const MAX_CHARGE = 100000.0
|
||||
|
||||
var open = false
|
||||
var attached = true
|
||||
onready var activationRange = $ActivationRange as ActivationRange
|
||||
onready var manager = $PowerManager as PowerManager
|
||||
|
||||
var current_charge = MAX_CHARGE
|
||||
export var current_charge = MAX_CHARGE
|
||||
export var max_discharge_rate = 200
|
||||
|
||||
func _ready():
|
||||
if not Engine.editor_hint:
|
||||
activationRange.visible = true
|
||||
|
||||
func _physics_process(_delta):
|
||||
if $PowerManager.wired:
|
||||
if $PowerManager.DEBUG:
|
||||
func _physics_process(delta: float):
|
||||
if manager.wired:
|
||||
if current_charge > 0:
|
||||
manager.power_source = min(current_charge, max_discharge_rate)
|
||||
if manager.power_load > 0:
|
||||
current_charge -= manager.power_load * delta
|
||||
if PowerNetwork.DEBUG:
|
||||
update()
|
||||
$Control/PowerUI.displayed_charge = current_charge
|
||||
|
||||
func _input(event):
|
||||
if event is InputEventMouseButton and event.pressed and not is_inside and open:
|
||||
|
@ -48,7 +55,7 @@ func _force_close_ui():
|
|||
$UIAnimation.play("fadeout")
|
||||
|
||||
func _draw():
|
||||
if $PowerManager.DEBUG and $PowerManager.wired:
|
||||
if PowerNetwork.DEBUG and manager.wired:
|
||||
var charge_px = int(current_charge / MAX_CHARGE * 32)
|
||||
var charge_color = Color.greenyellow
|
||||
if charge_px < 20:
|
||||
|
|
|
@ -60,7 +60,7 @@ tracks/1/keys = {
|
|||
"times": PoolRealArray( 0, 0.2 )
|
||||
}
|
||||
|
||||
[sub_resource type="CircleShape2D" id=5]
|
||||
[sub_resource type="CircleShape2D" id=4]
|
||||
radius = 56.0
|
||||
|
||||
[node name="StaticBody2D" type="StaticBody2D"]
|
||||
|
@ -89,7 +89,7 @@ z_index = 999
|
|||
[node name="PowerUI" parent="Control" instance=ExtResource( 4 )]
|
||||
visible = false
|
||||
margin_left = -50.0
|
||||
margin_top = -73.0
|
||||
margin_top = -85.0
|
||||
margin_right = 150.0
|
||||
margin_bottom = 57.0
|
||||
rect_scale = Vector2( 0.5, 0.5 )
|
||||
|
@ -100,7 +100,7 @@ position = Vector2( 16, 16 )
|
|||
script = ExtResource( 3 )
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="ActivationRange"]
|
||||
shape = SubResource( 5 )
|
||||
shape = SubResource( 4 )
|
||||
[connection signal="mouse_entered" from="Control/PowerUI" to="." method="_ui_focus_changed" binds= [ true ]]
|
||||
[connection signal="mouse_exited" from="Control/PowerUI" to="." method="_ui_focus_changed" binds= [ false ]]
|
||||
[connection signal="player_left" from="ActivationRange" to="." method="_force_close_ui"]
|
||||
|
|
|
@ -2,5 +2,12 @@ extends Control
|
|||
|
||||
onready var scene = $"/root/scene" as GameInstance
|
||||
|
||||
func _physics_process(_delta):
|
||||
pass
|
||||
var displayed_charge = 0 setget set_current_charge
|
||||
var max_charge = 1 setget set_max_charge
|
||||
|
||||
func set_current_charge(val):
|
||||
$Container/CurrentBox/HBoxContainer/CurrentChargeLabel.text = "(" + str(round(val/10)/100) + "kJ)"
|
||||
$Container/CurrentBox/ProgressBar.value = val
|
||||
|
||||
func set_max_charge(val: float):
|
||||
$Container/CurrentBox/ProgressBar.max_value = max_charge
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
[gd_scene load_steps=4 format=2]
|
||||
[gd_scene load_steps=5 format=2]
|
||||
|
||||
[ext_resource path="res://Actors/Objects/PowerStorage/UI/PowerUI.gd" type="Script" id=1]
|
||||
[ext_resource path="res://Graphics/UI/ui-popup-panel.png" type="Texture" id=2]
|
||||
[ext_resource path="res://Graphics/UI/ui_theme.tres" type="Theme" id=3]
|
||||
[ext_resource path="res://Graphics/unshaded_mat.tres" type="Material" id=4]
|
||||
|
||||
[node name="PowerUI" type="Control"]
|
||||
material = ExtResource( 4 )
|
||||
margin_left = -100.0
|
||||
margin_top = -150.0
|
||||
margin_right = 100.0
|
||||
margin_left = -110.0
|
||||
margin_top = -160.0
|
||||
margin_right = 110.0
|
||||
margin_bottom = -20.0
|
||||
mouse_filter = 1
|
||||
script = ExtResource( 1 )
|
||||
|
@ -19,11 +20,13 @@ __meta__ = {
|
|||
[node name="TextureRect" type="TextureRect" parent="."]
|
||||
material = ExtResource( 4 )
|
||||
anchor_left = 0.5
|
||||
anchor_top = 1.0
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 1.0
|
||||
margin_left = -8.0
|
||||
margin_top = 111.826
|
||||
margin_top = -18.0
|
||||
margin_right = 8.27014
|
||||
margin_bottom = 143.855
|
||||
margin_bottom = 14.182
|
||||
texture = ExtResource( 2 )
|
||||
stretch_mode = 3
|
||||
__meta__ = {
|
||||
|
@ -34,6 +37,7 @@ __meta__ = {
|
|||
material = ExtResource( 4 )
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
mouse_filter = 1
|
||||
texture = ExtResource( 2 )
|
||||
region_rect = Rect2( 0, 0, 16, 16 )
|
||||
patch_margin_left = 4
|
||||
|
@ -59,3 +63,81 @@ custom_constants/separation = 20
|
|||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="CurrentBox" type="VBoxContainer" parent="Container"]
|
||||
margin_right = 200.0
|
||||
margin_bottom = 40.0
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="Container/CurrentBox"]
|
||||
margin_right = 200.0
|
||||
margin_bottom = 18.0
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Label" type="Label" parent="Container/CurrentBox/HBoxContainer"]
|
||||
margin_right = 102.0
|
||||
margin_bottom = 18.0
|
||||
mouse_filter = 1
|
||||
theme = ExtResource( 3 )
|
||||
text = "Current charge"
|
||||
|
||||
[node name="CurrentChargeLabel" type="Label" parent="Container/CurrentBox/HBoxContainer"]
|
||||
margin_left = 106.0
|
||||
margin_right = 106.0
|
||||
margin_bottom = 18.0
|
||||
mouse_filter = 1
|
||||
theme = ExtResource( 3 )
|
||||
|
||||
[node name="ProgressBar" type="ProgressBar" parent="Container/CurrentBox"]
|
||||
margin_top = 22.0
|
||||
margin_right = 200.0
|
||||
margin_bottom = 40.0
|
||||
mouse_filter = 1
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
theme = ExtResource( 3 )
|
||||
|
||||
[node name="ChargeBox" type="GridContainer" parent="Container"]
|
||||
margin_top = 60.0
|
||||
margin_right = 200.0
|
||||
margin_bottom = 120.0
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
columns = 2
|
||||
|
||||
[node name="Charge rate" type="Label" parent="Container/ChargeBox"]
|
||||
margin_top = 5.0
|
||||
margin_right = 84.0
|
||||
margin_bottom = 23.0
|
||||
mouse_filter = 1
|
||||
theme = ExtResource( 3 )
|
||||
text = "Limit charge"
|
||||
|
||||
[node name="SpinBox" type="SpinBox" parent="Container/ChargeBox"]
|
||||
margin_left = 88.0
|
||||
margin_right = 186.0
|
||||
margin_bottom = 28.0
|
||||
mouse_filter = 1
|
||||
theme = ExtResource( 3 )
|
||||
max_value = 200.0
|
||||
suffix = "W"
|
||||
|
||||
[node name="Discharge" type="Label" parent="Container/ChargeBox"]
|
||||
margin_top = 37.0
|
||||
margin_right = 84.0
|
||||
margin_bottom = 55.0
|
||||
mouse_filter = 1
|
||||
theme = ExtResource( 3 )
|
||||
text = "Limit output"
|
||||
|
||||
[node name="SpinBox2" type="SpinBox" parent="Container/ChargeBox"]
|
||||
margin_left = 88.0
|
||||
margin_top = 32.0
|
||||
margin_right = 186.0
|
||||
margin_bottom = 60.0
|
||||
mouse_filter = 1
|
||||
theme = ExtResource( 3 )
|
||||
max_value = 200.0
|
||||
value = 200.0
|
||||
suffix = "W"
|
||||
|
|
|
@ -21,3 +21,4 @@ centered = false
|
|||
|
||||
[node name="PowerManager" type="Node" parent="."]
|
||||
script = ExtResource( 3 )
|
||||
power_usage = 10.0
|
||||
|
|
|
@ -2,23 +2,26 @@ extends Node
|
|||
|
||||
class_name PowerNetwork
|
||||
|
||||
const DEBUG = true
|
||||
const DEBUG = false
|
||||
|
||||
var nodes = []
|
||||
var sockets = []
|
||||
|
||||
var total_source = 0
|
||||
var total_usage = 0
|
||||
|
||||
var debugColor = Color.cyan
|
||||
|
||||
func _ready():
|
||||
name = "PowerNetwork"
|
||||
debugColor = Color.from_hsv(randf(), 0.8, 0.8)
|
||||
|
||||
func add_node(node):
|
||||
func add_node(node) -> void:
|
||||
nodes.append(node)
|
||||
if node is ElectricSocket:
|
||||
if "connections" in node:
|
||||
sockets.append(node)
|
||||
|
||||
func remove_node(node):
|
||||
func remove_node(node) -> void:
|
||||
var node_idx = nodes.find(node)
|
||||
if node_idx >= 0:
|
||||
nodes.remove(node_idx)
|
||||
|
@ -28,19 +31,53 @@ func remove_node(node):
|
|||
# Do other splitting here
|
||||
node.network = null
|
||||
|
||||
func join(network):
|
||||
func join(network) -> void:
|
||||
for node in network.nodes:
|
||||
nodes.append(node)
|
||||
node.network = self
|
||||
for socket in network.sockets:
|
||||
sockets.append(socket)
|
||||
socket.network = self
|
||||
# Do other merging here
|
||||
network.queue_free()
|
||||
|
||||
func _physics_process(_delta):
|
||||
func _physics_process(_delta: float) -> void:
|
||||
# Recalculate power availability and usage
|
||||
var total_source = 0
|
||||
var total_usage = 0
|
||||
total_source = 0
|
||||
total_usage = 0
|
||||
var sources = []
|
||||
var sinks = []
|
||||
# Calculate totals
|
||||
for socket in sockets:
|
||||
for connection in socket.connections:
|
||||
var manager = connection as PowerManager
|
||||
total_source += manager.power_source
|
||||
match socket.flow:
|
||||
ElectricSocket.Flow.SINK:
|
||||
total_usage += manager.power_usage
|
||||
sinks.append(manager)
|
||||
ElectricSocket.Flow.SOURCE:
|
||||
total_source += manager.power_source
|
||||
sources.append(manager)
|
||||
ElectricSocket.Flow.BIDIRECTIONAL:
|
||||
total_usage += manager.power_usage
|
||||
total_source += manager.power_source
|
||||
sinks.append(manager)
|
||||
sources.append(manager)
|
||||
# Update manager stats
|
||||
var available_supply = total_source
|
||||
for sink in sinks:
|
||||
# Check if item can be powered this cycle
|
||||
if sink.power_usage > 0:
|
||||
if available_supply > sink.power_usage:
|
||||
available_supply -= sink.power_usage
|
||||
sink.powered = true
|
||||
else:
|
||||
sink.powered = false
|
||||
# Update available power to sinks
|
||||
for sink in sinks:
|
||||
sink.available = available_supply
|
||||
# Check how much we actually need to drain from sources
|
||||
var remaining_drain = total_source - available_supply
|
||||
for source in sources:
|
||||
var source_load = source.power_source / total_source * remaining_drain
|
||||
source.power_load = source_load
|
||||
|
|
|
@ -50,7 +50,7 @@ cell_size = Vector2( 32, 32 )
|
|||
cell_quadrant_size = 32
|
||||
occluder_light_mask = -2147483647
|
||||
format = 1
|
||||
tile_data = PoolIntArray( 393214, 0, 327681, 393215, 0, 262145, 327680, 0, 458752, 458749, 0, 65537, 458750, 0, 262150, 458751, 0, 458754, 393216, 0, 393218, 524284, 0, 327681, 524285, 0, 131078, 524287, 0, 262151, 458752, 0, 458755, 458755, 0, 131072, 458756, 0, 0, 589820, 0, 262151, 589821, 0, 6, 589822, 0, 1, 589823, 0, 196611, 655355, 0, 131072, 655356, 0, 131074, 655358, 0, 65539, 589828, 0, 131073, 720892, 0, 65538, 720893, 0, 1, 720894, 0, 2, 720895, 0, 262144, 655363, 0, 131072, 655364, 0, 2, 655365, 0, 65536, 655366, 0, 65536, 655367, 0, 1, 655368, 0, 262144, 786429, 0, 131075, 720903, 0, 131075 )
|
||||
tile_data = PoolIntArray( 393212, 0, 131072, 393213, 0, 65536, 393214, 0, 65536, 393215, 0, 65536, 327680, 0, 65536, 327681, 0, 65536, 327682, 0, 65536, 327683, 0, 65536, 327684, 0, 262144, 589828, 0, 131073, 655364, 0, 65538, 655365, 0, 65536, 655366, 0, 65536, 655367, 0, 1, 655368, 0, 262144, 720903, 0, 131075 )
|
||||
|
||||
[node name="floor" type="TileMap" parent="."]
|
||||
tile_set = ExtResource( 9 )
|
||||
|
@ -121,8 +121,8 @@ computer_type = 4
|
|||
position = Vector2( -128, 128 )
|
||||
computer_type = 5
|
||||
|
||||
[node name="StaticBody2D2" parent="objects" instance=ExtResource( 12 )]
|
||||
position = Vector2( 193, 128 )
|
||||
[node name="SMES2" parent="objects" instance=ExtResource( 12 )]
|
||||
position = Vector2( 128, 128 )
|
||||
|
||||
[node name="SMES1" parent="objects" instance=ExtResource( 12 )]
|
||||
position = Vector2( 128, 256 )
|
||||
|
@ -137,6 +137,7 @@ position = Vector2( 288, 320 )
|
|||
[node name="ElectricSocket" parent="objects" instance=ExtResource( 13 )]
|
||||
position = Vector2( 128, 288 )
|
||||
connectionPaths = [ NodePath("../SMES1") ]
|
||||
flow = 0
|
||||
|
||||
[node name="ElectricSocket2" parent="objects" instance=ExtResource( 13 )]
|
||||
position = Vector2( 256, 320 )
|
||||
|
@ -144,6 +145,45 @@ direction = 1
|
|||
connectionPaths = [ NodePath("../Scanner") ]
|
||||
flow = 1
|
||||
|
||||
[node name="ElectricSocket4" parent="objects" instance=ExtResource( 13 )]
|
||||
position = Vector2( -128, 160 )
|
||||
connectionPaths = [ NodePath("../Computer6") ]
|
||||
flow = 1
|
||||
|
||||
[node name="ElectricSocket5" parent="objects" instance=ExtResource( 13 )]
|
||||
position = Vector2( -96, 160 )
|
||||
connectionPaths = [ NodePath("../Computer5") ]
|
||||
flow = 1
|
||||
|
||||
[node name="ElectricSocket6" parent="objects" instance=ExtResource( 13 )]
|
||||
position = Vector2( -64, 160 )
|
||||
connectionPaths = [ NodePath("../Computer") ]
|
||||
flow = 1
|
||||
|
||||
[node name="ElectricSocket7" parent="objects" instance=ExtResource( 13 )]
|
||||
position = Vector2( -32, 160 )
|
||||
connectionPaths = [ NodePath("../Computer2") ]
|
||||
flow = 1
|
||||
|
||||
[node name="ElectricSocket8" parent="objects" instance=ExtResource( 13 )]
|
||||
position = Vector2( 0, 160 )
|
||||
connectionPaths = [ NodePath("../Computer3") ]
|
||||
flow = 1
|
||||
|
||||
[node name="ElectricSocket9" parent="objects" instance=ExtResource( 13 )]
|
||||
position = Vector2( 32, 160 )
|
||||
connectionPaths = [ NodePath("../Computer4") ]
|
||||
flow = 1
|
||||
|
||||
[node name="ElectricSocket10" parent="objects" instance=ExtResource( 13 )]
|
||||
position = Vector2( 64, 160 )
|
||||
connectionPaths = [ NodePath("../Computer7") ]
|
||||
flow = 1
|
||||
|
||||
[node name="ElectricSocket3" parent="objects" instance=ExtResource( 13 )]
|
||||
position = Vector2( 128, 160 )
|
||||
connectionPaths = [ NodePath("../SMES2") ]
|
||||
|
||||
[node name="lights" type="Node2D" parent="."]
|
||||
modulate = Color( 0.980392, 0.980392, 0.980392, 1 )
|
||||
__meta__ = {
|
||||
|
|
Reference in a new issue