diff --git a/src/main/java/org/KaiFlo/SolarCell/Components/EnergyConsumer/IEnergyConsumer.java b/src/main/java/org/KaiFlo/SolarCell/Components/EnergyConsumer/IEnergyConsumer.java new file mode 100644 index 0000000..5a8b1bd --- /dev/null +++ b/src/main/java/org/KaiFlo/SolarCell/Components/EnergyConsumer/IEnergyConsumer.java @@ -0,0 +1,11 @@ +package org.KaiFlo.SolarCell.Components.EnergyConsumer; + +public interface IEnergyConsumer { + float getWorkingCapabilityRatio(); + + void setWorkingCapabilityRatio(float workingCapabilityRatio); + + long getConsumptionPerTick(); + + void setConsumptionPerTick(long consumptionPerTick); +} diff --git a/src/main/java/org/KaiFlo/SolarCell/Components/EnergyConsumer/Implementations/EnergyConsumerComponent.java b/src/main/java/org/KaiFlo/SolarCell/Components/EnergyConsumer/Implementations/EnergyConsumerComponent.java new file mode 100644 index 0000000..d784558 --- /dev/null +++ b/src/main/java/org/KaiFlo/SolarCell/Components/EnergyConsumer/Implementations/EnergyConsumerComponent.java @@ -0,0 +1,71 @@ +package org.KaiFlo.SolarCell.Components.EnergyConsumer.Implementations; + +import com.hypixel.hytale.codec.Codec; +import com.hypixel.hytale.codec.KeyedCodec; +import com.hypixel.hytale.codec.builder.BuilderCodec; +import com.hypixel.hytale.codec.validation.Validators; +import com.hypixel.hytale.component.Component; +import com.hypixel.hytale.component.ComponentType; +import com.hypixel.hytale.logger.HytaleLogger; +import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore; +import org.KaiFlo.SolarCell.Components.EnergyConsumer.IEnergyConsumer; +import org.KaiFlo.SolarCell.SolarCellPlugin; +import org.checkerframework.checker.nullness.compatqual.NullableDecl; + +public class EnergyConsumerComponent implements Component, IEnergyConsumer { + public static final BuilderCodec CODEC = BuilderCodec.builder(EnergyConsumerComponent.class, EnergyConsumerComponent::new) + .append(new KeyedCodec<>("ConsumptionPerTick", Codec.LONG), + (component, value) -> component.consumptionPerTick = value, + (component) -> component.consumptionPerTick + ) + .addValidator(Validators.greaterThanOrEqual(0L)) + .documentation("ConsumptionPerTick defines the Consumers ConsumptionPerTick") + .add() + .build(); + + private long consumptionPerTick; + private float workingCapabilityRatio; + + private final HytaleLogger Logger = HytaleLogger.getLogger(); + + @Override + public float getWorkingCapabilityRatio() { + return workingCapabilityRatio; + } + + @Override + public void setWorkingCapabilityRatio(float workingCapabilityRatio) { + this.workingCapabilityRatio = workingCapabilityRatio; + } + + @Override + public long getConsumptionPerTick() { + return consumptionPerTick; + } + + @Override + public void setConsumptionPerTick(long consumptionPerTick) { + this.consumptionPerTick = consumptionPerTick; + } + + private EnergyConsumerComponent copyFrom(EnergyConsumerComponent other) { + this.consumptionPerTick = other.consumptionPerTick; + this.workingCapabilityRatio = other.workingCapabilityRatio; + return this; + } + + @NullableDecl + @Override + public Component clone() { + try { + super.clone(); + } catch (CloneNotSupportedException e) { + Logger.atWarning().log("Cloning of " + this.getClass().getName() + " failed."); + } + return new EnergyConsumerComponent().copyFrom(this); + } + + public static ComponentType getComponentType() { + return SolarCellPlugin.get().getEnergyConsumerComponentType(); + } +} diff --git a/src/main/java/org/KaiFlo/SolarCell/Components/EnergySource/AbstractEnergySource.java b/src/main/java/org/KaiFlo/SolarCell/Components/EnergySource/AbstractEnergySource.java deleted file mode 100644 index 7cf3d26..0000000 --- a/src/main/java/org/KaiFlo/SolarCell/Components/EnergySource/AbstractEnergySource.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.KaiFlo.SolarCell.Components.EnergySource; - -public class AbstractEnergySource implements IEnergySource{ - @Override - public boolean isEndless() { - return true; - } - - @Override - public long getEnergyCapacity() { - return -1; - } - - @Override - public long getEnergyRatePerTick() { - return 1; - } -} diff --git a/src/main/java/org/KaiFlo/SolarCell/Components/EnergySource/IEnergySource.java b/src/main/java/org/KaiFlo/SolarCell/Components/EnergySource/IEnergySource.java index 628f2fc..201ccf4 100644 --- a/src/main/java/org/KaiFlo/SolarCell/Components/EnergySource/IEnergySource.java +++ b/src/main/java/org/KaiFlo/SolarCell/Components/EnergySource/IEnergySource.java @@ -15,5 +15,11 @@ public interface IEnergySource { /** * @return The amount of energy the source produces per Tick */ - long getEnergyRatePerTick(); + long getGeneratesPerTick(); + + void setGeneratesPerTick(long generatesPerTick); + + void setEndless(boolean endless); + + void setEnergyCapacity(long energyCapacity); } diff --git a/src/main/java/org/KaiFlo/SolarCell/Components/EnergySource/Implementations/EnergySourceComponent.java b/src/main/java/org/KaiFlo/SolarCell/Components/EnergySource/Implementations/EnergySourceComponent.java index 1a0fcd2..fb13485 100644 --- a/src/main/java/org/KaiFlo/SolarCell/Components/EnergySource/Implementations/EnergySourceComponent.java +++ b/src/main/java/org/KaiFlo/SolarCell/Components/EnergySource/Implementations/EnergySourceComponent.java @@ -1,26 +1,47 @@ package org.KaiFlo.SolarCell.Components.EnergySource.Implementations; +import com.hypixel.hytale.codec.Codec; +import com.hypixel.hytale.codec.KeyedCodec; import com.hypixel.hytale.codec.builder.BuilderCodec; +import com.hypixel.hytale.codec.validation.Validators; import com.hypixel.hytale.component.Component; import com.hypixel.hytale.component.ComponentType; import com.hypixel.hytale.logger.HytaleLogger; import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore; -import org.KaiFlo.SolarCell.Components.EnergySource.AbstractEnergySource; +import org.KaiFlo.SolarCell.Components.EnergySource.IEnergySource; import org.KaiFlo.SolarCell.SolarCellPlugin; import org.checkerframework.checker.nullness.compatqual.NullableDecl; -public class EnergySourceComponent extends AbstractEnergySource implements Component { - public static final BuilderCodec CODEC = BuilderCodec.builder(EnergySourceComponent.class, EnergySourceComponent::new).build(); +public class EnergySourceComponent implements Component, IEnergySource { + @SuppressWarnings("unchecked") + public static final BuilderCodec CODEC = BuilderCodec.builder(EnergySourceComponent.class, EnergySourceComponent::new) + .append(new KeyedCodec<>("GeneratesPerTick", Codec.LONG), + (component, value) -> component.generatesPerTick = value, + (component) -> component.generatesPerTick + ) + .addValidator(Validators.greaterThanOrEqual(0L)) + .documentation("GeneratesPerTick defines the Sources GeneratesPerTick") + .add() + .append(new KeyedCodec<>("EnergyCapacity", Codec.LONG), + (component, value) -> component.energyCapacity = value, + (component) -> component.energyCapacity + ) + .addValidator(Validators.or(Validators.equal(-1L), Validators.greaterThanOrEqual(0L))) + .documentation("EnergyCapacity defines how long energy can be produced (Set to -1 if endless energy production)") + .add() + .build(); private final HytaleLogger Logger = HytaleLogger.getLogger(); - private long energyRatePerTick = 5; + private long generatesPerTick = 5; + private boolean isEndless = true; + private long energyCapacity = -1; public static ComponentType getComponentType() { - return SolarCellPlugin.get().getSolarCellComponentType(); + return SolarCellPlugin.get().getEnergySourceComponentType(); } private EnergySourceComponent copyFrom(EnergySourceComponent other) { - this.energyRatePerTick = other.energyRatePerTick; + this.generatesPerTick = other.generatesPerTick; return this; } @@ -36,11 +57,32 @@ public class EnergySourceComponent extends AbstractEnergySource implements Compo } @Override - public long getEnergyRatePerTick() { - return energyRatePerTick; + public boolean isEndless() { + return isEndless; } - public void setEnergyRatePerTick(long energyRatePerTick) { - this.energyRatePerTick = energyRatePerTick; + @Override + public void setEndless(boolean endless) { + isEndless = endless; + } + + @Override + public long getEnergyCapacity() { + return energyCapacity; + } + + @Override + public void setEnergyCapacity(long energyCapacity) { + this.energyCapacity = energyCapacity; + } + + @Override + public long getGeneratesPerTick() { + return generatesPerTick; + } + + @Override + public void setGeneratesPerTick(long generatesPerTick) { + this.generatesPerTick = generatesPerTick; } } diff --git a/src/main/java/org/KaiFlo/SolarCell/Components/EnergyStorage/IEnergyStorage.java b/src/main/java/org/KaiFlo/SolarCell/Components/EnergyStorage/IEnergyStorage.java new file mode 100644 index 0000000..a100ce3 --- /dev/null +++ b/src/main/java/org/KaiFlo/SolarCell/Components/EnergyStorage/IEnergyStorage.java @@ -0,0 +1,26 @@ +package org.KaiFlo.SolarCell.Components.EnergyStorage; + +public interface IEnergyStorage { + + long getMaxCapacity(); + + void setMaxCapacity(long maxCapacity); + + long getExtractEnergyPerTick(); + + void setExtractEnergyPerTick(long extractEnergyPerTick); + + long getCurrentEnergyAmount(); + + void setCurrentEnergyAmount(long currentEnergyAmount); + + long getReceiveEnergyPerTick(); + + void setReceiveEnergyPerTick(long receiveEnergyPerTick); + + long extractEnergy(long requiredEnergy); + + long receiveEnergy(long inputEnergy); + + double getCurrentEnergyToCapacityRatio(); +} diff --git a/src/main/java/org/KaiFlo/SolarCell/Components/EnergyStorage/Implementations/EnergyStorageComponent.java b/src/main/java/org/KaiFlo/SolarCell/Components/EnergyStorage/Implementations/EnergyStorageComponent.java new file mode 100644 index 0000000..ba7cdd3 --- /dev/null +++ b/src/main/java/org/KaiFlo/SolarCell/Components/EnergyStorage/Implementations/EnergyStorageComponent.java @@ -0,0 +1,136 @@ +package org.KaiFlo.SolarCell.Components.EnergyStorage.Implementations; + +import com.hypixel.hytale.codec.Codec; +import com.hypixel.hytale.codec.KeyedCodec; +import com.hypixel.hytale.codec.builder.BuilderCodec; +import com.hypixel.hytale.codec.validation.Validators; +import com.hypixel.hytale.component.Component; +import com.hypixel.hytale.component.ComponentType; +import com.hypixel.hytale.logger.HytaleLogger; +import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore; +import org.KaiFlo.SolarCell.Components.EnergyStorage.IEnergyStorage; +import org.KaiFlo.SolarCell.SolarCellPlugin; +import org.checkerframework.checker.nullness.compatqual.NullableDecl; + +public class EnergyStorageComponent implements Component, IEnergyStorage { + public static final BuilderCodec CODEC = BuilderCodec.builder(EnergyStorageComponent.class, EnergyStorageComponent::new) + .append(new KeyedCodec<>("MaxCapacity", Codec.LONG), + (component, value) -> component.maxCapacity = value, + (component) -> component.maxCapacity + ) + .addValidator(Validators.greaterThanOrEqual(0L)) + .documentation("MaxCapacity defines the Storage MaxCapacity") + .add() + .append(new KeyedCodec<>("ExtractEnergyPerTick", Codec.LONG), + (component, value) -> component.extractEnergyPerTick = value, + (component) -> component.extractEnergyPerTick + ) + .addValidator(Validators.greaterThanOrEqual(0L)) + .documentation("ExtractEnergyPerTick defines the Storage ExtractEnergyPerTick") + .add() + .append(new KeyedCodec<>("ReceiveEnergyPerTick", Codec.LONG), + (component, value) -> component.receiveEnergyPerTick = value, + (component) -> component.receiveEnergyPerTick + ) + .addValidator(Validators.greaterThanOrEqual(0L)) + .documentation("ReceiveEnergyPerTick defines the Storage ReceiveEnergyPerTick") + .add() + .append(new KeyedCodec<>("CurrentEnergyAmount", Codec.LONG), + (component, value) -> component.currentEnergyAmount = value, + (component) -> component.currentEnergyAmount + ) + .addValidator(Validators.greaterThanOrEqual(0L)) + .documentation("CurrentEnergyAmount defines the Storage CurrentEnergyAmount") + .add() + .build(); + + private final HytaleLogger Logger = HytaleLogger.getLogger(); + + private long maxCapacity; + private long extractEnergyPerTick; + private long currentEnergyAmount; + private long receiveEnergyPerTick; + + @Override + public long getMaxCapacity() { + return maxCapacity; + } + + @Override + public void setMaxCapacity(long maxCapacity) { + this.maxCapacity = maxCapacity; + } + + @Override + public long getExtractEnergyPerTick() { + return extractEnergyPerTick; + } + + @Override + public void setExtractEnergyPerTick(long extractEnergyPerTick) { + this.extractEnergyPerTick = extractEnergyPerTick; + } + + @Override + public long getCurrentEnergyAmount() { + return currentEnergyAmount; + } + + @Override + public void setCurrentEnergyAmount(long currentEnergyAmount) { + this.currentEnergyAmount = currentEnergyAmount; + } + + @Override + public long getReceiveEnergyPerTick() { + return receiveEnergyPerTick; + } + + @Override + public void setReceiveEnergyPerTick(long receiveEnergyPerTick) { + this.receiveEnergyPerTick = receiveEnergyPerTick; + } + + @Override + public double getCurrentEnergyToCapacityRatio(){ + return (double) currentEnergyAmount / maxCapacity; + } + + @Override + public long extractEnergy(long requiredEnergy) { + var extractedEnergy = Math.min(currentEnergyAmount, Math.min(requiredEnergy, extractEnergyPerTick)); + currentEnergyAmount -= extractedEnergy; + return extractedEnergy; + } + + @Override + public long receiveEnergy(long inputEnergy) { + var receivedEnergy = Math.min(maxCapacity - currentEnergyAmount, Math.min(inputEnergy, receiveEnergyPerTick)); + currentEnergyAmount += receivedEnergy; + return receivedEnergy; + } + + private EnergyStorageComponent copyFrom(EnergyStorageComponent other) { + this.maxCapacity = other.maxCapacity; + this.currentEnergyAmount = other.currentEnergyAmount; + this.receiveEnergyPerTick = other.receiveEnergyPerTick; + this.extractEnergyPerTick = other.extractEnergyPerTick; + return this; + } + + @NullableDecl + @Override + public Component clone() { + try { + super.clone(); + } catch (CloneNotSupportedException e) { + Logger.atWarning().log("Cloning of " + this.getClass().getName() + " failed."); + } + return new EnergyStorageComponent().copyFrom(this); + } + + public static ComponentType getComponentType() { + return SolarCellPlugin.get().getEnergyStorageComponentType(); + } + +} diff --git a/src/main/java/org/KaiFlo/SolarCell/SolarCellPlugin.java b/src/main/java/org/KaiFlo/SolarCell/SolarCellPlugin.java index 8bfa2ed..a96e8cd 100644 --- a/src/main/java/org/KaiFlo/SolarCell/SolarCellPlugin.java +++ b/src/main/java/org/KaiFlo/SolarCell/SolarCellPlugin.java @@ -6,7 +6,9 @@ import com.hypixel.hytale.server.core.plugin.JavaPlugin; import com.hypixel.hytale.server.core.plugin.JavaPluginInit; import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore; import org.KaiFlo.SolarCell.Commands.ExampleCommand; +import org.KaiFlo.SolarCell.Components.EnergyConsumer.Implementations.EnergyConsumerComponent; import org.KaiFlo.SolarCell.Components.EnergySource.Implementations.EnergySourceComponent; +import org.KaiFlo.SolarCell.Components.EnergyStorage.Implementations.EnergyStorageComponent; import org.KaiFlo.SolarCell.Systems.EnergySource.EnergySourceInitializerSystem; import org.KaiFlo.SolarCell.Systems.EnergySource.EnergyProducerTickingSystem; @@ -22,7 +24,9 @@ public class SolarCellPlugin extends JavaPlugin { private static final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass(); - private ComponentType solarCellComponentType; + private ComponentType energySourceComponentType; + private ComponentType energyConsumerComponentType; + private ComponentType energyStorageComponentType; public SolarCellPlugin(@Nonnull JavaPluginInit init) { super(init); @@ -34,7 +38,9 @@ public class SolarCellPlugin extends JavaPlugin { instance = this; LOGGER.atInfo().log("Setting up plugin " + this.getName()); - solarCellComponentType = this.getChunkStoreRegistry().registerComponent(EnergySourceComponent.class, "SolarCell", EnergySourceComponent.CODEC); + energySourceComponentType = this.getChunkStoreRegistry().registerComponent(EnergySourceComponent.class, "EnergySource", EnergySourceComponent.CODEC); + energyConsumerComponentType = this.getChunkStoreRegistry().registerComponent(EnergyConsumerComponent.class, "EnergyConsumer", EnergyConsumerComponent.CODEC); + energyStorageComponentType = this.getChunkStoreRegistry().registerComponent(EnergyStorageComponent.class, "EnergyStorage", EnergyStorageComponent.CODEC); this.getCommandRegistry().registerCommand(new ExampleCommand(this.getName(), this.getManifest().getVersion().toString())); @@ -43,7 +49,15 @@ public class SolarCellPlugin extends JavaPlugin { } - public ComponentType getSolarCellComponentType() { - return solarCellComponentType; + public ComponentType getEnergySourceComponentType() { + return energySourceComponentType; + } + + public ComponentType getEnergyConsumerComponentType() { + return energyConsumerComponentType; + } + + public ComponentType getEnergyStorageComponentType() { + return energyStorageComponentType; } } \ No newline at end of file diff --git a/src/main/java/org/KaiFlo/SolarCell/Systems/EnergySource/EnergyProducerTickingSystem.java b/src/main/java/org/KaiFlo/SolarCell/Systems/EnergySource/EnergyProducerTickingSystem.java index 21b6106..5943e25 100644 --- a/src/main/java/org/KaiFlo/SolarCell/Systems/EnergySource/EnergyProducerTickingSystem.java +++ b/src/main/java/org/KaiFlo/SolarCell/Systems/EnergySource/EnergyProducerTickingSystem.java @@ -54,7 +54,7 @@ public class EnergyProducerTickingSystem extends EntityTickingSystem var targetEnergyStorage = commandBuffer.getComponent(targetRef, EnergyStorageBlockComponent.getComponentType()); if (targetEnergySource == null || targetEnergyStorage == null) return; - var energy = targetEnergyStorage.extractEnergy(targetEnergySource.getEnergyRatePerTick(), false); + var energy = targetEnergyStorage.extractEnergy(targetEnergySource.getGeneratesPerTick(), false); var inserted = thisEnergyStorageComponent.receiveEnergy(energy, false); LOGGER.atInfo().log("Inserted " + inserted + "/" + energy + " |" + targetEnergyStorage.getEnergyStored() + "| into storage" + " at Block " + globalX + ", " + localY + ", " + globalZ + ", " + diff --git a/src/main/resources/Common/Items/SolarPanels/SolarCell1.bbmodel b/src/main/resources/Common/Items/SolarPanels/SolarCell1.bbmodel index a54871d..976547e 100644 --- a/src/main/resources/Common/Items/SolarPanels/SolarCell1.bbmodel +++ b/src/main/resources/Common/Items/SolarPanels/SolarCell1.bbmodel @@ -1 +1 @@ -{"meta":{"format_version":"5.0","model_format":"hytale_prop","box_uv":false},"name":"SolarCell1","visible_box":[1,1,0],"variable_placeholders":"","variable_placeholder_buttons":[],"timeline_setups":[],"unhandled_root_fields":{},"resolution":{"width":128,"height":128},"elements":[{"name":"cube","box_uv":false,"render_order":"default","locked":false,"allow_mirror_modeling":true,"shading_mode":"flat","double_sided":false,"from":[-11,0,-13],"to":[11,6,13],"autouv":1,"color":3,"origin":[1,0,0],"faces":{"north":{"uv":[44,44,66,50],"texture":0},"east":{"uv":[44,32,70,38],"texture":0},"south":{"uv":[44,50,66,56],"texture":0},"west":{"uv":[44,38,70,44],"texture":0},"up":{"uv":[22,58,0,32],"texture":0},"down":{"uv":[44,32,22,58],"texture":0}},"type":"cube","uuid":"6295774b-c2df-c426-733f-0ef141183d35"},{"name":"cube","box_uv":false,"render_order":"default","locked":false,"allow_mirror_modeling":true,"shading_mode":"flat","double_sided":false,"from":[-3,5,-2],"to":[3,25,3],"autouv":1,"color":8,"origin":[0,5,-2],"faces":{"north":{"uv":[44,56,50,76],"texture":0},"east":{"uv":[56,56,61,76],"texture":0},"south":{"uv":[50,56,56,76],"texture":0},"west":{"uv":[0,58,5,78],"texture":0},"up":{"uv":[43,63,37,58],"texture":0},"down":{"uv":[66,9,60,14],"texture":0}},"type":"cube","uuid":"a047256d-9b05-734c-b4df-5f3bd0dbb0ec"},{"name":"cube","box_uv":false,"render_order":"default","locked":false,"allow_mirror_modeling":true,"shading_mode":"flat","double_sided":false,"from":[-15,27,-16],"to":[15,30,16],"autouv":1,"color":8,"rotation":[32.5,0,0],"origin":[14,28,-5],"faces":{"north":{"uv":[60,3,90,6],"texture":0},"east":{"uv":[5,58,37,61],"texture":0},"south":{"uv":[60,6,90,9],"texture":0},"west":{"uv":[60,0,92,3],"texture":0},"up":{"uv":[30,32,0,0],"texture":0},"down":{"uv":[60,0,30,32],"texture":0}},"type":"cube","uuid":"67893b6a-376a-b2e2-67a2-bfdf18086817"}],"groups":[],"outliner":["6295774b-c2df-c426-733f-0ef141183d35","a047256d-9b05-734c-b4df-5f3bd0dbb0ec","67893b6a-376a-b2e2-67a2-bfdf18086817"],"textures":[{"name":"SolarCell1.png","relative_path":"SolarCell1.png","folder":"block","namespace":"","id":"0","group":"","width":256,"height":256,"uv_width":256,"uv_height":256,"particle":false,"use_as_default":true,"layers_enabled":false,"sync_to_project":"","render_mode":"default","render_sides":"auto","pbr_channel":"color","frame_time":1,"frame_order_type":"loop","frame_order":"","frame_interpolate":false,"visible":true,"internal":true,"saved":true,"uuid":"a4802f2a-f789-5c45-618a-94df92d60a63","source":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAYAAABccqhmAAAMyklEQVR4AezdP4xc1RXH8Tvb2Mq6JOxaazmsbIvGHbJlqkQiihSFLkUUpUKRQhUap9qCSFEEDXH6SMRFQhHJFKFBQnJFwQpER2NhyZblFbtAQcEibbXsHeath/F7M/e9d/+dc76Ik3k7896993yO/dPaOLB27dq14xL165d/f2yxfvvKX45z1rdvvHFsuRx/LRVYW/opH0YX2NrYdLmqOfz69kVnsZr+ee0WOA2AT7742Pk6c+Fj58tf+/LXvvy1L3/ty1/78te+/LUvf+3LX/vy1778ta/uo/AJAgjkFjgNgNwbW9vvytUXnC9rfdNvvQL+ZASAV6AQMCpAABgY/OGDR85iGRjt6BYJgNGEdS/w6vXXnKU6t7Mzma+6p1P+dARA+RkkP8Fzm+vOQiWHVLRB0woB0EjwioBBAXMB8JOfbk1/N/7K7Hflc70a/LFFywIEzAWAgJlwRASyCRAA2ajLbfRw/9BZqHLCsnaePy0BMK+h8Prt7dedpVI4wqQtEQBJeetY/MzW885C1aEt6xQEgKx5cVoEogoQAFE5WQyBugUWT0cALIrwNQKGBAgAA8M+2rvnLJSBUUZvkQCITlrXgn/4+5rrU2cv3ZpIrrr06z8NAVD/jEafMPTfQDR6IxaoWqDtcARAmwrvIWBEgAAwMmjaRKBNgABoU+E9BIwIEABGBk2btgW6uicAumR4HwEDAgSAgSHTIgJdAgRAlwzvI2BAgAAwMOS9g30XUgYoTLa4rGkCYJmOgs/evf3WpE8paJkWeggQAD2wuBUBbQKnAXDt/HXn6+jxdefLX/vy1778tS9/7ctf+/LXvvy1L3/ty1/78te+/LUvbYD0g4BkgdMAkNwEZ0cAgXaBVe8+FQDPbFx2Q2pxo1VrLN4f+vXXB/dDb22977uv9tznn326tD66+7/WZ3kTAW0C0wCY/8k6tMEYawzdm+cQQGCYwDQAhj3KUwggIF2AAJA+Qc6PQIdAyNtr/lv3kBv73JNizT77cy8CCIQJ8B1AmBN3IaBSgACYjdX/04WmZm/xgoB6AQJgNmL/y5amZm/xgoBYgdCDEwChUtyHgEIBAkDhUGkJgVABAiBUivsQUChAACgcKi3ZFujTPQFwouV/9//K1RdcUy++9LuTd/kbAf0CBID+GdMhAp0CBEAnDR8goF+AANA/Yzo0JNC3VQKgrxj3I6BIgABQNExaQaCvgMgA8L9r31TfhrkfAQSeCIgMgObP7PvXJ61whYBtgSHdiwyAIY3yDAIIPC0gNgD+9dEHT3fDOwgg0Etgzf9autcTATenWHNx2z+9+KvFt/gaAQR6Coj9DqBnn9yOgGqBoc2JDAD/HcaYav7Mf/PKn/0f+sOH56QLTANg/ifT0IZirDF0b55DAIFhAtMAmH/U/0Se/zr02v8jufkKfa7tvv/c+a/rqrb7eQ8BBIYJPBUAw5bhKQQQKCUwZl8CYIwezyIgXKA1ALq+/c71vnBTjo+AGIHWABBzeg6KAAKjBFoDYPf+Y1drjep29vDewb6zULN2eVEsMLa11gAYuyjPPxH45s3zrmS9tP+P45j1pDOuNAi0BsCNyxdcjeUi/bW1selyVHPcGxvPOg3V9MOrHoHWANDTHp0ggMAyAQJgmQ6fIVCxQIyjEQAxFFkDAaECBIDQwXFsBGIIEAAxFFkDAaECBIDQwXFs2wKxuicAYkmyDgICBQgAgUPjyAjEEiAAYkmyDgICBQiADEPbPfjSaagMVGwRIBDzFnEBcPHqz53/d/iNqZiAq9b6/7+PnKZa1S+fyxIQFwCyeH847fr2RaehfuiG/9UksPbX23fc+x/u/qg0NUgvCCDQLcB3AN02fIJAdQKxD0QAxBZlPQQECRAAgobFURGILUAAxBZlPQQECRAAgobFUW0LpOieAEihypoICBEgAIQMimMikEKAAEihypoICBEgADIM6vDBI6ehMlCxRYdAqrcJgFSys3Vfvf6ak1TndnYmy2rWFi9KBAiADIN8bnPdSagMFGxRmQABUNlAOA4COQUIgJza7IXAAIGUjxAAKXVZG4HKBQiAygfE8RBIKUAApNRlbQQqFyAAKh8Qx7MtkLp7AiC1MOsjULEAAVDxcDgaAqkFCIDUwqyPQMUCBECG4TzcP3QSKgMFW/QQyHErAZBY+e3t152kSszB8pUJEAAZBnJm63knoTJQsEVlAgRAZQPhOAjkFCAAcmqzFwKBArluIwBySbMPAhUKEAAVDoUjIZBLgADIJc0+CFQoQABUOBSOZFsgZ/cEQE5t9kKgMgECoLKBcBwEcgoQADm12QuBygQIgAwDOdq75yRUBgq2WCGQ+2MCILH4Hx/8zfWpvsf5zfqWC6mzl25NQqrv/twvW4AAyDC/0P8mQHOU0P/fQHP/jY1n3bJq7uMVgUUBAmBRhK8RMCQwDYDd+4+dhGrmsnew7yRUc15eEQgRKHHP2i/ee8eF1D+fueNqqG/ePO9K1Cs3/+z61Lu335r4KjFU9kQgVGD6HcD69kW3rJrFlv06U/Nnp/1fvuBuBJTjLwSECEwDQMhZOSYCCEQWIAAig7IcAkMESj1DAJSSZ18EKhDoFQC7B186i1XBnDgCAkkEggPg7ubNieVKos+iCBQWCA6AwudkewTUCpRsjAAoqc/eCBQWIAB6DCD0T0v2WJJbESgqQAAE8r989WeTPhW4LLchUFSAACjKz+bWBUr3TwCUngD7I1BQgAAoiM/WCJQWIABKT4D9ESgoQAAUxGdr2wI1dE8A1DAFzoBAIQECoBA82yJQgwABUMMUOAMChQQIgELwbGtboJbuCYBaJsE5ECggQAAUQGdLBGoRIABqmQTnQKCAAAFQAJ0tbQvU1D0BUNM0OAsCmQUIgMzgbIdATQIEQE3T4CwIZBYgADKDs51tgdq6JwBqmwjnQSCjAAGQEZutEKhNgACobSKcB4GMAgRARmy2si1QY/cEQI1T4UwIZBIgADJBsw0CNQoQADVOhTMhkEmAAMgA/XD/0IVUc5SjvXsupJr7V/0Xm5v7eC0nUOvOBEDiybzzy3OTPnX20q1Jn7q7eXMSUonbZHmhAgSA0MFxbARiCBAAMRRZAwGhAtMAOHzwyC0rob1xbASqEKj5EGvndnYmIVVzE5wNAQSGCUy/Axj2KE8hgIB0AQJA+gQ5PwIjBAiAEXg8isAqgdo/JwBqnxDnQyChAAGQEJelEahdgACofUKcD4GEAgRAQlyWti0goXsCQMKUOCMCiQQIgESwLIuABAECQMKUOCMCiQQIgESwLGtbQEr3BICUSXFOBBIIEAAJUFkSASkCBICUSXFOBBIIEAAJUFnStoCk7gkASdPirAhEFiAAIoOyHAKSBAgASdPirAhEFiAAIoOynG0Bad0TANImxnkRiChAAETEZCkEpAkQANImxnkRiChAAETEZCnbAhK7JwAkTo0zIxBJgACIBMkyCEgUIAAkTo0zIxBJgACIBMkytgWkdk8ASJ0c50YgggABEAGRJRCQKkAASJ0c50YgggABEAGRJWwLSO6eAJA8Pc6OwEgBAmAkII8jIFmAAJA8Pc6OwEgBAmAkII/bFpDePQEgfYKcH4ERAgTACDweRUC6AAEgfYKcH4ERAgTACDwetS2goXsCQMMU6QGBgQIEwEA4HkNAgwABoGGK9IDAQAECYCAcj9kW0NI9AaBlkvSBwAABAmAAGo8goEWAANAySfpAYIAAATAAjUdsC2jqngDQNE16QaCnAAHQE4zbEdAkQABomia9INBTgADoCcbttgW0dU8AaJso/SDQQ4AA6IHFrQhoEyAAtE2UfhDoIUAA9MDiVtsCGrsnADROlZ4QCBQgAAKhuA0BjQIEgMap0hMCgQIEQCAUt9kW0No9AaB1svSFQIAAARCAxC0IaBUgALROlr4QCBAgAAKQuMW2gObuCQDN06U3BFYIEAArgPgYAc0CBIDm6dIbAisECIAVQHxsW0B79wSA9gnTHwJLBAiAJTh8hIB2AQJA+4TpD4ElAgTAEhw+si1goXsCwMKU6RGBDgECoAOGtxGwIEAAWJgyPSLQIUAAdMDwtm0BK90TAFYmTZ8ItAgQAC0ovIWAFQECwMqk6ROBFgECoAWFt2wLWOqeALA0bXpFYEGAAFgA4UsELAkQAJamTa8ILAgQAAsgfGlbwFr3BIC1idMvAnMCBMAcBpcIWBMgAKxNnH4RmBMgAOYwuLQtYLF7AsDi1OkZgZkAATCD4AUBiwIEgMWp0zMCMwECYAbBi20Bq90TAFYnT98InAgQACcI/I2AVQECwOrk6RuBEwEC4ASBv20LWO6eALA8fXo3L0AAmP8hAIBlAQLA8vTp3bwAAWD+h4BtAOvdfw8AAP//k7rCtQAAAAZJREFUAwDD8svE0N2FFAAAAABJRU5ErkJggg=="}]} \ No newline at end of file +{"meta":{"format_version":"5.0","model_format":"hytale_prop","box_uv":false},"name":"SolarCell1","visible_box":[1,1,0],"variable_placeholders":"","variable_placeholder_buttons":[],"timeline_setups":[],"unhandled_root_fields":{},"resolution":{"width":128,"height":128},"elements":[{"name":"cube","box_uv":false,"render_order":"default","locked":false,"allow_mirror_modeling":true,"shading_mode":"flat","double_sided":false,"from":[-11,0,-13],"to":[11,6,13],"autouv":1,"color":3,"origin":[1,0,0],"faces":{"north":{"uv":[44,44,66,50],"texture":0},"east":{"uv":[44,32,70,38],"texture":0},"south":{"uv":[44,50,66,56],"texture":0},"west":{"uv":[44,38,70,44],"texture":0},"up":{"uv":[22,58,0,32],"texture":0},"down":{"uv":[44,32,22,58],"texture":0}},"type":"cube","uuid":"6295774b-c2df-c426-733f-0ef141183d35"},{"name":"cube","box_uv":false,"render_order":"default","locked":false,"allow_mirror_modeling":true,"shading_mode":"flat","double_sided":false,"from":[-3,5,-2],"to":[3,25,3],"autouv":1,"color":8,"origin":[0,5,-2],"faces":{"north":{"uv":[44,56,50,76],"texture":0},"east":{"uv":[56,56,61,76],"texture":0},"south":{"uv":[50,56,56,76],"texture":0},"west":{"uv":[0,58,5,78],"texture":0},"up":{"uv":[43,63,37,58],"texture":0},"down":{"uv":[66,9,60,14],"texture":0}},"type":"cube","uuid":"a047256d-9b05-734c-b4df-5f3bd0dbb0ec"},{"name":"cube","box_uv":false,"render_order":"default","locked":false,"allow_mirror_modeling":true,"shading_mode":"flat","double_sided":false,"from":[-15,27,-16],"to":[15,30,16],"autouv":1,"color":8,"rotation":[32.5,0,0],"origin":[14,28,-5],"faces":{"north":{"uv":[60,3,90,6],"texture":0},"east":{"uv":[5,58,37,61],"texture":0},"south":{"uv":[60,6,90,9],"texture":0},"west":{"uv":[60,0,92,3],"texture":0},"up":{"uv":[30,32,0,0],"texture":0},"down":{"uv":[60,0,30,32],"texture":0}},"type":"cube","uuid":"67893b6a-376a-b2e2-67a2-bfdf18086817"}],"groups":[],"outliner":["6295774b-c2df-c426-733f-0ef141183d35","a047256d-9b05-734c-b4df-5f3bd0dbb0ec","67893b6a-376a-b2e2-67a2-bfdf18086817"],"textures":[{"name":"SolarCell1.png","relative_path":"SolarCell1.png","folder":"block","namespace":"","id":"0","group":"","width":256,"height":256,"uv_width":256,"uv_height":256,"particle":false,"use_as_default":true,"layers_enabled":false,"sync_to_project":"","render_mode":"default","render_sides":"auto","pbr_channel":"color","frame_time":1,"frame_order_type":"loop","frame_order":"","frame_interpolate":false,"visible":true,"internal":true,"saved":true,"uuid":"a4802f2a-f789-5c45-618a-94df92d60a63","source":"data:image/png;base64,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"}]} \ No newline at end of file