artifact crusher (#22301)
This commit is contained in:
@@ -37,15 +37,27 @@ public sealed class EntityStorageVisualizerSystem : VisualizerSystem<EntityStora
|
||||
{
|
||||
if (open)
|
||||
{
|
||||
args.Sprite.LayerSetVisible(StorageVisualLayers.Door, true);
|
||||
if (comp.OpenDrawDepth != null)
|
||||
args.Sprite.DrawDepth = comp.OpenDrawDepth.Value;
|
||||
|
||||
if (comp.StateDoorOpen != null)
|
||||
{
|
||||
args.Sprite.LayerSetState(StorageVisualLayers.Door, comp.StateDoorOpen);
|
||||
args.Sprite.LayerSetVisible(StorageVisualLayers.Door, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
args.Sprite.LayerSetVisible(StorageVisualLayers.Door, false);
|
||||
}
|
||||
|
||||
if (comp.StateBaseOpen != null)
|
||||
args.Sprite.LayerSetState(StorageVisualLayers.Base, comp.StateBaseOpen);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (comp.ClosedDrawDepth != null)
|
||||
args.Sprite.DrawDepth = comp.ClosedDrawDepth.Value;
|
||||
|
||||
if (comp.StateDoorClosed != null)
|
||||
{
|
||||
args.Sprite.LayerSetState(StorageVisualLayers.Door, comp.StateDoorClosed);
|
||||
|
||||
@@ -45,4 +45,16 @@ public sealed partial class EntityStorageVisualsComponent : Component
|
||||
[DataField("stateUnlocked")]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public string? StateUnlocked = "unlocked";
|
||||
|
||||
/// <summary>
|
||||
/// The drawdepth the object has when it's open
|
||||
/// </summary>
|
||||
[DataField, ViewVariables(VVAccess.ReadWrite)]
|
||||
public int? OpenDrawDepth;
|
||||
|
||||
/// <summary>
|
||||
/// The drawdepth the object has when it's closed
|
||||
/// </summary>
|
||||
[DataField, ViewVariables(VVAccess.ReadWrite)]
|
||||
public int? ClosedDrawDepth;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
using Content.Shared.Xenoarchaeology.Equipment;
|
||||
|
||||
namespace Content.Client.Xenoarchaeology.Equipment;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public sealed class ArtifactCrusherSystem : SharedArtifactCrusherSystem
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
using Content.Server.Body.Systems;
|
||||
using Content.Server.Power.Components;
|
||||
using Content.Server.Power.EntitySystems;
|
||||
using Content.Server.Stack;
|
||||
using Content.Server.Storage.Components;
|
||||
using Content.Server.Xenoarchaeology.XenoArtifacts;
|
||||
using Content.Shared.Body.Components;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Verbs;
|
||||
using Content.Shared.Xenoarchaeology.Equipment;
|
||||
using Robust.Shared.Collections;
|
||||
using Robust.Shared.Random;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Server.Xenoarchaeology.Equipment.Systems;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public sealed class ArtifactCrusherSystem : SharedArtifactCrusherSystem
|
||||
{
|
||||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
[Dependency] private readonly ArtifactSystem _artifact = default!;
|
||||
[Dependency] private readonly BodySystem _body = default!;
|
||||
[Dependency] private readonly DamageableSystem _damageable = default!;
|
||||
[Dependency] private readonly StackSystem _stack = default!;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<ArtifactCrusherComponent, GetVerbsEvent<AlternativeVerb>>(OnGetVerbs);
|
||||
SubscribeLocalEvent<ArtifactCrusherComponent, PowerChangedEvent>(OnPowerChanged);
|
||||
}
|
||||
|
||||
private void OnGetVerbs(Entity<ArtifactCrusherComponent> ent, ref GetVerbsEvent<AlternativeVerb> args)
|
||||
{
|
||||
if (!args.CanAccess || !args.CanInteract || args.Hands == null || ent.Comp.Crushing)
|
||||
return;
|
||||
|
||||
if (!TryComp<EntityStorageComponent>(ent, out var entityStorageComp) || entityStorageComp.Contents.ContainedEntities.Count == 0)
|
||||
return;
|
||||
|
||||
if (entityStorageComp.Contents.Contains(args.User) || !this.IsPowered(ent, EntityManager))
|
||||
return;
|
||||
|
||||
var verb = new AlternativeVerb
|
||||
{
|
||||
Text = Loc.GetString("artifact-crusher-verb-start-crushing"),
|
||||
Priority = 2,
|
||||
Act = () => StartCrushing((ent, ent.Comp, entityStorageComp))
|
||||
};
|
||||
args.Verbs.Add(verb);
|
||||
}
|
||||
|
||||
private void OnPowerChanged(Entity<ArtifactCrusherComponent> ent, ref PowerChangedEvent args)
|
||||
{
|
||||
if (!args.Powered)
|
||||
StopCrushing(ent);
|
||||
}
|
||||
|
||||
public void StartCrushing(Entity<ArtifactCrusherComponent, EntityStorageComponent> ent)
|
||||
{
|
||||
var (_, crusher, _) = ent;
|
||||
|
||||
if (crusher.Crushing)
|
||||
return;
|
||||
|
||||
crusher.Crushing = true;
|
||||
crusher.NextSecond = _timing.CurTime + TimeSpan.FromSeconds(1);
|
||||
crusher.CrushEndTime = _timing.CurTime + crusher.CrushDuration;
|
||||
crusher.CrushingSoundEntity = AudioSystem.PlayPvs(crusher.CrushingSound, ent);
|
||||
Appearance.SetData(ent, ArtifactCrusherVisuals.Crushing, true);
|
||||
Dirty(ent, ent.Comp1);
|
||||
}
|
||||
|
||||
public void FinishCrushing(Entity<ArtifactCrusherComponent, EntityStorageComponent> ent)
|
||||
{
|
||||
var (_, crusher, storage) = ent;
|
||||
StopCrushing((ent, ent.Comp1), false);
|
||||
AudioSystem.PlayPvs(crusher.CrushingCompleteSound, ent);
|
||||
crusher.CrushingSoundEntity = null;
|
||||
Dirty(ent, ent.Comp1);
|
||||
|
||||
var contents = new ValueList<EntityUid>(storage.Contents.ContainedEntities);
|
||||
var coords = Transform(ent).Coordinates;
|
||||
foreach (var contained in contents)
|
||||
{
|
||||
if (crusher.CrushingWhitelist.IsValid(contained, EntityManager))
|
||||
{
|
||||
var amount = _random.Next(crusher.MinFragments, crusher.MaxFragments);
|
||||
var stacks = _stack.SpawnMultiple(crusher.FragmentStackProtoId, amount, coords);
|
||||
foreach (var stack in stacks)
|
||||
{
|
||||
ContainerSystem.Insert((stack, null, null, null), crusher.OutputContainer);
|
||||
}
|
||||
_artifact.ForceActivateArtifact(contained);
|
||||
}
|
||||
|
||||
if (!TryComp<BodyComponent>(contained, out var body))
|
||||
Del(contained);
|
||||
|
||||
var gibs = _body.GibBody(contained, body: body, gibOrgans: true, deleteBrain: true);
|
||||
foreach (var gib in gibs)
|
||||
{
|
||||
ContainerSystem.Insert((gib, null, null, null), crusher.OutputContainer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
base.Update(frameTime);
|
||||
|
||||
var query = EntityQueryEnumerator<ArtifactCrusherComponent, EntityStorageComponent>();
|
||||
while (query.MoveNext(out var uid, out var crusher, out var storage))
|
||||
{
|
||||
if (!crusher.Crushing)
|
||||
continue;
|
||||
|
||||
if (crusher.NextSecond < _timing.CurTime)
|
||||
{
|
||||
var contents = new ValueList<EntityUid>(storage.Contents.ContainedEntities);
|
||||
foreach (var contained in contents)
|
||||
{
|
||||
_damageable.TryChangeDamage(contained, crusher.CrushingDamage);
|
||||
}
|
||||
crusher.NextSecond += TimeSpan.FromSeconds(1);
|
||||
Dirty(uid, crusher);
|
||||
}
|
||||
|
||||
if (crusher.CrushEndTime < _timing.CurTime)
|
||||
{
|
||||
FinishCrushing((uid, crusher, storage));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Stacks;
|
||||
using Content.Shared.Whitelist;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Audio.Components;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
|
||||
|
||||
namespace Content.Shared.Xenoarchaeology.Equipment;
|
||||
|
||||
/// <summary>
|
||||
/// This is an entity storage that, when activated, crushes the artifact inside of it and gives artifact fragments.
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
|
||||
[Access(typeof(SharedArtifactCrusherSystem))]
|
||||
public sealed partial class ArtifactCrusherComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// Whether or not the crusher is currently in the process of crushing something.
|
||||
/// </summary>
|
||||
[DataField, AutoNetworkedField]
|
||||
public bool Crushing;
|
||||
|
||||
/// <summary>
|
||||
/// When the current crushing will end.
|
||||
/// </summary>
|
||||
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
|
||||
public TimeSpan CrushEndTime;
|
||||
|
||||
/// <summary>
|
||||
/// The next second. Used to apply damage over time.
|
||||
/// </summary>
|
||||
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
|
||||
public TimeSpan NextSecond;
|
||||
|
||||
/// <summary>
|
||||
/// The total duration of the crushing.
|
||||
/// </summary>
|
||||
[DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
|
||||
public TimeSpan CrushDuration = TimeSpan.FromSeconds(10);
|
||||
|
||||
/// <summary>
|
||||
/// A whitelist specifying what items, when crushed, will give fragments.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public EntityWhitelist CrushingWhitelist = new();
|
||||
|
||||
/// <summary>
|
||||
/// The minimum amount of fragments spawned.
|
||||
/// </summary>
|
||||
[DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
|
||||
public int MinFragments = 2;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum amount of fragments spawned, non-inclusive.
|
||||
/// </summary>
|
||||
[DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
|
||||
public int MaxFragments = 5;
|
||||
|
||||
/// <summary>
|
||||
/// The material for the fragments.
|
||||
/// </summary>
|
||||
[DataField, ViewVariables(VVAccess.ReadWrite)]
|
||||
public ProtoId<StackPrototype> FragmentStackProtoId = "ArtifactFragment";
|
||||
|
||||
/// <summary>
|
||||
/// A container used to hold fragments and gibs from crushing.
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
public Container OutputContainer;
|
||||
|
||||
/// <summary>
|
||||
/// The ID for <see cref="OutputContainer"/>
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public string OutputContainerName = "output_container";
|
||||
|
||||
/// <summary>
|
||||
/// Damage dealt each second to entities inside while crushing.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public DamageSpecifier CrushingDamage = new();
|
||||
|
||||
/// <summary>
|
||||
/// Sound played at the end of a successful crush.
|
||||
/// </summary>
|
||||
[DataField, AutoNetworkedField]
|
||||
public SoundSpecifier? CrushingCompleteSound = new SoundPathSpecifier("/Audio/Effects/metal_crunch.ogg");
|
||||
|
||||
/// <summary>
|
||||
/// Sound played throughout the entire crushing. Cut off if ended early.
|
||||
/// </summary>
|
||||
[DataField, AutoNetworkedField]
|
||||
public SoundSpecifier? CrushingSound = new SoundPathSpecifier("/Audio/Effects/hydraulic_press.ogg");
|
||||
|
||||
/// <summary>
|
||||
/// Stores entity of <see cref="CrushingSound"/> to allow ending it early.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public (EntityUid, AudioComponent)? CrushingSoundEntity;
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum ArtifactCrusherVisuals : byte
|
||||
{
|
||||
Crushing
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
using Content.Shared.Storage.Components;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
using Robust.Shared.Containers;
|
||||
|
||||
namespace Content.Shared.Xenoarchaeology.Equipment;
|
||||
|
||||
/// <summary>
|
||||
/// This handles logic relating to <see cref="ArtifactCrusherComponent"/>
|
||||
/// </summary>
|
||||
public abstract class SharedArtifactCrusherSystem : EntitySystem
|
||||
{
|
||||
[Dependency] protected readonly SharedAppearanceSystem Appearance = default!;
|
||||
[Dependency] protected readonly SharedAudioSystem AudioSystem = default!;
|
||||
[Dependency] protected readonly SharedContainerSystem ContainerSystem = default!;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<ArtifactCrusherComponent, ComponentInit>(OnInit);
|
||||
SubscribeLocalEvent<ArtifactCrusherComponent, StorageAfterOpenEvent>(OnStorageAfterOpen);
|
||||
}
|
||||
|
||||
private void OnInit(Entity<ArtifactCrusherComponent> ent, ref ComponentInit args)
|
||||
{
|
||||
ent.Comp.OutputContainer = ContainerSystem.EnsureContainer<Container>(ent, ent.Comp.OutputContainerName);
|
||||
}
|
||||
|
||||
private void OnStorageAfterOpen(Entity<ArtifactCrusherComponent> ent, ref StorageAfterOpenEvent args)
|
||||
{
|
||||
StopCrushing(ent);
|
||||
ContainerSystem.EmptyContainer(ent.Comp.OutputContainer);
|
||||
}
|
||||
|
||||
public void StopCrushing(Entity<ArtifactCrusherComponent> ent, bool early = true)
|
||||
{
|
||||
var (_, crusher) = ent;
|
||||
|
||||
if (!crusher.Crushing)
|
||||
return;
|
||||
|
||||
crusher.Crushing = false;
|
||||
Appearance.SetData(ent, ArtifactCrusherVisuals.Crushing, false);
|
||||
|
||||
if (early)
|
||||
{
|
||||
AudioSystem.Stop(crusher.CrushingSoundEntity?.Item1, crusher.CrushingSoundEntity?.Item2);
|
||||
crusher.CrushingSoundEntity = null;
|
||||
}
|
||||
|
||||
Dirty(ent, ent.Comp);
|
||||
}
|
||||
}
|
||||
@@ -107,6 +107,16 @@
|
||||
license: "CC-BY-4.0"
|
||||
source: "https://freesound.org/people/thomas_evdokimoff/sounds/202193/"
|
||||
|
||||
- files: ["hydraulic_press.ogg"]
|
||||
copyright: 'Created by chainsaw_dinner_party on Freesound.org. Extended and converted to MONO and .ogg by EmoGarbage404 (github)'
|
||||
license: "CC0-1.0"
|
||||
source: "https://freesound.org/people/chainsaw_dinner_party/sounds/403075/"
|
||||
|
||||
- files: ["metal_crunch.ogg"]
|
||||
copyright: 'Created by PNMCarrieRailfan on Freesound.org. Edited and exported to .ogg by EmoGarbage404 (github)'
|
||||
license: "CC-BY-NC-4.0"
|
||||
source: "https://freesound.org/people/PNMCarrieRailfan/sounds/682439/"
|
||||
|
||||
- files: ["voteding.ogg"]
|
||||
copyright: '"Bike, Bell Ding, Single, 01-01.wav" byInspectorJ (www.jshaw.co.uk) of Freesound.org; The volume has been reduced.'
|
||||
license: "CC-BY-4.0"
|
||||
|
||||
BIN
Resources/Audio/Effects/hydraulic_press.ogg
Normal file
BIN
Resources/Audio/Effects/hydraulic_press.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/Effects/metal_crunch.ogg
Normal file
BIN
Resources/Audio/Effects/metal_crunch.ogg
Normal file
Binary file not shown.
@@ -6,6 +6,7 @@ wires-board-name-thermomachine = Thermomachine
|
||||
wires-board-name-pa = Mk2 Particle Accelerator
|
||||
wires-board-name-highsec = HighSec Control
|
||||
wires-board-name-vessel = Vessel
|
||||
wires-board-name-crusher = Crusher
|
||||
wires-board-name-smes = SMES
|
||||
wires-board-name-substation = Substation
|
||||
wires-board-name-apc = APC
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
artifact-crusher-verb-start-crushing = Start crushing
|
||||
@@ -217,6 +217,22 @@
|
||||
Steel: 5
|
||||
Cable: 1
|
||||
|
||||
- type: entity
|
||||
id: ArtifactCrusherMachineCircuitboard
|
||||
parent: BaseMachineCircuitboard
|
||||
name: artifact crusher machine board
|
||||
description: A machine printed circuit board for an artifact crusher.
|
||||
components:
|
||||
- type: Sprite
|
||||
state: science
|
||||
- type: MachineBoard
|
||||
prototype: MachineArtifactCrusher
|
||||
requirements:
|
||||
Manipulator: 2
|
||||
materialRequirements:
|
||||
Glass: 1
|
||||
Steel: 5
|
||||
|
||||
- type: entity
|
||||
parent: BaseMachineCircuitboard
|
||||
id: AnomalyVesselCircuitboard
|
||||
|
||||
@@ -133,3 +133,81 @@
|
||||
enum.PowerDeviceVisualLayers.Powered:
|
||||
True: { visible: true }
|
||||
False: { visible: false }
|
||||
|
||||
- type: entity
|
||||
id: MachineArtifactCrusher
|
||||
parent: [ ConstructibleMachine, BaseMachinePowered ]
|
||||
name: artifact crusher
|
||||
description: Best not to let your fingers get stuck...
|
||||
components:
|
||||
- type: ArtifactCrusher
|
||||
crushingWhitelist:
|
||||
components:
|
||||
- Artifact
|
||||
crushingDamage:
|
||||
types:
|
||||
Blunt: 10
|
||||
- type: Machine
|
||||
board: ArtifactCrusherMachineCircuitboard
|
||||
- type: Wires
|
||||
boardName: wires-board-name-crusher
|
||||
layoutId: Crusher
|
||||
- type: WiresPanel
|
||||
- type: Sprite
|
||||
sprite: Structures/Machines/artifact_crusher.rsi
|
||||
offset: 0,0.5
|
||||
noRot: true
|
||||
layers:
|
||||
- state: base
|
||||
map: ["enum.StorageVisualLayers.Base"]
|
||||
- state: door-closed
|
||||
map: ["enum.StorageVisualLayers.Door"]
|
||||
- state: piston
|
||||
map: ["pistonlayer"]
|
||||
- state: glass
|
||||
- state: lights
|
||||
map: ["enum.PowerDeviceVisualLayers.Powered"]
|
||||
shader: unshaded
|
||||
- type: Fixtures
|
||||
fixtures:
|
||||
fix1:
|
||||
shape:
|
||||
!type:PhysShapeCircle
|
||||
radius: 0.45
|
||||
density: 50
|
||||
mask:
|
||||
- HighImpassable
|
||||
layer:
|
||||
- HighImpassable
|
||||
- type: EntityStorage
|
||||
capacity: 1
|
||||
whitelist:
|
||||
components:
|
||||
- Artifact
|
||||
- type: Appearance
|
||||
- type: GenericVisualizer
|
||||
visuals:
|
||||
enum.ArtifactCrusherVisuals.Crushing:
|
||||
pistonlayer:
|
||||
True: {state: piston-push}
|
||||
False: {state: piston}
|
||||
enum.PowerDeviceVisuals.Powered:
|
||||
enum.PowerDeviceVisualLayers.Powered:
|
||||
True: { visible: true }
|
||||
False: { visible: false }
|
||||
- type: EntityStorageVisuals
|
||||
stateDoorClosed: door-closed
|
||||
openDrawDepth: 0
|
||||
closedDrawDepth: 4
|
||||
- type: Construction
|
||||
containers:
|
||||
- machine_board
|
||||
- machine_parts
|
||||
- entity_storage
|
||||
- output_container
|
||||
- type: ContainerContainer
|
||||
containers:
|
||||
machine_board: !type:Container
|
||||
machine_parts: !type:Container
|
||||
entity_storage: !type:Container
|
||||
output_container: !type:Container
|
||||
|
||||
@@ -374,6 +374,7 @@
|
||||
- APECircuitboard
|
||||
- ArtifactAnalyzerMachineCircuitboard
|
||||
- TraversalDistorterMachineCircuitboard
|
||||
- ArtifactCrusherMachineCircuitboard
|
||||
- BoozeDispenserMachineCircuitboard
|
||||
- SodaDispenserMachineCircuitboard
|
||||
- TelecomServerCircuitboard
|
||||
|
||||
@@ -240,6 +240,15 @@
|
||||
Glass: 900
|
||||
Gold: 100
|
||||
|
||||
- type: latheRecipe
|
||||
id: ArtifactCrusherMachineCircuitboard
|
||||
result: ArtifactCrusherMachineCircuitboard
|
||||
completetime: 4
|
||||
materials:
|
||||
Steel: 100
|
||||
Glass: 900
|
||||
Gold: 100
|
||||
|
||||
- type: latheRecipe
|
||||
id: AnomalyVesselCircuitboard
|
||||
result: AnomalyVesselCircuitboard
|
||||
|
||||
@@ -97,6 +97,7 @@
|
||||
cost: 5000
|
||||
recipeUnlocks:
|
||||
- TraversalDistorterMachineCircuitboard
|
||||
- ArtifactCrusherMachineCircuitboard
|
||||
|
||||
- type: technology
|
||||
id: AdvancedAnomalyResearch
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.2 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 368 B |
Binary file not shown.
|
After Width: | Height: | Size: 193 B |
Binary file not shown.
|
After Width: | Height: | Size: 152 B |
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"version": 1,
|
||||
"license": "CC-BY-SA-3.0",
|
||||
"copyright": "Made by brainfood1183 (github) for ss14",
|
||||
"size": {
|
||||
"x": 32,
|
||||
"y": 64
|
||||
},
|
||||
"states": [
|
||||
{
|
||||
"name": "glass"
|
||||
},
|
||||
{
|
||||
"name": "door-closed"
|
||||
},
|
||||
{
|
||||
"name": "piston"
|
||||
},
|
||||
{
|
||||
"name": "base"
|
||||
},
|
||||
{
|
||||
"name": "lights"
|
||||
},
|
||||
{
|
||||
"name": "piston-push",
|
||||
"delays": [
|
||||
[
|
||||
0.66,
|
||||
0.66,
|
||||
0.66,
|
||||
0.66,
|
||||
0.66,
|
||||
0.66,
|
||||
0.66,
|
||||
0.66,
|
||||
0.66,
|
||||
0.66,
|
||||
0.66,
|
||||
0.66,
|
||||
0.66,
|
||||
0.66,
|
||||
1
|
||||
]
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.6 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 345 B |
Reference in New Issue
Block a user