Removed Git LFS

This commit is contained in:
Eduard Urbach 2024-02-02 20:12:14 +01:00
parent 3e2329c3b9
commit d6843621ce
Signed by: akyoto
GPG Key ID: C874F672B1AF20C0
17 changed files with 136 additions and 308 deletions

2
.gitattributes vendored
View File

@ -1,3 +1 @@
* text=auto eol=lf * text=auto eol=lf
*.blend filter=lfs diff=lfs merge=lfs -text
*.ttf filter=lfs diff=lfs merge=lfs -text

3
.gitignore vendored
View File

@ -10,11 +10,10 @@
!*.svg !*.svg
!*.tres !*.tres
!*.tscn !*.tscn
!*.blend
!*.ttf
!*.cfg !*.cfg
!.gitignore !.gitignore
!.gitattributes !.gitattributes
!project.godot !project.godot
!project.code-workspace !project.code-workspace
.godot/ .godot/
assets/

View File

@ -1,3 +1,10 @@
# bom # bom
An attempt at highly efficient networking between Go servers and Godot clients. An attempt at highly efficient networking between Go servers and Godot clients.
## Assets
Git LFS is not suited for hosting large files because it keeps the entire history on the server.
There is `git lfs prune` for the client side, but we need it on the server side and this functionality simply does not exist.
Therefore the `client/assets` directory needs to be downloaded separately. Download link will be here in the future.

View File

@ -1,4 +1,4 @@
[gd_scene load_steps=25 format=3 uid="uid://b40y7iuskv1ar"] [gd_scene load_steps=23 format=3 uid="uid://b40y7iuskv1ar"]
[ext_resource type="Script" path="res://Main.gd" id="1_cw3ws"] [ext_resource type="Script" path="res://Main.gd" id="1_cw3ws"]
[ext_resource type="Script" path="res://network/Client.gd" id="2_8hxcx"] [ext_resource type="Script" path="res://network/Client.gd" id="2_8hxcx"]
@ -13,16 +13,15 @@
[ext_resource type="Script" path="res://network/Chat.gd" id="10_y3len"] [ext_resource type="Script" path="res://network/Chat.gd" id="10_y3len"]
[ext_resource type="Script" path="res://world/Sun.gd" id="11_4jb08"] [ext_resource type="Script" path="res://world/Sun.gd" id="11_4jb08"]
[ext_resource type="Environment" uid="uid://dixa0yso2s1u3" path="res://world/Environment.tres" id="12_cscto"] [ext_resource type="Environment" uid="uid://dixa0yso2s1u3" path="res://world/Environment.tres" id="12_cscto"]
[ext_resource type="CameraAttributesPractical" uid="uid://b835orxyqq6w5" path="res://camera/CameraAttributes.tres" id="13_pvug4"] [ext_resource type="PackedScene" uid="uid://hnn0n1xc2qt7" path="res://assets/models/tree/Tree.blend" id="14_7jtdl"]
[ext_resource type="PackedScene" uid="uid://hnn0n1xc2qt7" path="res://world/Tree.blend" id="14_7jtdl"] [ext_resource type="CameraAttributesPractical" uid="uid://b835orxyqq6w5" path="res://world/CameraPractical.tres" id="14_e2m00"]
[ext_resource type="PackedScene" uid="uid://cb2t7bvvf3gwh" path="res://enemy/slime/Slime.tscn" id="15_hgl78"] [ext_resource type="PackedScene" uid="uid://cb2t7bvvf3gwh" path="res://enemy/slime/Slime.tscn" id="15_hgl78"]
[ext_resource type="Script" path="res://world/PlayerManager.gd" id="16_dp6bj"] [ext_resource type="Script" path="res://world/PlayerManager.gd" id="16_dp6bj"]
[ext_resource type="PackedScene" uid="uid://dagn5bf7ou3sd" path="res://ui/UI.tscn" id="17_43qhq"] [ext_resource type="PackedScene" uid="uid://dagn5bf7ou3sd" path="res://ui/UI.tscn" id="17_43qhq"]
[ext_resource type="Script" path="res://camera/Camera.gd" id="18_wogcj"] [ext_resource type="Script" path="res://camera/Camera.gd" id="18_wogcj"]
[ext_resource type="Material" uid="uid://ddy5gkw0k16dq" path="res://shader/OutlineMaterial.tres" id="19_d2i56"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_lp0k7"] [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_lp0k7"]
albedo_color = Color(0, 0, 0, 1) albedo_color = Color(0.184314, 0.113725, 0, 1)
[sub_resource type="BoxMesh" id="BoxMesh_j5fsa"] [sub_resource type="BoxMesh" id="BoxMesh_j5fsa"]
material = SubResource("StandardMaterial3D_lp0k7") material = SubResource("StandardMaterial3D_lp0k7")
@ -31,11 +30,6 @@ size = Vector3(100, 1, 100)
[sub_resource type="BoxShape3D" id="BoxShape3D_yg2lt"] [sub_resource type="BoxShape3D" id="BoxShape3D_yg2lt"]
size = Vector3(100, 1, 100) size = Vector3(100, 1, 100)
[sub_resource type="QuadMesh" id="QuadMesh_7yiqd"]
material = ExtResource("19_d2i56")
flip_faces = true
size = Vector2(2, 2)
[node name="Main" type="Node"] [node name="Main" type="Node"]
script = ExtResource("1_cw3ws") script = ExtResource("1_cw3ws")
@ -94,15 +88,26 @@ autostart = true
[node name="World" type="Node3D" parent="."] [node name="World" type="Node3D" parent="."]
[node name="CameraPivot" type="Node3D" parent="World"]
[node name="Camera" type="Camera3D" parent="World/CameraPivot" node_paths=PackedStringArray("center")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 10, 10)
current = true
fov = 30.0
size = 10.0
far = 100.0
script = ExtResource("18_wogcj")
center = NodePath("..")
follow_speed = 5.0
[node name="Sun" type="DirectionalLight3D" parent="World"] [node name="Sun" type="DirectionalLight3D" parent="World"]
transform = Transform3D(0.984808, 0.122788, -0.122788, 0, 0.707107, 0.707107, 0.173648, -0.696364, 0.696364, 0, 10, 0) transform = Transform3D(0.984808, 0.122788, -0.122788, 0, 0.707107, 0.707107, 0.173648, -0.696364, 0.696364, 0, 3, 0)
shadow_enabled = true shadow_enabled = true
directional_shadow_mode = 0
script = ExtResource("11_4jb08") script = ExtResource("11_4jb08")
[node name="Environment" type="WorldEnvironment" parent="World"] [node name="Environment" type="WorldEnvironment" parent="World"]
environment = ExtResource("12_cscto") environment = ExtResource("12_cscto")
camera_attributes = ExtResource("13_pvug4") camera_attributes = ExtResource("14_e2m00")
[node name="Trees" type="Node3D" parent="World"] [node name="Trees" type="Node3D" parent="World"]
@ -139,38 +144,6 @@ script = ExtResource("16_dp6bj")
[node name="UI" parent="." instance=ExtResource("17_43qhq")] [node name="UI" parent="." instance=ExtResource("17_43qhq")]
process_mode = 3 process_mode = 3
[node name="Viewport" type="SubViewportContainer" parent="."]
texture_filter = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
stretch = true
[node name="SubViewport" type="SubViewport" parent="Viewport"]
handle_input_locally = false
size = Vector2i(960, 540)
render_target_update_mode = 4
[node name="CameraPivot" type="Node3D" parent="Viewport/SubViewport"]
[node name="Camera" type="Camera3D" parent="Viewport/SubViewport/CameraPivot" node_paths=PackedStringArray("center")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 20, 20)
current = true
fov = 30.0
size = 10.0
far = 100.0
script = ExtResource("18_wogcj")
center = NodePath("..")
follow_speed = 5.0
[node name="PostProcessing" type="MeshInstance3D" parent="Viewport/SubViewport/CameraPivot/Camera"]
unique_name_in_owner = true
visible = false
extra_cull_margin = 16384.0
mesh = SubResource("QuadMesh_7yiqd")
[connection signal="timeout" from="Client/Ping/Timer" to="Client/Ping" method="send_ping"] [connection signal="timeout" from="Client/Ping/Timer" to="Client/Ping" method="send_ping"]
[connection signal="timeout" from="Client/Login/Timer" to="Client/Login" method="send_login"] [connection signal="timeout" from="Client/Login/Timer" to="Client/Login" method="send_login"]
[connection signal="timeout" from="Client/Statistics" to="Client" method="update_statistics"] [connection signal="timeout" from="Client/Statistics" to="Client" method="update_statistics"]

View File

@ -1,50 +0,0 @@
[remap]
importer="scene"
importer_version=1
type="PackedScene"
uid="uid://b358op5h1y83m"
path="res://.godot/imported/Slime.blend-ea5047bc644fde7498b554f0822da73a.scn"
[deps]
source_file="res://enemy/slime/Slime.blend"
dest_files=["res://.godot/imported/Slime.blend-ea5047bc644fde7498b554f0822da73a.scn"]
[params]
nodes/root_type=""
nodes/root_name=""
nodes/apply_root_scale=true
nodes/root_scale=1.0
meshes/ensure_tangents=true
meshes/generate_lods=true
meshes/create_shadow_meshes=true
meshes/light_baking=1
meshes/lightmap_texel_size=0.2
meshes/force_disable_compression=false
skins/use_named_skins=true
animation/import=true
animation/fps=30
animation/trimming=false
animation/remove_immutable_tracks=true
import_script/path=""
_subresources={}
gltf/naming_version=1
gltf/embedded_image_handling=1
blender/nodes/visible=0
blender/nodes/punctual_lights=true
blender/nodes/cameras=true
blender/nodes/custom_properties=true
blender/nodes/modifiers=1
blender/meshes/colors=false
blender/meshes/uvs=true
blender/meshes/normals=true
blender/meshes/tangents=true
blender/meshes/skins=2
blender/meshes/export_bones_deforming_mesh_only=false
blender/materials/unpack_enabled=true
blender/materials/export_materials=1
blender/animation/limit_playback=true
blender/animation/always_sample=true
blender/animation/group_tracks=true

View File

@ -1,6 +1,6 @@
[gd_scene load_steps=8 format=3 uid="uid://cb2t7bvvf3gwh"] [gd_scene load_steps=8 format=3 uid="uid://cb2t7bvvf3gwh"]
[ext_resource type="PackedScene" uid="uid://b358op5h1y83m" path="res://enemy/slime/Slime.blend" id="1_1h1hj"] [ext_resource type="PackedScene" uid="uid://b358op5h1y83m" path="res://assets/models/slime/Slime.blend" id="1_1h1hj"]
[ext_resource type="Script" path="res://enemy/Enemy.gd" id="1_r5888"] [ext_resource type="Script" path="res://enemy/Enemy.gd" id="1_r5888"]
[ext_resource type="PackedScene" uid="uid://2bbycjulf00g" path="res://character/health/HealthComponent.tscn" id="2_fsqxc"] [ext_resource type="PackedScene" uid="uid://2bbycjulf00g" path="res://character/health/HealthComponent.tscn" id="2_fsqxc"]

View File

@ -0,0 +1,56 @@
extends Node
@export var animation_player: AnimationPlayer
@export var blend_time: float
var next_animation: StringName = "RESET"
func _ready():
assert(animation_player)
assert(blend_time >= 0.0)
func _process(_delta):
play("idle")
if animation_player.current_animation == next_animation:
return
animation_player.play(next_animation, blend_time)
func play(action_name: StringName):
next_animation = action_name
# func air(y_velocity: float):
# if y_velocity > 0:
# play("rifle_jump")
# else:
# play("falling")
# func aim(move: Vector2, is_shooting: bool):
# if move.x > 0:
# play("rifle_aim_strafe_right")
# elif move.x < 0:
# play("rifle_aim_strafe_left")
# elif move.y < 0:
# play("rifle_aim_walk_forward")
# elif move.y > 0:
# play("rifle_aim_walk_backward")
# else:
# play("rifle_aim")
# if is_shooting:
# play("rifle_shoot")
# func run(move: Vector2, is_shooting: bool):
# if move.y < 0:
# play("rifle_run_forward")
# elif move.y > 0:
# play("rifle_run_backward")
# elif move.x > 0:
# play("rifle_run_right")
# elif move.x < 0:
# play("rifle_run_left")
# elif is_shooting:
# play("rifle_shoot")
# else:
# play("rifle_idle")

View File

@ -1,8 +1,9 @@
[gd_scene load_steps=5 format=3 uid="uid://2lcnu3dy54lx"] [gd_scene load_steps=6 format=3 uid="uid://2lcnu3dy54lx"]
[ext_resource type="Script" path="res://player/Player.gd" id="1_8gebs"] [ext_resource type="Script" path="res://player/Player.gd" id="1_8gebs"]
[ext_resource type="PackedScene" uid="uid://dglu2uaewno0p" path="res://player/model/FemaleBase.blend" id="2_24ena"] [ext_resource type="PackedScene" uid="uid://dnr3o1rbkqpgu" path="res://assets/models/female/Female.blend" id="2_8nah6"]
[ext_resource type="PackedScene" uid="uid://2bbycjulf00g" path="res://character/health/HealthComponent.tscn" id="2_np5ag"] [ext_resource type="PackedScene" uid="uid://2bbycjulf00g" path="res://character/health/HealthComponent.tscn" id="2_np5ag"]
[ext_resource type="FontFile" uid="uid://b7mov13kwi8u8" path="res://assets/ui/font/ubuntu_nf_regular.ttf" id="4_76ehj"]
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_2f50n"] [sub_resource type="CapsuleShape3D" id="CapsuleShape3D_2f50n"]
radius = 0.25 radius = 0.25
@ -14,18 +15,16 @@ model = NodePath("Model")
[node name="Model" type="Node3D" parent="."] [node name="Model" type="Node3D" parent="."]
[node name="FemaleBase" parent="Model" instance=ExtResource("2_24ena")] [node name="Female" parent="Model" instance=ExtResource("2_8nah6")]
transform = Transform3D(0.33, 0, 0, 0, 0.33, 0, 0, 0, 0.33, 0, 0, 0)
[node name="Collision" type="CollisionShape3D" parent="."] [node name="Collision" type="CollisionShape3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.8, 0) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.8, 0)
shape = SubResource("CapsuleShape3D_2f50n") shape = SubResource("CapsuleShape3D_2f50n")
[node name="Animation" type="AnimationPlayer" parent="."]
[node name="Health" parent="." instance=ExtResource("2_np5ag")] [node name="Health" parent="." instance=ExtResource("2_np5ag")]
[node name="Label" type="Label3D" parent="."] [node name="Label" type="Label3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2, 0) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2, 0)
billboard = 1 billboard = 1
text = "Player" text = "Player"
font = ExtResource("4_76ehj")

View File

@ -5,9 +5,7 @@ extends Controller
var server_position: Vector3 var server_position: Vector3
func _ready(): func _ready():
print(character.name, ".old: ", server_position)
server_position = character.position server_position = character.position
print(character.name, ".new: ", server_position)
func _process(_delta): func _process(_delta):
var move := server_position - character.position var move := server_position - character.position

View File

@ -1,50 +0,0 @@
[remap]
importer="scene"
importer_version=1
type="PackedScene"
uid="uid://dglu2uaewno0p"
path="res://.godot/imported/FemaleBase.blend-ffb0211788dfb291cbc8516269a785f5.scn"
[deps]
source_file="res://player/model/FemaleBase.blend"
dest_files=["res://.godot/imported/FemaleBase.blend-ffb0211788dfb291cbc8516269a785f5.scn"]
[params]
nodes/root_type=""
nodes/root_name=""
nodes/apply_root_scale=true
nodes/root_scale=1.0
meshes/ensure_tangents=true
meshes/generate_lods=true
meshes/create_shadow_meshes=true
meshes/light_baking=1
meshes/lightmap_texel_size=0.2
meshes/force_disable_compression=false
skins/use_named_skins=true
animation/import=true
animation/fps=30
animation/trimming=false
animation/remove_immutable_tracks=true
import_script/path=""
_subresources={}
gltf/naming_version=1
gltf/embedded_image_handling=1
blender/nodes/visible=0
blender/nodes/punctual_lights=true
blender/nodes/cameras=true
blender/nodes/custom_properties=true
blender/nodes/modifiers=1
blender/meshes/colors=false
blender/meshes/uvs=true
blender/meshes/normals=true
blender/meshes/tangents=true
blender/meshes/skins=2
blender/meshes/export_bones_deforming_mesh_only=false
blender/materials/unpack_enabled=true
blender/materials/export_materials=1
blender/animation/limit_playback=true
blender/animation/always_sample=true
blender/animation/group_tracks=true

View File

@ -1,38 +0,0 @@
[remap]
importer="font_data_dynamic"
type="FontFile"
uid="uid://b7mov13kwi8u8"
path="res://.godot/imported/ubuntu_nf_regular.ttf-b453c07942f661257c0c0781f805a134.fontdata"
[deps]
source_file="res://ui/font/ubuntu_nf_regular.ttf"
dest_files=["res://.godot/imported/ubuntu_nf_regular.ttf-b453c07942f661257c0c0781f805a134.fontdata"]
[params]
Rendering=null
antialiasing=1
generate_mipmaps=false
multichannel_signed_distance_field=false
msdf_pixel_range=8
msdf_size=48
allow_system_fallback=true
force_autohinter=false
hinting=1
subpixel_positioning=1
oversampling=0.0
Fallbacks=null
fallbacks=[]
Compress=null
compress=true
preload=[{
"chars": [],
"glyphs": [],
"name": "New Configuration",
"size": Vector2i(16, 0)
}]
language_support={}
script_support={}
opentype_features={}

View File

@ -1,6 +1,6 @@
[gd_resource type="Theme" load_steps=2 format=3 uid="uid://caqphxkvcu3tb"] [gd_resource type="Theme" load_steps=2 format=3 uid="uid://caqphxkvcu3tb"]
[ext_resource type="FontFile" uid="uid://b7mov13kwi8u8" path="res://ui/font/ubuntu_nf_regular.ttf" id="1_1unma"] [ext_resource type="FontFile" uid="uid://b7mov13kwi8u8" path="res://assets/ui/font/ubuntu_nf_regular.ttf" id="1_1unma"]
[resource] [resource]
default_font = ExtResource("1_1unma") default_font = ExtResource("1_1unma")

View File

@ -1,56 +0,0 @@
[remap]
importer="scene"
importer_version=1
type="PackedScene"
uid="uid://tgmbtt7u172g"
path="res://.godot/imported/Arena.blend-c720f6651d38b4cfd30aa3f4d2266924.scn"
[deps]
source_file="res://world/Arena.blend"
dest_files=["res://.godot/imported/Arena.blend-c720f6651d38b4cfd30aa3f4d2266924.scn"]
[params]
nodes/root_type=""
nodes/root_name=""
nodes/apply_root_scale=true
nodes/root_scale=1.0
meshes/ensure_tangents=true
meshes/generate_lods=true
meshes/create_shadow_meshes=true
meshes/light_baking=1
meshes/lightmap_texel_size=0.2
meshes/force_disable_compression=false
skins/use_named_skins=true
animation/import=true
animation/fps=30
animation/trimming=false
animation/remove_immutable_tracks=true
import_script/path=""
_subresources={
"nodes": {
"PATH:Plane": {
"physics/shape_type": 2
}
}
}
gltf/naming_version=1
gltf/embedded_image_handling=1
blender/nodes/visible=0
blender/nodes/punctual_lights=true
blender/nodes/cameras=true
blender/nodes/custom_properties=true
blender/nodes/modifiers=1
blender/meshes/colors=false
blender/meshes/uvs=true
blender/meshes/normals=true
blender/meshes/tangents=true
blender/meshes/skins=2
blender/meshes/export_bones_deforming_mesh_only=false
blender/materials/unpack_enabled=true
blender/materials/export_materials=1
blender/animation/limit_playback=true
blender/animation/always_sample=true
blender/animation/group_tracks=true

View File

@ -1,10 +1,21 @@
[gd_resource type="Environment" format=3 uid="uid://dixa0yso2s1u3"] [gd_resource type="Environment" load_steps=3 format=3 uid="uid://dixa0yso2s1u3"]
[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_4vcsp"]
ground_bottom_color = Color(0.568627, 0.501961, 0.423529, 1)
[sub_resource type="Sky" id="Sky_bq3yo"]
sky_material = SubResource("ProceduralSkyMaterial_4vcsp")
[resource] [resource]
background_mode = 1 background_mode = 2
background_color = Color(0.317647, 0.541176, 0.713726, 1) background_color = Color(0.317647, 0.541176, 0.713726, 1)
sky = SubResource("Sky_bq3yo")
ambient_light_source = 3 ambient_light_source = 3
ambient_light_color = Color(0.607843, 0.756863, 0.92549, 1) reflected_light_source = 2
ambient_light_sky_contribution = 0.17
tonemap_mode = 2 tonemap_mode = 2
ssao_intensity = 16.0 ssao_intensity = 16.0
glow_bloom = 0.5
volumetric_fog_density = 0.0
adjustment_enabled = true
adjustment_contrast = 1.1
adjustment_saturation = 1.1

View File

@ -1,50 +0,0 @@
[remap]
importer="scene"
importer_version=1
type="PackedScene"
uid="uid://hnn0n1xc2qt7"
path="res://.godot/imported/Tree.blend-8edaf7c4bb18f0f1f1c8fa5b8380d9ea.scn"
[deps]
source_file="res://world/Tree.blend"
dest_files=["res://.godot/imported/Tree.blend-8edaf7c4bb18f0f1f1c8fa5b8380d9ea.scn"]
[params]
nodes/root_type=""
nodes/root_name=""
nodes/apply_root_scale=true
nodes/root_scale=1.0
meshes/ensure_tangents=true
meshes/generate_lods=true
meshes/create_shadow_meshes=true
meshes/light_baking=1
meshes/lightmap_texel_size=0.2
meshes/force_disable_compression=false
skins/use_named_skins=true
animation/import=true
animation/fps=30
animation/trimming=false
animation/remove_immutable_tracks=true
import_script/path=""
_subresources={}
gltf/naming_version=1
gltf/embedded_image_handling=1
blender/nodes/visible=0
blender/nodes/punctual_lights=true
blender/nodes/cameras=true
blender/nodes/custom_properties=true
blender/nodes/modifiers=1
blender/meshes/colors=false
blender/meshes/uvs=true
blender/meshes/normals=true
blender/meshes/tangents=true
blender/meshes/skins=2
blender/meshes/export_bones_deforming_mesh_only=false
blender/materials/unpack_enabled=true
blender/materials/export_materials=1
blender/animation/limit_playback=true
blender/animation/always_sample=true
blender/animation/group_tracks=true

View File

@ -0,0 +1,31 @@
[gd_scene load_steps=3 format=3 uid="uid://54qkf5fflkjy"]
[ext_resource type="Material" uid="uid://ddy5gkw0k16dq" path="res://shader/OutlineMaterial.tres" id="1_f8tos"]
[sub_resource type="QuadMesh" id="QuadMesh_7yiqd"]
material = ExtResource("1_f8tos")
flip_faces = true
size = Vector2(2, 2)
[node name="Viewport" type="SubViewportContainer"]
visible = false
texture_filter = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
stretch = true
[node name="SubViewport" type="SubViewport" parent="."]
handle_input_locally = false
size = Vector2i(960, 540)
render_target_update_mode = 0
[node name="PostProcessing" type="MeshInstance3D" parent="SubViewport"]
unique_name_in_owner = true
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 10, 10)
visible = false
extra_cull_margin = 16384.0
mesh = SubResource("QuadMesh_7yiqd")
skeleton = NodePath("../../../CameraPivot/Camera")