Compare commits
28 Commits
realBritak
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 6d7c36ab0c | |||
|
|
9bd333d74f | ||
|
|
ba5f5e11b4 | ||
| b085d8b6ad | |||
| 96dee9509b | |||
| f45043f571 | |||
| 051940b64b | |||
| 3950bdab08 | |||
|
|
59e8fc1734 | ||
|
|
7b6fc8ce02 | ||
| 5380b275a8 | |||
|
|
2e3feb5c61 | ||
|
|
837d7ceb02 | ||
| a979a77e3e | |||
|
|
9aea3a3e83 | ||
|
|
0f496ca03f | ||
| 75900d50f9 | |||
| 486254b6dd | |||
|
|
2ccc7ba5e3 | ||
| 6fc02d82b4 | |||
| 4cb965adb9 | |||
| 2370f624c7 | |||
| 790012e4c4 | |||
| 63482565c5 | |||
| 66fb1d619c | |||
| 5ed67d4e0d | |||
| 6f20b8268b | |||
| 14012dbb2a |
38
build.gradle
38
build.gradle
@@ -8,16 +8,13 @@ import org.gradle.internal.os.OperatingSystem
|
||||
ext {
|
||||
if (project.hasProperty('hytale_home')) {
|
||||
hytaleHome = project.findProperty('hytale_home')
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
def os = OperatingSystem.current()
|
||||
if (os.isWindows()) {
|
||||
hytaleHome = "${System.getProperty("user.home")}/AppData/Roaming/Hytale"
|
||||
}
|
||||
else if (os.isMacOsX()) {
|
||||
} else if (os.isMacOsX()) {
|
||||
hytaleHome = "${System.getProperty("user.home")}/Library/Application Support/Hytale"
|
||||
}
|
||||
else if (os.isLinux()) {
|
||||
} else if (os.isLinux()) {
|
||||
hytaleHome = "${System.getProperty("user.home")}/.var/app/com.hypixel.HytaleLauncher/data/Hytale"
|
||||
if (!file(hytaleHome).exists()) {
|
||||
hytaleHome = "${System.getProperty("user.home")}/.local/share/Hytale"
|
||||
@@ -28,8 +25,7 @@ ext {
|
||||
|
||||
if (!project.hasProperty('hytaleHome')) {
|
||||
throw new GradleException('Your Hytale install could not be detected automatically. If you are on an unsupported platform or using a custom install location, please define the install location using the hytale_home property.');
|
||||
}
|
||||
else if (!file(project.findProperty('hytaleHome')).exists()) {
|
||||
} else if (!file(project.findProperty('hytaleHome')).exists()) {
|
||||
throw new GradleException("Failed to find Hytale at the expected location. Please make sure you have installed the game. The expected location can be changed using the hytale_home property. Currently looking in ${project.findProperty('hytaleHome')}")
|
||||
}
|
||||
|
||||
@@ -44,6 +40,12 @@ javadoc {
|
||||
options.addStringOption('Xdoclint:-missing', '-quiet')
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven {
|
||||
url = uri("https://cursemaven.com")
|
||||
}
|
||||
}
|
||||
|
||||
// Adds the Hytale server as a build dependency, allowing you to reference and
|
||||
// compile against their code. This requires you to have Hytale installed using
|
||||
// the official launcher for now.
|
||||
@@ -114,17 +116,17 @@ tasks.register('generateVSCodeLaunch') {
|
||||
}
|
||||
def programParams = createServerRunArguments("\${workspaceFolder}")
|
||||
def launchConfig = [
|
||||
version: "0.2.0",
|
||||
configurations: [
|
||||
[
|
||||
type: "java",
|
||||
name: "HytaleServer",
|
||||
request: "launch",
|
||||
mainClass: "com.hypixel.hytale.Main",
|
||||
args: programParams,
|
||||
cwd: "\${workspaceFolder}/run"
|
||||
version : "0.2.0",
|
||||
configurations: [
|
||||
[
|
||||
type : "java",
|
||||
name : "HytaleServer",
|
||||
request : "launch",
|
||||
mainClass: "com.hypixel.hytale.Main",
|
||||
args : programParams,
|
||||
cwd : "\${workspaceFolder}/run"
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
launchFile.text = groovy.json.JsonOutput.prettyPrint(groovy.json.JsonOutput.toJson(launchConfig))
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# The current version of your project. Please use semantic versioning!
|
||||
version=0.0.2
|
||||
version=0.0.1
|
||||
|
||||
# The group ID used for maven publishing. Usually the same as your package name
|
||||
# but not the same as your plugin group!
|
||||
maven_group=org.example
|
||||
maven_group=org.KaiFlo
|
||||
|
||||
# The version of Java used by your plugin. The game is built on Java 21 but
|
||||
# actually runs on Java 25.
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
package com.example.templateplugin;
|
||||
|
||||
import com.hypixel.hytale.server.core.plugin.JavaPlugin;
|
||||
import com.hypixel.hytale.server.core.plugin.JavaPluginInit;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.logging.Level;
|
||||
|
||||
/**
|
||||
* Main plugin class.
|
||||
*
|
||||
* TODO: Implement your plugin logic here.
|
||||
*
|
||||
* @author YourName
|
||||
* @version 1.0.0
|
||||
*/
|
||||
public class TemplatePlugin extends JavaPlugin {
|
||||
|
||||
private static TemplatePlugin instance;
|
||||
|
||||
/**
|
||||
* Constructor - Called when plugin is loaded.
|
||||
*/
|
||||
public TemplatePlugin(@Nonnull JavaPluginInit init) {
|
||||
super(init);
|
||||
instance = this;
|
||||
getLogger().at(Level.INFO).log("[TemplatePlugin] Plugin loaded!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get plugin instance.
|
||||
*/
|
||||
public static TemplatePlugin getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when plugin is set up.
|
||||
*/
|
||||
@Override
|
||||
protected void setup() {
|
||||
getLogger().at(Level.INFO).log("[TemplatePlugin] Plugin setup!");
|
||||
|
||||
// TODO: Initialize your plugin here
|
||||
// - Load configuration
|
||||
// - Register event listeners
|
||||
// - Register commands
|
||||
// - Start services
|
||||
registerEvents();
|
||||
registerCommands();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when plugin is enabled.
|
||||
*/
|
||||
@Override
|
||||
protected void start() {
|
||||
getLogger().at(Level.INFO).log("[TemplatePlugin] Plugin enabled!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when plugin is disabled.
|
||||
*/
|
||||
@Override
|
||||
public void shutdown() {
|
||||
getLogger().at(Level.INFO).log("[TemplatePlugin] Plugin disabled!");
|
||||
|
||||
// TODO: Cleanup your plugin here
|
||||
// - Save data
|
||||
// - Stop services
|
||||
// - Close connections
|
||||
}
|
||||
|
||||
/**
|
||||
* Register your commands here.
|
||||
*/
|
||||
private void registerEvents() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Register your commands here.
|
||||
*/
|
||||
private void registerCommands() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package org.KaiFlo.SolarCell.Commands;
|
||||
|
||||
import com.hypixel.hytale.component.Store;
|
||||
import com.hypixel.hytale.logger.HytaleLogger;
|
||||
import com.hypixel.hytale.math.vector.Vector3i;
|
||||
import com.hypixel.hytale.protocol.GameMode;
|
||||
import com.hypixel.hytale.server.core.Message;
|
||||
import com.hypixel.hytale.server.core.command.system.CommandContext;
|
||||
import com.hypixel.hytale.server.core.command.system.arguments.system.OptionalArg;
|
||||
import com.hypixel.hytale.server.core.command.system.arguments.types.ArgTypes;
|
||||
import com.hypixel.hytale.server.core.command.system.basecommands.CommandBase;
|
||||
import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent;
|
||||
import com.hypixel.hytale.server.core.universe.Universe;
|
||||
import com.hypixel.hytale.server.core.universe.world.World;
|
||||
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
|
||||
import org.KaiFlo.SolarCell.Helpers.BlockHelper;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.Objects;
|
||||
|
||||
public class ExampleCommand extends CommandBase {
|
||||
|
||||
private static final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass();
|
||||
private final String pluginName;
|
||||
private final String pluginVersion;
|
||||
private final OptionalArg<Integer> sizeArg;
|
||||
|
||||
public ExampleCommand(String pluginName, String pluginVersion) {
|
||||
super("test", "Prints a test message from the " + pluginName + " plugin.");
|
||||
this.setPermissionGroup(GameMode.Adventure); // Allows the command to be used by anyone, not just OP
|
||||
this.pluginName = pluginName;
|
||||
this.pluginVersion = pluginVersion;
|
||||
this.sizeArg = this.withOptionalArg("", "", ArgTypes.INTEGER);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void executeSync(@Nonnull CommandContext ctx) {
|
||||
ctx.sendMessage(Message.raw("Hello from the " + pluginName + " v" + pluginVersion + " plugin!"));
|
||||
World defaultWorld = Objects.requireNonNull(Universe.get().getDefaultWorld());
|
||||
defaultWorld.execute(() -> {
|
||||
|
||||
Store<EntityStore> store = defaultWorld.getEntityStore().getStore();
|
||||
var playerRef = ctx.senderAsPlayerRef();
|
||||
var playerTransform = store.getComponent(Objects.requireNonNull(playerRef), TransformComponent.getComponentType());
|
||||
Vector3i playerPosition = Objects.requireNonNull(playerTransform).getPosition().toVector3i();
|
||||
var size = sizeArg.get(ctx);
|
||||
if (size == null) size = 5;
|
||||
BlockHelper.executeForCubeAround(playerPosition.x, playerPosition.y, playerPosition.z, size,true, (x, y, z) -> {
|
||||
defaultWorld.breakBlock(x, y, z, 0);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
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.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;
|
||||
|
||||
import static org.KaiFlo.SolarCell.Helpers.BlockHelper.HyLogger;
|
||||
|
||||
public class EnergyConsumerComponent implements Component<ChunkStore>, IEnergyConsumer {
|
||||
public static final BuilderCodec<EnergyConsumerComponent> 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;
|
||||
|
||||
@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<ChunkStore> clone() {
|
||||
try {
|
||||
super.clone();
|
||||
} catch (CloneNotSupportedException e) {
|
||||
HyLogger.atWarning().log("Cloning of " + this.getClass().getName() + " failed.");
|
||||
}
|
||||
return new EnergyConsumerComponent().copyFrom(this);
|
||||
}
|
||||
|
||||
public static ComponentType<ChunkStore, EnergyConsumerComponent> getComponentType() {
|
||||
return SolarCellPlugin.get().getEnergyConsumerComponentType();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package org.KaiFlo.SolarCell.Components.EnergySource;
|
||||
|
||||
public interface IEnergySource {
|
||||
|
||||
/**
|
||||
* @return True if energy source is endless, False otherwise
|
||||
*/
|
||||
boolean isEndless();
|
||||
|
||||
/**
|
||||
* @return If the energy source is not endless, returns the Capacity of the energy source, otherwise -1
|
||||
*/
|
||||
long getEnergyCapacity();
|
||||
|
||||
/**
|
||||
* @return The amount of energy the source produces per Tick
|
||||
*/
|
||||
long getGeneratesPerTick();
|
||||
|
||||
void setGeneratesPerTick(long generatesPerTick);
|
||||
|
||||
void setEnergyCapacity(long energyCapacity);
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
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.server.core.universe.world.storage.ChunkStore;
|
||||
import org.KaiFlo.SolarCell.Components.EnergySource.IEnergySource;
|
||||
import org.KaiFlo.SolarCell.SolarCellPlugin;
|
||||
import org.checkerframework.checker.nullness.compatqual.NullableDecl;
|
||||
|
||||
import static org.KaiFlo.SolarCell.Helpers.BlockHelper.HyLogger;
|
||||
|
||||
public class EnergySourceComponent implements Component<ChunkStore>, IEnergySource {
|
||||
public static final BuilderCodec<EnergySourceComponent> 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.greaterThanOrEqual(-1L))
|
||||
.documentation("EnergyCapacity defines how long energy can be produced (Set to -1 if endless energy production)")
|
||||
.add()
|
||||
.build();
|
||||
|
||||
private long generatesPerTick = 5;
|
||||
private long energyCapacity = -1;
|
||||
|
||||
public static ComponentType<ChunkStore, EnergySourceComponent> getComponentType() {
|
||||
return SolarCellPlugin.get().getEnergySourceComponentType();
|
||||
}
|
||||
|
||||
private EnergySourceComponent copyFrom(EnergySourceComponent other) {
|
||||
this.generatesPerTick = other.generatesPerTick;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NullableDecl
|
||||
@Override
|
||||
public Component<ChunkStore> clone() {
|
||||
try {
|
||||
super.clone();
|
||||
} catch (CloneNotSupportedException e) {
|
||||
HyLogger.atWarning().log("Cloning of " + this.getClass().getName() + " failed.");
|
||||
}
|
||||
return new EnergySourceComponent().copyFrom(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEndless() {
|
||||
return energyCapacity == -1;
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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.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;
|
||||
|
||||
import static org.KaiFlo.SolarCell.Helpers.BlockHelper.HyLogger;
|
||||
|
||||
public class EnergyStorageComponent implements Component<ChunkStore>, IEnergyStorage {
|
||||
public static final BuilderCodec<EnergyStorageComponent> 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 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<ChunkStore> clone() {
|
||||
try {
|
||||
super.clone();
|
||||
} catch (CloneNotSupportedException e) {
|
||||
HyLogger.atWarning().log("Cloning of " + this.getClass().getName() + " failed.");
|
||||
}
|
||||
return new EnergyStorageComponent().copyFrom(this);
|
||||
}
|
||||
|
||||
public static ComponentType<ChunkStore, EnergyStorageComponent> getComponentType() {
|
||||
return SolarCellPlugin.get().getEnergyStorageComponentType();
|
||||
}
|
||||
|
||||
}
|
||||
19
src/main/java/org/KaiFlo/SolarCell/Enums/BlockRotation.java
Normal file
19
src/main/java/org/KaiFlo/SolarCell/Enums/BlockRotation.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package org.KaiFlo.SolarCell.Enums;
|
||||
|
||||
public enum BlockRotation {
|
||||
NORTH,
|
||||
EAST,
|
||||
SOUTH,
|
||||
WEST;
|
||||
public static BlockRotation getEnum(int rotationIndex) {
|
||||
return switch ( rotationIndex )
|
||||
{
|
||||
case 0 -> NORTH;
|
||||
case 1 -> WEST;
|
||||
case 2 -> SOUTH;
|
||||
case 3 -> EAST;
|
||||
default -> NORTH;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
189
src/main/java/org/KaiFlo/SolarCell/Helpers/BlockHelper.java
Normal file
189
src/main/java/org/KaiFlo/SolarCell/Helpers/BlockHelper.java
Normal file
@@ -0,0 +1,189 @@
|
||||
package org.KaiFlo.SolarCell.Helpers;
|
||||
|
||||
import com.hypixel.hytale.component.CommandBuffer;
|
||||
import com.hypixel.hytale.component.Ref;
|
||||
import com.hypixel.hytale.logger.HytaleLogger;
|
||||
import com.hypixel.hytale.math.util.ChunkUtil;
|
||||
import com.hypixel.hytale.server.core.modules.block.BlockModule;
|
||||
import com.hypixel.hytale.server.core.universe.world.World;
|
||||
import com.hypixel.hytale.server.core.universe.world.chunk.BlockComponentChunk;
|
||||
import com.hypixel.hytale.server.core.universe.world.chunk.WorldChunk;
|
||||
import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
|
||||
import org.KaiFlo.SolarCell.Enums.BlockRotation;
|
||||
import org.checkerframework.checker.nullness.compatqual.NonNullDecl;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class BlockHelper {
|
||||
public static final HytaleLogger HyLogger = HytaleLogger.getLogger();
|
||||
|
||||
public static void executeForCubeAround(int x, int y, int z, int size, boolean own, Callback callback) {
|
||||
for (int xOffset = 0; xOffset < size; xOffset++) {
|
||||
for (int yOffset = 0; yOffset < size; yOffset++) {
|
||||
for (int zOffset = 0; zOffset < size; zOffset++) {
|
||||
var xPos = (xOffset - size / 2) + x;
|
||||
var yPos = (yOffset - size / 2) + y;
|
||||
var zPos = (zOffset - size / 2) + z;
|
||||
if (!(xPos == x && yPos == y && zPos == z)) {
|
||||
callback.accept(xPos, yPos, zPos);
|
||||
} else if (own) {
|
||||
callback.accept(xPos, yPos, zPos);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void executeForDirection(
|
||||
int centerX, int centerY, int centerZ,
|
||||
World world,
|
||||
CommandBuffer<ChunkStore> commandBuffer,
|
||||
BlockRotation direction,
|
||||
ChunkSafeCallback chunkSafeCallback){
|
||||
Map<Long, List<BlockPos>> positionsByChunk = new HashMap<>();
|
||||
addBlockInDirectionToPositions(centerX, centerY, centerZ, direction, positionsByChunk);
|
||||
addBlockDownwardToPositions(centerX, centerY, centerZ, positionsByChunk);
|
||||
|
||||
executeChunkSafeCallbackForPositions(world, commandBuffer, chunkSafeCallback, positionsByChunk);
|
||||
}
|
||||
|
||||
private static void addBlockInDirectionToPositions(
|
||||
int centerX, int centerY, int centerZ, BlockRotation direction, Map<Long, List<BlockPos>> positionsByChunk) {
|
||||
|
||||
int xPos = centerX;
|
||||
int zPos = centerZ;
|
||||
|
||||
if(direction == BlockRotation.NORTH || direction == BlockRotation.SOUTH){
|
||||
zPos += direction == BlockRotation.SOUTH ? 1 : -1;
|
||||
}else{
|
||||
xPos += direction == BlockRotation.EAST ? 1 : -1;
|
||||
}
|
||||
|
||||
int chunkX = Math.floorDiv(xPos, 32);
|
||||
int chunkZ = Math.floorDiv(zPos, 32);
|
||||
long chunkIndex = ChunkUtil.indexChunk(chunkX, chunkZ);
|
||||
|
||||
int localX = Math.floorMod(xPos, 32);
|
||||
int localZ = Math.floorMod(zPos, 32);
|
||||
|
||||
positionsByChunk
|
||||
.computeIfAbsent(chunkIndex, _ -> new ArrayList<>())
|
||||
.add(new BlockPos(xPos, centerY, zPos, localX, localZ));
|
||||
}
|
||||
|
||||
private static void addBlockDownwardToPositions(
|
||||
int centerX, int centerY, int centerZ, Map<Long, List<BlockPos>> positionsByChunk) {
|
||||
|
||||
int yPos = centerY - 1;
|
||||
|
||||
int chunkX = Math.floorDiv(centerX, 32);
|
||||
int chunkZ = Math.floorDiv(centerZ, 32);
|
||||
long chunkIndex = ChunkUtil.indexChunk(chunkX, chunkZ);
|
||||
|
||||
int localX = Math.floorMod(centerX, 32);
|
||||
int localZ = Math.floorMod(centerZ, 32);
|
||||
|
||||
positionsByChunk
|
||||
.computeIfAbsent(chunkIndex, _ -> new ArrayList<>())
|
||||
.add(new BlockPos(centerX, yPos, centerZ, localX, localZ));
|
||||
}
|
||||
|
||||
|
||||
public static void executeForCubeAroundChunkSafe(
|
||||
int centerX, int centerY, int centerZ,
|
||||
int size,
|
||||
boolean includeCenter,
|
||||
World world,
|
||||
CommandBuffer<ChunkStore> commandBuffer,
|
||||
ChunkSafeCallback chunkSafeCallback
|
||||
) {
|
||||
int halfSize = size / 2;
|
||||
Map<Long, List<BlockPos>> positionsByChunk = new HashMap<>();
|
||||
|
||||
for (int xOffset = -halfSize; xOffset <= halfSize; xOffset++) {
|
||||
for (int yOffset = -halfSize; yOffset <= halfSize; yOffset++) {
|
||||
for (int zOffset = -halfSize; zOffset <= halfSize; zOffset++) {
|
||||
|
||||
int xPos = centerX + xOffset;
|
||||
int yPos = centerY + yOffset;
|
||||
int zPos = centerZ + zOffset;
|
||||
|
||||
if (!includeCenter && xPos == centerX && yPos == centerY && zPos == centerZ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int chunkX = Math.floorDiv(xPos, 32);
|
||||
int chunkZ = Math.floorDiv(zPos, 32);
|
||||
long chunkIndex = ChunkUtil.indexChunk(chunkX, chunkZ);
|
||||
|
||||
int localX = Math.floorMod(xPos, 32);
|
||||
int localZ = Math.floorMod(zPos, 32);
|
||||
|
||||
positionsByChunk
|
||||
.computeIfAbsent(chunkIndex, _ -> new ArrayList<>())
|
||||
.add(new BlockPos(xPos, yPos, zPos, localX, localZ));
|
||||
}
|
||||
}
|
||||
}
|
||||
executeChunkSafeCallbackForPositions(world, commandBuffer, chunkSafeCallback, positionsByChunk);
|
||||
}
|
||||
|
||||
private static void executeChunkSafeCallbackForPositions(World world, CommandBuffer<ChunkStore> commandBuffer, ChunkSafeCallback chunkSafeCallback, Map<Long, List<BlockPos>> positionsByChunk) {
|
||||
world.execute(() -> {
|
||||
for (var entry : positionsByChunk.entrySet()) {
|
||||
long chunkIndexCI = entry.getKey();
|
||||
List<BlockPos> blockPositions = entry.getValue();
|
||||
|
||||
WorldChunk worldChunk = world.getChunkIfLoaded(chunkIndexCI);
|
||||
if (worldChunk == null) continue;
|
||||
|
||||
var blockComponentChunk = commandBuffer.getComponent(
|
||||
worldChunk.getReference(),
|
||||
BlockComponentChunk.getComponentType()
|
||||
);
|
||||
if (blockComponentChunk == null) continue;
|
||||
|
||||
for (BlockPos pos : blockPositions) {
|
||||
int index = ChunkUtil.indexBlockInColumn(
|
||||
pos.localX(), pos.y(), pos.localZ()
|
||||
);
|
||||
|
||||
var targetRef = blockComponentChunk.getEntityReference(index);
|
||||
if (targetRef == null) continue;
|
||||
|
||||
chunkSafeCallback.accept(
|
||||
pos.x(), pos.y(), pos.z(),
|
||||
targetRef,
|
||||
blockComponentChunk,
|
||||
worldChunk
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
record BlockPos(int x, int y, int z, int localX, int localZ) {}
|
||||
public interface Callback {
|
||||
void accept(int x, int y, int z);
|
||||
}
|
||||
public interface ChunkSafeCallback {
|
||||
|
||||
void accept(int x, int y, int z, Ref<ChunkStore> targetRef, BlockComponentChunk blockComponentChunk, WorldChunk targetChunk);
|
||||
}
|
||||
|
||||
public static void setBlockRefTicking(Ref<ChunkStore> blockRef, @NonNullDecl CommandBuffer<ChunkStore> commandBuffer) {
|
||||
BlockModule.BlockStateInfo blockInfo = commandBuffer.getComponent(blockRef, BlockModule.BlockStateInfo.getComponentType());
|
||||
if (blockInfo == null) return;
|
||||
|
||||
WorldChunk worldChunk = commandBuffer.getComponent(blockInfo.getChunkRef(), WorldChunk.getComponentType());
|
||||
if (worldChunk == null) return;
|
||||
|
||||
int x = ChunkUtil.xFromBlockInColumn(blockInfo.getIndex());
|
||||
int y = ChunkUtil.yFromBlockInColumn(blockInfo.getIndex());
|
||||
int z = ChunkUtil.zFromBlockInColumn(blockInfo.getIndex());
|
||||
|
||||
worldChunk.setTicking(x, y, z, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package org.KaiFlo.SolarCell.Helpers;
|
||||
|
||||
import com.hypixel.hytale.component.Component;
|
||||
import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public class ComponentHelper {
|
||||
public static<T> Optional<T> getComponentOfType(List<Component<ChunkStore>> components, Class<T> type){
|
||||
return components.stream()
|
||||
.filter(x -> x.getClass() == type)
|
||||
.map(type::cast)
|
||||
.findFirst();
|
||||
}
|
||||
}
|
||||
75
src/main/java/org/KaiFlo/SolarCell/SolarCellPlugin.java
Normal file
75
src/main/java/org/KaiFlo/SolarCell/SolarCellPlugin.java
Normal file
@@ -0,0 +1,75 @@
|
||||
package org.KaiFlo.SolarCell;
|
||||
|
||||
import com.hypixel.hytale.component.ComponentType;
|
||||
import com.hypixel.hytale.logger.HytaleLogger;
|
||||
import com.hypixel.hytale.server.core.modules.interaction.interaction.config.Interaction;
|
||||
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.TickingImplementations.SolarCellSourceTicking;
|
||||
import org.KaiFlo.SolarCell.Systems.EnergyStorage.EnergyStorageInitializerSystem;
|
||||
import org.KaiFlo.SolarCell.Systems.EnergyStorage.TickingImplementations.BatteryStorageTicking;
|
||||
import org.KaiFlo.SolarCell.Systems.EnergyTickingSystem;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.List;
|
||||
|
||||
public class SolarCellPlugin extends JavaPlugin {
|
||||
|
||||
protected static SolarCellPlugin instance;
|
||||
|
||||
public static SolarCellPlugin get() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
private static final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass();
|
||||
|
||||
private ComponentType<ChunkStore, EnergySourceComponent> energySourceComponentType;
|
||||
private ComponentType<ChunkStore, EnergyConsumerComponent> energyConsumerComponentType;
|
||||
private ComponentType<ChunkStore, EnergyStorageComponent> energyStorageComponentType;
|
||||
|
||||
public SolarCellPlugin(@Nonnull JavaPluginInit init) {
|
||||
super(init);
|
||||
LOGGER.atInfo().log("Hello from " + this.getName() + " version " + this.getManifest().getVersion().toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setup() {
|
||||
instance = this;
|
||||
LOGGER.atInfo().log("Setting up plugin " + this.getName());
|
||||
|
||||
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()));
|
||||
|
||||
var energyTickingSystem = new EnergyTickingSystem()
|
||||
.withTickingSystemForComponentTypes(List.of(energyStorageComponentType), new BatteryStorageTicking())
|
||||
.withTickingSystemForComponentTypes(List.of(energySourceComponentType,energyStorageComponentType), new SolarCellSourceTicking());
|
||||
|
||||
this.getChunkStoreRegistry().registerSystem(new EnergySourceInitializerSystem());
|
||||
this.getChunkStoreRegistry().registerSystem(new EnergyStorageInitializerSystem());
|
||||
this.getChunkStoreRegistry().registerSystem(energyTickingSystem);
|
||||
|
||||
this.getCodecRegistry(Interaction.CODEC).register("StorageUseInteraction", StorageIntercationListener.class, StorageIntercationListener.CODEC);
|
||||
|
||||
}
|
||||
|
||||
public ComponentType<ChunkStore, EnergySourceComponent> getEnergySourceComponentType() {
|
||||
return energySourceComponentType;
|
||||
}
|
||||
|
||||
public ComponentType<ChunkStore, EnergyConsumerComponent> getEnergyConsumerComponentType() {
|
||||
return energyConsumerComponentType;
|
||||
}
|
||||
|
||||
public ComponentType<ChunkStore, EnergyStorageComponent> getEnergyStorageComponentType() {
|
||||
return energyStorageComponentType;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package org.KaiFlo.SolarCell;
|
||||
|
||||
import com.hypixel.hytale.codec.builder.BuilderCodec;
|
||||
import com.hypixel.hytale.component.CommandBuffer;
|
||||
import com.hypixel.hytale.component.Ref;
|
||||
import com.hypixel.hytale.math.util.ChunkUtil;
|
||||
import com.hypixel.hytale.protocol.InteractionType;
|
||||
|
||||
import com.hypixel.hytale.protocol.SimpleBlockInteraction;
|
||||
import com.hypixel.hytale.server.core.entity.InteractionContext;
|
||||
import com.hypixel.hytale.server.core.entity.entities.Player;
|
||||
|
||||
import com.hypixel.hytale.server.core.modules.entity.component.DisplayNameComponent;
|
||||
import com.hypixel.hytale.server.core.modules.interaction.interaction.CooldownHandler;
|
||||
import com.hypixel.hytale.server.core.modules.interaction.interaction.config.SimpleInstantInteraction;
|
||||
import com.hypixel.hytale.server.core.modules.interaction.interaction.config.SimpleInteraction;
|
||||
import com.hypixel.hytale.server.core.modules.interaction.interaction.config.client.UseBlockInteraction;
|
||||
import com.hypixel.hytale.server.core.universe.world.World;
|
||||
import com.hypixel.hytale.server.core.universe.world.chunk.BlockComponentChunk;
|
||||
import com.hypixel.hytale.server.core.universe.world.chunk.WorldChunk;
|
||||
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
|
||||
import com.hypixel.hytale.server.core.util.NotificationUtil;
|
||||
|
||||
import com.hypixel.hytale.protocol.BlockPosition;
|
||||
import org.KaiFlo.SolarCell.Components.EnergyStorage.Implementations.EnergyStorageComponent;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class StorageIntercationListener extends SimpleInstantInteraction {
|
||||
public static final BuilderCodec<StorageIntercationListener> CODEC = BuilderCodec.builder(
|
||||
StorageIntercationListener.class, StorageIntercationListener::new, SimpleInstantInteraction.CODEC
|
||||
).build();
|
||||
|
||||
@Override
|
||||
protected void firstRun(@Nonnull InteractionType interactionType, @Nonnull InteractionContext interactionContext, @Nonnull CooldownHandler cooldownHandler) {
|
||||
CommandBuffer<EntityStore> commandBuffer = interactionContext.getCommandBuffer();
|
||||
Ref<EntityStore> ref = interactionContext.getEntity();
|
||||
BlockPosition pos = interactionContext.getTargetBlock();
|
||||
Player player = commandBuffer.getComponent(ref, Player.getComponentType());
|
||||
World world = commandBuffer.getExternalData().getWorld();
|
||||
|
||||
if (interactionType.getValue() == InteractionType.Use.getValue()) {
|
||||
|
||||
int chunkX = Math.floorDiv(pos.x, 32);
|
||||
int chunkZ = Math.floorDiv(pos.z, 32);
|
||||
int localX = Math.floorMod(pos.x, 32);
|
||||
int localZ = Math.floorMod(pos.z, 32);
|
||||
|
||||
world.execute(() -> {
|
||||
var chunkStore = world.getChunkStore().getStore();
|
||||
|
||||
var targetChunk = world.getChunk(ChunkUtil.indexChunk(chunkX, chunkZ));
|
||||
if (targetChunk == null) return;
|
||||
|
||||
var blockComponentChunk = chunkStore.getComponent(
|
||||
targetChunk.getReference(),
|
||||
BlockComponentChunk.getComponentType()
|
||||
);
|
||||
if (blockComponentChunk == null) return;
|
||||
|
||||
int index = ChunkUtil.indexBlockInColumn(localX, pos.y, localZ);
|
||||
var targetRef = blockComponentChunk.getEntityReference(index);
|
||||
if (targetRef == null) return;
|
||||
|
||||
var energyStorage = chunkStore.getComponent(targetRef, EnergyStorageComponent.getComponentType());
|
||||
if (energyStorage == null) return;
|
||||
NotificationUtil.sendNotificationToUniverse(String.format("%d/%d (%.2f%%)",
|
||||
energyStorage.getCurrentEnergyAmount(),
|
||||
energyStorage.getMaxCapacity(),
|
||||
energyStorage.getCurrentEnergyToCapacityRatio() * 100
|
||||
));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package org.KaiFlo.SolarCell.Systems.EnergySource;
|
||||
|
||||
import com.hypixel.hytale.component.*;
|
||||
import com.hypixel.hytale.component.query.Query;
|
||||
import com.hypixel.hytale.component.system.RefSystem;
|
||||
import com.hypixel.hytale.server.core.modules.block.BlockModule;
|
||||
import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
|
||||
import org.KaiFlo.SolarCell.Components.EnergySource.Implementations.EnergySourceComponent;
|
||||
import org.checkerframework.checker.nullness.compatqual.NonNullDecl;
|
||||
import org.checkerframework.checker.nullness.compatqual.NullableDecl;
|
||||
|
||||
import static org.KaiFlo.SolarCell.Helpers.BlockHelper.setBlockRefTicking;
|
||||
|
||||
public class EnergySourceInitializerSystem extends RefSystem<ChunkStore> {
|
||||
@Override
|
||||
public void onEntityAdded(@NonNullDecl Ref<ChunkStore> ref, @NonNullDecl AddReason addReason, @NonNullDecl Store<ChunkStore> store, @NonNullDecl CommandBuffer<ChunkStore> commandBuffer) {
|
||||
setBlockRefTicking(ref, commandBuffer);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onEntityRemove(@NonNullDecl Ref ref, @NonNullDecl RemoveReason removeReason, @NonNullDecl Store store, @NonNullDecl CommandBuffer commandBuffer) {
|
||||
//Nothing to do yet
|
||||
}
|
||||
|
||||
@NullableDecl
|
||||
@Override
|
||||
public Query<ChunkStore> getQuery() {
|
||||
return Query.and(EnergySourceComponent.getComponentType(), BlockModule.BlockStateInfo.getComponentType());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package org.KaiFlo.SolarCell.Systems.EnergySource.TickingImplementations;
|
||||
|
||||
import com.hypixel.hytale.component.Archetype;
|
||||
import com.hypixel.hytale.component.CommandBuffer;
|
||||
import com.hypixel.hytale.component.Component;
|
||||
import com.hypixel.hytale.component.Ref;
|
||||
import com.hypixel.hytale.protocol.Vector3i;
|
||||
import com.hypixel.hytale.server.core.universe.world.World;
|
||||
import com.hypixel.hytale.server.core.universe.world.chunk.BlockComponentChunk;
|
||||
import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
|
||||
import org.KaiFlo.SolarCell.Components.EnergySource.Implementations.EnergySourceComponent;
|
||||
import org.KaiFlo.SolarCell.Components.EnergyStorage.Implementations.EnergyStorageComponent;
|
||||
import org.KaiFlo.SolarCell.Systems.ITickingSystem;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.KaiFlo.SolarCell.Helpers.BlockHelper.HyLogger;
|
||||
import static org.KaiFlo.SolarCell.Helpers.ComponentHelper.getComponentOfType;
|
||||
|
||||
public class SolarCellSourceTicking implements ITickingSystem {
|
||||
|
||||
@Override
|
||||
public void accept(Ref<ChunkStore> blockRef, List<Component<ChunkStore>> foundComponents, Archetype<ChunkStore> archetype, Vector3i globalPosition, BlockComponentChunk blockComponentChunk, CommandBuffer<ChunkStore> commandBuffer, World world) {
|
||||
var energyStorage = getComponentOfType(foundComponents, EnergyStorageComponent.class).orElse(null);
|
||||
if (energyStorage == null) return;
|
||||
var energySource = getComponentOfType(foundComponents, EnergySourceComponent.class).orElse(null);
|
||||
if (energySource == null) return;
|
||||
var received = energyStorage.receiveEnergy(energySource.getGeneratesPerTick());
|
||||
if (received!= 0){
|
||||
HyLogger.atInfo().log("Block at " + globalPosition.x+", "+ globalPosition.y+", " +globalPosition.z+" received " + received + " Energy, now at "+energyStorage.getCurrentEnergyAmount());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package org.KaiFlo.SolarCell.Systems.EnergyStorage;
|
||||
|
||||
import com.hypixel.hytale.component.*;
|
||||
import com.hypixel.hytale.component.query.Query;
|
||||
import com.hypixel.hytale.component.system.RefSystem;
|
||||
import com.hypixel.hytale.server.core.modules.block.BlockModule;
|
||||
import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
|
||||
import org.KaiFlo.SolarCell.Components.EnergyStorage.Implementations.EnergyStorageComponent;
|
||||
import org.checkerframework.checker.nullness.compatqual.NonNullDecl;
|
||||
import org.checkerframework.checker.nullness.compatqual.NullableDecl;
|
||||
|
||||
import static org.KaiFlo.SolarCell.Helpers.BlockHelper.setBlockRefTicking;
|
||||
|
||||
public class EnergyStorageInitializerSystem extends RefSystem<ChunkStore> {
|
||||
@Override
|
||||
public void onEntityAdded(@NonNullDecl Ref<ChunkStore> ref, @NonNullDecl AddReason addReason, @NonNullDecl Store<ChunkStore> store, @NonNullDecl CommandBuffer<ChunkStore> commandBuffer) {
|
||||
setBlockRefTicking(ref, commandBuffer);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onEntityRemove(@NonNullDecl Ref ref, @NonNullDecl RemoveReason removeReason, @NonNullDecl Store store, @NonNullDecl CommandBuffer commandBuffer) {
|
||||
//Nothing to do yet
|
||||
}
|
||||
|
||||
@NullableDecl
|
||||
@Override
|
||||
public Query<ChunkStore> getQuery() {
|
||||
return Query.and(EnergyStorageComponent.getComponentType(), BlockModule.BlockStateInfo.getComponentType());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package org.KaiFlo.SolarCell.Systems.EnergyStorage.TickingImplementations;
|
||||
|
||||
import com.hypixel.hytale.component.Archetype;
|
||||
import com.hypixel.hytale.component.CommandBuffer;
|
||||
import com.hypixel.hytale.component.Component;
|
||||
import com.hypixel.hytale.component.Ref;
|
||||
import com.hypixel.hytale.logger.HytaleLogger;
|
||||
import com.hypixel.hytale.protocol.Vector3i;
|
||||
import com.hypixel.hytale.server.core.universe.world.World;
|
||||
import com.hypixel.hytale.server.core.universe.world.chunk.BlockComponentChunk;
|
||||
import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
|
||||
import com.hypixel.hytale.server.core.util.NotificationUtil;
|
||||
import org.KaiFlo.SolarCell.Components.EnergySource.Implementations.EnergySourceComponent;
|
||||
import org.KaiFlo.SolarCell.Components.EnergyStorage.Implementations.EnergyStorageComponent;
|
||||
import org.KaiFlo.SolarCell.Enums.BlockRotation;
|
||||
import org.KaiFlo.SolarCell.Systems.ITickingSystem;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.KaiFlo.SolarCell.Helpers.BlockHelper.*;
|
||||
import static org.KaiFlo.SolarCell.Helpers.ComponentHelper.getComponentOfType;
|
||||
|
||||
public class BatteryStorageTicking implements ITickingSystem {
|
||||
|
||||
@Override
|
||||
public void accept(Ref<ChunkStore> blockRef, List<Component<ChunkStore>> foundComponents, Archetype<ChunkStore> archetype, Vector3i globalPosition, BlockComponentChunk blockComponentChunk, CommandBuffer<ChunkStore> commandBuffer, World world) {
|
||||
var energyStorage = getComponentOfType(foundComponents, EnergyStorageComponent.class).orElse(null);
|
||||
if (energyStorage == null) return;
|
||||
var energySourceComponent = getComponentOfType(foundComponents, EnergySourceComponent.class).orElse(null);
|
||||
if (energySourceComponent != null) return;
|
||||
|
||||
int blockRotationIndex = world.getBlockRotationIndex(globalPosition.x, globalPosition.y, globalPosition.z);
|
||||
// HyLogger.atInfo().log("Block at " + globalPosition.x+", "+ globalPosition.y+", " +globalPosition.z+": "+blockRotationIndex);
|
||||
|
||||
var rotation = BlockRotation.getEnum(blockRotationIndex);
|
||||
|
||||
executeForDirection(globalPosition.x, globalPosition.y, globalPosition.z, world, commandBuffer, rotation,
|
||||
(x, y, z, targetRef, _, _) -> {
|
||||
if (energyStorage.getCurrentEnergyAmount() >= energyStorage.getMaxCapacity()) return;
|
||||
var targetEnergyStorage = commandBuffer.getComponent(targetRef, EnergyStorageComponent.getComponentType());
|
||||
if (targetEnergyStorage == null) return;
|
||||
if (targetEnergyStorage.getCurrentEnergyAmount() < energyStorage.getCurrentEnergyAmount() && commandBuffer.getComponent(targetRef, EnergySourceComponent.getComponentType()) == null) return;
|
||||
|
||||
var extractEnergy = Math.min(energyStorage.getReceiveEnergyPerTick(), targetEnergyStorage.getCurrentEnergyAmount());
|
||||
|
||||
transmitEnergy(energyStorage,targetEnergyStorage,extractEnergy,globalPosition, x, y, z);
|
||||
|
||||
//Input bei Lüftungsgitter
|
||||
//INPUT index 0 --> North
|
||||
//INPUT index 1 --> West
|
||||
//INPUT index 2 --> South
|
||||
//INPUT index 3 --> East
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static void transmitEnergy( EnergyStorageComponent energyStorage, EnergyStorageComponent targetEnergyStorage,long extractTarget, Vector3i globalPosition, int x, int y, int z) {
|
||||
long energy = 1;
|
||||
if (extractTarget > 1 && !(energyStorage.getCurrentEnergyAmount()+1>=energyStorage.getMaxCapacity())) {
|
||||
energy = targetEnergyStorage.extractEnergy(extractTarget);
|
||||
HyLogger.atInfo().log("Extracted " + energy + "/" + extractTarget +
|
||||
" |" + targetEnergyStorage.getCurrentEnergyAmount() + "| from storage" +
|
||||
" at Block " + x + ", " + y + ", " + z + ", now at " +
|
||||
targetEnergyStorage.getCurrentEnergyAmount() + "/" + targetEnergyStorage.getMaxCapacity());
|
||||
}
|
||||
|
||||
long inserted = energyStorage.receiveEnergy(energy);
|
||||
if (inserted < energy) {
|
||||
var received = targetEnergyStorage.receiveEnergy(energy - inserted);
|
||||
HyLogger.atInfo().log("TO MUCH:Inserted " + received + "/" + (energy - inserted) +
|
||||
" |" + targetEnergyStorage.getCurrentEnergyAmount() + "| into storage" +
|
||||
" at Block " + x + ", " + y + ", " + z + ", now at " +
|
||||
targetEnergyStorage.getCurrentEnergyAmount() + "/" + targetEnergyStorage.getMaxCapacity());
|
||||
}
|
||||
|
||||
if (inserted != 0) {
|
||||
HyLogger.atInfo().log("Inserted " + inserted + "/" + energy +
|
||||
" |" + energyStorage.getCurrentEnergyAmount() + "| into storage" +
|
||||
" at Block " + globalPosition.x + ", " + globalPosition.y + ", " + globalPosition.z + ", now at " +
|
||||
energyStorage.getCurrentEnergyAmount() + "/" + energyStorage.getMaxCapacity());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package org.KaiFlo.SolarCell.Systems;
|
||||
|
||||
import com.hypixel.hytale.component.*;
|
||||
import com.hypixel.hytale.component.query.Query;
|
||||
import com.hypixel.hytale.component.system.tick.EntityTickingSystem;
|
||||
import com.hypixel.hytale.math.util.ChunkUtil;
|
||||
import com.hypixel.hytale.protocol.Vector3i;
|
||||
import com.hypixel.hytale.server.core.asset.type.blocktick.BlockTickStrategy;
|
||||
import com.hypixel.hytale.server.core.universe.world.chunk.BlockComponentChunk;
|
||||
import com.hypixel.hytale.server.core.universe.world.chunk.WorldChunk;
|
||||
import com.hypixel.hytale.server.core.universe.world.chunk.section.BlockSection;
|
||||
import com.hypixel.hytale.server.core.universe.world.chunk.section.ChunkSection;
|
||||
import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
|
||||
import org.checkerframework.checker.nullness.compatqual.NonNullDecl;
|
||||
import org.checkerframework.checker.nullness.compatqual.NullableDecl;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public class EnergyTickingSystem extends EntityTickingSystem<ChunkStore> {
|
||||
|
||||
private final Map<List<ComponentType<ChunkStore, ?>>, ITickingSystem> componentsToTickingSystem = new HashMap<>();
|
||||
|
||||
|
||||
@Override
|
||||
public void tick(float v, int archetypeIndex, @NonNullDecl ArchetypeChunk<ChunkStore> archetypeChunk, @NonNullDecl Store<ChunkStore> store, @NonNullDecl CommandBuffer<ChunkStore> commandBuffer) {
|
||||
var blockSection = archetypeChunk.getComponent(archetypeIndex, BlockSection.getComponentType());
|
||||
if (blockSection == null) return;
|
||||
|
||||
var chunkSection = archetypeChunk.getComponent(archetypeIndex, ChunkSection.getComponentType());
|
||||
if (chunkSection == null) return;
|
||||
|
||||
var blockComponentChunk = commandBuffer.getComponent(chunkSection.getChunkColumnReference(), BlockComponentChunk.getComponentType());
|
||||
var worldChunk = commandBuffer.getComponent(chunkSection.getChunkColumnReference(), WorldChunk.getComponentType());
|
||||
if (blockComponentChunk == null || worldChunk == null) return;
|
||||
|
||||
var entrySet = componentsToTickingSystem.entrySet();
|
||||
var foundComponentTypes = new ArrayList<ComponentType<ChunkStore, ?>>();
|
||||
|
||||
blockSection.forEachTicking(null, null, chunkSection.getY(), (_, _, localX, localY, localZ, _) -> {
|
||||
var blockRef = blockComponentChunk.getEntityReference(ChunkUtil.indexBlockInColumn(localX, localY, localZ));
|
||||
if (blockRef == null) {
|
||||
return BlockTickStrategy.IGNORED;
|
||||
}
|
||||
|
||||
int globalX = localX + (worldChunk.getX() * 32);
|
||||
int globalZ = localZ + (worldChunk.getZ() * 32);
|
||||
var globalPosition = new Vector3i(globalX, localY, globalZ);
|
||||
|
||||
var archetype = commandBuffer.getArchetype(blockRef);
|
||||
|
||||
foundComponentTypes.clear();
|
||||
var foundComponents = new ArrayList<Component<ChunkStore>>();
|
||||
for (int i = 0; i < archetype.length(); i++) {
|
||||
var type = archetype.get(i);
|
||||
if (type == null) continue;
|
||||
foundComponentTypes.add(type);
|
||||
foundComponents.add(commandBuffer.getComponent(blockRef, type));
|
||||
}
|
||||
|
||||
AtomicBoolean hasAny = new AtomicBoolean(false);
|
||||
entrySet.stream()
|
||||
.filter(entry -> foundComponentTypes.containsAll(entry.getKey())).map(Map.Entry::getValue)
|
||||
.forEach(tickingSystem -> {
|
||||
hasAny.set(true);
|
||||
tickingSystem.accept(blockRef, foundComponents, archetype, globalPosition, blockComponentChunk, commandBuffer, worldChunk.getWorld());
|
||||
});
|
||||
return hasAny.get() ? BlockTickStrategy.CONTINUE : BlockTickStrategy.IGNORED;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@NullableDecl
|
||||
@Override
|
||||
public Query<ChunkStore> getQuery() {
|
||||
return Query.and(BlockSection.getComponentType(), ChunkSection.getComponentType());
|
||||
}
|
||||
|
||||
public EnergyTickingSystem withTickingSystemForComponentTypes(List<ComponentType<ChunkStore, ?>> componentTypes, ITickingSystem tickingSystem) {
|
||||
componentsToTickingSystem.put(componentTypes, tickingSystem);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package org.KaiFlo.SolarCell.Systems;
|
||||
|
||||
import com.hypixel.hytale.component.Archetype;
|
||||
import com.hypixel.hytale.component.CommandBuffer;
|
||||
import com.hypixel.hytale.component.Component;
|
||||
import com.hypixel.hytale.component.Ref;
|
||||
import com.hypixel.hytale.protocol.Vector3i;
|
||||
import com.hypixel.hytale.server.core.universe.world.World;
|
||||
import com.hypixel.hytale.server.core.universe.world.chunk.BlockComponentChunk;
|
||||
import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ITickingSystem {
|
||||
|
||||
void accept(Ref<ChunkStore> blockRef, List<Component<ChunkStore>> foundComponents, Archetype<ChunkStore> archetype, Vector3i globalPosition, BlockComponentChunk blockComponentChunk, CommandBuffer<ChunkStore> commandBuffer, World world);
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
package org.example.plugin;
|
||||
|
||||
import com.hypixel.hytale.protocol.GameMode;
|
||||
import com.hypixel.hytale.server.core.Message;
|
||||
import com.hypixel.hytale.server.core.command.system.CommandContext;
|
||||
import com.hypixel.hytale.server.core.command.system.basecommands.CommandBase;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* This is an example command that will simply print the name of the plugin in chat when used.
|
||||
*/
|
||||
public class ExampleCommand extends CommandBase {
|
||||
|
||||
private final String pluginName;
|
||||
private final String pluginVersion;
|
||||
|
||||
public ExampleCommand(String pluginName, String pluginVersion) {
|
||||
super("test", "Prints a test message from the " + pluginName + " plugin.");
|
||||
this.setPermissionGroup(GameMode.Adventure); // Allows the command to be used by anyone, not just OP
|
||||
this.pluginName = pluginName;
|
||||
this.pluginVersion = pluginVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void executeSync(@Nonnull CommandContext ctx) {
|
||||
ctx.sendMessage(Message.raw("Hello from the " + pluginName + " v" + pluginVersion + " plugin!"));
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
package org.example.plugin;
|
||||
|
||||
import com.hypixel.hytale.logger.HytaleLogger;
|
||||
import com.hypixel.hytale.server.core.plugin.JavaPlugin;
|
||||
import com.hypixel.hytale.server.core.plugin.JavaPluginInit;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* This class serves as the entrypoint for your plugin. Use the setup method to register into game registries or add
|
||||
* event listeners.
|
||||
*/
|
||||
public class ExamplePlugin extends JavaPlugin {
|
||||
|
||||
private static final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass();
|
||||
|
||||
public ExamplePlugin(@Nonnull JavaPluginInit init) {
|
||||
super(init);
|
||||
LOGGER.atInfo().log("Hello from " + this.getName() + " version " + this.getManifest().getVersion().toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setup() {
|
||||
LOGGER.atInfo().log("Setting up plugin " + this.getName());
|
||||
this.getCommandRegistry().registerCommand(new ExampleCommand(this.getName(), this.getManifest().getVersion().toString()));
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,266 @@
|
||||
{
|
||||
"nodes": [
|
||||
{
|
||||
"id": "1",
|
||||
"name": "cube",
|
||||
"position": {"x": 0, "y": 0, "z": 0},
|
||||
"orientation": {"x": 0, "y": 0, "z": 0, "w": 1},
|
||||
"shape": {
|
||||
"type": "box",
|
||||
"offset": {"x": 0, "y": 4, "z": 0},
|
||||
"stretch": {"x": 1, "y": 1, "z": 1},
|
||||
"settings": {
|
||||
"isPiece": false,
|
||||
"size": {"x": 32, "y": 8, "z": 32},
|
||||
"isStaticBox": true
|
||||
},
|
||||
"textureLayout": {
|
||||
"back": {
|
||||
"offset": {"x": 78, "y": 58},
|
||||
"mirror": {"x": false, "y": false},
|
||||
"angle": 0
|
||||
},
|
||||
"right": {
|
||||
"offset": {"x": 78, "y": 66},
|
||||
"mirror": {"x": false, "y": false},
|
||||
"angle": 0
|
||||
},
|
||||
"front": {
|
||||
"offset": {"x": 78, "y": 74},
|
||||
"mirror": {"x": false, "y": false},
|
||||
"angle": 0
|
||||
},
|
||||
"left": {
|
||||
"offset": {"x": 26, "y": 80},
|
||||
"mirror": {"x": false, "y": false},
|
||||
"angle": 0
|
||||
},
|
||||
"top": {
|
||||
"offset": {"x": 32, "y": 32},
|
||||
"mirror": {"x": true, "y": true},
|
||||
"angle": 0
|
||||
},
|
||||
"bottom": {
|
||||
"offset": {"x": 32, "y": 32},
|
||||
"mirror": {"x": true, "y": false},
|
||||
"angle": 0
|
||||
}
|
||||
},
|
||||
"unwrapMode": "custom",
|
||||
"visible": true,
|
||||
"doubleSided": false,
|
||||
"shadingMode": "flat"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"name": "cube",
|
||||
"position": {"x": 0, "y": 24, "z": 0},
|
||||
"orientation": {"x": 0, "y": 0, "z": 0, "w": 1},
|
||||
"shape": {
|
||||
"type": "box",
|
||||
"offset": {"x": 0, "y": 4, "z": 0},
|
||||
"stretch": {"x": 1, "y": 1, "z": 1},
|
||||
"settings": {
|
||||
"isPiece": false,
|
||||
"size": {"x": 32, "y": 8, "z": 32},
|
||||
"isStaticBox": true
|
||||
},
|
||||
"textureLayout": {
|
||||
"back": {
|
||||
"offset": {"x": 58, "y": 82},
|
||||
"mirror": {"x": false, "y": false},
|
||||
"angle": 0
|
||||
},
|
||||
"right": {
|
||||
"offset": {"x": 26, "y": 88},
|
||||
"mirror": {"x": false, "y": false},
|
||||
"angle": 0
|
||||
},
|
||||
"front": {
|
||||
"offset": {"x": 90, "y": 0},
|
||||
"mirror": {"x": false, "y": false},
|
||||
"angle": 0
|
||||
},
|
||||
"left": {
|
||||
"offset": {"x": 90, "y": 8},
|
||||
"mirror": {"x": false, "y": false},
|
||||
"angle": 0
|
||||
},
|
||||
"top": {
|
||||
"offset": {"x": 64, "y": 32},
|
||||
"mirror": {"x": true, "y": true},
|
||||
"angle": 0
|
||||
},
|
||||
"bottom": {
|
||||
"offset": {"x": 64, "y": 32},
|
||||
"mirror": {"x": true, "y": false},
|
||||
"angle": 0
|
||||
}
|
||||
},
|
||||
"unwrapMode": "custom",
|
||||
"visible": true,
|
||||
"doubleSided": false,
|
||||
"shadingMode": "flat"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"name": "cube",
|
||||
"position": {"x": 0, "y": 8, "z": 0},
|
||||
"orientation": {"x": 0, "y": 0, "z": 0, "w": 1},
|
||||
"shape": {
|
||||
"type": "box",
|
||||
"offset": {"x": 0, "y": 8, "z": 0},
|
||||
"stretch": {"x": 1, "y": 1, "z": 1},
|
||||
"settings": {
|
||||
"isPiece": false,
|
||||
"size": {"x": 26, "y": 16, "z": 26},
|
||||
"isStaticBox": true
|
||||
},
|
||||
"textureLayout": {
|
||||
"back": {
|
||||
"offset": {"x": 26, "y": 64},
|
||||
"mirror": {"x": false, "y": false},
|
||||
"angle": 0
|
||||
},
|
||||
"right": {
|
||||
"offset": {"x": 64, "y": 26},
|
||||
"mirror": {"x": false, "y": false},
|
||||
"angle": 0
|
||||
},
|
||||
"front": {
|
||||
"offset": {"x": 64, "y": 42},
|
||||
"mirror": {"x": false, "y": false},
|
||||
"angle": 0
|
||||
},
|
||||
"left": {
|
||||
"offset": {"x": 52, "y": 64},
|
||||
"mirror": {"x": false, "y": false},
|
||||
"angle": 0
|
||||
},
|
||||
"top": {
|
||||
"offset": {"x": 26, "y": 90},
|
||||
"mirror": {"x": true, "y": true},
|
||||
"angle": 0
|
||||
},
|
||||
"bottom": {
|
||||
"offset": {"x": 90, "y": 0},
|
||||
"mirror": {"x": true, "y": false},
|
||||
"angle": 0
|
||||
}
|
||||
},
|
||||
"unwrapMode": "custom",
|
||||
"visible": true,
|
||||
"doubleSided": false,
|
||||
"shadingMode": "flat"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "4",
|
||||
"name": "cube",
|
||||
"position": {"x": 2, "y": 11, "z": -14},
|
||||
"orientation": {"x": 0, "y": 0, "z": 0, "w": 1},
|
||||
"shape": {
|
||||
"type": "box",
|
||||
"offset": {"x": -2, "y": 5, "z": 0},
|
||||
"stretch": {"x": 1, "y": 1, "z": 1},
|
||||
"settings": {
|
||||
"isPiece": false,
|
||||
"size": {"x": 10, "y": 10, "z": 2},
|
||||
"isStaticBox": true
|
||||
},
|
||||
"textureLayout": {
|
||||
"back": {
|
||||
"offset": {"x": 3, "y": 1},
|
||||
"mirror": {"x": false, "y": false},
|
||||
"angle": 0
|
||||
},
|
||||
"right": {
|
||||
"offset": {"x": 0, "y": 1},
|
||||
"mirror": {"x": false, "y": false},
|
||||
"angle": 0
|
||||
},
|
||||
"front": {
|
||||
"offset": {"x": 0, "y": 1},
|
||||
"mirror": {"x": false, "y": false},
|
||||
"angle": 0
|
||||
},
|
||||
"left": {
|
||||
"offset": {"x": 0, "y": 1},
|
||||
"mirror": {"x": false, "y": false},
|
||||
"angle": 0
|
||||
},
|
||||
"top": {
|
||||
"offset": {"x": 0, "y": 0},
|
||||
"mirror": {"x": false, "y": false},
|
||||
"angle": 0
|
||||
},
|
||||
"bottom": {
|
||||
"offset": {"x": 0, "y": 0},
|
||||
"mirror": {"x": false, "y": false},
|
||||
"angle": 0
|
||||
}
|
||||
},
|
||||
"unwrapMode": "custom",
|
||||
"visible": true,
|
||||
"doubleSided": false,
|
||||
"shadingMode": "flat"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "5",
|
||||
"name": "cube",
|
||||
"position": {"x": 0, "y": 15, "z": -15},
|
||||
"orientation": {"x": 0, "y": 0, "z": 0, "w": 1},
|
||||
"shape": {
|
||||
"type": "box",
|
||||
"offset": {"x": 0, "y": 1, "z": 0},
|
||||
"stretch": {"x": 1, "y": 1, "z": 1},
|
||||
"settings": {
|
||||
"isPiece": false,
|
||||
"size": {"x": 6, "y": 6, "z": 2},
|
||||
"isStaticBox": true
|
||||
},
|
||||
"textureLayout": {
|
||||
"back": {
|
||||
"offset": {"x": 0, "y": 0},
|
||||
"mirror": {"x": false, "y": false},
|
||||
"angle": 0
|
||||
},
|
||||
"right": {
|
||||
"offset": {"x": 0, "y": 0},
|
||||
"mirror": {"x": false, "y": false},
|
||||
"angle": 0
|
||||
},
|
||||
"front": {
|
||||
"offset": {"x": 1, "y": 0},
|
||||
"mirror": {"x": false, "y": false},
|
||||
"angle": 0
|
||||
},
|
||||
"left": {
|
||||
"offset": {"x": 0, "y": 0},
|
||||
"mirror": {"x": false, "y": false},
|
||||
"angle": 0
|
||||
},
|
||||
"top": {
|
||||
"offset": {"x": 1, "y": 0},
|
||||
"mirror": {"x": false, "y": false},
|
||||
"angle": 0
|
||||
},
|
||||
"bottom": {
|
||||
"offset": {"x": 1, "y": 0},
|
||||
"mirror": {"x": false, "y": false},
|
||||
"angle": 0
|
||||
}
|
||||
},
|
||||
"unwrapMode": "custom",
|
||||
"visible": true,
|
||||
"doubleSided": false,
|
||||
"shadingMode": "flat"
|
||||
}
|
||||
}
|
||||
],
|
||||
"format": "prop",
|
||||
"lod": "auto"
|
||||
}
|
||||
BIN
src/main/resources/Common/Items/EnergyStorages/texture.png
Normal file
BIN
src/main/resources/Common/Items/EnergyStorages/texture.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
File diff suppressed because one or more lines are too long
@@ -0,0 +1,162 @@
|
||||
{
|
||||
"nodes": [
|
||||
{
|
||||
"id": "1",
|
||||
"name": "cube",
|
||||
"position": {"x": 1, "y": 0, "z": 0},
|
||||
"orientation": {"x": 0, "y": 0, "z": 0, "w": 1},
|
||||
"shape": {
|
||||
"type": "box",
|
||||
"offset": {"x": -1, "y": 3, "z": 0},
|
||||
"stretch": {"x": 1, "y": 1, "z": 1},
|
||||
"settings": {
|
||||
"isPiece": false,
|
||||
"size": {"x": 22, "y": 6, "z": 26},
|
||||
"isStaticBox": true
|
||||
},
|
||||
"textureLayout": {
|
||||
"back": {
|
||||
"offset": {"x": 44, "y": 43},
|
||||
"mirror": {"x": false, "y": false},
|
||||
"angle": 0
|
||||
},
|
||||
"right": {
|
||||
"offset": {"x": 44, "y": 31},
|
||||
"mirror": {"x": false, "y": false},
|
||||
"angle": 0
|
||||
},
|
||||
"front": {
|
||||
"offset": {"x": 44, "y": 49},
|
||||
"mirror": {"x": false, "y": false},
|
||||
"angle": 0
|
||||
},
|
||||
"left": {
|
||||
"offset": {"x": 44, "y": 37},
|
||||
"mirror": {"x": false, "y": false},
|
||||
"angle": 0
|
||||
},
|
||||
"top": {
|
||||
"offset": {"x": 22, "y": 57},
|
||||
"mirror": {"x": true, "y": true},
|
||||
"angle": 0
|
||||
},
|
||||
"bottom": {
|
||||
"offset": {"x": 44, "y": 31},
|
||||
"mirror": {"x": true, "y": false},
|
||||
"angle": 0
|
||||
}
|
||||
},
|
||||
"unwrapMode": "custom",
|
||||
"visible": true,
|
||||
"doubleSided": false,
|
||||
"shadingMode": "flat"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"name": "cube",
|
||||
"position": {"x": 0, "y": 5, "z": -2},
|
||||
"orientation": {"x": 0, "y": 0, "z": 0, "w": 1},
|
||||
"shape": {
|
||||
"type": "box",
|
||||
"offset": {"x": 0, "y": 10, "z": 2.5},
|
||||
"stretch": {"x": 1, "y": 1, "z": 1},
|
||||
"settings": {
|
||||
"isPiece": false,
|
||||
"size": {"x": 6, "y": 20, "z": 5},
|
||||
"isStaticBox": true
|
||||
},
|
||||
"textureLayout": {
|
||||
"back": {
|
||||
"offset": {"x": 44, "y": 55},
|
||||
"mirror": {"x": false, "y": false},
|
||||
"angle": 0
|
||||
},
|
||||
"right": {
|
||||
"offset": {"x": 56, "y": 55},
|
||||
"mirror": {"x": false, "y": false},
|
||||
"angle": 0
|
||||
},
|
||||
"front": {
|
||||
"offset": {"x": 50, "y": 55},
|
||||
"mirror": {"x": false, "y": false},
|
||||
"angle": 0
|
||||
},
|
||||
"left": {
|
||||
"offset": {"x": 0, "y": 57},
|
||||
"mirror": {"x": false, "y": false},
|
||||
"angle": 0
|
||||
},
|
||||
"top": {
|
||||
"offset": {"x": 42, "y": 62},
|
||||
"mirror": {"x": true, "y": true},
|
||||
"angle": 0
|
||||
},
|
||||
"bottom": {
|
||||
"offset": {"x": 66, "y": 6},
|
||||
"mirror": {"x": true, "y": false},
|
||||
"angle": 0
|
||||
}
|
||||
},
|
||||
"unwrapMode": "custom",
|
||||
"visible": true,
|
||||
"doubleSided": false,
|
||||
"shadingMode": "flat"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"name": "cube",
|
||||
"position": {"x": 14, "y": 28, "z": -5},
|
||||
"orientation": {"x": 0.27983, "y": 0, "z": 0, "w": 0.96005},
|
||||
"shape": {
|
||||
"type": "box",
|
||||
"offset": {"x": -14, "y": 0.5, "z": 5.5},
|
||||
"stretch": {"x": 1, "y": 1, "z": 1},
|
||||
"settings": {
|
||||
"isPiece": false,
|
||||
"size": {"x": 30, "y": 3, "z": 31},
|
||||
"isStaticBox": true
|
||||
},
|
||||
"textureLayout": {
|
||||
"back": {
|
||||
"offset": {"x": 60, "y": 3},
|
||||
"mirror": {"x": false, "y": false},
|
||||
"angle": 0
|
||||
},
|
||||
"right": {
|
||||
"offset": {"x": 5, "y": 57},
|
||||
"mirror": {"x": false, "y": false},
|
||||
"angle": 0
|
||||
},
|
||||
"front": {
|
||||
"offset": {"x": 5, "y": 60},
|
||||
"mirror": {"x": false, "y": false},
|
||||
"angle": 0
|
||||
},
|
||||
"left": {
|
||||
"offset": {"x": 60, "y": 0},
|
||||
"mirror": {"x": false, "y": false},
|
||||
"angle": 0
|
||||
},
|
||||
"top": {
|
||||
"offset": {"x": 30, "y": 31},
|
||||
"mirror": {"x": true, "y": true},
|
||||
"angle": 0
|
||||
},
|
||||
"bottom": {
|
||||
"offset": {"x": 60, "y": 0},
|
||||
"mirror": {"x": true, "y": false},
|
||||
"angle": 0
|
||||
}
|
||||
},
|
||||
"unwrapMode": "custom",
|
||||
"visible": true,
|
||||
"doubleSided": false,
|
||||
"shadingMode": "flat"
|
||||
}
|
||||
}
|
||||
],
|
||||
"format": "prop",
|
||||
"lod": "auto"
|
||||
}
|
||||
BIN
src/main/resources/Common/Items/SolarPanels/SolarCell1.png
Normal file
BIN
src/main/resources/Common/Items/SolarPanels/SolarCell1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.2 KiB |
217
src/main/resources/Server/Item/Items/EnergyOven.json
Normal file
217
src/main/resources/Server/Item/Items/EnergyOven.json
Normal file
@@ -0,0 +1,217 @@
|
||||
{
|
||||
"TranslationProperties": {
|
||||
"Name": "server.items.Bench_Furnace.name",
|
||||
"Description": "server.items.Bench_Furnace.description"
|
||||
},
|
||||
"Icon": "Icons/ItemsGenerated/Bench_Furnace.png",
|
||||
"Categories": [
|
||||
"Furniture.Benches"
|
||||
],
|
||||
"Recipe": {
|
||||
"Input": [
|
||||
{
|
||||
"ResourceTypeId": "Wood_Trunk",
|
||||
"Quantity": 6
|
||||
},
|
||||
{
|
||||
"ResourceTypeId": "Rock",
|
||||
"Quantity": 6
|
||||
}
|
||||
],
|
||||
"Output": [
|
||||
{
|
||||
"ItemId": "Bench_Furnace",
|
||||
"Metadata": {
|
||||
"BlockState": {
|
||||
"Type": "processingBench",
|
||||
"FuelContainer": {
|
||||
"Capacity": 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"BenchRequirement": [
|
||||
{
|
||||
"Type": "Crafting",
|
||||
"Categories": [
|
||||
"Workbench_Crafting"
|
||||
],
|
||||
"Id": "Workbench"
|
||||
}
|
||||
],
|
||||
"TimeSeconds": 3
|
||||
},
|
||||
"BlockType": {
|
||||
"Material": "Solid",
|
||||
"DrawType": "Model",
|
||||
"Opacity": "Solid",
|
||||
"CustomModel": "Items/EnergyStorages/EnergyStorage1.blockymodel",
|
||||
"CustomModelTexture": [
|
||||
{
|
||||
"Texture": "Items/EnergyStorages/texture.png",
|
||||
"Weight": 1
|
||||
}
|
||||
],
|
||||
"VariantRotation": "NESW",
|
||||
"Bench": {
|
||||
"Type": "Processing",
|
||||
"AllowNoInputProcessing": true,
|
||||
"Input": [
|
||||
{
|
||||
"FilterValidIngredients": true
|
||||
},
|
||||
{
|
||||
"FilterValidIngredients": true
|
||||
}
|
||||
],
|
||||
"Fuel": [
|
||||
{
|
||||
"ResourceTypeId": "Fuel",
|
||||
"Icon": "Icons/Processing/FuelSlotIcon.png"
|
||||
}
|
||||
],
|
||||
"LocalOpenSoundEventId": "SFX_Furnace_Bench_Open",
|
||||
"LocalCloseSoundEventId": "SFX_Furnace_Bench_Close",
|
||||
"CompletedSoundEventId": "SFX_Furnace_Bench_Processing_Complete",
|
||||
"EndSoundEventId": "SFX_Furnace_Bench_Processing_End",
|
||||
"FailedSoundEventId": "SFX_Furnace_Bench_Processing_Failed",
|
||||
"BenchUpgradeSoundEventId": "SFX_Workbench_Upgrade_Start_Default",
|
||||
"BenchUpgradeCompletedSoundEventId": "SFX_Workbench_Upgrade_Complete_Default",
|
||||
"ExtraOutput": {
|
||||
"Outputs": [
|
||||
{
|
||||
"ItemId": "Ingredient_Charcoal"
|
||||
}
|
||||
],
|
||||
"PerFuelItemsConsumed": 2,
|
||||
"IgnoredFuelSources": [
|
||||
{
|
||||
"ItemId": "Ingredient_Charcoal"
|
||||
},
|
||||
{
|
||||
"ItemId": "Ingredient_Fibre"
|
||||
},
|
||||
{
|
||||
"ItemId": "Ingredient_Tree_Sap"
|
||||
}
|
||||
]
|
||||
},
|
||||
"OutputSlotsCount": 4,
|
||||
"Id": "Furnace",
|
||||
"TierLevels": [
|
||||
{
|
||||
"UpgradeRequirement": {
|
||||
"Material": [
|
||||
{
|
||||
"ItemId": "Ingredient_Bar_Copper",
|
||||
"Quantity": 5
|
||||
},
|
||||
{
|
||||
"ItemId": "Ingredient_Bar_Iron",
|
||||
"Quantity": 5
|
||||
},
|
||||
{
|
||||
"ItemId": "Ingredient_Bar_Thorium",
|
||||
"Quantity": 5
|
||||
},
|
||||
{
|
||||
"ItemId": "Ingredient_Bar_Cobalt",
|
||||
"Quantity": 5
|
||||
}
|
||||
],
|
||||
"TimeSeconds": 3
|
||||
},
|
||||
"CraftingTimeReductionModifier": 0.0
|
||||
},
|
||||
{
|
||||
"CraftingTimeReductionModifier": 0.3,
|
||||
"ExtraInputSlot": 1
|
||||
}
|
||||
]
|
||||
},
|
||||
"State": {
|
||||
"Id": "processingBench",
|
||||
"Definitions": {
|
||||
"Processing": {
|
||||
"Looping": true,
|
||||
"Light": {
|
||||
"Color": "#B72"
|
||||
},
|
||||
"CustomModelTexture": [
|
||||
{
|
||||
"Texture": "Blocks/Benches/Furnace_Texture.png",
|
||||
"Weight": 1
|
||||
}
|
||||
],
|
||||
"Particles": [
|
||||
{
|
||||
"SystemId": "Fire_Furnace_On",
|
||||
"TargetNodeName": "Fire",
|
||||
"Scale": 0.7,
|
||||
"PositionOffset": {
|
||||
"X": 0,
|
||||
"Z": 0.3
|
||||
}
|
||||
}
|
||||
],
|
||||
"AmbientSoundEventId": "SFX_Furnace_Bench_Processing",
|
||||
"CustomModelAnimation": "Blocks/Benches/Furnace_Smelting.blockyanim"
|
||||
},
|
||||
"ProcessCompleted": {
|
||||
"Light": {
|
||||
"Color": "#B72"
|
||||
},
|
||||
"CustomModelTexture": [
|
||||
{
|
||||
"Texture": "Blocks/Benches/Furnace_Texture.png",
|
||||
"Weight": 1
|
||||
}
|
||||
],
|
||||
"AmbientSoundEventId": "SFX_Furnace_Bench_Processing",
|
||||
"Looping": true,
|
||||
"CustomModelAnimation": "Blocks/Benches/Furnace_Smelting.blockyanim"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Gathering": {
|
||||
"Breaking": {
|
||||
"GatherType": "Benches"
|
||||
}
|
||||
},
|
||||
"BlockParticleSetId": "Stone",
|
||||
"ParticleColor": "#5C583E",
|
||||
"Support": {
|
||||
"Down": [
|
||||
{
|
||||
"FaceType": "Full"
|
||||
}
|
||||
]
|
||||
},
|
||||
"BlockSoundSetId": "Stone",
|
||||
"Interactions": {
|
||||
"Use": "Open_Processing_Bench"
|
||||
}
|
||||
},
|
||||
"PlayerAnimationsId": "Block",
|
||||
"IconProperties": {
|
||||
"Scale": 0.365,
|
||||
"Rotation": [
|
||||
22.5,
|
||||
45,
|
||||
22.5
|
||||
],
|
||||
"Translation": [
|
||||
12,
|
||||
-17.4
|
||||
]
|
||||
},
|
||||
"Tags": {
|
||||
"Type": [
|
||||
"Bench"
|
||||
]
|
||||
},
|
||||
"MaxStack": 1,
|
||||
"ItemLevel": 1,
|
||||
"ItemSoundSetId": "ISS_Blocks_Stone"
|
||||
}
|
||||
77
src/main/resources/Server/Item/Items/EnergyStorage.json
Normal file
77
src/main/resources/Server/Item/Items/EnergyStorage.json
Normal file
@@ -0,0 +1,77 @@
|
||||
{
|
||||
"TranslationProperties": {
|
||||
"Name": "EnergyStorage Tier 1"
|
||||
},
|
||||
"Icon": "Icons/Items/EditorTools/Layers.png",
|
||||
"IconProperties": {
|
||||
"Scale": 0.36,
|
||||
"Rotation": [
|
||||
22.5,
|
||||
45,
|
||||
22.5
|
||||
],
|
||||
"Translation": [
|
||||
12.6,
|
||||
-24.6
|
||||
]
|
||||
},
|
||||
"BlockType": {
|
||||
"BlockEntity": {
|
||||
"Components": {
|
||||
"EnergyStorage": {
|
||||
"MaxCapacity": 10000,
|
||||
"ExtractEnergyPerTick": 500,
|
||||
"ReceiveEnergyPerTick": 1000,
|
||||
"CurrentEnergyAmount": 100
|
||||
}
|
||||
}
|
||||
},
|
||||
"CustomModel": "Items/EnergyStorages/EnergyStorage1.blockymodel",
|
||||
"CustomModelTexture": [
|
||||
{
|
||||
"Texture": "Items/EnergyStorages/texture.png",
|
||||
"Weight": 1
|
||||
}
|
||||
],
|
||||
"DrawType": "Model",
|
||||
"Material": "Solid",
|
||||
"Gathering": {
|
||||
"Breaking": {
|
||||
"GatherType": "Woods"
|
||||
}
|
||||
},
|
||||
"Interactions": {
|
||||
"Use": {
|
||||
"Interactions": [
|
||||
{
|
||||
"Type": "StorageUseInteraction"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"BlockSoundSetId": "Wood",
|
||||
"BlockParticleSetId": "Wood",
|
||||
"VariantRotation": "NESW",
|
||||
"ParticleColor": "#3e352a"
|
||||
},
|
||||
"Scale": 1,
|
||||
"ResourceTypes": [
|
||||
{
|
||||
"Id": "Fuel"
|
||||
},
|
||||
{
|
||||
"Id": "Charcoal"
|
||||
}
|
||||
],
|
||||
"Tags": {
|
||||
"Type": [
|
||||
"Furniture"
|
||||
],
|
||||
"Family": [
|
||||
"Human"
|
||||
]
|
||||
},
|
||||
"Set": "Wardrobe",
|
||||
"PlayerAnimationsId": "Block",
|
||||
"ItemSoundSetId": "ISS_Blocks_Wood"
|
||||
}
|
||||
89
src/main/resources/Server/Item/Items/SolarCell.json
Normal file
89
src/main/resources/Server/Item/Items/SolarCell.json
Normal file
@@ -0,0 +1,89 @@
|
||||
{
|
||||
"TranslationProperties": {
|
||||
"Name": "SolarCell Tier 1"
|
||||
},
|
||||
"Icon": "Icons/Items/EditorTools/Layers.png",
|
||||
"IconProperties": {
|
||||
"Scale": 0.36,
|
||||
"Rotation": [
|
||||
22.5,
|
||||
45,
|
||||
22.5
|
||||
],
|
||||
"Translation": [
|
||||
12.6,
|
||||
-24.6
|
||||
]
|
||||
},
|
||||
"BlockType": {
|
||||
"BlockEntity": {
|
||||
"Components": {
|
||||
"EnergyStorage": {
|
||||
"MaxCapacity": 1000,
|
||||
"ExtractEnergyPerTick": 100,
|
||||
"ReceiveEnergyPerTick": 1000,
|
||||
"CurrentEnergyAmount": 0
|
||||
},
|
||||
"EnergySource": {
|
||||
"EnergyCapacity": -1,
|
||||
"GeneratesPerTick": 200
|
||||
}
|
||||
}
|
||||
},
|
||||
"CustomModel": "Items/SolarPanels/SolarCell1.blockymodel",
|
||||
"CustomModelTexture": [
|
||||
{
|
||||
"Texture": "Items/SolarPanels/SolarCell1.png",
|
||||
"Weight": 1
|
||||
}
|
||||
],
|
||||
"DrawType": "Model",
|
||||
"Material": "Solid",
|
||||
"Gathering": {
|
||||
"Breaking": {
|
||||
"GatherType": "Woods"
|
||||
}
|
||||
},
|
||||
"Support": {
|
||||
"Down": [
|
||||
{
|
||||
"FaceType": "Full"
|
||||
}
|
||||
]
|
||||
},
|
||||
"State": {},
|
||||
"BlockSoundSetId": "Wood",
|
||||
"BlockParticleSetId": "Wood",
|
||||
"VariantRotation": "NESW",
|
||||
"ParticleColor": "#3e352a",
|
||||
"Interactions": {
|
||||
"Use": {
|
||||
"Interactions": [
|
||||
{
|
||||
"Type": "StorageUseInteraction"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"Scale": 1,
|
||||
"ResourceTypes": [
|
||||
{
|
||||
"Id": "Fuel"
|
||||
},
|
||||
{
|
||||
"Id": "Charcoal"
|
||||
}
|
||||
],
|
||||
"Tags": {
|
||||
"Type": [
|
||||
"Furniture"
|
||||
],
|
||||
"Family": [
|
||||
"Human"
|
||||
]
|
||||
},
|
||||
"Set": "Wardrobe",
|
||||
"PlayerAnimationsId": "Block",
|
||||
"ItemSoundSetId": "ISS_Blocks_Wood"
|
||||
}
|
||||
@@ -1,22 +1,26 @@
|
||||
{
|
||||
"Group": "Example",
|
||||
"Name": "ExamplePlugin",
|
||||
"Version": "0.0.2",
|
||||
"Description": "An example plugin for HyTale!",
|
||||
"Group": "KaiFlo",
|
||||
"Name": "SolarCell",
|
||||
"Version": "0.0.1",
|
||||
"Description": "A Solar Cell Mod",
|
||||
"Authors": [
|
||||
{
|
||||
"Name": "It's you!"
|
||||
"Name": "Florian Greindl"
|
||||
},
|
||||
{
|
||||
"Name": "Tim Kainz"
|
||||
}
|
||||
],
|
||||
"Website": "example.org",
|
||||
"Website": "https://github.com/KainTim/hytale-solar-cell-plugin",
|
||||
"ServerVersion": "*",
|
||||
"Dependencies": {
|
||||
|
||||
"Hytale:EntityModule": "*",
|
||||
"Hytale:BlockModule": "*"
|
||||
},
|
||||
"OptionalDependencies": {
|
||||
|
||||
},
|
||||
"DisabledByDefault": false,
|
||||
"Main": "org.example.plugin.ExamplePlugin",
|
||||
"Main": "org.KaiFlo.SolarCell.SolarCellPlugin",
|
||||
"IncludesAssetPack": true
|
||||
}
|
||||
Reference in New Issue
Block a user