mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2026-04-11 10:16:15 +00:00
reconfigure implementation projects
This commit is contained in:
@@ -0,0 +1,258 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra;
|
||||
|
||||
import com.dfsek.tectonic.loading.TypeRegistry;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.yaml.snakeyaml.Yaml;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import com.dfsek.terra.addon.BootstrapAddonLoader;
|
||||
import com.dfsek.terra.addon.DependencySorter;
|
||||
import com.dfsek.terra.api.Platform;
|
||||
import com.dfsek.terra.api.addon.BaseAddon;
|
||||
import com.dfsek.terra.api.command.CommandManager;
|
||||
import com.dfsek.terra.api.command.exception.MalformedCommandException;
|
||||
import com.dfsek.terra.api.config.ConfigPack;
|
||||
import com.dfsek.terra.api.config.PluginConfig;
|
||||
import com.dfsek.terra.api.event.EventManager;
|
||||
import com.dfsek.terra.api.event.events.platform.PlatformInitializationEvent;
|
||||
import com.dfsek.terra.api.event.functional.FunctionalEventHandler;
|
||||
import com.dfsek.terra.api.inject.Injector;
|
||||
import com.dfsek.terra.api.inject.impl.InjectorImpl;
|
||||
import com.dfsek.terra.api.lang.Language;
|
||||
import com.dfsek.terra.api.profiler.Profiler;
|
||||
import com.dfsek.terra.api.registry.CheckedRegistry;
|
||||
import com.dfsek.terra.api.registry.Registry;
|
||||
import com.dfsek.terra.api.util.mutable.MutableBoolean;
|
||||
import com.dfsek.terra.commands.CommandUtil;
|
||||
import com.dfsek.terra.commands.TerraCommandManager;
|
||||
import com.dfsek.terra.config.GenericLoaders;
|
||||
import com.dfsek.terra.config.PluginConfigImpl;
|
||||
import com.dfsek.terra.config.lang.LangUtil;
|
||||
import com.dfsek.terra.event.EventManagerImpl;
|
||||
import com.dfsek.terra.profiler.ProfilerImpl;
|
||||
import com.dfsek.terra.registry.CheckedRegistryImpl;
|
||||
import com.dfsek.terra.registry.LockedRegistryImpl;
|
||||
import com.dfsek.terra.registry.OpenRegistryImpl;
|
||||
import com.dfsek.terra.registry.master.ConfigRegistry;
|
||||
|
||||
|
||||
/**
|
||||
* Skeleton implementation of {@link Platform}
|
||||
* <p>
|
||||
* Implementations must invoke {@link #load()} in their constructors.
|
||||
*/
|
||||
public abstract class AbstractPlatform implements Platform {
|
||||
private static final Logger logger = LoggerFactory.getLogger(AbstractPlatform.class);
|
||||
|
||||
private static final MutableBoolean LOADED = new MutableBoolean(false);
|
||||
private final EventManager eventManager = new EventManagerImpl();
|
||||
private final ConfigRegistry configRegistry = new ConfigRegistry();
|
||||
|
||||
private final CheckedRegistry<ConfigPack> checkedConfigRegistry = new CheckedRegistryImpl<>(configRegistry);
|
||||
|
||||
private final Profiler profiler = new ProfilerImpl();
|
||||
|
||||
private final GenericLoaders loaders = new GenericLoaders(this);
|
||||
|
||||
private final PluginConfigImpl config = new PluginConfigImpl();
|
||||
|
||||
private final CommandManager manager = new TerraCommandManager(this);
|
||||
|
||||
private final CheckedRegistry<BaseAddon> addonRegistry = new CheckedRegistryImpl<>(new OpenRegistryImpl<>());
|
||||
|
||||
private final Registry<BaseAddon> lockedAddonRegistry = new LockedRegistryImpl<>(addonRegistry);
|
||||
|
||||
public ConfigRegistry getRawConfigRegistry() {
|
||||
return configRegistry;
|
||||
}
|
||||
|
||||
public CommandManager getManager() {
|
||||
return manager;
|
||||
}
|
||||
|
||||
protected Optional<BaseAddon> platformAddon() {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
protected void load() {
|
||||
if(LOADED.get()) {
|
||||
throw new IllegalStateException(
|
||||
"Someone tried to initialize Terra, but Terra has already initialized. This is most likely due to a broken platform " +
|
||||
"implementation, or a misbehaving mod.");
|
||||
}
|
||||
LOADED.set(true);
|
||||
|
||||
logger.info("Initializing Terra...");
|
||||
|
||||
try(InputStream stream = getClass().getResourceAsStream("/config.yml")) {
|
||||
File configFile = new File(getDataFolder(), "config.yml");
|
||||
if(!configFile.exists()) {
|
||||
FileUtils.copyInputStreamToFile(stream, configFile);
|
||||
}
|
||||
} catch(IOException e) {
|
||||
logger.error("Error loading config.yml resource from jar", e);
|
||||
}
|
||||
|
||||
|
||||
config.load(this); // load config.yml
|
||||
|
||||
LangUtil.load(config.getLanguage(), this); // load language
|
||||
|
||||
if(config.dumpDefaultConfig()) {
|
||||
try(InputStream resourcesConfig = getClass().getResourceAsStream("/resources.yml")) {
|
||||
if(resourcesConfig == null) {
|
||||
logger.info("No resources config found. Skipping resource dumping.");
|
||||
return;
|
||||
}
|
||||
String resourceYaml = IOUtils.toString(resourcesConfig, StandardCharsets.UTF_8);
|
||||
Map<String, List<String>> resources = new Yaml().load(resourceYaml);
|
||||
resources.forEach((dir, entries) -> entries.forEach(entry -> {
|
||||
String resourcePath = String.format("%s/%s", dir, entry);
|
||||
File resource = new File(getDataFolder(), resourcePath);
|
||||
if(resource.exists())
|
||||
return; // dont overwrite
|
||||
logger.info("Dumping resource {}...", resource.getAbsolutePath());
|
||||
try {
|
||||
resource.getParentFile().mkdirs();
|
||||
resource.createNewFile();
|
||||
} catch(IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
try(InputStream is = getClass().getResourceAsStream("/" + resourcePath);
|
||||
OutputStream os = new FileOutputStream(resource)) {
|
||||
IOUtils.copy(is, os);
|
||||
} catch(IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}));
|
||||
} catch(IOException e) {
|
||||
logger.error("Error while dumping resources...", e);
|
||||
}
|
||||
} else {
|
||||
logger.info("Skipping resource dumping.");
|
||||
}
|
||||
|
||||
if(config.isDebugProfiler()) { // if debug.profiler is enabled, start profiling
|
||||
profiler.start();
|
||||
}
|
||||
|
||||
List<BaseAddon> addonList = new ArrayList<>();
|
||||
|
||||
InternalAddon internalAddon = new InternalAddon();
|
||||
|
||||
addonList.add(internalAddon);
|
||||
|
||||
platformAddon().ifPresent(addonList::add);
|
||||
|
||||
BootstrapAddonLoader bootstrapAddonLoader = new BootstrapAddonLoader(this);
|
||||
|
||||
Path addonsFolder = getDataFolder().toPath().resolve("addons");
|
||||
|
||||
Injector<Platform> platformInjector = new InjectorImpl<>(this);
|
||||
platformInjector.addExplicitTarget(Platform.class);
|
||||
|
||||
bootstrapAddonLoader.loadAddons(addonsFolder, getClass().getClassLoader())
|
||||
.forEach(bootstrap -> {
|
||||
platformInjector.inject(bootstrap);
|
||||
bootstrap.loadAddons(addonsFolder, getClass().getClassLoader())
|
||||
.forEach(addonList::add);
|
||||
});
|
||||
|
||||
DependencySorter sorter = new DependencySorter();
|
||||
addonList.forEach(sorter::add);
|
||||
sorter.sort().forEach(addon -> {
|
||||
platformInjector.inject(addon);
|
||||
addon.initialize();
|
||||
addonRegistry.register(addon.getID(), addon);
|
||||
});
|
||||
|
||||
eventManager
|
||||
.getHandler(FunctionalEventHandler.class)
|
||||
.register(internalAddon, PlatformInitializationEvent.class)
|
||||
.then(event -> {
|
||||
logger.info("Loading config packs...");
|
||||
getRawConfigRegistry().loadAll(this);
|
||||
logger.info("Loaded packs.");
|
||||
})
|
||||
.global();
|
||||
|
||||
|
||||
logger.info("Loaded addons.");
|
||||
|
||||
try {
|
||||
CommandUtil.registerAll(manager);
|
||||
} catch(MalformedCommandException e) {
|
||||
logger.error("Error registering commands", e);
|
||||
}
|
||||
|
||||
|
||||
logger.info("Finished initialization.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(TypeRegistry registry) {
|
||||
loaders.register(registry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PluginConfig getTerraConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Language getLanguage() {
|
||||
return LangUtil.getLanguage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CheckedRegistry<ConfigPack> getConfigRegistry() {
|
||||
return checkedConfigRegistry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Registry<BaseAddon> getAddons() {
|
||||
return lockedAddonRegistry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EventManager getEventManager() {
|
||||
return eventManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Profiler getProfiler() {
|
||||
return profiler;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra;
|
||||
|
||||
import ca.solostudios.strata.Versions;
|
||||
import ca.solostudios.strata.version.Version;
|
||||
|
||||
import com.dfsek.terra.api.addon.BaseAddon;
|
||||
|
||||
|
||||
public class InternalAddon implements BaseAddon {
|
||||
private static final Version VERSION = Versions.getVersion(1, 0, 0);
|
||||
@Override
|
||||
public String getID() {
|
||||
return "terra";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Version getVersion() {
|
||||
return VERSION;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.addon;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.dfsek.terra.addon.dependency.CircularDependencyException;
|
||||
import com.dfsek.terra.addon.dependency.DependencyException;
|
||||
import com.dfsek.terra.addon.dependency.DependencyVersionException;
|
||||
import com.dfsek.terra.api.addon.BaseAddon;
|
||||
|
||||
|
||||
public class DependencySorter {
|
||||
private final Map<String, BaseAddon> addons = new HashMap<>();
|
||||
private final Map<String, Boolean> visited = new HashMap<>();
|
||||
|
||||
private final List<BaseAddon> addonList = new ArrayList<>();
|
||||
|
||||
public void add(BaseAddon addon) {
|
||||
addons.put(addon.getID(), addon);
|
||||
visited.put(addon.getID(), false);
|
||||
addonList.add(addon);
|
||||
}
|
||||
|
||||
private void sortDependencies(BaseAddon addon, List<BaseAddon> sort) {
|
||||
addon.getDependencies().forEach((id, range) -> {
|
||||
if(!addons.containsKey(id)) {
|
||||
throw new DependencyException("Addon " + addon.getID() + " specifies dependency on " + id + ", versions " + range +
|
||||
", but no such addon is installed.");
|
||||
}
|
||||
|
||||
BaseAddon dependency = addons.get(id);
|
||||
|
||||
if(!range.isSatisfiedBy(dependency.getVersion())) {
|
||||
throw new DependencyVersionException("Addon " + addon.getID() + " specifies dependency on " + id + ", versions " + range +
|
||||
", but non-matching version " + dependency.getVersion() + " is installed..");
|
||||
}
|
||||
|
||||
if(!visited.get(dependency.getID())) { // if we've not visited it yet
|
||||
visited.put(dependency.getID(), true); // we've visited it now
|
||||
|
||||
sortDependencies(dependency, sort);
|
||||
|
||||
sort.add(dependency); // add it to the list.
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void checkDependencies(BaseAddon base, BaseAddon current) {
|
||||
current.getDependencies().forEach((id, range) -> {
|
||||
BaseAddon dependency = addons.get(id);
|
||||
if(dependency.getID().equals(base.getID())) {
|
||||
throw new CircularDependencyException(
|
||||
"Addon " + base.getID() + " has circular dependency beginning with " + dependency.getID());
|
||||
}
|
||||
checkDependencies(base, dependency);
|
||||
});
|
||||
}
|
||||
public List<BaseAddon> sort() {
|
||||
List<BaseAddon> sorted = new ArrayList<>();
|
||||
|
||||
for(int i = addonList.size() - 1; i >= 0; i--) {
|
||||
BaseAddon addon = addonList.get(i);
|
||||
|
||||
checkDependencies(addon, addon);
|
||||
|
||||
addonList.remove(i);
|
||||
|
||||
if(!visited.get(addon.getID())) {
|
||||
sortDependencies(addon, sorted);
|
||||
}
|
||||
|
||||
if(!visited.get(addon.getID())) {
|
||||
sorted.add(addon);
|
||||
visited.put(addon.getID(), true);
|
||||
}
|
||||
}
|
||||
|
||||
return sorted;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.addon.dependency;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
|
||||
public class CircularDependencyException extends DependencyException{
|
||||
@Serial
|
||||
private static final long serialVersionUID = -6098780459461482651L;
|
||||
|
||||
public CircularDependencyException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public CircularDependencyException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.addon.dependency;
|
||||
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
|
||||
public class DependencyException extends RuntimeException {
|
||||
@Serial
|
||||
private static final long serialVersionUID = 4864727433635612759L;
|
||||
|
||||
public DependencyException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public DependencyException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.addon.dependency;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
|
||||
public class DependencyVersionException extends DependencyException{
|
||||
@Serial
|
||||
private static final long serialVersionUID = 3564288935278878135L;
|
||||
|
||||
public DependencyVersionException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public DependencyVersionException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.commands;
|
||||
|
||||
import com.dfsek.terra.api.Platform;
|
||||
import com.dfsek.terra.api.command.CommandTemplate;
|
||||
import com.dfsek.terra.api.command.annotation.Command;
|
||||
import com.dfsek.terra.api.entity.CommandSender;
|
||||
import com.dfsek.terra.api.inject.annotations.Inject;
|
||||
|
||||
|
||||
@Command(
|
||||
usage = "/terra addons"
|
||||
)
|
||||
public class AddonsCommand implements CommandTemplate {
|
||||
@Inject
|
||||
private Platform platform;
|
||||
|
||||
@Override
|
||||
public void execute(CommandSender sender) {
|
||||
sender.sendMessage("Installed Addons:");
|
||||
platform.getAddons().forEach(addon -> {
|
||||
sender.sendMessage(" - " + addon.getID());
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.commands;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.dfsek.terra.api.command.CommandManager;
|
||||
import com.dfsek.terra.api.command.exception.MalformedCommandException;
|
||||
import com.dfsek.terra.commands.profiler.ProfileCommand;
|
||||
|
||||
|
||||
public final class CommandUtil {
|
||||
private static final Logger logger = LoggerFactory.getLogger(CommandUtil.class);
|
||||
public static void registerAll(CommandManager manager) throws MalformedCommandException {
|
||||
logger.info("Registering Terra commands...");
|
||||
manager.register("profile", ProfileCommand.class);
|
||||
manager.register("reload", ReloadCommand.class);
|
||||
manager.register("addons", AddonsCommand.class);
|
||||
manager.register("version", VersionCommand.class);
|
||||
manager.register("getblock", GetBlockCommand.class);
|
||||
manager.register("packs", PacksCommand.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.commands;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.dfsek.terra.api.entity.CommandSender;
|
||||
|
||||
|
||||
public final class ExecutionState {
|
||||
private final Set<String> switches = new HashSet<>();
|
||||
private final Map<String, String> args = new HashMap<>();
|
||||
private final CommandSender sender;
|
||||
|
||||
public ExecutionState(CommandSender sender) {
|
||||
this.sender = sender;
|
||||
}
|
||||
|
||||
public void addSwitch(String flag) {
|
||||
switches.add(flag);
|
||||
}
|
||||
|
||||
public void addArgument(String arg, String value) {
|
||||
args.put(arg, value);
|
||||
}
|
||||
|
||||
public String getArgument(String argument) {
|
||||
return args.get(argument);
|
||||
}
|
||||
|
||||
public boolean hasSwitch(String flag) {
|
||||
return switches.contains(flag);
|
||||
}
|
||||
|
||||
public CommandSender getSender() {
|
||||
return sender;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.commands;
|
||||
|
||||
import com.dfsek.terra.api.Platform;
|
||||
import com.dfsek.terra.api.command.CommandTemplate;
|
||||
import com.dfsek.terra.api.command.annotation.Command;
|
||||
import com.dfsek.terra.api.command.annotation.type.DebugCommand;
|
||||
import com.dfsek.terra.api.command.annotation.type.PlayerCommand;
|
||||
import com.dfsek.terra.api.command.annotation.type.WorldCommand;
|
||||
import com.dfsek.terra.api.entity.CommandSender;
|
||||
import com.dfsek.terra.api.entity.Player;
|
||||
import com.dfsek.terra.api.inject.annotations.Inject;
|
||||
|
||||
|
||||
@WorldCommand
|
||||
@DebugCommand
|
||||
@PlayerCommand
|
||||
@Command(
|
||||
usage = "/terra getblock"
|
||||
)
|
||||
public class GetBlockCommand implements CommandTemplate {
|
||||
@Inject
|
||||
private Platform platform;
|
||||
|
||||
@Override
|
||||
public void execute(CommandSender sender) {
|
||||
Player player = (Player) sender;
|
||||
sender.sendMessage("Block: " + player.world().getGenerator().getBlock(player.world(), player.position()).getAsString());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.commands;
|
||||
|
||||
import com.dfsek.terra.api.Platform;
|
||||
import com.dfsek.terra.api.command.CommandTemplate;
|
||||
import com.dfsek.terra.api.command.annotation.Command;
|
||||
import com.dfsek.terra.api.config.ConfigPack;
|
||||
import com.dfsek.terra.api.entity.CommandSender;
|
||||
import com.dfsek.terra.api.inject.annotations.Inject;
|
||||
import com.dfsek.terra.api.registry.CheckedRegistry;
|
||||
import com.dfsek.terra.config.lang.LangUtil;
|
||||
|
||||
|
||||
@Command(
|
||||
usage = "/terra packs"
|
||||
)
|
||||
public class PacksCommand implements CommandTemplate {
|
||||
@Inject
|
||||
private Platform platform;
|
||||
|
||||
@Override
|
||||
public void execute(CommandSender sender) {
|
||||
CheckedRegistry<ConfigPack> registry = platform.getConfigRegistry();
|
||||
|
||||
if(registry.entries().isEmpty()) {
|
||||
LangUtil.send("command.packs.none", sender);
|
||||
return;
|
||||
}
|
||||
|
||||
LangUtil.send("command.packs.main", sender);
|
||||
registry.entries().forEach(
|
||||
entry -> LangUtil.send("command.packs.pack", sender, entry.getID(), entry.getAuthor(), entry.getVersion()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.commands;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.dfsek.terra.api.Platform;
|
||||
import com.dfsek.terra.api.command.CommandTemplate;
|
||||
import com.dfsek.terra.api.command.annotation.Command;
|
||||
import com.dfsek.terra.api.entity.CommandSender;
|
||||
import com.dfsek.terra.api.inject.annotations.Inject;
|
||||
import com.dfsek.terra.config.lang.LangUtil;
|
||||
|
||||
|
||||
@Command(
|
||||
usage = "/terra reload"
|
||||
)
|
||||
public class ReloadCommand implements CommandTemplate {
|
||||
private static final Logger logger = LoggerFactory.getLogger(ReloadCommand.class);
|
||||
|
||||
@Inject
|
||||
private Platform platform;
|
||||
|
||||
@Override
|
||||
public void execute(CommandSender sender) {
|
||||
logger.info("Reloading Terra...");
|
||||
if(platform.reload()) {
|
||||
logger.info("Terra reloaded successfully.");
|
||||
LangUtil.send("command.reload", sender);
|
||||
} else {
|
||||
logger.warn("Terra failed to reload.");
|
||||
LangUtil.send("command.reload-error", sender);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,311 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.commands;
|
||||
|
||||
import net.jafama.FastMath;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.dfsek.terra.api.Platform;
|
||||
import com.dfsek.terra.api.command.CommandManager;
|
||||
import com.dfsek.terra.api.command.CommandTemplate;
|
||||
import com.dfsek.terra.api.command.annotation.Argument;
|
||||
import com.dfsek.terra.api.command.annotation.Command;
|
||||
import com.dfsek.terra.api.command.annotation.Subcommand;
|
||||
import com.dfsek.terra.api.command.annotation.Switch;
|
||||
import com.dfsek.terra.api.command.annotation.inject.ArgumentTarget;
|
||||
import com.dfsek.terra.api.command.annotation.inject.SwitchTarget;
|
||||
import com.dfsek.terra.api.command.annotation.type.DebugCommand;
|
||||
import com.dfsek.terra.api.command.annotation.type.PlayerCommand;
|
||||
import com.dfsek.terra.api.command.annotation.type.WorldCommand;
|
||||
import com.dfsek.terra.api.command.arg.ArgumentParser;
|
||||
import com.dfsek.terra.api.command.exception.CommandException;
|
||||
import com.dfsek.terra.api.command.exception.ExecutionException;
|
||||
import com.dfsek.terra.api.command.exception.InvalidArgumentsException;
|
||||
import com.dfsek.terra.api.command.exception.MalformedCommandException;
|
||||
import com.dfsek.terra.api.command.exception.SwitchFormatException;
|
||||
import com.dfsek.terra.api.command.tab.TabCompleter;
|
||||
import com.dfsek.terra.api.entity.CommandSender;
|
||||
import com.dfsek.terra.api.entity.Player;
|
||||
import com.dfsek.terra.api.inject.exception.InjectionException;
|
||||
import com.dfsek.terra.api.inject.impl.InjectorImpl;
|
||||
import com.dfsek.terra.api.util.reflection.ReflectionUtil;
|
||||
|
||||
|
||||
public class TerraCommandManager implements CommandManager {
|
||||
private final Map<String, CommandHolder> commands = new HashMap<>();
|
||||
private final InjectorImpl<Platform> pluginInjector;
|
||||
private final Platform platform;
|
||||
|
||||
public TerraCommandManager(Platform platform) {
|
||||
this.platform = platform;
|
||||
this.pluginInjector = new InjectorImpl<>(platform);
|
||||
pluginInjector.addExplicitTarget(Platform.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(String commandName, CommandSender sender, List<String> argsIn) throws CommandException {
|
||||
if(!commands.containsKey(commandName)) throw new InvalidArgumentsException("No such command \"" + commandName + "\"");
|
||||
execute(commands.get(commandName), sender, new ArrayList<>(argsIn));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(String name, Class<? extends CommandTemplate> clazz) throws MalformedCommandException {
|
||||
commands.put(name, new CommandHolder(clazz));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> tabComplete(String command, CommandSender sender, List<String> args) throws CommandException {
|
||||
if(args.isEmpty()) return new ArrayList<>(commands.keySet()).stream().sorted(String::compareTo).collect(Collectors.toList());
|
||||
if(!commands.containsKey(command)) return Collections.emptyList();
|
||||
return tabComplete(commands.get(command), sender, new ArrayList<>(args)).stream().filter(
|
||||
s -> s.toLowerCase().startsWith(args.get(args.size() - 1).toLowerCase())).sorted(String::compareTo).collect(
|
||||
Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxArgumentDepth() {
|
||||
int max = 0;
|
||||
for(CommandHolder value : commands.values()) {
|
||||
max = FastMath.max(getMaxArgumentDepth(value), max);
|
||||
}
|
||||
return max;
|
||||
}
|
||||
|
||||
private void execute(CommandHolder commandHolder, CommandSender sender, List<String> args) throws CommandException {
|
||||
Class<? extends CommandTemplate> commandClass = commandHolder.clazz;
|
||||
|
||||
if(commandClass.isAnnotationPresent(DebugCommand.class) && !platform.getTerraConfig().isDebugCommands()) {
|
||||
sender.sendMessage("Command must be executed with debug commands enabled.");
|
||||
return;
|
||||
}
|
||||
|
||||
if(commandClass.isAnnotationPresent(PlayerCommand.class) && !(sender instanceof Player)) {
|
||||
sender.sendMessage("Command must be executed by player.");
|
||||
return;
|
||||
}
|
||||
|
||||
if(commandClass.isAnnotationPresent(WorldCommand.class) && (!(sender instanceof Player))) {
|
||||
sender.sendMessage("Command must be executed in a Terra world.");
|
||||
return;
|
||||
}
|
||||
|
||||
List<String> ogArgs = new ArrayList<>(args);
|
||||
|
||||
ExecutionState state = new ExecutionState(sender);
|
||||
|
||||
if(!commandClass.isAnnotationPresent(Command.class)) {
|
||||
invoke(commandClass, state, commandHolder);
|
||||
return;
|
||||
}
|
||||
|
||||
Command command = commandClass.getAnnotation(Command.class);
|
||||
|
||||
if(command.arguments().length == 0 && command.subcommands().length == 0) {
|
||||
if(args.isEmpty()) {
|
||||
invoke(commandClass, state, commandHolder);
|
||||
return;
|
||||
} else throw new InvalidArgumentsException("Expected 0 arguments, found " + args.size());
|
||||
}
|
||||
|
||||
if(!args.isEmpty() && commandHolder.subcommands.containsKey(args.get(0))) {
|
||||
String c = args.get(0);
|
||||
args.remove(0);
|
||||
execute(commandHolder.subcommands.get(c), sender, args);
|
||||
return;
|
||||
}
|
||||
|
||||
boolean req = true;
|
||||
for(Argument argument : command.arguments()) {
|
||||
if(!req && argument.required()) {
|
||||
throw new MalformedCommandException(
|
||||
"Required arguments must come first! Arguments: " + Arrays.toString(command.arguments()));
|
||||
}
|
||||
req = argument.required();
|
||||
|
||||
if(args.isEmpty()) {
|
||||
if(req) throw new InvalidArgumentsException("Invalid arguments: " + ogArgs + ", usage: " + command.usage());
|
||||
break;
|
||||
}
|
||||
|
||||
String arg = args.get(0);
|
||||
|
||||
if(arg.startsWith("-")) { // switches have started.
|
||||
if(req) throw new InvalidArgumentsException("Switches must come after arguments.");
|
||||
break;
|
||||
}
|
||||
|
||||
state.addArgument(argument.value(), args.remove(0));
|
||||
}
|
||||
|
||||
while(!args.isEmpty()) {
|
||||
String aSwitch = args.remove(0);
|
||||
if(!aSwitch.startsWith("-")) throw new SwitchFormatException("Invalid switch \"" + aSwitch + "\"");
|
||||
|
||||
String val = aSwitch.substring(1); // remove dash
|
||||
|
||||
if(!commandHolder.switches.containsKey(val)) throw new SwitchFormatException("No such switch \"" + aSwitch + "\"");
|
||||
|
||||
state.addSwitch(commandHolder.switches.get(val));
|
||||
}
|
||||
|
||||
invoke(commandClass, state, commandHolder);
|
||||
}
|
||||
|
||||
private void invoke(Class<? extends CommandTemplate> clazz, ExecutionState state, CommandHolder holder) throws CommandException {
|
||||
try {
|
||||
CommandTemplate template = clazz.getConstructor().newInstance();
|
||||
|
||||
pluginInjector.inject(template);
|
||||
|
||||
for(Field field : ReflectionUtil.getFields(clazz)) {
|
||||
if(field.isAnnotationPresent(ArgumentTarget.class)) {
|
||||
ArgumentTarget argumentTarget = field.getAnnotation(ArgumentTarget.class);
|
||||
if(!holder.argumentMap.containsKey(argumentTarget.value())) {
|
||||
throw new MalformedCommandException(
|
||||
"Argument Target specifies nonexistent argument \"" + argumentTarget.value() + "\"");
|
||||
}
|
||||
|
||||
String argument = argumentTarget.value();
|
||||
|
||||
ArgumentParser<?> argumentParser = holder.argumentMap.get(argumentTarget.value())
|
||||
.argumentParser()
|
||||
.getConstructor()
|
||||
.newInstance();
|
||||
|
||||
pluginInjector.inject(argumentParser);
|
||||
|
||||
field.setAccessible(true);
|
||||
String value = state.getArgument(argument);
|
||||
|
||||
if(value == null) value = holder.argumentMap.get(argumentTarget.value()).defaultValue();
|
||||
|
||||
field.set(template, argumentParser.parse(state.getSender(), value));
|
||||
}
|
||||
if(field.isAnnotationPresent(SwitchTarget.class)) {
|
||||
SwitchTarget switchTarget = field.getAnnotation(SwitchTarget.class);
|
||||
if(!holder.switches.containsValue(switchTarget.value())) {
|
||||
throw new MalformedCommandException("Switch Target specifies nonexistent switch \"" + switchTarget.value() + "\"");
|
||||
}
|
||||
|
||||
if(!(field.getType() == boolean.class)) {
|
||||
throw new MalformedCommandException("Switch Target must be of type boolean.");
|
||||
}
|
||||
|
||||
field.setAccessible(true);
|
||||
field.setBoolean(template, state.hasSwitch(switchTarget.value()));
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
template.execute(state.getSender());
|
||||
} catch(Throwable e) {
|
||||
throw new ExecutionException("Failed to execute command: " + e.getMessage(), e);
|
||||
}
|
||||
} catch(InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException | InjectionException e) {
|
||||
throw new MalformedCommandException("Unable to reflectively instantiate command: ", e);
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> tabComplete(CommandHolder holder, CommandSender sender, List<String> args) throws CommandException {
|
||||
if(args.isEmpty()) return Collections.emptyList();
|
||||
List<String> completions = new ArrayList<>();
|
||||
|
||||
if(args.size() == 1) {
|
||||
completions.addAll(holder.subcommands.keySet());
|
||||
}
|
||||
|
||||
if(holder.subcommands.containsKey(args.get(0))) {
|
||||
List<String> newArgs = new ArrayList<>(args);
|
||||
newArgs.remove(0);
|
||||
completions.addAll(tabComplete(holder.subcommands.get(args.get(0)), sender, newArgs));
|
||||
}
|
||||
try {
|
||||
if(args.size() <= holder.arguments.size()) {
|
||||
TabCompleter completer = holder.arguments.get(args.size() - 1).tabCompleter().getConstructor().newInstance();
|
||||
pluginInjector.inject(completer);
|
||||
completions.addAll(completer.complete(sender));
|
||||
}
|
||||
} catch(InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException | InjectionException e) {
|
||||
throw new MalformedCommandException("Unable to reflectively instantiate tab-completer: ", e);
|
||||
}
|
||||
return completions;
|
||||
}
|
||||
|
||||
private int getMaxArgumentDepth(CommandHolder holder) {
|
||||
int max = 0;
|
||||
max = FastMath.max(holder.arguments.size() + holder.switchList.size(), max);
|
||||
for(CommandHolder value : holder.subcommands.values()) {
|
||||
max = FastMath.max(max, getMaxArgumentDepth(value) + 1);
|
||||
}
|
||||
return max;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Pre-processes command metadata.
|
||||
*/
|
||||
private static final class CommandHolder {
|
||||
private final Class<? extends CommandTemplate> clazz;
|
||||
private final Map<String, CommandHolder> subcommands = new HashMap<>();
|
||||
private final Map<String, String> switches = new HashMap<>();
|
||||
private final List<Argument> arguments;
|
||||
private final List<Switch> switchList;
|
||||
private final Map<String, Argument> argumentMap = new HashMap<>();
|
||||
|
||||
private CommandHolder(Class<? extends CommandTemplate> clazz) throws MalformedCommandException {
|
||||
this.clazz = clazz;
|
||||
if(clazz.isAnnotationPresent(Command.class)) {
|
||||
Command command = clazz.getAnnotation(Command.class);
|
||||
for(Subcommand subcommand : command.subcommands()) {
|
||||
if(subcommands.containsKey(subcommand.value()))
|
||||
throw new MalformedCommandException("Duplicate subcommand: " + subcommand);
|
||||
CommandHolder holder = new CommandHolder(subcommand.clazz());
|
||||
subcommands.put(subcommand.value(), holder);
|
||||
for(String alias : subcommand.aliases()) {
|
||||
subcommands.put(alias, holder);
|
||||
}
|
||||
}
|
||||
for(Switch aSwitch : command.switches()) {
|
||||
if(switches.containsKey(aSwitch.value())) throw new MalformedCommandException("Duplicate switch: " + aSwitch);
|
||||
switches.put(aSwitch.value(), aSwitch.value());
|
||||
for(String alias : aSwitch.aliases()) {
|
||||
switches.put(alias, aSwitch.value());
|
||||
}
|
||||
}
|
||||
for(Argument argument : command.arguments()) {
|
||||
if(argumentMap.containsKey(argument.value())) throw new MalformedCommandException("Duplicate argument: " + argument);
|
||||
argumentMap.put(argument.value(), argument);
|
||||
}
|
||||
arguments = Arrays.asList(command.arguments());
|
||||
switchList = Arrays.asList(command.switches());
|
||||
} else {
|
||||
arguments = Collections.emptyList();
|
||||
switchList = Collections.emptyList();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.commands;
|
||||
|
||||
import com.dfsek.terra.api.Platform;
|
||||
import com.dfsek.terra.api.command.CommandTemplate;
|
||||
import com.dfsek.terra.api.command.annotation.Command;
|
||||
import com.dfsek.terra.api.entity.CommandSender;
|
||||
import com.dfsek.terra.api.inject.annotations.Inject;
|
||||
import com.dfsek.terra.config.lang.LangUtil;
|
||||
|
||||
|
||||
@Command(
|
||||
usage = "/terra version"
|
||||
)
|
||||
public class VersionCommand implements CommandTemplate {
|
||||
@Inject
|
||||
private Platform platform;
|
||||
|
||||
@Override
|
||||
public void execute(CommandSender sender) {
|
||||
String terraVersion = platform.getVersion();
|
||||
LangUtil.send("command.version", sender, terraVersion, platform.platformName());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.commands.profiler;
|
||||
|
||||
import com.dfsek.terra.api.command.CommandTemplate;
|
||||
import com.dfsek.terra.api.command.annotation.Command;
|
||||
import com.dfsek.terra.api.command.annotation.Subcommand;
|
||||
import com.dfsek.terra.api.command.annotation.type.DebugCommand;
|
||||
import com.dfsek.terra.api.command.annotation.type.PlayerCommand;
|
||||
import com.dfsek.terra.api.command.annotation.type.WorldCommand;
|
||||
import com.dfsek.terra.api.entity.CommandSender;
|
||||
import com.dfsek.terra.config.lang.LangUtil;
|
||||
|
||||
|
||||
@Command(
|
||||
subcommands = {
|
||||
@Subcommand(value = "query", aliases = "q", clazz = ProfileQueryCommand.class),
|
||||
@Subcommand(value = "start", aliases = "s", clazz = ProfileStartCommand.class),
|
||||
@Subcommand(value = "stop", aliases = "st", clazz = ProfileStopCommand.class),
|
||||
@Subcommand(value = "reset", aliases = "r", clazz = ProfileResetCommand.class)
|
||||
},
|
||||
usage = "Commands to enable/disable/query/reset the profiler."
|
||||
)
|
||||
@WorldCommand
|
||||
@PlayerCommand
|
||||
@DebugCommand
|
||||
public class ProfileCommand implements CommandTemplate {
|
||||
@Override
|
||||
public void execute(CommandSender sender) {
|
||||
LangUtil.send("command.profile.main-menu", sender);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.commands.profiler;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.dfsek.terra.api.Platform;
|
||||
import com.dfsek.terra.api.command.CommandTemplate;
|
||||
import com.dfsek.terra.api.command.annotation.Command;
|
||||
import com.dfsek.terra.api.command.annotation.type.DebugCommand;
|
||||
import com.dfsek.terra.api.entity.CommandSender;
|
||||
import com.dfsek.terra.api.inject.annotations.Inject;
|
||||
|
||||
|
||||
@Command
|
||||
@DebugCommand
|
||||
public class ProfileQueryCommand implements CommandTemplate {
|
||||
private static final Logger logger = LoggerFactory.getLogger(ProfileQueryCommand.class);
|
||||
|
||||
@Inject
|
||||
private Platform platform;
|
||||
|
||||
@Override
|
||||
public void execute(CommandSender sender) {
|
||||
StringBuilder data = new StringBuilder("Terra Profiler data dump: \n");
|
||||
platform.getProfiler().getTimings().forEach((id, timings) -> data.append(id).append(": ").append(timings.toString()).append('\n'));
|
||||
logger.info(data.toString());
|
||||
sender.sendMessage("Profiler data dumped to console.");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.commands.profiler;
|
||||
|
||||
import com.dfsek.terra.api.Platform;
|
||||
import com.dfsek.terra.api.command.CommandTemplate;
|
||||
import com.dfsek.terra.api.command.annotation.Command;
|
||||
import com.dfsek.terra.api.command.annotation.type.DebugCommand;
|
||||
import com.dfsek.terra.api.entity.CommandSender;
|
||||
import com.dfsek.terra.api.inject.annotations.Inject;
|
||||
|
||||
|
||||
@Command
|
||||
@DebugCommand
|
||||
public class ProfileResetCommand implements CommandTemplate {
|
||||
@Inject
|
||||
private Platform platform;
|
||||
|
||||
@Override
|
||||
public void execute(CommandSender sender) {
|
||||
platform.getProfiler().reset();
|
||||
sender.sendMessage("Profiler reset.");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.commands.profiler;
|
||||
|
||||
import com.dfsek.terra.api.Platform;
|
||||
import com.dfsek.terra.api.command.CommandTemplate;
|
||||
import com.dfsek.terra.api.command.annotation.Command;
|
||||
import com.dfsek.terra.api.command.annotation.type.DebugCommand;
|
||||
import com.dfsek.terra.api.entity.CommandSender;
|
||||
import com.dfsek.terra.api.inject.annotations.Inject;
|
||||
|
||||
|
||||
@Command
|
||||
@DebugCommand
|
||||
public class ProfileStartCommand implements CommandTemplate {
|
||||
@Inject
|
||||
private Platform platform;
|
||||
|
||||
@Override
|
||||
public void execute(CommandSender sender) {
|
||||
platform.getProfiler().start();
|
||||
sender.sendMessage("Profiling enabled.");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.commands.profiler;
|
||||
|
||||
import com.dfsek.terra.api.Platform;
|
||||
import com.dfsek.terra.api.command.CommandTemplate;
|
||||
import com.dfsek.terra.api.command.annotation.Command;
|
||||
import com.dfsek.terra.api.command.annotation.type.DebugCommand;
|
||||
import com.dfsek.terra.api.entity.CommandSender;
|
||||
import com.dfsek.terra.api.inject.annotations.Inject;
|
||||
|
||||
|
||||
@Command
|
||||
@DebugCommand
|
||||
public class ProfileStopCommand implements CommandTemplate {
|
||||
@Inject
|
||||
private Platform platform;
|
||||
|
||||
@Override
|
||||
public void execute(CommandSender sender) {
|
||||
platform.getProfiler().stop();
|
||||
sender.sendMessage("Profiling disabled.");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.config;
|
||||
|
||||
import ca.solostudios.strata.version.VersionRange;
|
||||
import com.dfsek.tectonic.loading.TypeRegistry;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
import com.dfsek.terra.api.Platform;
|
||||
import com.dfsek.terra.api.addon.BaseAddon;
|
||||
import com.dfsek.terra.api.block.BlockType;
|
||||
import com.dfsek.terra.api.block.state.BlockState;
|
||||
import com.dfsek.terra.api.tectonic.LoaderRegistrar;
|
||||
import com.dfsek.terra.api.util.Range;
|
||||
import com.dfsek.terra.api.util.collection.MaterialSet;
|
||||
import com.dfsek.terra.api.util.collection.ProbabilityCollection;
|
||||
import com.dfsek.terra.config.loaders.LinkedHashMapLoader;
|
||||
import com.dfsek.terra.config.loaders.MaterialSetLoader;
|
||||
import com.dfsek.terra.config.loaders.ProbabilityCollectionLoader;
|
||||
import com.dfsek.terra.config.loaders.RangeLoader;
|
||||
import com.dfsek.terra.config.loaders.VersionRangeLoader;
|
||||
|
||||
|
||||
public class GenericLoaders implements LoaderRegistrar {
|
||||
private final Platform platform;
|
||||
|
||||
public GenericLoaders(Platform platform) {
|
||||
this.platform = platform;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(TypeRegistry registry) {
|
||||
registry.registerLoader(ProbabilityCollection.class, new ProbabilityCollectionLoader())
|
||||
.registerLoader(Range.class, new RangeLoader())
|
||||
.registerLoader(MaterialSet.class, new MaterialSetLoader())
|
||||
.registerLoader(VersionRange.class, new VersionRangeLoader())
|
||||
.registerLoader(LinkedHashMap.class, new LinkedHashMapLoader());
|
||||
|
||||
if(platform != null) {
|
||||
registry.registerLoader(BaseAddon.class, platform.getAddons())
|
||||
.registerLoader(BlockType.class,
|
||||
(t, object, cf) -> platform.getWorldHandle().createBlockData((String) object).getBlockType())
|
||||
.registerLoader(BlockState.class, (t, object, cf) -> platform.getWorldHandle().createBlockData((String) object));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.config;
|
||||
|
||||
import com.dfsek.tectonic.annotations.Default;
|
||||
import com.dfsek.tectonic.annotations.Value;
|
||||
import com.dfsek.tectonic.config.ConfigTemplate;
|
||||
import com.dfsek.tectonic.exception.ConfigException;
|
||||
import com.dfsek.tectonic.loading.ConfigLoader;
|
||||
import com.dfsek.tectonic.yaml.YamlConfiguration;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.time.Duration;
|
||||
|
||||
import com.dfsek.terra.api.Platform;
|
||||
|
||||
|
||||
@SuppressWarnings("FieldMayBeFinal")
|
||||
public class PluginConfigImpl implements ConfigTemplate, com.dfsek.terra.api.config.PluginConfig {
|
||||
private static final Logger logger = LoggerFactory.getLogger(PluginConfigImpl.class);
|
||||
|
||||
@Value("debug.commands")
|
||||
@Default
|
||||
private boolean debugCommands = false;
|
||||
|
||||
@Value("debug.profiler")
|
||||
@Default
|
||||
private boolean debugProfiler = false;
|
||||
|
||||
@Value("debug.script")
|
||||
@Default
|
||||
private boolean debugScript = false;
|
||||
|
||||
@Value("language")
|
||||
@Default
|
||||
private String language = "en_us";
|
||||
|
||||
@Value("data-save")
|
||||
@Default
|
||||
private Duration dataSave = Duration.parse("PT6M");
|
||||
|
||||
@Value("biome-search-resolution")
|
||||
@Default
|
||||
private int biomeSearch = 4;
|
||||
|
||||
@Value("cache.carver")
|
||||
@Default
|
||||
private int carverCache = 256;
|
||||
|
||||
@Value("cache.structure")
|
||||
@Default
|
||||
private int structureCache = 32;
|
||||
|
||||
@Value("cache.sampler")
|
||||
@Default
|
||||
private int samplerCache = 64;
|
||||
|
||||
@Value("cache.biome")
|
||||
@Default
|
||||
private int biomeCache = 512;
|
||||
|
||||
@Value("cache.biome-provider")
|
||||
@Default
|
||||
private int providerCache = 32;
|
||||
|
||||
@Value("dump-default")
|
||||
@Default
|
||||
private boolean dumpDefaultData = true;
|
||||
|
||||
@Value("script.max-recursion")
|
||||
@Default
|
||||
private int maxRecursion = 1000;
|
||||
|
||||
@Override
|
||||
public void load(Platform platform) {
|
||||
logger.info("Loading config values from config.yml");
|
||||
try(FileInputStream file = new FileInputStream(new File(platform.getDataFolder(), "config.yml"))) {
|
||||
ConfigLoader loader = new ConfigLoader();
|
||||
loader.load(this, new YamlConfiguration(file, "config.yml"));
|
||||
} catch(ConfigException | IOException | UncheckedIOException e) {
|
||||
logger.error("Failed to load config", e);
|
||||
}
|
||||
|
||||
if(debugCommands)
|
||||
logger.info("Debug commands enabled.");
|
||||
if(debugProfiler)
|
||||
logger.info("Debug profiler enabled.");
|
||||
if(debugScript)
|
||||
logger.info("Script debug blocks enabled.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dumpDefaultConfig() {
|
||||
return dumpDefaultData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLanguage() {
|
||||
return language;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDebugCommands() {
|
||||
return debugCommands;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDebugProfiler() {
|
||||
return debugProfiler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDebugScript() {
|
||||
return debugScript;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getDataSaveInterval() {
|
||||
return dataSave.toMillis() / 20L;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBiomeSearchResolution() {
|
||||
return biomeSearch;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCarverCacheSize() {
|
||||
return carverCache;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getStructureCache() {
|
||||
return structureCache;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSamplerCache() {
|
||||
return samplerCache;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxRecursion() {
|
||||
return maxRecursion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBiomeCache() {
|
||||
return biomeCache;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getProviderCache() {
|
||||
return providerCache;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.config.dummy;
|
||||
|
||||
import com.dfsek.terra.api.block.entity.BlockEntity;
|
||||
import com.dfsek.terra.api.block.state.BlockState;
|
||||
import com.dfsek.terra.api.config.WorldConfig;
|
||||
import com.dfsek.terra.api.entity.Entity;
|
||||
import com.dfsek.terra.api.entity.EntityType;
|
||||
import com.dfsek.terra.api.util.vector.Vector3;
|
||||
import com.dfsek.terra.api.world.Chunk;
|
||||
import com.dfsek.terra.api.world.World;
|
||||
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
|
||||
import com.dfsek.terra.api.world.generator.ChunkGenerator;
|
||||
|
||||
|
||||
public class DummyWorld implements World {
|
||||
@Override
|
||||
public Entity spawnEntity(Vector3 location, EntityType entityType) {
|
||||
throw new UnsupportedOperationException("Cannot spawn entity in DummyWorld");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBlockData(int x, int y, int z, BlockState data, boolean physics) {
|
||||
throw new UnsupportedOperationException("Cannot set block in DummyWorld");
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSeed() {
|
||||
return 2403L;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxHeight() {
|
||||
return 255;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Chunk getChunkAt(int x, int z) {
|
||||
throw new UnsupportedOperationException("Cannot get chunk in DummyWorld");
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getBlockData(int x, int y, int z) {
|
||||
throw new UnsupportedOperationException("Cannot get block in DummyWorld");
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockEntity getBlockState(int x, int y, int z) {
|
||||
throw new UnsupportedOperationException("Cannot get block in DummyWorld");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinHeight() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChunkGenerator getGenerator() {
|
||||
throw new UnsupportedOperationException("Cannot get generator of DummyWorld");
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeProvider getBiomeProvider() {
|
||||
throw new UnsupportedOperationException("Cannot get biome provider of DummyWorld");
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldConfig getConfig() {
|
||||
throw new UnsupportedOperationException("Cannot get config of DummyWorld");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getHandle() {
|
||||
throw new UnsupportedOperationException("Cannot get handle of DummyWorld");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.config.fileloaders;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
|
||||
/**
|
||||
* Load all {@code *.yml} files from a {@link java.nio.file.Path}.
|
||||
*/
|
||||
public class FolderLoader extends LoaderImpl {
|
||||
private static final Logger logger = LoggerFactory.getLogger(FolderLoader.class);
|
||||
|
||||
private final Path path;
|
||||
|
||||
public FolderLoader(Path path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream get(String singleFile) throws IOException {
|
||||
return new FileInputStream(new File(path.toFile(), singleFile));
|
||||
}
|
||||
|
||||
protected void load(String directory, String extension) {
|
||||
File newPath = new File(path.toFile(), directory);
|
||||
newPath.mkdirs();
|
||||
try(Stream<Path> paths = Files.walk(newPath.toPath())) {
|
||||
paths.filter(Files::isRegularFile).filter(file -> file.toString().toLowerCase().endsWith(extension)).forEach(file -> {
|
||||
try {
|
||||
String rel = newPath.toPath().relativize(file).toString();
|
||||
streams.put(rel, new FileInputStream(file.toFile()));
|
||||
} catch(FileNotFoundException e) {
|
||||
logger.error("Could not find file to load", e);
|
||||
}
|
||||
});
|
||||
} catch(IOException e) {
|
||||
logger.error("Error while loading files", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.config.fileloaders;
|
||||
|
||||
import com.dfsek.tectonic.exception.ConfigException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import com.dfsek.terra.api.config.Loader;
|
||||
|
||||
|
||||
public abstract class LoaderImpl implements Loader {
|
||||
private static final Logger logger = LoggerFactory.getLogger(LoaderImpl.class);
|
||||
|
||||
protected final Map<String, InputStream> streams = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public Loader thenNames(Consumer<List<String>> consumer) throws ConfigException {
|
||||
consumer.accept(new ArrayList<>(streams.keySet()));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Loader thenEntries(Consumer<Set<Map.Entry<String, InputStream>>> consumer) throws ConfigException {
|
||||
consumer.accept(streams.entrySet());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a subdirectory.
|
||||
*
|
||||
* @param directory Directory to open
|
||||
* @param extension File extension
|
||||
*/
|
||||
@Override
|
||||
public LoaderImpl open(String directory, String extension) {
|
||||
if(!streams.isEmpty()) throw new IllegalStateException("Attempted to load new directory before closing existing InputStreams");
|
||||
load(directory, extension);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close all InputStreams opened.
|
||||
*/
|
||||
@Override
|
||||
public Loader close() {
|
||||
streams.forEach((name, input) -> {
|
||||
try {
|
||||
input.close();
|
||||
} catch(IOException e) {
|
||||
logger.error("Error occurred while loading", e);
|
||||
}
|
||||
});
|
||||
streams.clear();
|
||||
return this;
|
||||
}
|
||||
|
||||
protected abstract void load(String directory, String extension);
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.config.fileloaders;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Enumeration;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
|
||||
public class ZIPLoader extends LoaderImpl {
|
||||
private static final Logger logger = LoggerFactory.getLogger(ZIPLoader.class);
|
||||
|
||||
private final ZipFile file;
|
||||
|
||||
public ZIPLoader(ZipFile file) {
|
||||
this.file = file;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream get(String singleFile) throws IOException {
|
||||
Enumeration<? extends ZipEntry> entries = file.entries();
|
||||
while(entries.hasMoreElements()) {
|
||||
ZipEntry entry = entries.nextElement();
|
||||
if(!entry.isDirectory() && entry.getName().equals(singleFile)) return file.getInputStream(entry);
|
||||
}
|
||||
throw new IllegalArgumentException("No such file: " + singleFile);
|
||||
}
|
||||
|
||||
protected void load(String directory, String extension) {
|
||||
Enumeration<? extends ZipEntry> entries = file.entries();
|
||||
while(entries.hasMoreElements()) {
|
||||
ZipEntry entry = entries.nextElement();
|
||||
if(!entry.isDirectory() && entry.getName().startsWith(directory) && entry.getName().endsWith(extension)) {
|
||||
try {
|
||||
String rel = entry.getName().substring(directory.length());
|
||||
streams.put(rel, file.getInputStream(entry));
|
||||
} catch(IOException e) {
|
||||
logger.error("Error while loading file from zip", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.config.lang;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
import com.dfsek.terra.api.Platform;
|
||||
import com.dfsek.terra.api.entity.CommandSender;
|
||||
import com.dfsek.terra.api.lang.Language;
|
||||
|
||||
|
||||
public final class LangUtil {
|
||||
private static final Logger logger = LoggerFactory.getLogger(LangUtil.class);
|
||||
|
||||
@Nullable
|
||||
private static Language LANGUAGE = null;
|
||||
|
||||
private LangUtil() { }
|
||||
|
||||
public static void load(String langID, Platform platform) {
|
||||
File file = new File(platform.getDataFolder(), "lang");
|
||||
try {
|
||||
File file1 = new File(file, langID + ".yml");
|
||||
logger.info(file1.getAbsolutePath());
|
||||
LANGUAGE = new LanguageImpl(file1);
|
||||
logger.info("Loaded language {}", langID);
|
||||
} catch(IOException e) {
|
||||
logger.error("Unable to load language: {}.\nDouble-check your configuration before reporting this to Terra!", langID, e);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Language getLanguage() {
|
||||
return Objects.requireNonNull(LANGUAGE);
|
||||
}
|
||||
|
||||
public static void send(String messageID, CommandSender sender, String... args) {
|
||||
Objects.requireNonNull(LANGUAGE).getMessage(messageID).send(sender, args);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.config.lang;
|
||||
|
||||
|
||||
import com.dfsek.tectonic.config.Configuration;
|
||||
import com.dfsek.tectonic.yaml.YamlConfiguration;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.dfsek.terra.api.entity.CommandSender;
|
||||
import com.dfsek.terra.api.lang.Message;
|
||||
|
||||
|
||||
public class LanguageImpl implements com.dfsek.terra.api.lang.Language {
|
||||
private final Configuration configuration;
|
||||
|
||||
public LanguageImpl(File file) throws IOException {
|
||||
configuration = new YamlConfiguration(new FileInputStream(file), file.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(String messageID, Level level, Logger logger, String... args) {
|
||||
getMessage(messageID).log(logger, level, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(String messageID, CommandSender sender, String... args) {
|
||||
getMessage(messageID).send(sender, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Message getMessage(String id) {
|
||||
Message temp = null;
|
||||
if(configuration.contains(id)) {
|
||||
Object m = configuration.get(id);
|
||||
|
||||
if(m instanceof List) {
|
||||
temp = new MultiLineMessage((List<String>) m);
|
||||
} else if(m instanceof String) {
|
||||
temp = new SingleLineMessage((String) m);
|
||||
} else return new SingleLineMessage("message:" + id + ":translation_undefined");
|
||||
}
|
||||
if(temp == null || temp.isEmpty()) return new SingleLineMessage("message:" + id + ":translation_undefined");
|
||||
return temp;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.config.lang;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.dfsek.terra.api.entity.CommandSender;
|
||||
import com.dfsek.terra.api.lang.Message;
|
||||
|
||||
|
||||
public class MultiLineMessage implements Message {
|
||||
private final List<String> message;
|
||||
|
||||
public MultiLineMessage(List<String> message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(Logger logger, Level level, String... args) {
|
||||
for(String line : message) {
|
||||
logger.log(level, String.format(line, Arrays.asList(args).toArray()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(CommandSender sender, String... args) {
|
||||
for(String line : message) {
|
||||
sender.sendMessage(String.format(line, Arrays.asList(args).toArray()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return message == null || message.isEmpty();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.config.lang;
|
||||
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.dfsek.terra.api.entity.CommandSender;
|
||||
import com.dfsek.terra.api.lang.Message;
|
||||
|
||||
|
||||
public class SingleLineMessage implements Message {
|
||||
private final String message;
|
||||
|
||||
public SingleLineMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(Logger logger, Level level, String... args) {
|
||||
logger.log(level, String.format(message, Arrays.asList(args).toArray()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(CommandSender sender, String... args) {
|
||||
sender.sendMessage(String.format(message, Arrays.asList(args).toArray()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return message == null || message.equals("");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.config.loaders;
|
||||
|
||||
import com.dfsek.tectonic.config.MapConfiguration;
|
||||
import com.dfsek.tectonic.exception.ConfigException;
|
||||
import com.dfsek.tectonic.exception.LoadException;
|
||||
import com.dfsek.tectonic.loading.ConfigLoader;
|
||||
import com.dfsek.tectonic.loading.TypeLoader;
|
||||
import com.dfsek.tectonic.loading.object.ObjectTemplate;
|
||||
|
||||
import java.lang.reflect.AnnotatedType;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.dfsek.terra.api.registry.Registry;
|
||||
|
||||
|
||||
public class GenericTemplateSupplierLoader<T> implements TypeLoader<T> {
|
||||
private final Registry<Supplier<ObjectTemplate<T>>> registry;
|
||||
|
||||
public GenericTemplateSupplierLoader(Registry<Supplier<ObjectTemplate<T>>> registry) {
|
||||
this.registry = registry;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public T load(AnnotatedType t, Object c, ConfigLoader loader) throws LoadException {
|
||||
Map<String, Object> map = (Map<String, Object>) c;
|
||||
try {
|
||||
if(!registry.contains((String) map.get("type"))) {
|
||||
throw new LoadException("No such entry: " + map.get("type"));
|
||||
}
|
||||
ObjectTemplate<T> template = registry.get(((String) map.get("type"))).get();
|
||||
loader.load(template, new MapConfiguration(map));
|
||||
return template.get();
|
||||
} catch(ConfigException e) {
|
||||
throw new LoadException("Unable to load object: ", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.config.loaders;
|
||||
|
||||
import com.dfsek.tectonic.exception.LoadException;
|
||||
import com.dfsek.tectonic.loading.ConfigLoader;
|
||||
import com.dfsek.tectonic.loading.TypeLoader;
|
||||
|
||||
import java.lang.reflect.AnnotatedParameterizedType;
|
||||
import java.lang.reflect.AnnotatedType;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public class LinkedHashMapLoader implements TypeLoader<LinkedHashMap<Object, Object>> {
|
||||
@Override
|
||||
public LinkedHashMap<Object, Object> load(AnnotatedType t, Object c, ConfigLoader loader) throws LoadException {
|
||||
Map<String, Object> config = (Map<String, Object>) c;
|
||||
LinkedHashMap<Object, Object> map = new LinkedHashMap<>();
|
||||
if(t instanceof AnnotatedParameterizedType) {
|
||||
AnnotatedParameterizedType pType = (AnnotatedParameterizedType) t;
|
||||
AnnotatedType key = pType.getAnnotatedActualTypeArguments()[0];
|
||||
AnnotatedType value = pType.getAnnotatedActualTypeArguments()[1];
|
||||
for(Map.Entry<String, Object> entry : config.entrySet()) {
|
||||
map.put(loader.loadType(key, entry.getKey()), loader.loadType(value, entry.getValue()));
|
||||
}
|
||||
} else throw new LoadException("Unable to load config");
|
||||
|
||||
return map;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.config.loaders;
|
||||
|
||||
import com.dfsek.tectonic.exception.LoadException;
|
||||
import com.dfsek.tectonic.loading.ConfigLoader;
|
||||
import com.dfsek.tectonic.loading.TypeLoader;
|
||||
|
||||
import java.lang.reflect.AnnotatedType;
|
||||
import java.util.List;
|
||||
|
||||
import com.dfsek.terra.api.block.BlockType;
|
||||
import com.dfsek.terra.api.util.collection.MaterialSet;
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public class MaterialSetLoader implements TypeLoader<MaterialSet> {
|
||||
@Override
|
||||
public MaterialSet load(AnnotatedType type, Object o, ConfigLoader configLoader) throws LoadException {
|
||||
List<String> stringData = (List<String>) o;
|
||||
MaterialSet set = new MaterialSet();
|
||||
|
||||
for(String string : stringData) {
|
||||
try {
|
||||
set.add(configLoader.loadType(BlockType.class, string));
|
||||
} catch(NullPointerException e) {
|
||||
throw new LoadException("Invalid data identifier \"" + string + "\"", e);
|
||||
}
|
||||
}
|
||||
|
||||
return set;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.config.loaders;
|
||||
|
||||
import com.dfsek.tectonic.exception.LoadException;
|
||||
import com.dfsek.tectonic.loading.ConfigLoader;
|
||||
import com.dfsek.tectonic.loading.TypeLoader;
|
||||
|
||||
import java.lang.reflect.AnnotatedParameterizedType;
|
||||
import java.lang.reflect.AnnotatedType;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.dfsek.terra.api.util.collection.ProbabilityCollection;
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public class ProbabilityCollectionLoader implements TypeLoader<ProbabilityCollection<Object>> {
|
||||
@Override
|
||||
public ProbabilityCollection<Object> load(AnnotatedType type, Object o, ConfigLoader configLoader) throws LoadException {
|
||||
ProbabilityCollection<Object> collection = new ProbabilityCollection<>();
|
||||
|
||||
if(type instanceof AnnotatedParameterizedType) {
|
||||
AnnotatedParameterizedType pType = (AnnotatedParameterizedType) type;
|
||||
AnnotatedType generic = pType.getAnnotatedActualTypeArguments()[0];
|
||||
if(o instanceof Map) {
|
||||
Map<Object, Integer> map = (Map<Object, Integer>) o;
|
||||
for(Map.Entry<Object, Integer> entry : map.entrySet()) {
|
||||
collection.add(configLoader.loadType(generic, entry.getKey()), entry.getValue());
|
||||
}
|
||||
} else if(o instanceof List) {
|
||||
List<Map<Object, Integer>> map = (List<Map<Object, Integer>>) o;
|
||||
for(Map<Object, Integer> l : map) {
|
||||
for(Map.Entry<Object, Integer> entry : l.entrySet()) {
|
||||
if(entry.getValue() == null) throw new LoadException("No probability defined for entry \"" + entry.getKey() + "\"");
|
||||
Object val = configLoader.loadType(generic, entry.getKey());
|
||||
collection.add(val, entry.getValue());
|
||||
}
|
||||
}
|
||||
} else if(o instanceof String) {
|
||||
return new ProbabilityCollection.Singleton<>(configLoader.loadType(generic, o));
|
||||
} else {
|
||||
throw new LoadException("Malformed Probability Collection: " + o);
|
||||
}
|
||||
} else throw new LoadException("Unable to load config! Could not retrieve parameterized type: " + type);
|
||||
|
||||
|
||||
return collection;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.config.loaders;
|
||||
|
||||
import com.dfsek.tectonic.exception.LoadException;
|
||||
import com.dfsek.tectonic.loading.ConfigLoader;
|
||||
import com.dfsek.tectonic.loading.TypeLoader;
|
||||
|
||||
import java.lang.reflect.AnnotatedType;
|
||||
import java.util.Map;
|
||||
|
||||
import com.dfsek.terra.api.util.ConstantRange;
|
||||
import com.dfsek.terra.api.util.Range;
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public class RangeLoader implements TypeLoader<Range> {
|
||||
@Override
|
||||
public Range load(AnnotatedType type, Object o, ConfigLoader configLoader) throws LoadException {
|
||||
if(o instanceof Map) {
|
||||
Map<String, Integer> map = (Map<String, Integer>) o;
|
||||
return new ConstantRange(map.get("min"), map.get("max"));
|
||||
} else {
|
||||
int h = configLoader.loadType(Integer.class, o);
|
||||
return new ConstantRange(h, h + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.config.loaders;
|
||||
|
||||
import ca.solostudios.strata.Versions;
|
||||
import ca.solostudios.strata.parser.tokenizer.ParseException;
|
||||
import ca.solostudios.strata.version.VersionRange;
|
||||
import com.dfsek.tectonic.exception.LoadException;
|
||||
import com.dfsek.tectonic.loading.ConfigLoader;
|
||||
import com.dfsek.tectonic.loading.TypeLoader;
|
||||
|
||||
import java.lang.reflect.AnnotatedType;
|
||||
|
||||
|
||||
public class VersionRangeLoader implements TypeLoader<VersionRange> {
|
||||
@Override
|
||||
public VersionRange load(AnnotatedType t, Object c, ConfigLoader loader) throws LoadException {
|
||||
try {
|
||||
return Versions.parseVersionRange((String) c);
|
||||
} catch(ParseException e) {
|
||||
throw new LoadException("Failed to parse version range: ", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.config.loaders.config;
|
||||
|
||||
import com.dfsek.tectonic.exception.LoadException;
|
||||
import com.dfsek.tectonic.loading.ConfigLoader;
|
||||
import com.dfsek.tectonic.loading.TypeLoader;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.AnnotatedType;
|
||||
|
||||
import com.dfsek.terra.api.config.Loader;
|
||||
|
||||
|
||||
public class BufferedImageLoader implements TypeLoader<BufferedImage> {
|
||||
private final Loader files;
|
||||
|
||||
public BufferedImageLoader(Loader files) {
|
||||
this.files = files;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BufferedImage load(AnnotatedType t, Object c, ConfigLoader loader) throws LoadException {
|
||||
try {
|
||||
return ImageIO.read(files.get((String) c));
|
||||
} catch(IOException e) {
|
||||
throw new LoadException("Unable to load image", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.config.loaders.config;
|
||||
|
||||
import com.dfsek.tectonic.loading.ConfigLoader;
|
||||
import com.dfsek.tectonic.loading.TypeLoader;
|
||||
|
||||
import java.lang.reflect.AnnotatedType;
|
||||
import java.util.Map;
|
||||
|
||||
import com.dfsek.terra.api.structure.StructureSpawn;
|
||||
import com.dfsek.terra.math.GridSpawn;
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public class GridSpawnLoader implements TypeLoader<StructureSpawn> {
|
||||
@Override
|
||||
public StructureSpawn load(AnnotatedType type, Object o, ConfigLoader configLoader) {
|
||||
Map<String, Integer> map = (Map<String, Integer>) o;
|
||||
return new GridSpawn(map.get("width"), map.get("padding"), map.getOrDefault("salt", 0));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.config.pack;
|
||||
|
||||
import ca.solostudios.strata.version.VersionRange;
|
||||
import com.dfsek.tectonic.annotations.Default;
|
||||
import com.dfsek.tectonic.annotations.Value;
|
||||
import com.dfsek.tectonic.config.ConfigTemplate;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
|
||||
import com.dfsek.terra.api.addon.BaseAddon;
|
||||
|
||||
|
||||
@SuppressWarnings("FieldMayBeFinal")
|
||||
public class ConfigPackAddonsTemplate implements ConfigTemplate {
|
||||
@Value("addons")
|
||||
@Default
|
||||
private Map<BaseAddon, VersionRange> addons = new HashMap<>();
|
||||
|
||||
|
||||
public Map<BaseAddon, VersionRange> getAddons() {
|
||||
return addons;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,485 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.config.pack;
|
||||
|
||||
import ca.solostudios.strata.version.VersionRange;
|
||||
import com.dfsek.paralithic.eval.parser.Scope;
|
||||
import com.dfsek.tectonic.abstraction.AbstractConfigLoader;
|
||||
import com.dfsek.tectonic.abstraction.AbstractConfiguration;
|
||||
import com.dfsek.tectonic.config.ConfigTemplate;
|
||||
import com.dfsek.tectonic.config.Configuration;
|
||||
import com.dfsek.tectonic.exception.ConfigException;
|
||||
import com.dfsek.tectonic.exception.LoadException;
|
||||
import com.dfsek.tectonic.loading.ConfigLoader;
|
||||
import com.dfsek.tectonic.loading.TypeLoader;
|
||||
import com.dfsek.tectonic.loading.TypeRegistry;
|
||||
import com.dfsek.tectonic.loading.object.ObjectTemplate;
|
||||
import com.dfsek.tectonic.yaml.YamlConfiguration;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
import com.dfsek.terra.api.Platform;
|
||||
import com.dfsek.terra.api.addon.BaseAddon;
|
||||
import com.dfsek.terra.api.config.ConfigFactory;
|
||||
import com.dfsek.terra.api.config.ConfigPack;
|
||||
import com.dfsek.terra.api.config.ConfigType;
|
||||
import com.dfsek.terra.api.config.Loader;
|
||||
import com.dfsek.terra.api.config.meta.Meta;
|
||||
import com.dfsek.terra.api.event.events.config.ConfigurationDiscoveryEvent;
|
||||
import com.dfsek.terra.api.event.events.config.ConfigurationLoadEvent;
|
||||
import com.dfsek.terra.api.event.events.config.pack.ConfigPackPostLoadEvent;
|
||||
import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent;
|
||||
import com.dfsek.terra.api.event.events.config.type.ConfigTypePostLoadEvent;
|
||||
import com.dfsek.terra.api.event.events.config.type.ConfigTypePreLoadEvent;
|
||||
import com.dfsek.terra.api.registry.CheckedRegistry;
|
||||
import com.dfsek.terra.api.registry.OpenRegistry;
|
||||
import com.dfsek.terra.api.registry.Registry;
|
||||
import com.dfsek.terra.api.registry.exception.DuplicateEntryException;
|
||||
import com.dfsek.terra.api.registry.meta.RegistryFactory;
|
||||
import com.dfsek.terra.api.util.generic.pair.ImmutablePair;
|
||||
import com.dfsek.terra.api.util.reflection.ReflectionUtil;
|
||||
import com.dfsek.terra.api.world.World;
|
||||
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
|
||||
import com.dfsek.terra.api.world.generator.ChunkGeneratorProvider;
|
||||
import com.dfsek.terra.api.world.generator.GenerationStageProvider;
|
||||
import com.dfsek.terra.config.dummy.DummyWorld;
|
||||
import com.dfsek.terra.config.fileloaders.FolderLoader;
|
||||
import com.dfsek.terra.config.fileloaders.ZIPLoader;
|
||||
import com.dfsek.terra.config.loaders.GenericTemplateSupplierLoader;
|
||||
import com.dfsek.terra.config.loaders.config.BufferedImageLoader;
|
||||
import com.dfsek.terra.config.preprocessor.MetaListLikePreprocessor;
|
||||
import com.dfsek.terra.config.preprocessor.MetaMapPreprocessor;
|
||||
import com.dfsek.terra.config.preprocessor.MetaNumberPreprocessor;
|
||||
import com.dfsek.terra.config.preprocessor.MetaStringPreprocessor;
|
||||
import com.dfsek.terra.config.preprocessor.MetaValuePreprocessor;
|
||||
import com.dfsek.terra.config.prototype.ProtoConfig;
|
||||
import com.dfsek.terra.registry.CheckedRegistryImpl;
|
||||
import com.dfsek.terra.registry.OpenRegistryImpl;
|
||||
import com.dfsek.terra.registry.RegistryFactoryImpl;
|
||||
import com.dfsek.terra.registry.config.ConfigTypeRegistry;
|
||||
|
||||
|
||||
/**
|
||||
* Represents a Terra configuration pack.
|
||||
*/
|
||||
public class ConfigPackImpl implements ConfigPack {
|
||||
private static final Logger logger = LoggerFactory.getLogger(ConfigPackImpl.class);
|
||||
|
||||
private final ConfigPackTemplate template = new ConfigPackTemplate();
|
||||
|
||||
private final RegistryFactory registryFactory = new RegistryFactoryImpl();
|
||||
|
||||
private final AbstractConfigLoader abstractConfigLoader = new AbstractConfigLoader();
|
||||
private final ConfigLoader selfLoader = new ConfigLoader();
|
||||
private final Scope varScope = new Scope();
|
||||
private final Platform platform;
|
||||
private final Loader loader;
|
||||
|
||||
private final Configuration configuration;
|
||||
|
||||
private final Map<BaseAddon, VersionRange> addons;
|
||||
|
||||
private final BiomeProvider seededBiomeProvider;
|
||||
|
||||
private final Map<Type, ImmutablePair<OpenRegistry<?>, CheckedRegistry<?>>> registryMap = new HashMap<>();
|
||||
|
||||
private final ConfigTypeRegistry configTypeRegistry;
|
||||
|
||||
|
||||
private final TreeMap<Integer, List<ImmutablePair<String, ConfigType<?, ?>>>> configTypes = new TreeMap<>();
|
||||
|
||||
public ConfigPackImpl(File folder, Platform platform) throws ConfigException {
|
||||
try {
|
||||
this.loader = new FolderLoader(folder.toPath());
|
||||
this.platform = platform;
|
||||
this.configTypeRegistry = createRegistry();
|
||||
long l = System.nanoTime();
|
||||
|
||||
register(abstractConfigLoader);
|
||||
platform.register(abstractConfigLoader);
|
||||
|
||||
register(selfLoader);
|
||||
platform.register(selfLoader);
|
||||
|
||||
File pack = new File(folder, "pack.yml");
|
||||
|
||||
try {
|
||||
this.configuration = new YamlConfiguration(new FileInputStream(pack), "pack.yml");
|
||||
|
||||
ConfigPackAddonsTemplate addonsTemplate = new ConfigPackAddonsTemplate();
|
||||
selfLoader.load(addonsTemplate, configuration);
|
||||
this.addons = addonsTemplate.getAddons();
|
||||
|
||||
platform.getEventManager().callEvent(
|
||||
new ConfigPackPreLoadEvent(this, template -> selfLoader.load(template, configuration)));
|
||||
|
||||
selfLoader.load(template, configuration);
|
||||
|
||||
logger.info("Loading config pack \"{}\"", template.getID());
|
||||
load(l, platform);
|
||||
|
||||
ConfigPackPostTemplate packPostTemplate = new ConfigPackPostTemplate();
|
||||
selfLoader.load(packPostTemplate, configuration);
|
||||
seededBiomeProvider = packPostTemplate.getProviderBuilder();
|
||||
checkDeadEntries();
|
||||
} catch(FileNotFoundException e) {
|
||||
throw new LoadException("No pack.yml file found in " + folder.getAbsolutePath(), e);
|
||||
}
|
||||
} catch(Exception e) {
|
||||
logger.error("Failed to load config pack from folder \"{}\"", folder.getAbsolutePath(), e);
|
||||
throw e;
|
||||
}
|
||||
toWorldConfig(new DummyWorld()); // Build now to catch any errors immediately.
|
||||
}
|
||||
|
||||
public ConfigPackImpl(ZipFile file, Platform platform) throws ConfigException {
|
||||
try {
|
||||
this.loader = new ZIPLoader(file);
|
||||
this.platform = platform;
|
||||
this.configTypeRegistry = createRegistry();
|
||||
long l = System.nanoTime();
|
||||
|
||||
register(selfLoader);
|
||||
platform.register(selfLoader);
|
||||
|
||||
register(abstractConfigLoader);
|
||||
platform.register(abstractConfigLoader);
|
||||
|
||||
try {
|
||||
ZipEntry pack = null;
|
||||
Enumeration<? extends ZipEntry> entries = file.entries();
|
||||
while(entries.hasMoreElements()) {
|
||||
ZipEntry entry = entries.nextElement();
|
||||
if(entry.getName().equals("pack.yml")) pack = entry;
|
||||
}
|
||||
|
||||
if(pack == null) throw new LoadException("No pack.yml file found in " + file.getName());
|
||||
|
||||
this.configuration = new YamlConfiguration(file.getInputStream(pack), "pack.yml");
|
||||
|
||||
ConfigPackAddonsTemplate addonsTemplate = new ConfigPackAddonsTemplate();
|
||||
selfLoader.load(addonsTemplate, configuration);
|
||||
this.addons = addonsTemplate.getAddons();
|
||||
|
||||
platform.getEventManager().callEvent(
|
||||
new ConfigPackPreLoadEvent(this, template -> selfLoader.load(template, configuration)));
|
||||
|
||||
|
||||
selfLoader.load(template, configuration);
|
||||
logger.info("Loading config pack \"" + template.getID() + "\"");
|
||||
|
||||
load(l, platform);
|
||||
|
||||
ConfigPackPostTemplate packPostTemplate = new ConfigPackPostTemplate();
|
||||
|
||||
selfLoader.load(packPostTemplate, configuration);
|
||||
seededBiomeProvider = packPostTemplate.getProviderBuilder();
|
||||
checkDeadEntries();
|
||||
} catch(IOException e) {
|
||||
throw new LoadException("Unable to load pack.yml from ZIP file", e);
|
||||
}
|
||||
} catch(Exception e) {
|
||||
logger.error("Failed to load config pack from ZIP archive \"{}\"", file.getName());
|
||||
throw e;
|
||||
}
|
||||
|
||||
toWorldConfig(new DummyWorld()); // Build now to catch any errors immediately.
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> ConfigPackImpl applyLoader(Type type, TypeLoader<T> loader) {
|
||||
abstractConfigLoader.registerLoader(type, loader);
|
||||
selfLoader.registerLoader(type, loader);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> ConfigPackImpl applyLoader(Type type, Supplier<ObjectTemplate<T>> loader) {
|
||||
abstractConfigLoader.registerLoader(type, loader);
|
||||
selfLoader.registerLoader(type, loader);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(TypeRegistry registry) {
|
||||
registry
|
||||
.registerLoader(ConfigType.class, configTypeRegistry)
|
||||
.registerLoader(BufferedImage.class, new BufferedImageLoader(loader));
|
||||
registryMap.forEach((clazz, reg) -> registry.registerLoader(clazz, reg.getLeft()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldConfigImpl toWorldConfig(World world) {
|
||||
return new WorldConfigImpl(world, this, platform);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerConfigType(ConfigType<?, ?> type, String id, int priority) {
|
||||
Set<String> contained = new HashSet<>();
|
||||
configTypes.forEach((p, configs) -> configs.forEach(pair -> {
|
||||
if(contained.contains(pair.getLeft())) throw new IllegalArgumentException("Duplicate config ID: " + id);
|
||||
contained.add(id);
|
||||
}));
|
||||
configTypes.computeIfAbsent(priority, p -> new ArrayList<>()).add(ImmutablePair.of(id, type));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<BaseAddon, VersionRange> addons() {
|
||||
return addons;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean vanillaMobs() {
|
||||
return template.vanillaMobs();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean vanillaStructures() {
|
||||
return template.vanillaStructures();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean vanillaCaves() {
|
||||
return template.vanillaCaves();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean disableStructures() {
|
||||
return template.disableStructures();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean doBetaCarvers() {
|
||||
return template.doBetaCarvers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean vanillaFlora() {
|
||||
return template.vanillaDecorations();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeProvider getBiomeProviderBuilder() {
|
||||
return seededBiomeProvider;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T> CheckedRegistry<T> getOrCreateRegistry(Type type) {
|
||||
return (CheckedRegistry<T>) registryMap.computeIfAbsent(type, c -> {
|
||||
OpenRegistry<T> registry = new OpenRegistryImpl<>();
|
||||
selfLoader.registerLoader(c, registry);
|
||||
abstractConfigLoader.registerLoader(c, registry);
|
||||
logger.debug("Registered loader for registry of class {}", ReflectionUtil.typeToString(c));
|
||||
|
||||
if(type instanceof ParameterizedType param) {
|
||||
Type base = param.getRawType();
|
||||
if(base instanceof Class // should always be true but we'll check anyways
|
||||
&& Supplier.class.isAssignableFrom((Class<?>) base)) { // If it's a supplier
|
||||
Type supplied = param.getActualTypeArguments()[0]; // Grab the supplied type
|
||||
if(supplied instanceof ParameterizedType suppliedParam) {
|
||||
Type suppliedBase = suppliedParam.getRawType();
|
||||
if(suppliedBase instanceof Class // should always be true but we'll check anyways
|
||||
&& ObjectTemplate.class.isAssignableFrom((Class<?>) suppliedBase)) {
|
||||
Type templateType = suppliedParam.getActualTypeArguments()[0];
|
||||
GenericTemplateSupplierLoader<?> loader = new GenericTemplateSupplierLoader<>(
|
||||
(Registry<Supplier<ObjectTemplate<Supplier<ObjectTemplate<?>>>>>) registry);
|
||||
selfLoader.registerLoader(templateType, loader);
|
||||
abstractConfigLoader.registerLoader(templateType, loader);
|
||||
logger.debug("Registered template loader for registry of class {}", ReflectionUtil.typeToString(templateType));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ImmutablePair.of(registry, new CheckedRegistryImpl<>(registry));
|
||||
}).getRight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GenerationStageProvider> getStages() {
|
||||
return template.getStages();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Loader getLoader() {
|
||||
return loader;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAuthor() {
|
||||
return template.getAuthor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return template.getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getLocatable() {
|
||||
return template.getLocatable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegistryFactory getRegistryFactory() {
|
||||
return registryFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChunkGeneratorProvider getGeneratorProvider() {
|
||||
return template.getGeneratorProvider();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private ConfigTypeRegistry createRegistry() {
|
||||
return new ConfigTypeRegistry(platform, (id, configType) -> {
|
||||
OpenRegistry<?> openRegistry = configType.registrySupplier(this).get();
|
||||
if(registryMap.containsKey(configType.getTypeKey()
|
||||
.getType())) { // Someone already registered something; we need to copy things to the
|
||||
// new registry.
|
||||
logger.warn("Copying values from old registry for {}", configType.getTypeKey());
|
||||
registryMap.get(configType.getTypeKey().getType()).getLeft().forEach(((OpenRegistry<Object>) openRegistry)::register);
|
||||
}
|
||||
selfLoader.registerLoader(configType.getTypeKey().getType(), openRegistry);
|
||||
abstractConfigLoader.registerLoader(configType.getTypeKey().getType(), openRegistry);
|
||||
registryMap.put(configType.getTypeKey().getType(), ImmutablePair.of(openRegistry, new CheckedRegistryImpl<>(openRegistry)));
|
||||
});
|
||||
}
|
||||
|
||||
private void checkDeadEntries() {
|
||||
registryMap.forEach((clazz, pair) -> ((OpenRegistryImpl<?>) pair.getLeft())
|
||||
.getDeadEntries()
|
||||
.forEach((id, value) -> logger.warn("Dead entry in '{}' registry: '{}'", ReflectionUtil.typeToString(clazz), id)));
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
private void load(long start, Platform platform) throws ConfigException {
|
||||
configTypes.values().forEach(list -> list.forEach(pair -> configTypeRegistry.register(pair.getLeft(), pair.getRight())));
|
||||
|
||||
for(Map.Entry<String, Double> var : template.getVariables().entrySet()) {
|
||||
varScope.create(var.getKey(), var.getValue());
|
||||
}
|
||||
|
||||
Map<String, Configuration> configurations = new HashMap<>();
|
||||
|
||||
platform.getEventManager().callEvent(new ConfigurationDiscoveryEvent(this, loader, (s, c) -> configurations.put(s.replace("\\","/"), c))); // Create all the configs.
|
||||
|
||||
MetaStringPreprocessor stringPreprocessor = new MetaStringPreprocessor(configurations);
|
||||
selfLoader.registerPreprocessor(Meta.class, stringPreprocessor);
|
||||
abstractConfigLoader.registerPreprocessor(Meta.class, stringPreprocessor);
|
||||
|
||||
MetaListLikePreprocessor listPreprocessor = new MetaListLikePreprocessor(configurations);
|
||||
selfLoader.registerPreprocessor(Meta.class, listPreprocessor);
|
||||
abstractConfigLoader.registerPreprocessor(Meta.class, listPreprocessor);
|
||||
|
||||
MetaMapPreprocessor mapPreprocessor = new MetaMapPreprocessor(configurations);
|
||||
selfLoader.registerPreprocessor(Meta.class, mapPreprocessor);
|
||||
abstractConfigLoader.registerPreprocessor(Meta.class, mapPreprocessor);
|
||||
|
||||
MetaValuePreprocessor valuePreprocessor = new MetaValuePreprocessor(configurations);
|
||||
selfLoader.registerPreprocessor(Meta.class, valuePreprocessor);
|
||||
abstractConfigLoader.registerPreprocessor(Meta.class, valuePreprocessor);
|
||||
|
||||
MetaNumberPreprocessor numberPreprocessor = new MetaNumberPreprocessor(configurations);
|
||||
selfLoader.registerPreprocessor(Meta.class, numberPreprocessor);
|
||||
abstractConfigLoader.registerPreprocessor(Meta.class, numberPreprocessor);
|
||||
|
||||
Map<ConfigType<? extends ConfigTemplate, ?>, List<Configuration>> configs = new HashMap<>();
|
||||
|
||||
for(Configuration configuration : configurations.values()) { // Sort the configs
|
||||
if(configuration.contains("type")) { // Only sort configs with type key
|
||||
ProtoConfig config = new ProtoConfig();
|
||||
selfLoader.load(config, configuration);
|
||||
configs.computeIfAbsent(config.getType(), configType -> new ArrayList<>()).add(configuration);
|
||||
}
|
||||
}
|
||||
|
||||
for(ConfigType<?, ?> configType : configTypeRegistry.entries()) { // Load the configs
|
||||
CheckedRegistry registry = getCheckedRegistry(configType.getTypeKey());
|
||||
platform.getEventManager().callEvent(new ConfigTypePreLoadEvent(configType, registry, this));
|
||||
for(AbstractConfiguration config : abstractConfigLoader.loadConfigs(
|
||||
configs.getOrDefault(configType, Collections.emptyList()))) {
|
||||
try {
|
||||
Object loaded = ((ConfigFactory) configType.getFactory()).build(
|
||||
selfLoader.load(configType.getTemplate(this, platform), config), platform);
|
||||
registry.register(config.getID(), loaded);
|
||||
platform.getEventManager().callEvent(
|
||||
new ConfigurationLoadEvent(this, config, template -> selfLoader.load(template, config), configType, loaded));
|
||||
} catch(DuplicateEntryException e) {
|
||||
throw new LoadException("Duplicate registry entry: ", e);
|
||||
}
|
||||
}
|
||||
platform.getEventManager().callEvent(new ConfigTypePostLoadEvent(configType, registry, this));
|
||||
}
|
||||
|
||||
platform.getEventManager().callEvent(new ConfigPackPostLoadEvent(this, template -> selfLoader.load(template, configuration)));
|
||||
logger.info("Loaded config pack \"{}\" v{} by {} in {}ms.",
|
||||
template.getID(), template.getVersion(), template.getAuthor(), (System.nanoTime() - start) / 1000000.0D);
|
||||
}
|
||||
|
||||
protected Map<Type, ImmutablePair<OpenRegistry<?>, CheckedRegistry<?>>> getRegistryMap() {
|
||||
return registryMap;
|
||||
}
|
||||
|
||||
public ConfigPackTemplate getTemplate() {
|
||||
return template;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> CheckedRegistry<T> getRegistry(Type type) {
|
||||
return (CheckedRegistry<T>) registryMap.getOrDefault(type, ImmutablePair.ofNull()).getRight();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T> CheckedRegistry<T> getCheckedRegistry(Type type) throws IllegalStateException {
|
||||
return (CheckedRegistry<T>) registryMap.getOrDefault(type, ImmutablePair.ofNull()).getRight();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected <T> OpenRegistry<T> getOpenRegistry(Class<T> clazz) {
|
||||
return (OpenRegistry<T>) registryMap.getOrDefault(clazz, ImmutablePair.ofNull()).getLeft();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getID() {
|
||||
return template.getID();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.config.pack;
|
||||
|
||||
import com.dfsek.tectonic.annotations.Value;
|
||||
import com.dfsek.tectonic.config.ConfigTemplate;
|
||||
|
||||
import com.dfsek.terra.api.config.meta.Meta;
|
||||
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
|
||||
|
||||
|
||||
public class ConfigPackPostTemplate implements ConfigTemplate {
|
||||
@Value("biomes")
|
||||
private @Meta BiomeProvider providerBuilder;
|
||||
|
||||
public BiomeProvider getProviderBuilder() {
|
||||
return providerBuilder;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.config.pack;
|
||||
|
||||
import com.dfsek.tectonic.annotations.Default;
|
||||
import com.dfsek.tectonic.annotations.Value;
|
||||
import com.dfsek.tectonic.config.ConfigTemplate;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.dfsek.terra.api.config.meta.Meta;
|
||||
import com.dfsek.terra.api.world.generator.ChunkGeneratorProvider;
|
||||
import com.dfsek.terra.api.world.generator.GenerationStageProvider;
|
||||
|
||||
|
||||
@SuppressWarnings({ "unused", "FieldMayBeFinal" })
|
||||
public class ConfigPackTemplate implements ConfigTemplate {
|
||||
@Value("id")
|
||||
private String id;
|
||||
|
||||
@Value("variables")
|
||||
@Default
|
||||
private @Meta Map<String, @Meta Double> variables = new HashMap<>();
|
||||
|
||||
@Value("beta.carving")
|
||||
@Default
|
||||
private @Meta boolean betaCarvers = false;
|
||||
|
||||
@Value("structures.locatable")
|
||||
@Default
|
||||
private @Meta Map<@Meta String, @Meta String> locatable = new HashMap<>();
|
||||
|
||||
@Value("blend.terrain.elevation")
|
||||
@Default
|
||||
private @Meta int elevationBlend = 4;
|
||||
|
||||
@Value("vanilla.mobs")
|
||||
@Default
|
||||
private @Meta boolean vanillaMobs = true;
|
||||
|
||||
@Value("vanilla.caves")
|
||||
@Default
|
||||
private @Meta boolean vanillaCaves = false;
|
||||
|
||||
@Value("vanilla.decorations")
|
||||
@Default
|
||||
private @Meta boolean vanillaDecorations = false;
|
||||
|
||||
@Value("vanilla.structures")
|
||||
@Default
|
||||
private @Meta boolean vanillaStructures = false;
|
||||
|
||||
@Value("author")
|
||||
@Default
|
||||
private String author = "Anon Y. Mous";
|
||||
|
||||
@Value("disable.sapling")
|
||||
@Default
|
||||
private @Meta boolean disableSaplings = false;
|
||||
|
||||
@Value("stages")
|
||||
private @Meta List<@Meta GenerationStageProvider> stages;
|
||||
|
||||
@Value("version")
|
||||
@Default
|
||||
private String version = "0.1.0";
|
||||
|
||||
@Value("disable.carvers")
|
||||
@Default
|
||||
private @Meta boolean disableCarvers = false;
|
||||
|
||||
@Value("disable.structures")
|
||||
@Default
|
||||
private @Meta boolean disableStructures = false;
|
||||
|
||||
@Value("disable.ores")
|
||||
@Default
|
||||
private @Meta boolean disableOres = false;
|
||||
|
||||
@Value("disable.trees")
|
||||
@Default
|
||||
private @Meta boolean disableTrees = false;
|
||||
|
||||
@Value("disable.flora")
|
||||
@Default
|
||||
private @Meta boolean disableFlora = false;
|
||||
|
||||
@Value("generator")
|
||||
private @Meta ChunkGeneratorProvider generatorProvider;
|
||||
|
||||
public boolean disableCarvers() {
|
||||
return disableCarvers;
|
||||
}
|
||||
|
||||
public boolean disableFlora() {
|
||||
return disableFlora;
|
||||
}
|
||||
|
||||
public boolean disableOres() {
|
||||
return disableOres;
|
||||
}
|
||||
|
||||
public boolean disableStructures() {
|
||||
return disableStructures;
|
||||
}
|
||||
|
||||
public boolean disableTrees() {
|
||||
return disableTrees;
|
||||
}
|
||||
|
||||
public boolean vanillaMobs() {
|
||||
return vanillaMobs;
|
||||
}
|
||||
|
||||
public boolean vanillaCaves() {
|
||||
return vanillaCaves;
|
||||
}
|
||||
|
||||
public boolean vanillaDecorations() {
|
||||
return vanillaDecorations;
|
||||
}
|
||||
|
||||
public boolean vanillaStructures() {
|
||||
return vanillaStructures;
|
||||
}
|
||||
|
||||
public boolean doBetaCarvers() {
|
||||
return betaCarvers;
|
||||
}
|
||||
|
||||
public ChunkGeneratorProvider getGeneratorProvider() {
|
||||
return generatorProvider;
|
||||
}
|
||||
|
||||
public List<GenerationStageProvider> getStages() {
|
||||
return stages;
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public boolean isDisableSaplings() {
|
||||
return disableSaplings;
|
||||
}
|
||||
|
||||
public String getID() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getAuthor() {
|
||||
return author;
|
||||
}
|
||||
|
||||
public Map<String, Double> getVariables() {
|
||||
return variables;
|
||||
}
|
||||
|
||||
public int getElevationBlend() {
|
||||
return elevationBlend;
|
||||
}
|
||||
|
||||
public Map<String, String> getLocatable() {
|
||||
return locatable;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.config.pack;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.dfsek.terra.api.Platform;
|
||||
import com.dfsek.terra.api.config.ConfigPack;
|
||||
import com.dfsek.terra.api.config.WorldConfig;
|
||||
import com.dfsek.terra.api.registry.Registry;
|
||||
import com.dfsek.terra.api.world.World;
|
||||
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
|
||||
import com.dfsek.terra.api.world.generator.SamplerCache;
|
||||
import com.dfsek.terra.registry.LockedRegistryImpl;
|
||||
import com.dfsek.terra.world.SamplerCacheImpl;
|
||||
|
||||
|
||||
public class WorldConfigImpl implements WorldConfig {
|
||||
private final SamplerCache samplerCache;
|
||||
|
||||
private final BiomeProvider provider;
|
||||
|
||||
private final World world;
|
||||
private final ConfigPackImpl pack;
|
||||
|
||||
private final Map<Type, Registry<?>> registryMap = new HashMap<>();
|
||||
|
||||
public WorldConfigImpl(World world, ConfigPackImpl pack, Platform platform) {
|
||||
this.world = world;
|
||||
this.pack = pack;
|
||||
this.samplerCache = new SamplerCacheImpl(platform, world);
|
||||
|
||||
pack.getRegistryMap().forEach((clazz, pair) -> registryMap.put(clazz, new LockedRegistryImpl<>(pair.getLeft())));
|
||||
|
||||
this.provider = pack.getBiomeProviderBuilder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int elevationBlend() {
|
||||
return pack.getTemplate().getElevationBlend();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean disableTrees() {
|
||||
return pack.getTemplate().disableTrees();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean disableCarving() {
|
||||
return pack.getTemplate().disableCarvers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean disableOres() {
|
||||
return pack.getTemplate().disableOres();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean disableFlora() {
|
||||
return pack.getTemplate().disableFlora();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean disableStructures() {
|
||||
return pack.getTemplate().disableStructures();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> Registry<T> getRegistry(Class<T> clazz) {
|
||||
return (LockedRegistryImpl<T>) registryMap.get(clazz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public World getWorld() {
|
||||
return world;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SamplerCache getSamplerCache() {
|
||||
return samplerCache;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeProvider getProvider() {
|
||||
return provider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigPack getPack() {
|
||||
return pack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAuthor() {
|
||||
return pack.getAuthor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return pack.getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getLocatable() {
|
||||
return pack.getLocatable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDisableSaplings() {
|
||||
return getTemplate().isDisableSaplings();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getID() {
|
||||
return pack.getID();
|
||||
}
|
||||
|
||||
public ConfigPackTemplate getTemplate() {
|
||||
return pack.getTemplate();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.config.preprocessor;
|
||||
|
||||
import com.dfsek.tectonic.config.Configuration;
|
||||
import com.dfsek.tectonic.exception.LoadException;
|
||||
import com.dfsek.tectonic.loading.ConfigLoader;
|
||||
import com.dfsek.tectonic.preprocessor.Result;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.reflect.AnnotatedType;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.dfsek.terra.api.config.meta.Meta;
|
||||
|
||||
|
||||
public class MetaListLikePreprocessor extends MetaPreprocessor<Meta> {
|
||||
public MetaListLikePreprocessor(Map<String, Configuration> configs) {
|
||||
super(configs);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public @NotNull <T> Result<T> process(AnnotatedType t, T c, ConfigLoader loader, Meta annotation) {
|
||||
if(t.getType() instanceof ParameterizedType) {
|
||||
ParameterizedType parameterizedType = (ParameterizedType) t.getType();
|
||||
if(parameterizedType.getRawType() instanceof Class) { // Should always be true but we check anyways
|
||||
Class<?> baseClass = (Class<?>) parameterizedType.getRawType();
|
||||
|
||||
if((List.class.isAssignableFrom(baseClass) || Set.class.isAssignableFrom(baseClass)) &&
|
||||
c instanceof List) { // List or set metaconfig
|
||||
List<Object> list = (List<Object>) c;
|
||||
|
||||
int offset = 0;
|
||||
List<Object> newList = new ArrayList<>((List<Object>) c);
|
||||
|
||||
for(int i = 0; i < list.size(); i++) {
|
||||
Object o = list.get(i);
|
||||
if(!(o instanceof String)) continue;
|
||||
String s = ((String) o).trim();
|
||||
if(!s.startsWith("<< ")) continue;
|
||||
String meta = s.substring(3);
|
||||
|
||||
Object metaValue = getMetaValue(meta);
|
||||
|
||||
if(!(metaValue instanceof List)) {
|
||||
throw new LoadException(
|
||||
"MetaList/Set injection candidate must be list, is type " + metaValue.getClass().getCanonicalName());
|
||||
}
|
||||
|
||||
List<Object> metaList = (List<Object>) metaValue;
|
||||
|
||||
newList.remove(i + offset); // Remove placeholder
|
||||
newList.addAll(i + offset, metaList); // Add metalist values where placeholder was
|
||||
offset += metaList.size() - 1; // add metalist size to offset, subtract one to account for placeholder.
|
||||
}
|
||||
|
||||
return (Result<T>) Result.overwrite(newList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Result.noOp();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.config.preprocessor;
|
||||
|
||||
import com.dfsek.tectonic.config.Configuration;
|
||||
import com.dfsek.tectonic.exception.LoadException;
|
||||
import com.dfsek.tectonic.loading.ConfigLoader;
|
||||
import com.dfsek.tectonic.preprocessor.Result;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.reflect.AnnotatedType;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.dfsek.terra.api.config.meta.Meta;
|
||||
import com.dfsek.terra.api.util.reflection.TypeKey;
|
||||
|
||||
|
||||
public class MetaMapPreprocessor extends MetaPreprocessor<Meta> {
|
||||
private static final TypeKey<List<String>> STRING_LIST = new TypeKey<>() {
|
||||
};
|
||||
|
||||
public MetaMapPreprocessor(Map<String, Configuration> configs) {
|
||||
super(configs);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public @NotNull <T> Result<T> process(AnnotatedType t, T c, ConfigLoader loader, Meta annotation) {
|
||||
if(t.getType() instanceof ParameterizedType) {
|
||||
ParameterizedType parameterizedType = (ParameterizedType) t.getType();
|
||||
if(parameterizedType.getRawType() instanceof Class) { // Should always be true but we check anyways
|
||||
Class<?> baseClass = (Class<?>) parameterizedType.getRawType();
|
||||
|
||||
if(Map.class.isAssignableFrom(baseClass) && c instanceof Map) { // Map metaconfig
|
||||
Map<Object, Object> map = (Map<Object, Object>) c;
|
||||
|
||||
Map<Object, Object> newMap = new HashMap<>(map);
|
||||
|
||||
if(map.containsKey("<<")) {
|
||||
newMap.putAll(map);
|
||||
newMap.remove("<<"); // Remove placeholder
|
||||
|
||||
List<String> keys = (List<String>) loader.loadType(STRING_LIST.getAnnotatedType(), map.get("<<"));
|
||||
keys.forEach(key -> {
|
||||
Object meta = getMetaValue(key);
|
||||
if(!(meta instanceof Map)) {
|
||||
throw new LoadException(
|
||||
"MetaMap injection candidate must be list, is type " + meta.getClass().getCanonicalName());
|
||||
}
|
||||
newMap.putAll((Map<?, ?>) meta);
|
||||
});
|
||||
return (Result<T>) Result.overwrite(newMap);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Result.noOp();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.config.preprocessor;
|
||||
|
||||
import com.dfsek.paralithic.eval.parser.Parser;
|
||||
import com.dfsek.paralithic.eval.tokenizer.ParseException;
|
||||
import com.dfsek.tectonic.config.Configuration;
|
||||
import com.dfsek.tectonic.exception.LoadException;
|
||||
import com.dfsek.tectonic.loading.ConfigLoader;
|
||||
import com.dfsek.tectonic.preprocessor.Result;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.reflect.AnnotatedType;
|
||||
import java.util.Map;
|
||||
|
||||
import com.dfsek.terra.api.config.meta.Meta;
|
||||
import com.dfsek.terra.api.util.reflection.TypeKey;
|
||||
|
||||
|
||||
public class MetaNumberPreprocessor extends MetaPreprocessor<Meta> {
|
||||
public static final TypeKey<String> META_STRING_KEY = new TypeKey<@Meta String>() {
|
||||
};
|
||||
|
||||
public MetaNumberPreprocessor(Map<String, Configuration> configs) {
|
||||
super(configs);
|
||||
}
|
||||
|
||||
private static boolean isNumber(Class<?> clazz) {
|
||||
return Number.class.isAssignableFrom(clazz)
|
||||
|| byte.class.equals(clazz)
|
||||
|| int.class.equals(clazz)
|
||||
|| long.class.equals(clazz)
|
||||
|| float.class.equals(clazz)
|
||||
|| double.class.equals(clazz);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public @NotNull <T> Result<T> process(AnnotatedType t, T c, ConfigLoader loader, Meta annotation) {
|
||||
if(t.getType() instanceof Class && isNumber((Class<?>) t.getType()) && c instanceof String) {
|
||||
String expression = (String) loader.loadType(META_STRING_KEY.getAnnotatedType(), c);
|
||||
try {
|
||||
return (Result<T>) Result.overwrite(new Parser().parse(expression).evaluate());
|
||||
} catch(ParseException e) {
|
||||
throw new LoadException("Invalid expression: ", e);
|
||||
}
|
||||
}
|
||||
return Result.noOp();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.config.preprocessor;
|
||||
|
||||
import com.dfsek.tectonic.config.Configuration;
|
||||
import com.dfsek.tectonic.exception.LoadException;
|
||||
import com.dfsek.tectonic.preprocessor.ValuePreprocessor;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
public abstract class MetaPreprocessor<A extends Annotation> implements ValuePreprocessor<A> {
|
||||
private final Map<String, Configuration> configs;
|
||||
|
||||
public MetaPreprocessor(Map<String, Configuration> configs) {
|
||||
this.configs = configs;
|
||||
}
|
||||
|
||||
protected Object getMetaValue(String meta) {
|
||||
int sep = meta.indexOf(':');
|
||||
String file = meta.substring(0, sep);
|
||||
String key = meta.substring(sep + 1);
|
||||
|
||||
if(!configs.containsKey(file)) throw new LoadException("Cannot fetch metavalue: No such config: " + file);
|
||||
|
||||
Configuration config = configs.get(file);
|
||||
|
||||
if(!config.contains(key)) {
|
||||
throw new LoadException("Cannot fetch metavalue: No such key " + key + " in configuration " + config.getName());
|
||||
}
|
||||
|
||||
return config.get(key);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.config.preprocessor;
|
||||
|
||||
import com.dfsek.tectonic.config.Configuration;
|
||||
import com.dfsek.tectonic.exception.LoadException;
|
||||
import com.dfsek.tectonic.loading.ConfigLoader;
|
||||
import com.dfsek.tectonic.preprocessor.Result;
|
||||
import org.apache.commons.text.StringSubstitutor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.reflect.AnnotatedType;
|
||||
import java.util.Map;
|
||||
|
||||
import com.dfsek.terra.api.config.meta.Meta;
|
||||
|
||||
|
||||
public class MetaStringPreprocessor extends MetaPreprocessor<Meta> {
|
||||
public MetaStringPreprocessor(Map<String, Configuration> configs) {
|
||||
super(configs);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public @NotNull <T> Result<T> process(AnnotatedType t, T c, ConfigLoader loader, Meta annotation) {
|
||||
if(String.class.equals(t.getType()) && c instanceof String candidate) { // String is final so we use #equals
|
||||
StringSubstitutor substitutor = new StringSubstitutor(key -> {
|
||||
Object meta = getMetaValue(key);
|
||||
if(!(meta instanceof String) && !(meta instanceof Number) && !(meta instanceof Character) && !(meta instanceof Boolean)) {
|
||||
throw new LoadException("MetaString template injection candidate must be string or primitive, is type " +
|
||||
meta.getClass().getCanonicalName());
|
||||
}
|
||||
return meta.toString();
|
||||
});
|
||||
return (Result<T>) Result.overwrite(substitutor.replace(candidate));
|
||||
}
|
||||
return Result.noOp();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.config.preprocessor;
|
||||
|
||||
import com.dfsek.tectonic.config.Configuration;
|
||||
import com.dfsek.tectonic.loading.ConfigLoader;
|
||||
import com.dfsek.tectonic.preprocessor.Result;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.reflect.AnnotatedType;
|
||||
import java.util.Map;
|
||||
|
||||
import com.dfsek.terra.api.config.meta.Meta;
|
||||
|
||||
|
||||
public class MetaValuePreprocessor extends MetaPreprocessor<Meta> {
|
||||
|
||||
public MetaValuePreprocessor(Map<String, Configuration> configs) {
|
||||
super(configs);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public @NotNull <T> Result<T> process(AnnotatedType t, T c, ConfigLoader configLoader, Meta annotation) {
|
||||
if(c instanceof String) { // Can we do standard metaconfig?
|
||||
String value = ((String) c).trim();
|
||||
if(value.startsWith("$")) { // it's a meta value.
|
||||
return (Result<T>) Result.overwrite(getMetaValue(value.substring(1)));
|
||||
}
|
||||
}
|
||||
return Result.noOp();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.config.prototype;
|
||||
|
||||
import com.dfsek.tectonic.annotations.Value;
|
||||
import com.dfsek.tectonic.config.ConfigTemplate;
|
||||
|
||||
import com.dfsek.terra.api.config.ConfigType;
|
||||
|
||||
|
||||
public class ProtoConfig implements ConfigTemplate {
|
||||
@Value("id")
|
||||
private String id;
|
||||
|
||||
@Value("type")
|
||||
private ConfigType<?, ?> type;
|
||||
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public ConfigType<?, ?> getType() {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.event;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import com.dfsek.terra.api.addon.BaseAddon;
|
||||
import com.dfsek.terra.api.event.events.Event;
|
||||
import com.dfsek.terra.api.event.events.FailThroughEvent;
|
||||
import com.dfsek.terra.api.event.functional.EventContext;
|
||||
import com.dfsek.terra.api.util.reflection.ReflectionUtil;
|
||||
|
||||
|
||||
public class EventContextImpl<T extends Event> implements EventContext<T>, Comparable<EventContextImpl<?>> {
|
||||
private final List<Consumer<T>> actions = new ArrayList<>();
|
||||
private final BaseAddon addon;
|
||||
private final Type eventType;
|
||||
private final FunctionalEventHandlerImpl parent;
|
||||
private int priority;
|
||||
private boolean failThrough = false;
|
||||
private boolean global = false;
|
||||
|
||||
public EventContextImpl(BaseAddon addon, Type eventType, FunctionalEventHandlerImpl parent) {
|
||||
this.addon = addon;
|
||||
this.eventType = eventType;
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public void handle(T event) {
|
||||
actions.forEach(action -> action.accept(event));
|
||||
}
|
||||
|
||||
@Override
|
||||
public EventContext<T> then(Consumer<T> action) {
|
||||
actions.add(action);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EventContext<T> priority(int priority) {
|
||||
this.priority = priority;
|
||||
parent.recomputePriorities(eventType);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EventContext<T> failThrough() {
|
||||
if(!FailThroughEvent.class.isAssignableFrom(ReflectionUtil.getRawType(eventType))) {
|
||||
throw new IllegalStateException(
|
||||
"Cannot fail-through on event which does not implement FailThroughEvent: " + ReflectionUtil.typeToString(eventType));
|
||||
}
|
||||
this.failThrough = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EventContext<T> global() {
|
||||
this.global = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(@NotNull EventContextImpl<?> o) {
|
||||
return this.priority - o.priority;
|
||||
}
|
||||
|
||||
public boolean isGlobal() {
|
||||
return global;
|
||||
}
|
||||
|
||||
public int getPriority() {
|
||||
return priority;
|
||||
}
|
||||
|
||||
public BaseAddon getAddon() {
|
||||
return addon;
|
||||
}
|
||||
|
||||
public boolean isFailThrough() {
|
||||
return failThrough;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.event;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.dfsek.terra.api.event.EventHandler;
|
||||
import com.dfsek.terra.api.event.EventManager;
|
||||
import com.dfsek.terra.api.event.events.Event;
|
||||
import com.dfsek.terra.api.event.functional.FunctionalEventHandler;
|
||||
|
||||
|
||||
public class EventManagerImpl implements EventManager {
|
||||
private final Map<Class<?>, EventHandler> handlers = new HashMap<>();
|
||||
|
||||
public EventManagerImpl() {
|
||||
registerHandler(FunctionalEventHandler.class, new FunctionalEventHandlerImpl()); // default handler
|
||||
}
|
||||
|
||||
@Override
|
||||
public void callEvent(Event event) {
|
||||
handlers.values().forEach(handler -> handler.handle(event));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends EventHandler> void registerHandler(Class<T> clazz, T handler) {
|
||||
handlers.put(clazz, handler);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T extends EventHandler> T getHandler(Class<T> clazz) {
|
||||
return (T) handlers.computeIfAbsent(clazz, c -> {
|
||||
throw new IllegalArgumentException("No event handler registered for class " + clazz.getCanonicalName());
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.event;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.dfsek.terra.api.addon.BaseAddon;
|
||||
import com.dfsek.terra.api.event.events.Event;
|
||||
import com.dfsek.terra.api.event.events.FailThroughEvent;
|
||||
import com.dfsek.terra.api.event.events.PackEvent;
|
||||
import com.dfsek.terra.api.event.functional.EventContext;
|
||||
import com.dfsek.terra.api.event.functional.FunctionalEventHandler;
|
||||
import com.dfsek.terra.api.util.reflection.TypeKey;
|
||||
|
||||
|
||||
public class FunctionalEventHandlerImpl implements FunctionalEventHandler {
|
||||
private static final Logger logger = LoggerFactory.getLogger(FunctionalEventHandlerImpl.class);
|
||||
|
||||
private final Map<Type, List<EventContextImpl<?>>> contextMap = new HashMap<>();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void handle(Event event) {
|
||||
contextMap.getOrDefault(event.getClass(), Collections.emptyList()).forEach(context -> {
|
||||
try {
|
||||
if(event instanceof PackEvent) {
|
||||
if((context.isGlobal() || ((PackEvent) event).getPack().addons().containsKey(context.getAddon()))) {
|
||||
((EventContextImpl<Event>) context).handle(event);
|
||||
}
|
||||
} else {
|
||||
((EventContextImpl<Event>) context).handle(event);
|
||||
}
|
||||
} catch(Exception e) {
|
||||
if(context.isFailThrough() && event instanceof FailThroughEvent)
|
||||
throw e; // Rethrow if it's fail-through.
|
||||
// else warn
|
||||
logger.warn("Exception occurred during event handling. Report this to the maintainers of {}@{}",
|
||||
context.getAddon().getID(), context.getAddon().getVersion().getFormatted(), e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Event> EventContext<T> register(BaseAddon addon, Class<T> clazz) {
|
||||
EventContextImpl<T> eventContext = new EventContextImpl<>(addon, clazz, this);
|
||||
contextMap.computeIfAbsent(clazz, c -> new ArrayList<>()).add(eventContext);
|
||||
return eventContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Event> EventContext<T> register(BaseAddon addon, TypeKey<T> clazz) {
|
||||
EventContextImpl<T> eventContext = new EventContextImpl<>(addon, clazz.getType(), this);
|
||||
contextMap.computeIfAbsent(clazz.getType(), c -> new ArrayList<>()).add(eventContext);
|
||||
return eventContext;
|
||||
}
|
||||
|
||||
public void recomputePriorities(Type target) {
|
||||
contextMap.get(target).sort(Comparator.naturalOrder());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.math;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import com.dfsek.terra.api.util.PopulationUtil;
|
||||
import com.dfsek.terra.api.util.vector.Vector3;
|
||||
import com.dfsek.terra.util.FastRandom;
|
||||
|
||||
|
||||
/**
|
||||
* Class to procedurally determine the spawn point of an object based on a grid with padding between cells.
|
||||
*/
|
||||
public class GridSpawn implements com.dfsek.terra.api.structure.StructureSpawn {
|
||||
private final int separation;
|
||||
private final int width;
|
||||
private final int salt;
|
||||
|
||||
public GridSpawn(int width, int separation, int salt) {
|
||||
this.separation = separation;
|
||||
this.width = width;
|
||||
this.salt = salt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector3 getNearestSpawn(int x, int z, long seed) {
|
||||
int structureChunkX = x / (width + 2 * separation);
|
||||
int structureChunkZ = z / (width + 2 * separation);
|
||||
List<Vector3> zones = new ArrayList<>(9);
|
||||
for(int xi = structureChunkX - 1; xi <= structureChunkX + 1; xi++) {
|
||||
for(int zi = structureChunkZ - 1; zi <= structureChunkZ + 1; zi++) {
|
||||
zones.add(getChunkSpawn(xi, zi, seed));
|
||||
}
|
||||
}
|
||||
Vector3 shortest = zones.get(0);
|
||||
Vector3 compare = new Vector3(x, 0, z);
|
||||
for(Vector3 v : zones) {
|
||||
if(compare.distanceSquared(shortest) > compare.distanceSquared(v)) shortest = v.clone();
|
||||
}
|
||||
return shortest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the X/Z coordinates of the spawn point in the nearest Chunk (not Minecraft chunk)
|
||||
*
|
||||
* @param structureChunkX Chunk X coordinate
|
||||
* @param structureChunkZ Chunk Z coordinate
|
||||
* @param seed Seed for RNG
|
||||
*
|
||||
* @return Vector representing spawnpoint
|
||||
*/
|
||||
public Vector3 getChunkSpawn(int structureChunkX, int structureChunkZ, long seed) {
|
||||
Random r = new FastRandom(PopulationUtil.getCarverChunkSeed(structureChunkX, structureChunkZ, seed + salt));
|
||||
int offsetX = r.nextInt(width);
|
||||
int offsetZ = r.nextInt(width);
|
||||
int sx = structureChunkX * (width + 2 * separation) + offsetX;
|
||||
int sz = structureChunkZ * (width + 2 * separation) + offsetZ;
|
||||
return new Vector3(sx, 0, sz);
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
public int getSeparation() {
|
||||
return separation;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.profiler;
|
||||
|
||||
public class Frame {
|
||||
private final String id;
|
||||
private final long start;
|
||||
|
||||
public Frame(String id) {
|
||||
this.id = id;
|
||||
this.start = System.nanoTime();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public long getStart() {
|
||||
return start;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.profiler;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Stack;
|
||||
|
||||
import com.dfsek.terra.api.profiler.Profiler;
|
||||
import com.dfsek.terra.api.profiler.Timings;
|
||||
import com.dfsek.terra.api.util.mutable.MutableInteger;
|
||||
import com.dfsek.terra.profiler.exception.MalformedStackException;
|
||||
|
||||
|
||||
public class ProfilerImpl implements Profiler {
|
||||
private static final Logger logger = LoggerFactory.getLogger(ProfilerImpl.class);
|
||||
|
||||
private static final ThreadLocal<Stack<Frame>> THREAD_STACK = ThreadLocal.withInitial(Stack::new);
|
||||
private static final ThreadLocal<Map<String, List<Long>>> TIMINGS = ThreadLocal.withInitial(HashMap::new);
|
||||
private static final ThreadLocal<Boolean> SAFE = ThreadLocal.withInitial(() -> false);
|
||||
private static final ThreadLocal<MutableInteger> STACK_SIZE = ThreadLocal.withInitial(() -> new MutableInteger(0));
|
||||
private static boolean instantiated = false;
|
||||
private final List<Map<String, List<Long>>> accessibleThreadMaps = new ArrayList<>();
|
||||
private volatile boolean running = false;
|
||||
|
||||
public ProfilerImpl() {
|
||||
if(instantiated)
|
||||
throw new IllegalStateException("Only one instance of Profiler may exist!");
|
||||
instantiated = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void push(String frame) {
|
||||
STACK_SIZE.get().increment();
|
||||
if(running && SAFE.get()) {
|
||||
Stack<Frame> stack = THREAD_STACK.get();
|
||||
stack.push(new Frame(stack.isEmpty() ? frame : stack.peek().getId() + "." + frame));
|
||||
} else SAFE.set(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pop(String frame) {
|
||||
MutableInteger size = STACK_SIZE.get();
|
||||
size.decrement();
|
||||
if(running && SAFE.get()) {
|
||||
long time = System.nanoTime();
|
||||
Stack<Frame> stack = THREAD_STACK.get();
|
||||
|
||||
Map<String, List<Long>> timingsMap = TIMINGS.get();
|
||||
|
||||
if(timingsMap.isEmpty()) {
|
||||
synchronized(accessibleThreadMaps) {
|
||||
accessibleThreadMaps.add(timingsMap);
|
||||
}
|
||||
}
|
||||
|
||||
Frame top = stack.pop();
|
||||
if(!stack.isEmpty() ? !top.getId().endsWith("." + frame) : !top.getId().equals(frame))
|
||||
throw new MalformedStackException("Expected " + frame + ", found " + top);
|
||||
|
||||
List<Long> timings = timingsMap.computeIfAbsent(top.getId(), id -> new ArrayList<>());
|
||||
|
||||
timings.add(time - top.getStart());
|
||||
}
|
||||
if(size.get() == 0) SAFE.set(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
logger.info("Starting Terra profiler");
|
||||
running = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
logger.info("Stopping Terra profiler");
|
||||
running = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
logger.info("Resetting Terra profiler");
|
||||
accessibleThreadMaps.forEach(Map::clear);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Timings> getTimings() {
|
||||
Map<String, Timings> map = new HashMap<>();
|
||||
accessibleThreadMaps.forEach(smap -> smap.forEach((key, list) -> {
|
||||
String[] keys = key.split("\\.");
|
||||
Timings timings = map.computeIfAbsent(keys[0], id -> new Timings());
|
||||
for(int i = 1; i < keys.length; i++) {
|
||||
timings = timings.getSubItem(keys[i]);
|
||||
}
|
||||
list.forEach(timings::addTime);
|
||||
}));
|
||||
return map;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.profiler.exception;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
|
||||
public class MalformedStackException extends ProfilerException {
|
||||
@Serial
|
||||
private static final long serialVersionUID = -3009539681021691054L;
|
||||
|
||||
public MalformedStackException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public MalformedStackException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public MalformedStackException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.profiler.exception;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
|
||||
public class ProfilerException extends RuntimeException {
|
||||
@Serial
|
||||
private static final long serialVersionUID = 8206737998791649002L;
|
||||
|
||||
public ProfilerException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public ProfilerException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public ProfilerException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.registry;
|
||||
|
||||
import com.dfsek.tectonic.exception.LoadException;
|
||||
import com.dfsek.tectonic.loading.ConfigLoader;
|
||||
|
||||
import java.lang.reflect.AnnotatedType;
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import com.dfsek.terra.api.registry.CheckedRegistry;
|
||||
import com.dfsek.terra.api.registry.OpenRegistry;
|
||||
import com.dfsek.terra.api.registry.exception.DuplicateEntryException;
|
||||
|
||||
|
||||
/**
|
||||
* Wrapper for a registry that ensures checked additions.
|
||||
*
|
||||
* @param <T> Type in registry
|
||||
*/
|
||||
public class CheckedRegistryImpl<T> implements CheckedRegistry<T> {
|
||||
private final OpenRegistry<T> registry;
|
||||
|
||||
public CheckedRegistryImpl(OpenRegistry<T> registry) {
|
||||
this.registry = registry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(String identifier, T value) throws DuplicateEntryException {
|
||||
registry.registerChecked(identifier, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T get(String identifier) {
|
||||
return registry.get(identifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(String identifier) {
|
||||
return registry.contains(identifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEach(Consumer<T> consumer) {
|
||||
registry.forEach(consumer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEach(BiConsumer<String, T> consumer) {
|
||||
registry.forEach(consumer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<T> entries() {
|
||||
return registry.entries();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> keys() {
|
||||
return registry.keys();
|
||||
}
|
||||
|
||||
@Override
|
||||
public T load(AnnotatedType t, Object c, ConfigLoader loader) throws LoadException {
|
||||
return registry.load(t, c, loader);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.registry;
|
||||
|
||||
import com.dfsek.tectonic.exception.LoadException;
|
||||
import com.dfsek.tectonic.loading.ConfigLoader;
|
||||
|
||||
import java.lang.reflect.AnnotatedType;
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import com.dfsek.terra.api.registry.Registry;
|
||||
|
||||
|
||||
/**
|
||||
* Wrapper for a registry that forbids all write access.
|
||||
*
|
||||
* @param <T> Type in registry
|
||||
*/
|
||||
public class LockedRegistryImpl<T> implements Registry<T> {
|
||||
private final Registry<T> registry;
|
||||
|
||||
public LockedRegistryImpl(Registry<T> registry) {
|
||||
this.registry = registry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T get(String identifier) {
|
||||
return registry.get(identifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(String identifier) {
|
||||
return registry.contains(identifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEach(Consumer<T> consumer) {
|
||||
registry.forEach(consumer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEach(BiConsumer<String, T> consumer) {
|
||||
registry.forEach(consumer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<T> entries() {
|
||||
return registry.entries();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> keys() {
|
||||
return registry.keys();
|
||||
}
|
||||
|
||||
@Override
|
||||
public T load(AnnotatedType t, Object c, ConfigLoader loader) throws LoadException {
|
||||
return registry.load(t, c, loader);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.registry;
|
||||
|
||||
import com.dfsek.tectonic.exception.LoadException;
|
||||
import com.dfsek.tectonic.loading.ConfigLoader;
|
||||
|
||||
import java.lang.reflect.AnnotatedType;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.dfsek.terra.api.registry.OpenRegistry;
|
||||
import com.dfsek.terra.api.registry.exception.DuplicateEntryException;
|
||||
|
||||
|
||||
/**
|
||||
* Registry implementation with read/write access. For internal use only.
|
||||
*
|
||||
* @param <T>
|
||||
*/
|
||||
public class OpenRegistryImpl<T> implements OpenRegistry<T> {
|
||||
private static final Entry<?> NULL = new Entry<>(null);
|
||||
private static final Pattern ID_PATTERN = Pattern.compile("^[a-zA-Z0-9_-]*$");
|
||||
private final Map<String, Entry<T>> objects;
|
||||
|
||||
public OpenRegistryImpl() {
|
||||
objects = new HashMap<>();
|
||||
}
|
||||
|
||||
protected OpenRegistryImpl(Map<String, Entry<T>> init) {
|
||||
this.objects = init;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T load(AnnotatedType type, Object o, ConfigLoader configLoader) throws LoadException {
|
||||
T obj = get((String) o);
|
||||
String list = objects.keySet().stream().sorted().reduce("", (a, b) -> a + "\n - " + b);
|
||||
|
||||
if(objects.isEmpty()) list = "[ ]";
|
||||
|
||||
if(obj == null)
|
||||
throw new LoadException("No such " + type.getType().getTypeName() + " matching \"" + o +
|
||||
"\" was found in this registry. Registry contains items: " + list);
|
||||
return obj;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean register(String identifier, T value) {
|
||||
return register(identifier, new Entry<>(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerChecked(String identifier, T value) throws DuplicateEntryException {
|
||||
if(objects.containsKey(identifier))
|
||||
throw new DuplicateEntryException("Value with identifier \"" + identifier + "\" is already defined in registry.");
|
||||
register(identifier, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
objects.clear();
|
||||
}
|
||||
|
||||
public boolean register(String identifier, Entry<T> value) {
|
||||
if(!ID_PATTERN.matcher(identifier).matches())
|
||||
throw new IllegalArgumentException(
|
||||
"Registry ID must only contain alphanumeric characters, hyphens, and underscores. \"" + identifier +
|
||||
"\" is not a valid ID.");
|
||||
boolean exists = objects.containsKey(identifier);
|
||||
objects.put(identifier, value);
|
||||
return exists;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public T get(String identifier) {
|
||||
return objects.getOrDefault(identifier, (Entry<T>) NULL).getValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(String identifier) {
|
||||
return objects.containsKey(identifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEach(Consumer<T> consumer) {
|
||||
objects.forEach((id, obj) -> consumer.accept(obj.getRaw()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEach(BiConsumer<String, T> consumer) {
|
||||
objects.forEach((id, entry) -> consumer.accept(id, entry.getRaw()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<T> entries() {
|
||||
return objects.values().stream().map(Entry::getRaw).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> keys() {
|
||||
return objects.keySet();
|
||||
}
|
||||
|
||||
public Map<String, T> getDeadEntries() {
|
||||
Map<String, T> dead = new HashMap<>();
|
||||
objects.forEach((id, entry) -> {
|
||||
if(entry.dead()) dead.put(id, entry.value); // dont increment value here.
|
||||
});
|
||||
return dead;
|
||||
}
|
||||
|
||||
|
||||
protected static final class Entry<T> {
|
||||
private final T value;
|
||||
private final AtomicInteger access = new AtomicInteger(0);
|
||||
|
||||
public Entry(T value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public boolean dead() {
|
||||
return access.get() == 0;
|
||||
}
|
||||
|
||||
public T getValue() {
|
||||
access.incrementAndGet();
|
||||
return value;
|
||||
}
|
||||
|
||||
private T getRaw() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.registry;
|
||||
|
||||
import com.dfsek.tectonic.exception.LoadException;
|
||||
import com.dfsek.tectonic.loading.ConfigLoader;
|
||||
import com.dfsek.tectonic.loading.TypeLoader;
|
||||
|
||||
import java.lang.reflect.AnnotatedType;
|
||||
import java.util.function.Function;
|
||||
|
||||
import com.dfsek.terra.api.registry.OpenRegistry;
|
||||
import com.dfsek.terra.api.registry.meta.RegistryFactory;
|
||||
import com.dfsek.terra.api.util.generic.Lazy;
|
||||
|
||||
|
||||
public class RegistryFactoryImpl implements RegistryFactory {
|
||||
@Override
|
||||
public <T> OpenRegistry<T> create() {
|
||||
return new OpenRegistryImpl<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> OpenRegistry<T> create(Function<OpenRegistry<T>, TypeLoader<T>> loader) {
|
||||
return new OpenRegistryImpl<>() {
|
||||
private final Lazy<TypeLoader<T>> loaderCache = Lazy.lazy(() -> loader.apply(this));
|
||||
|
||||
@Override
|
||||
public T load(AnnotatedType type, Object o, ConfigLoader configLoader) throws LoadException {
|
||||
return loaderCache.value().load(type, o, configLoader);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.registry.config;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
import com.dfsek.terra.api.Platform;
|
||||
import com.dfsek.terra.api.config.ConfigType;
|
||||
import com.dfsek.terra.api.util.reflection.ReflectionUtil;
|
||||
import com.dfsek.terra.registry.OpenRegistryImpl;
|
||||
|
||||
|
||||
public class ConfigTypeRegistry extends OpenRegistryImpl<ConfigType<?, ?>> {
|
||||
private static final Logger logger = LoggerFactory.getLogger(ConfigTypeRegistry.class);
|
||||
|
||||
private final BiConsumer<String, ConfigType<?, ?>> callback;
|
||||
|
||||
private final Platform platform;
|
||||
|
||||
public ConfigTypeRegistry(Platform platform, BiConsumer<String, ConfigType<?, ?>> callback) {
|
||||
super(new LinkedHashMap<>()); // Ordered
|
||||
this.callback = callback;
|
||||
this.platform = platform;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean register(String identifier, Entry<ConfigType<?, ?>> value) {
|
||||
callback.accept(identifier, value.getValue());
|
||||
logger.debug("Registered config registry with ID {} to type {}", identifier,
|
||||
ReflectionUtil.typeToString(value.getValue().getTypeKey().getType()));
|
||||
return super.register(identifier, value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.registry.master;
|
||||
|
||||
import com.dfsek.tectonic.exception.ConfigException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
import com.dfsek.terra.api.Platform;
|
||||
import com.dfsek.terra.api.config.ConfigPack;
|
||||
import com.dfsek.terra.config.pack.ConfigPackImpl;
|
||||
import com.dfsek.terra.registry.OpenRegistryImpl;
|
||||
|
||||
|
||||
/**
|
||||
* Class to hold config packs
|
||||
*/
|
||||
public class ConfigRegistry extends OpenRegistryImpl<ConfigPack> {
|
||||
private static final Logger logger = LoggerFactory.getLogger(ConfigRegistry.class);
|
||||
|
||||
public void load(File folder, Platform platform) throws ConfigException {
|
||||
ConfigPack pack = new ConfigPackImpl(folder, platform);
|
||||
register(pack.getID(), pack);
|
||||
}
|
||||
|
||||
public boolean loadAll(Platform platform) {
|
||||
boolean valid = true;
|
||||
File packsFolder = new File(platform.getDataFolder(), "packs");
|
||||
packsFolder.mkdirs();
|
||||
for(File dir : packsFolder.listFiles(File::isDirectory)) {
|
||||
try {
|
||||
load(dir, platform);
|
||||
} catch(ConfigException e) {
|
||||
logger.error("Error loading config pack {}", dir.getName(), e);
|
||||
valid = false;
|
||||
}
|
||||
}
|
||||
for(File zip : packsFolder.listFiles(file -> file.getName().endsWith(".zip") || file.getName().endsWith(".terra"))) {
|
||||
try {
|
||||
logger.info("Loading ZIP archive: " + zip.getName());
|
||||
load(new ZipFile(zip), platform);
|
||||
} catch(IOException | ConfigException e) {
|
||||
logger.error("Error loading config pack {}", zip.getName(), e);
|
||||
valid = false;
|
||||
}
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
public void load(ZipFile file, Platform platform) throws ConfigException {
|
||||
ConfigPackImpl pack = new ConfigPackImpl(file, platform);
|
||||
register(pack.getTemplate().getID(), pack);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.transform;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.dfsek.terra.api.transform.Transform;
|
||||
import com.dfsek.terra.api.transform.exception.TransformException;
|
||||
|
||||
|
||||
public class MapTransform<F, T> implements Transform<F, T> {
|
||||
private final Map<F, T> map;
|
||||
|
||||
public MapTransform(Map<F, T> map) {
|
||||
this.map = map;
|
||||
}
|
||||
|
||||
public MapTransform() {
|
||||
this.map = new HashMap<>();
|
||||
}
|
||||
|
||||
public MapTransform<F, T> add(F from, T to) {
|
||||
map.put(from, to);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MapTransform<F, T> remove(F from) {
|
||||
map.remove(from);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T transform(F input) throws TransformException {
|
||||
if(!map.containsKey(input)) throw new TransformException("No key matching " + input.toString() + " found in map.");
|
||||
return map.get(input);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.transform;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.dfsek.terra.api.transform.Transform;
|
||||
import com.dfsek.terra.api.transform.Transformer;
|
||||
import com.dfsek.terra.api.transform.Validator;
|
||||
import com.dfsek.terra.api.transform.exception.AttemptsFailedException;
|
||||
import com.dfsek.terra.api.transform.exception.TransformException;
|
||||
|
||||
|
||||
/**
|
||||
* Class to translate types from one style/platform to another.
|
||||
*
|
||||
* @param <F> Data type to transform from.
|
||||
* @param <T> Data type to transform to.
|
||||
*/
|
||||
public class TransformerImpl<F, T> implements Transformer<F, T> {
|
||||
private final LinkedHashMap<Transform<F, T>, List<Validator<T>>> transformers;
|
||||
|
||||
private TransformerImpl(LinkedHashMap<Transform<F, T>, List<Validator<T>>> transformer) {
|
||||
this.transformers = transformer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T translate(F from) {
|
||||
List<Throwable> exceptions = new ArrayList<>();
|
||||
for(Map.Entry<Transform<F, T>, List<Validator<T>>> transform : transformers.entrySet()) {
|
||||
try {
|
||||
T result = transform.getKey().transform(from);
|
||||
for(Validator<T> validator : transform.getValue()) {
|
||||
if(!validator.validate(result)) {
|
||||
throw new TransformException("Failed to validate result: " + result.toString());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
} catch(Exception exception) {
|
||||
exceptions.add(exception);
|
||||
}
|
||||
}
|
||||
throw new AttemptsFailedException("Could not transform input; all attempts failed: " + from.toString() + "\n", exceptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder pattern for building Transformers
|
||||
*
|
||||
* @param <T>
|
||||
* @param <F>
|
||||
*/
|
||||
public static final class Builder<F, T> {
|
||||
private final LinkedHashMap<Transform<F, T>, List<Validator<T>>> transforms = new LinkedHashMap<>();
|
||||
|
||||
@SafeVarargs
|
||||
@SuppressWarnings("varargs")
|
||||
public final Builder<F, T> addTransform(Transform<F, T> transform, Validator<T>... validators) {
|
||||
transforms.put(transform, Arrays.asList(validators));
|
||||
return this;
|
||||
}
|
||||
|
||||
public TransformerImpl<F, T> build() {
|
||||
return new TransformerImpl<>(transforms);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.util;
|
||||
|
||||
|
||||
import org.apache.commons.rng.core.source64.XoRoShiRo128PlusPlus;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.util.Random;
|
||||
import java.util.SplittableRandom;
|
||||
|
||||
|
||||
public class FastRandom extends Random {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 4571946470190183260L;
|
||||
private XoRoShiRo128PlusPlus random;
|
||||
|
||||
public FastRandom() {
|
||||
super();
|
||||
SplittableRandom randomseed = new SplittableRandom();
|
||||
this.random = new XoRoShiRo128PlusPlus(randomseed.nextLong(), randomseed.nextLong());
|
||||
}
|
||||
|
||||
public FastRandom(long seed) {
|
||||
super(seed);
|
||||
SplittableRandom randomseed = new SplittableRandom(seed);
|
||||
this.random = new XoRoShiRo128PlusPlus(randomseed.nextLong(), randomseed.nextLong());
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void setSeed(long seed) {
|
||||
SplittableRandom randomseed = new SplittableRandom(seed);
|
||||
this.random = new XoRoShiRo128PlusPlus(randomseed.nextLong(), randomseed.nextLong());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void nextBytes(byte[] bytes) {
|
||||
random.nextBytes(bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int nextInt() {
|
||||
return random.nextInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int nextInt(int bound) {
|
||||
return random.nextInt(bound);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long nextLong() {
|
||||
return random.nextLong();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean nextBoolean() {
|
||||
return random.nextBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float nextFloat() {
|
||||
return (float) random.nextDouble();
|
||||
}
|
||||
|
||||
@Override
|
||||
public double nextDouble() {
|
||||
return random.nextDouble();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.world;
|
||||
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import net.jafama.FastMath;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import com.dfsek.terra.api.Platform;
|
||||
import com.dfsek.terra.api.util.MathUtil;
|
||||
import com.dfsek.terra.api.util.math.Sampler;
|
||||
import com.dfsek.terra.api.world.World;
|
||||
|
||||
|
||||
public class SamplerCacheImpl implements com.dfsek.terra.api.world.generator.SamplerCache {
|
||||
private final LoadingCache<Long, Sampler> cache;
|
||||
|
||||
public SamplerCacheImpl(Platform platform, World world) {
|
||||
cache = CacheBuilder.newBuilder().maximumSize(platform.getTerraConfig().getSamplerCache())
|
||||
.build(new CacheLoader<>() {
|
||||
@Override
|
||||
public Sampler load(@NotNull Long key) {
|
||||
int cx = (int) (key >> 32);
|
||||
int cz = (int) key.longValue();
|
||||
return world.getGenerator().createSampler(cx, cz, world.getBiomeProvider(), world,
|
||||
world.getConfig().elevationBlend());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Sampler get(int x, int z) {
|
||||
int cx = FastMath.floorDiv(x, 16);
|
||||
int cz = FastMath.floorDiv(z, 16);
|
||||
return getChunk(cx, cz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
cache.invalidateAll();
|
||||
cache.cleanUp();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Sampler getChunk(int cx, int cz) {
|
||||
long key = MathUtil.squash(cx, cz);
|
||||
return cache.getUnchecked(key);
|
||||
}
|
||||
}
|
||||
16
common/implementation/base/src/main/resources/config.yml
Normal file
16
common/implementation/base/src/main/resources/config.yml
Normal file
@@ -0,0 +1,16 @@
|
||||
debug:
|
||||
commands: false
|
||||
log: false
|
||||
profiler: false
|
||||
script: false
|
||||
data-save: PT6M
|
||||
language: "en_us"
|
||||
dump-default: true
|
||||
biome-search-resolution: 4
|
||||
cache:
|
||||
carver: 512
|
||||
structure: 32
|
||||
sampler: 128
|
||||
biome-provider: 32
|
||||
script:
|
||||
max-recursion: 1000
|
||||
122
common/implementation/base/src/main/resources/lang/afr_sa.yml
Normal file
122
common/implementation/base/src/main/resources/lang/afr_sa.yml
Normal file
@@ -0,0 +1,122 @@
|
||||
enable:
|
||||
- "As u van Terra hou, oorweeg dit om die projek op Patreon te ondersteun!"
|
||||
- "U kry toegang tot eksperimentele funksies voordat dit vrygestel word!"
|
||||
- "Ondersteun die projek hier: https://www.patreon.com/dfsek"
|
||||
disable:
|
||||
- "Dankie dat u Terra gebruik!"
|
||||
command:
|
||||
debug-only: "Hierdie opdrag moet gebruik word as die ontfoutmodus geaktiveer is!"
|
||||
player-only: "Hierdie opdrag is slegs vir spelers!"
|
||||
invalid: "Ongeldige opdrag.(verwag %1$s argumente, argumente gevind is %2$s)."
|
||||
players-only: "Hierdie opdrag is slegs vir spelers."
|
||||
world: "This command must be executed in a Terra world!"
|
||||
reload: "Terra instel herlaai"
|
||||
reload-error: "Foute het voorgekom tydens die herlaai van Terra-konfigurasies. Gaan sien logboeke vir meer inligting."
|
||||
version: "Hierdie bediener gebruik die Terra-weergawe \"%s\""
|
||||
main-menu:
|
||||
- "--------------------Terra--------------------"
|
||||
- "Herlaai - Herlaai konfigurasiedata"
|
||||
- "bioom - Kry huidige bioom"
|
||||
- "erts - Genereer 'n ertsader op die plek waar u te staan kom (vir foutopsporing)"
|
||||
- "stoor-data - Stoor bevolkingsdata"
|
||||
- "struktuur - Laai en stoor strukture"
|
||||
- "profiel - Profielopsies"
|
||||
- "beeld - Beeld / GUI-opsies"
|
||||
biome:
|
||||
biome-found: "Bioom geleë te (%1$s, %2$s)"
|
||||
unable-to-locate: "Kan bioom nie opspoor nie."
|
||||
invalid-radius: "Ongeldige radius: \"%s\""
|
||||
invalid: "Ongeldige Biome-ID: \"%s\""
|
||||
in: "Jy is in \"%s\""
|
||||
packs:
|
||||
main: "Tans geïnstalleerde konfigurasiepakkette:"
|
||||
pack: " - %1$s v%3$s by %2$s"
|
||||
none: "Geen konfigurasiepakkette is geïnstalleer nie."
|
||||
ore:
|
||||
main-menu:
|
||||
- "---------------Terra/erts---------------"
|
||||
- "Genereer 'n ertsader by die blok waarna u kyk."
|
||||
out-of-range: "Blok buite bereik"
|
||||
invalid-ore: "Kan nie Erts vind nie \"%s\""
|
||||
geometry:
|
||||
main-menu:
|
||||
- "---------------Terra/meetkunde----------------"
|
||||
- "Verskeie opsporingsopdragte vir voxel-meetkunde"
|
||||
- "sfeer - Genereer 'n sfeer"
|
||||
- "vervorming - Genereer 'n misvormde sfeer"
|
||||
- "tube - Genereer 'n tube"
|
||||
deform:
|
||||
invalid-radius: "Ongeldige radius: \"%s\""
|
||||
invalid-deform: "Ongeldige vervorm: \"%s\""
|
||||
invalid-frequency: "Ongeldige frekwensie: \"%s\""
|
||||
sphere:
|
||||
invalid-radius: "Ongeldige radius: \"%s\""
|
||||
tube:
|
||||
invalid-radius: "Ongeldige radius: \"%s\""
|
||||
image:
|
||||
main-menu:
|
||||
- "---------------Terra/beeld---------------"
|
||||
- "weergee - gee 'n beeld met 'n gegewe breedte en hoogte, wat later as 'n wêreld ingevoer kan word."
|
||||
- "gui - Open debug GUI (moet in config geaktiveer word)"
|
||||
gui:
|
||||
main-menu:
|
||||
- "-------------Terra/beeld/gui-------------"
|
||||
- "rou - Open GUI met rou bioom-data"
|
||||
- "stap - Gee data weer om die grense duideliker aan te dui"
|
||||
debug: "Ontfoutmodus moet geaktiveer wees om die ontfout-GUI te gebruik! Die foutopsporing-GUI is NIE PRODUKSIEVEILIG NIE!"
|
||||
render:
|
||||
save: "Beeld gestoor as \"%s\""
|
||||
error: "Vout ondervind terwel die prent besig was om te genereer!"
|
||||
profile:
|
||||
main-menu:
|
||||
- "---------------Terra/profiel---------------"
|
||||
- "begin - Begin die profiel"
|
||||
- "stop - stop die profiel"
|
||||
- "navraag - Haal profiele-data op"
|
||||
- "reset - Stel profieldata terug"
|
||||
reset: "Profiler is teruggestel."
|
||||
start: "Profiler het begin."
|
||||
stop: "Profiler het opgehou."
|
||||
structure:
|
||||
main-menu:
|
||||
- "---------------Terra/struktuur---------------"
|
||||
- "uitvoer - voer u huidige WorldEdit-keuse uit as 'n Terra-struktuur."
|
||||
- "laai - Laai 'n Terra-struktuur"
|
||||
invalid-radius: "Ongeldig radius: \"%s\""
|
||||
invalid-rotation: "Ongeldige rotasie: \"%s\""
|
||||
invalid: "Ongeldig Struktuur ID: \"%s\""
|
||||
export: "struktuur gestoor na \"%s\""
|
||||
world-config:
|
||||
loading: "Laai wêreldkonfigurasiewaardes vir wêreld %s..."
|
||||
not-found: "Konfigurasie vir wêreld \"%s\" nie gevind nie. Kopieer standaardinstelling."
|
||||
using-image: "Laai wêreld vanaf prent."
|
||||
error: "Kon nie konfigurasie vir wêreld laai nie %s"
|
||||
done: "Wêreldlading voltooi. Tyd verloop: %sms"
|
||||
config-pack:
|
||||
loaded: "Laai konfigurasie %1$s in %2$sms."
|
||||
config:
|
||||
loaded: "Laai %1$s vanaf %2$s"
|
||||
loaded-all: "%1$s %2$s(s) gelaai in %3$sms."
|
||||
error:
|
||||
invalid-failover: "Ongeldige failover-tipe: \"%s\""
|
||||
duplicate: "Duplikaat-ID gevind in lêer: %s"
|
||||
file:
|
||||
- "Konfigurasiefout vir Terra-voorwerp. lêer: %1$s"
|
||||
- "%2$s"
|
||||
- "Stel dit reg voordat u verder gaan!"
|
||||
generic:
|
||||
- "Kon nie konfigurasies laai nie."
|
||||
- "Rapporteer dit asseblief aan Terra."
|
||||
warning:
|
||||
no-population: "Geen bevolkingstukke is gelaai nie. As dit die eerste keer is dat u u bediener met Terra begin, of as u 'n nuwe wêreld skep, is dit normaal."
|
||||
error:
|
||||
severe-config: "N Ernstige konfigurasiefout het Terra verhoed om terrein op koördinate behoorlik te genereer by: %1$s, %2$s. Gaan u konfigurasie na vir foute. Enige konfiguratiefoute sal hierbo gerapporteer word."
|
||||
debug:
|
||||
data-save: "Bevolkingsdata vir wêreld \"%s\" is gestoor"
|
||||
use-paper:
|
||||
- "Dit lyk asof u Spigot/CraftBukkit gebruik."
|
||||
- "terwel Terra &owel&r werk op Spigot, sal sommige funksies verlore gaan. (Terra is ongetoets op CraftBukkit; geen ondersteuning sal gegee word vir CraftBukkit)."
|
||||
- "Skakel asseblief oor na Paper om die beste uit Terra te kry."
|
||||
- "Plus bied Paper geweldige prestasieverbeterings ten opsigte van Spigot, en alle Spigot-inproppe moet met Paper werk!"
|
||||
- "Gebruik Paper om die beste ervaring met Terra en al u inproppe te hê."
|
||||
- "Lees meer op Paper se webwerf: https://papermc.io/"
|
||||
122
common/implementation/base/src/main/resources/lang/cs_cz.yml
Normal file
122
common/implementation/base/src/main/resources/lang/cs_cz.yml
Normal file
@@ -0,0 +1,122 @@
|
||||
enable:
|
||||
- "Pokud se vám líbí Terra, můžete nás podpořit na Patreon!"
|
||||
- "Získáte přístup k experimentálním funkcím, než budou vydány!"
|
||||
- "Podpořit projekt můžete zde: https://www.patreon.com/dfsek"
|
||||
disable:
|
||||
- "Děkujeme, že používáte Terra!"
|
||||
command:
|
||||
debug-only: "Tento příkaz musí být použit se zapnutým debug modem!"
|
||||
player-only: "Tento příkaz je pouze pro hráče!"
|
||||
invalid: "Neznámý příkaz. (Očekáváno %1$s argumentů, nalezeno %2$s)."
|
||||
players-only: "Příkaz je pouze pro použití hráčem."
|
||||
world: "Tento příkaz musí být použit v Terra světě!"
|
||||
reload: "Obnoven Terra konfig."
|
||||
reload-error: "Nastaly chyby při obnově Terra konfigurace. Podívejte se do logů pro více informací."
|
||||
version: "Na tomto serveru běží Terra verze \"%1$s\", na platformě \"%2$s\""
|
||||
main-menu:
|
||||
- "--------------------Terra--------------------"
|
||||
- "reload - Obnoví konfigurační data"
|
||||
- "biome - Ukáže aktuální biom"
|
||||
- "ore - Generuje žílu rud v lokaci, ve směru kam se koukáte (Pro debugging)"
|
||||
- "save-data - Uložit populační data"
|
||||
- "structure - Nahrát a exportovat struktury"
|
||||
- "profile - Profiler možnosti"
|
||||
- "image - Obrázek/GUI možnosti"
|
||||
biome:
|
||||
biome-found: "Lokalizován biom na (%1$s, %2$s)"
|
||||
unable-to-locate: "Nelze lokalizovat biom."
|
||||
invalid-radius: "Nesprávný radius: \"%s\""
|
||||
invalid: "Nesprávné ID bomu: \"%s\""
|
||||
in: "Jste v \"%s\""
|
||||
packs:
|
||||
main: "Aktuální instalované konfigurační balíčky:"
|
||||
pack: " - %1$s v%3$s od %2$s"
|
||||
none: "Žádné konfigurační balíčky nejsou nainstalovány."
|
||||
ore:
|
||||
main-menu:
|
||||
- "---------------Terra/ore---------------"
|
||||
- "Generuje žílu rud na bloku, na který koukáte."
|
||||
out-of-range: "Blok mimo dosah"
|
||||
invalid-ore: "Nelze nalézt Rudu \"%s\""
|
||||
geometry:
|
||||
main-menu:
|
||||
- "---------------Terra/geometry----------------"
|
||||
- "Různé voxel geometrické debugging příkazy"
|
||||
- "sphere - Generuje kouli"
|
||||
- "deformsphere - Generuje deformovanou kouli"
|
||||
- "tube - Generuje válec"
|
||||
deform:
|
||||
invalid-radius: "Nesprávný radius: \"%s\""
|
||||
invalid-deform: "Nesprávná deformace: \"%s\""
|
||||
invalid-frequency: "Nesprávná frekvence: \"%s\""
|
||||
sphere:
|
||||
invalid-radius: "Nesprávný radius: \"%s\""
|
||||
tube:
|
||||
invalid-radius: "Nesprávný radius: \"%s\""
|
||||
image:
|
||||
main-menu:
|
||||
- "---------------Terra/image---------------"
|
||||
- "render - Vykreslí obrázek s danou šířkou a výškou, který může být později importován jako svět."
|
||||
- "gui - Otevřít debug GUI (Musí být zapnuto v konfigu)"
|
||||
gui:
|
||||
main-menu:
|
||||
- "-------------Terra/image/gui-------------"
|
||||
- "raw - Otevře GUI s raw Biom daty"
|
||||
- "step - Znovu vykreslí data k lepšímu zobrazení borderu"
|
||||
debug: "Debug mod musí být zapnutý pro použití této možnosti! Debug GUI NENÍ PRODUKČNĚ BEZPEČNÉ!"
|
||||
render:
|
||||
save: "Uložen obrázek jako \"%s\""
|
||||
error: "Nastala chyba při generování obrázku!"
|
||||
profile:
|
||||
main-menu:
|
||||
- "---------------Terra/profile---------------"
|
||||
- "start - Zapne profiler"
|
||||
- "stop - Vypne profiler"
|
||||
- "query - Ukáže profiler data"
|
||||
- "reset - Resetuje profiler data"
|
||||
reset: "Profiler byl resetován."
|
||||
start: "Profiler byl zapnut."
|
||||
stop: "Profiler byl vypnut."
|
||||
structure:
|
||||
main-menu:
|
||||
- "---------------Terra/structure---------------"
|
||||
- "export - Export vašeho výběru WorldEdit jako Terra struktura."
|
||||
- "load - Načíst Terra strukturu"
|
||||
invalid-radius: "Nesprávný radius: \"%s\""
|
||||
invalid-rotation: "Nesprávná rotace: \"%s\""
|
||||
invalid: "Nesprávné ID struktury: \"%s\""
|
||||
export: "Uložena struktura do \"%s\""
|
||||
world-config:
|
||||
load: "Načteny konfigurační hodnoty světa pro svět \"%s\"..."
|
||||
not-found: "Konfigurace pro svět \"%s\" nenalezena. Kopíruji defaultní konfig."
|
||||
using-image: "Načítám svět z obrázku."
|
||||
error: "Nelze načíst konfigurace pro svět %s"
|
||||
done: "Načítání světa \"%1$s\" dokončeno. Uplynulý čas: %2$sms"
|
||||
config-pack:
|
||||
loaded: "Konfigurační balíček %1$s v%4$s od %3$s byl načten za %2$sms."
|
||||
config:
|
||||
loaded: "Načten %1$s ze souboru %2$s"
|
||||
loaded-all: "Načteno %1$s %2$s(s) za %3$sms."
|
||||
error:
|
||||
invalid-failover: "Nesprávný typ failover: \"%s\""
|
||||
duplicate: "Duplikační ID nalezeno v souboru: %s"
|
||||
file:
|
||||
- "Konfigurační chyba pro Terra objekt. Soubor: %1$s"
|
||||
- "%2$s"
|
||||
- "Opravte jej před pokračováním!"
|
||||
generic:
|
||||
- "Nastala chyba při načítání konfigurace."
|
||||
- "Prosíme nahlašte to na Terra."
|
||||
warning:
|
||||
no-population: "Žádné populační chunky nebyly načteny. Pokud je to poprvé, co zapínáte server s Terra, či vytváříte nový svět, je tohle normální."
|
||||
error:
|
||||
severe-config: "Vážná konfigurační chyba zabránila Terra ze správné generace terénu na koordinátech: %1$s, %2$s. Prosíme zkontrolujte konfiguraci pro chyby. Jakékoli konfigurační chyby jsou vypsány výše."
|
||||
debug:
|
||||
data-save: "Uložena populační data."
|
||||
use-paper:
|
||||
- "Vypadá to, že používáte Spigot/CraftBukkit."
|
||||
- "Ačkoli Terra &ofunguje&r na Spigot, některé funkce budou ztraceny. (Terra je netestována na CraftBukkit; žádná podpora nebude dána pro CraftBukkit)."
|
||||
- "Pro nejvíce funkcí s Terra, použijte Paper."
|
||||
- "Navíc, Paper přináší obrovské výkonnostní zlepešení než Spigot, a všechny Spigot pluginy by měli fungovat s Paper!"
|
||||
- "Pro nejlepší zážitek s Terra a všemi pluginy, použijte prosím Paper."
|
||||
- "Více info najdete na stránce Paperu: https://papermc.io/"
|
||||
122
common/implementation/base/src/main/resources/lang/da.yml
Normal file
122
common/implementation/base/src/main/resources/lang/da.yml
Normal file
@@ -0,0 +1,122 @@
|
||||
enable:
|
||||
- "Hvis du kan lide Terra, kan du overveje at støtte projektet på Patreon!"
|
||||
- "Du vil få adgang til eksperimentelle funktioner, før de udgives!"
|
||||
- "Støt projektet her: https://www.patreon.com/dfsek"
|
||||
disable:
|
||||
- "Tak for at du bruger Terra!"
|
||||
command:
|
||||
debug-only: "Denne kommando skal bruges med fejlfindingstilstand aktiveret!"
|
||||
player-only: "Denne kommando er kun til spillere!"
|
||||
invalid: "Ugyldig kommando. (Forventede %1$s argumenter, fandt %2$s)."
|
||||
players-only: "Kommando er kun til spillere."
|
||||
world: "Denne kommando skal anvendes i en Terra verden!"
|
||||
reload: "Genindlæste Terra konfigurationen."
|
||||
reload-error: "Der opstod fejl under genindlæsning af Terra konfigurationer. Tjek logfilerne for at få flere oplysninger."
|
||||
version: "Denne server kører Terra version \"%1$s\", implementerer Gaea version \"%2$s\""
|
||||
main-menu:
|
||||
- "--------------------Terra--------------------"
|
||||
- "reload - Genindlæs konfigurationsdataene"
|
||||
- "biome - Få den nuværende biome"
|
||||
- "ore - Generer en åre malm ved den lokation du står overfor (Til fejlfinding)"
|
||||
- "save-data - Gem populations data"
|
||||
- "structure - Indlæs og eksporter strukturer"
|
||||
- "profile - Profiler indstillinger"
|
||||
- "image - Billede/GUI indstillinger"
|
||||
biome:
|
||||
biome-found: "Lokaliserede biome ved (%1$s, %2$s)"
|
||||
unable-to-locate: "Kan ikke lokalisere biome."
|
||||
invalid-radius: "Ugyldig radius: \"%s\""
|
||||
invalid: "Ugyldigt Biome ID: \"%s\""
|
||||
in: "Du er i \"%s\""
|
||||
packs:
|
||||
main: "Aktuelt installerede konfigurationspakker:"
|
||||
pack: " - %1$s v%3$s ved %2$s"
|
||||
none: "Ingen konfigurationspakker er installeret."
|
||||
ore:
|
||||
main-menu:
|
||||
- "---------------Terra/malm---------------"
|
||||
- "Genererer en åre malm ved den blok, du kigger på."
|
||||
out-of-range: "Blok uden for rækkevidde"
|
||||
invalid-ore: "Kan ikke finde Malm \"%s\""
|
||||
geometry:
|
||||
main-menu:
|
||||
- "---------------Terra/geometri----------------"
|
||||
- "Forskellige kommandoer til fejlfinding af voxel-geometri"
|
||||
- "sphere - Generer en kugle"
|
||||
- "deformsphere - Generer en deformeret kugle"
|
||||
- "tube - Generer et rør"
|
||||
deform:
|
||||
invalid-radius: "Ugyldig radius: \"%s\""
|
||||
invalid-deform: "Ugyldig deformering: \"%s\""
|
||||
invalid-frequency: "Ugyldig frekvens: \"%s\""
|
||||
sphere:
|
||||
invalid-radius: "Ugyldig radius: \"%s\""
|
||||
tube:
|
||||
invalid-radius: "Ugyldig radius: \"%s\""
|
||||
image:
|
||||
main-menu:
|
||||
- "---------------Terra/billede---------------"
|
||||
- "render - Render et billede med en given bredde og højde, der senere kan importeres som en verden."
|
||||
- "gui - Åbn fejlfindings-GUI (Skal være aktiveret i konfigurationen)"
|
||||
gui:
|
||||
main-menu:
|
||||
- "-------------Terra/billede/gui-------------"
|
||||
- "raw - Åbn GUI med rå Biome-data"
|
||||
- "step - Re-render data igen for at vise grænser mere tydeligt"
|
||||
debug: "Fejlfindingstilstand skal være aktiveret for at bruge fejlfindings-GUI! Fejlfindings-GUI'en er IKKE PRODUKTIONSSIKKER!"
|
||||
render:
|
||||
save: "Gemte billede som \"%s\""
|
||||
error: "Der opstod en fejl under generering af billedet!"
|
||||
profile:
|
||||
main-menu:
|
||||
- "---------------Terra/profiler---------------"
|
||||
- "start - Starter profiler"
|
||||
- "stop - Stopper profiler"
|
||||
- "query - Henter profiler data"
|
||||
- "reset - Nulstiller profiler data"
|
||||
reset: "Profiler er blevet nulstillet."
|
||||
start: "Profiler er startet."
|
||||
stop: "Profiler er stoppet."
|
||||
structure:
|
||||
main-menu:
|
||||
- "---------------Terra/struktur---------------"
|
||||
- "export - Eksporter din nuværende WorldEdit selektion som en Terra struktur."
|
||||
- "load - Indlæs en Terra struktur"
|
||||
invalid-radius: "Ugyldig radius: \"%s\""
|
||||
invalid-rotation: "Ugyldig rotation: \"%s\""
|
||||
invalid: "Ugyldigt Struktur ID: \"%s\""
|
||||
export: "Gemte struktur til \"%s\""
|
||||
world-config:
|
||||
loading: "Indlæser verdenskonfigurationsværdier til verden \"%s\"..."
|
||||
not-found: "Konfiguration til verden \"%s\" ikke fundet. Kopier standardkonfigurationen."
|
||||
using-image: "Indlæser verden fra billede."
|
||||
error: "Kan ikke indlæse konfiguration til verden %s"
|
||||
done: "Indlæsning af verden \"%1$s\" er færdig. Forløbet tid: %2$sms"
|
||||
config-pack:
|
||||
loaded: "Konfigurationspakke %1$s v%4$s ved %3$s indlæst på %2$sms."
|
||||
config:
|
||||
loaded: "Indlæste %1$s fra fil %2$s"
|
||||
loaded-all: "Indlæste %1$s %2$s(s) på %3$sms."
|
||||
error:
|
||||
invalid-failover: "Ugyldig failover type: \"%s\""
|
||||
duplicate: "Duplikeret ID fundet i filen: %s"
|
||||
file:
|
||||
- "Konfigurationsfejl for Terra objekt. Fil: %1$s"
|
||||
- "%2$s"
|
||||
- "Ret dette, inden du fortsætter!"
|
||||
generic:
|
||||
- "Der opstod en fejl under indlæsning af konfigurationer."
|
||||
- "Rapporter dette til Terra."
|
||||
warning:
|
||||
no-population: "Ingen populations chunks blev indlæst. Hvis dette er første gang du starter din server med Terra, eller hvis du opretter en ny verden, er dette normalt."
|
||||
error:
|
||||
severe-config: "En alvorlig konfigurationsfejl har forhindret Terra i at generere terræn korrekt ved koordinater: %1$s, %2$s. Kontroller din konfiguration for fejl. Eventuelle konfigurationsfejl vil være rapporteret ovenfor."
|
||||
debug:
|
||||
data-save: "Gemte populations data for verden \"%s\""
|
||||
use-paper:
|
||||
- "Det ser ud til, at du bruger Spigot/CraftBukkit."
|
||||
- "Mens Terra &ovil&r virke på Spigot, vil nogle funktioner gå tabt. (Terra er uprøvet på CraftBukkit; ingen support vil blive givet til CraftBukkit)."
|
||||
- "For at få mest muligt ud af Terra, skal du skifte til Paper."
|
||||
- "Plus, Paper tilbyder store ydeevne forbedringer over Spigot, og alle Spigot plugins bør virke med Paper!"
|
||||
- "For at få den bedste oplevelse med Terra, og alle dine plugins, brug Paper."
|
||||
- "Få mere at vide på Paper's hjemmeside: https://papermc.io/"
|
||||
117
common/implementation/base/src/main/resources/lang/de_de.yml
Normal file
117
common/implementation/base/src/main/resources/lang/de_de.yml
Normal file
@@ -0,0 +1,117 @@
|
||||
enable:
|
||||
- "Wenn dir Terra gefällt, denk bitte darüber nach, das Projekt auf Patreon zu unterstützen!"
|
||||
- "Dadurch erhältsts du Zugriff auf experimentelle Funktionen!"
|
||||
- "Unterstütze das Projekt hier: https://www.patreon.com/dfsek"
|
||||
disable:
|
||||
- "Danke, dass du Terra benutzt!!"
|
||||
command:
|
||||
debug-only: "Dieser Befehl kann nur im Debugmodus benutzt werden!"
|
||||
player-only: "Dieser Befehl kann nur von Spielern benutzt werden!"
|
||||
invalid: "Ungültiger Befehl. (Erwartet %1$s Argumente, fand %2$s)."
|
||||
players-only: "Dieser Befehl kann nur von Spielern benutzt werden."
|
||||
world: "Dieser Befehl muss in einer von Terra generierten Welt ausgeführt werden!"
|
||||
reload: "Terra-Konfiguration wurde neu geladen."
|
||||
version: "Dieser Server verwendet Terra \"%s\""
|
||||
main-menu:
|
||||
- "--------------------Terra--------------------"
|
||||
- "reload - Lädt die Konfiguration neu"
|
||||
- "biome - Zeigt dir das derzeitige Biom"
|
||||
- "ore - Erzader an derzeitiger Position erzeugen (zum Debuggen)"
|
||||
- "save-data - Bevölkerungsdaten speichern"
|
||||
- "structure - Laden/Exportieren von Strukturen"
|
||||
- "profile - Profiler-Optionen"
|
||||
- "image - Bild-/GUI-Optionen"
|
||||
biome:
|
||||
biome-found: "Biom gefunden bei: (%1$s, %2$s)"
|
||||
unable-to-locate: "Biom konnte nicht gefunden werden!"
|
||||
invalid-radius: "Ungültiger Radius: \"%s\""
|
||||
invalid: "Ungültige Biom-ID: \"%s\""
|
||||
in: "Du bist in: \"%s\""
|
||||
ore:
|
||||
main-menu:
|
||||
- "---------------Terra/Erz---------------"
|
||||
- "Generiert eine Erzader an dem Block, den du anguckst"
|
||||
out-of-range: "Block außer Reichweite"
|
||||
invalid-ore: "Kann Erz \"%s\" nicht finden"
|
||||
geometry:
|
||||
main-menu:
|
||||
- "---------------Terra/Geometrie----------------"
|
||||
- "Verschiedene Debugging-Befehle für die Voxelgeometrie"
|
||||
- "sphere - Generiert eine Kugel"
|
||||
- "deformsphere - Generiert eine deformierte Kugel"
|
||||
- "tube - Generiert ein Rohr"
|
||||
deform:
|
||||
invalid-radius: "Ungültiger Radius: \"%s\""
|
||||
invalid-deform: "Ungültiger Deformation: \"%s\""
|
||||
invalid-frequency: "Ungültige Frequenz: \"%s\""
|
||||
sphere:
|
||||
invalid-radius: "Ungültiger Radius: \"%s\""
|
||||
tube:
|
||||
invalid-radius: "Ungültiger Radius: \"%s\""
|
||||
image:
|
||||
main-menu:
|
||||
- "---------------Terra/Bilde---------------"
|
||||
- "render - Rendert ein Bild mit einer bestimmten Breite und Höhe, das später als Welt importiert werden kann."
|
||||
- "gui - Debug-GUI öffnen (muss in der Konfiguration aktiviert sein)"
|
||||
gui:
|
||||
main-menu:
|
||||
- "-------------Terra/image/gui-------------"
|
||||
- "raw - Öffnet eine GUI mit Biome-Rohdaten"
|
||||
- "step - Daten erneut rendern, um Ränder deutlicher darzustellen"
|
||||
debug: "Der Debug-Modus muss aktiviert sein, um die Debug-GUI verwenden zu können! Die Debug-GUI ist NICHT PRODUKTIONSSICHER!"
|
||||
render:
|
||||
save: "Bild gespeichert unter: \"%s\""
|
||||
error: "Beim speichern ist ein Fehler aufgetreten!"
|
||||
profile:
|
||||
main-menu:
|
||||
- "---------------Terra/Profiler---------------"
|
||||
- "start - Startet den Profiler"
|
||||
- "stop - Stoppt den Profiler"
|
||||
- "query - Profiler-Daten anzeigen"
|
||||
- "reset - Profiler-Daten zurücksetzen"
|
||||
reset: "Profiler-Daten wurden zurückgesetzt."
|
||||
start: "Der Profiler wurde gestartet."
|
||||
stop: "Der Profiler wurde gestoppt."
|
||||
structure:
|
||||
main-menu:
|
||||
- "---------------Terra/Strukturen---------------"
|
||||
- "export - Exportiert deine aktuelle WorldEdit-Auswahl als Terra-Struktur."
|
||||
- "load - Ladt eine Terra-Struktur."
|
||||
invalid-radius: "Ungültiger Radius: \"%s\""
|
||||
invalid-rotation: "Ungültige Rotation: \"%s\""
|
||||
invalid: "Ungültige Strukturen-ID: \"%s\""
|
||||
export: "Struktur unter \"%s\" gespeichert."
|
||||
world-config:
|
||||
loading: "Lade Weltkonfigurationswerte für Welt %s..."
|
||||
not-found: "Weltkonfigurationswerte für Welt \"%s\" nicht gefunden. Lade Standardwerte."
|
||||
using-image: "Lade Welt von Bild."
|
||||
error: "Konfiguration für Welt %s kann nicht geladen werden!"
|
||||
done: "Laden der Welt abgeschlossen. Ladedauer: %sms"
|
||||
config-pack:
|
||||
loaded: "Konfiguration %1$s wurde in %2$sms geladen."
|
||||
config:
|
||||
loaded: "Erfolgreich %1$s aus Datei %2$s geladen"
|
||||
loaded-all: "%1$s %2$s(s) in %3$sms geladen."
|
||||
error:
|
||||
invalid-failover: "IUngültiger Failover-Typ: \"%s\""
|
||||
duplicate: "ID doppelt belegt in Datei: %s"
|
||||
file:
|
||||
- "Konfigurationsfehler in Terra-Objekt. Datei: %1$s"
|
||||
- "%2$s"
|
||||
- "Korrigier bitte diese(n) Fehler, bevor du fortfährst!"
|
||||
generic:
|
||||
- "Ein Fehler ist beim laden der Konfiguration aufegtreten."
|
||||
- "Bitte melde diesen Fehler!"
|
||||
warning:
|
||||
no-population: "Es wurden keine Bevölkerungs-Chunks geladen. Wenn du den Server zum ersten Mal mit Terra startest oder eine neue Welt erstellst, ist dies normal."
|
||||
error:
|
||||
severe-config: "Ein schwerwiegender Konfigurationsfehler hat Terra daran gehindert, Gelände an folgenden Koordinaten ordnungsgemäß zu generieren: %1$s, %2$s. Bitte überprüfe die Konfiguration auf Fehler. Alle Konfigurationsfehler wurden oben gemeldet."
|
||||
debug:
|
||||
data-save: "Bevölkerungsdaten für Welt \"%s\" gespeichert."
|
||||
use-paper:
|
||||
- "Anscheinend benutzt du Spigot/CraftBukkit."
|
||||
- "Terra funktioniert auf Spigot/CraftBukkit, aber einige Funktionen gehen verloren. (Terra wurde nicht auf Spigot/CraftBukkit getestet; Es gibt keine Hilfe für Spigot/CraftBukkit-Server)."
|
||||
- "Um Terra optimal zu benutzen, wechsle bitte zu Paper."
|
||||
- "Außerdem bietet Paper immense Leistungsverbesserungen gegenüber Spigot und CraftBukkit und (normalerweise) funktionieren alle Spigot/CraftBukkit Plugins auch auf Paper!"
|
||||
- "Benutze Paper, um die beste Erfahrung mit Terra und allen anderen Plugins zu haben."
|
||||
- "Finde mehr über Paper heraus: https://papermc.io"
|
||||
122
common/implementation/base/src/main/resources/lang/en_us.yml
Normal file
122
common/implementation/base/src/main/resources/lang/en_us.yml
Normal file
@@ -0,0 +1,122 @@
|
||||
enable:
|
||||
- "If you like Terra, please consider supporting the project on Patreon!"
|
||||
- "You'll gain access to experimental features before they are released!"
|
||||
- "Support the project here: https://www.patreon.com/dfsek"
|
||||
disable:
|
||||
- "Thank you for using Terra!"
|
||||
command:
|
||||
debug-only: "This command must be used with debug mode enabled!"
|
||||
player-only: "This command is for players only!"
|
||||
invalid: "Invalid command. (Expected %1$s arguments, found %2$s)."
|
||||
players-only: "Command is for players only."
|
||||
world: "This command must be executed in a Terra world!"
|
||||
reload: "Reloaded Terra config."
|
||||
reload-error: "Errors occurred while reloading Terra configurations. See logs for more information."
|
||||
version: "This server is running Terra version \"%1$s\", on platform \"%2$s\""
|
||||
main-menu:
|
||||
- "--------------------Terra--------------------"
|
||||
- "reload - Reload configuration data"
|
||||
- "biome - Get current biome"
|
||||
- "ore - Generate an ore vein at the location you are facing (For debugging)"
|
||||
- "save-data - Save population data"
|
||||
- "structure - Load and export structures"
|
||||
- "profile - Profiler options"
|
||||
- "image - Image/GUI options"
|
||||
biome:
|
||||
biome-found: "Located biome at (%1$s, %2$s)"
|
||||
unable-to-locate: "Unable to locate biome."
|
||||
invalid-radius: "Invalid radius: \"%s\""
|
||||
invalid: "Invalid Biome ID: \"%s\""
|
||||
in: "You are in \"%s\""
|
||||
packs:
|
||||
main: "Currently installed config packs:"
|
||||
pack: " - %1$s v%3$s by %2$s"
|
||||
none: "No config packs are installed."
|
||||
ore:
|
||||
main-menu:
|
||||
- "---------------Terra/ore---------------"
|
||||
- "Generates a vein of ore at the block you are looking at."
|
||||
out-of-range: "Block out of range"
|
||||
invalid-ore: "Unable to find Ore \"%s\""
|
||||
geometry:
|
||||
main-menu:
|
||||
- "---------------Terra/geometry----------------"
|
||||
- "Various voxel geometry debugging commands"
|
||||
- "sphere - Generate a sphere"
|
||||
- "deformsphere - Generate a deformed sphere"
|
||||
- "tube - Generate a tube"
|
||||
deform:
|
||||
invalid-radius: "Invalid radius: \"%s\""
|
||||
invalid-deform: "Invalid deform: \"%s\""
|
||||
invalid-frequency: "Invalid frequency: \"%s\""
|
||||
sphere:
|
||||
invalid-radius: "Invalid radius: \"%s\""
|
||||
tube:
|
||||
invalid-radius: "Invalid radius: \"%s\""
|
||||
image:
|
||||
main-menu:
|
||||
- "---------------Terra/image---------------"
|
||||
- "render - Render an image with a given width and height, that can later be imported as a world."
|
||||
- "gui - Open debug GUI (Must be enabled in config)"
|
||||
gui:
|
||||
main-menu:
|
||||
- "-------------Terra/image/gui-------------"
|
||||
- "raw - Open GUI with raw Biome data"
|
||||
- "step - Re-render data to show borders more clearly"
|
||||
debug: "Debug mode must be enabled to use the debug GUI! The debug GUI is NOT PRODUCTION SAFE!"
|
||||
render:
|
||||
save: "Saved image as \"%s\""
|
||||
error: "An error occurred while generating the image!"
|
||||
profile:
|
||||
main-menu:
|
||||
- "---------------Terra/profile---------------"
|
||||
- "start - Starts the profiler"
|
||||
- "stop - Stops the profiler"
|
||||
- "query - Fetches profiler data"
|
||||
- "reset - Resets profiler data"
|
||||
reset: "Profiler has been reset."
|
||||
start: "Profiler has started."
|
||||
stop: "Profiler has stopped."
|
||||
structure:
|
||||
main-menu:
|
||||
- "---------------Terra/structure---------------"
|
||||
- "export - Export your current WorldEdit selection as a Terra structure."
|
||||
- "load - Load a Terra structure"
|
||||
invalid-radius: "Invalid radius: \"%s\""
|
||||
invalid-rotation: "Invalid rotation: \"%s\""
|
||||
invalid: "Invalid Structure ID: \"%s\""
|
||||
export: "Saved structure to \"%s\""
|
||||
world-config:
|
||||
load: "Loading world configuration values for world \"%s\"..."
|
||||
not-found: "Configuration for world \"%s\" not found. Copying default config."
|
||||
using-image: "Loading world from image."
|
||||
error: "Unable to load configuration for world %s"
|
||||
done: "World load for world \"%1$s\" complete. Time elapsed: %2$sms"
|
||||
config-pack:
|
||||
loaded: "Config pack %1$s v%4$s by %3$s loaded in %2$sms."
|
||||
config:
|
||||
loaded: "Loaded %1$s from file %2$s"
|
||||
loaded-all: "Loaded %1$s %2$s(s) in %3$sms."
|
||||
error:
|
||||
invalid-failover: "Invalid failover type: \"%s\""
|
||||
duplicate: "Duplicate ID found in file: %s"
|
||||
file:
|
||||
- "Configuration error for Terra object. File: %1$s"
|
||||
- "%2$s"
|
||||
- "Correct this before proceeding!"
|
||||
generic:
|
||||
- "An error occurred while loading configurations."
|
||||
- "Please report this to Terra."
|
||||
warning:
|
||||
no-population: "No population chunks were loaded. If this is your first time starting your server with Terra, or if you are creating a new world, this is normal."
|
||||
error:
|
||||
severe-config: "A severe configuration error has prevented Terra from properly generating terrain at coordinates: %1$s, %2$s. Please check your configuration for errors. Any config errors will have been reported above."
|
||||
debug:
|
||||
data-save: "Saved population data."
|
||||
use-paper:
|
||||
- "You appear to be using Spigot/CraftBukkit."
|
||||
- "While Terra &odoes&r work on Spigot, some functionality will be lost. (Terra is untested on CraftBukkit; no support will be given for CraftBukkit)."
|
||||
- "To get the most out of Terra, please switch to Paper."
|
||||
- "Plus, Paper offers immense performance improvements over Spigot, and all Spigot plugins should work with Paper!"
|
||||
- "To have the best experience with Terra, and all your plugins, please use Paper."
|
||||
- "Find out more on Paper's website: https://papermc.io/"
|
||||
107
common/implementation/base/src/main/resources/lang/es.yml
Normal file
107
common/implementation/base/src/main/resources/lang/es.yml
Normal file
@@ -0,0 +1,107 @@
|
||||
enable:
|
||||
- "Si te gusta Terra, puedes considerar apoyar el proyecto en Patreon!"
|
||||
- "Tendrás acceso anticipado a caracteristicas experimentales antes de que sean lanzadas oficialmente!"
|
||||
- "Puedes apoyar el proyecto aquí: https://www.patreon.com/dfsek"
|
||||
disable:
|
||||
- "Gracias por usar Terra!"
|
||||
command:
|
||||
player-only: "Este comando solo puede ser usado por jugadores!"
|
||||
terra-world: "Este comando solo puede ser usado en un mundo Terra!"
|
||||
invalid: "Comando invalido. (Expected %1$s arguments, found %2$s)."
|
||||
players-only: "Este comando solo puede ser usado por jugadores"
|
||||
world: "Este comando puede ejecutarse solo en un mundo terra!"
|
||||
reload: "La configuración Terra ha sido recargada."
|
||||
main-menu:
|
||||
- "--------------------Terra--------------------"
|
||||
- "reload - Recarga los datos de configuración del plugin."
|
||||
- "biome - Obtienes información del bioma actual"
|
||||
- "ore - Genera una mena de ore en el lugar que estes mirando.(For debugging)"
|
||||
- "save-data - Guarda los datos actuales."
|
||||
- "structure - Cargar o exportar estructuras."
|
||||
- "profile - Opciones de perfil."
|
||||
- "image - Opciones de imagen/GUI."
|
||||
biome:
|
||||
biome-found: "Bioma localizado en (%1$s, %2$s)"
|
||||
unable-to-locate: "No se pudo localizar el bioma."
|
||||
invalid-radius: "Radio invalido: \"%s\""
|
||||
invalid: "ID del bioma invalido: \"%s\""
|
||||
in: "Te encuentras en \"%s\""
|
||||
ore:
|
||||
main-menu:
|
||||
- "---------------Terra/ore---------------"
|
||||
- "Generas una mena de ore en el bloque que te encuentres mirando."
|
||||
out-of-range: "Bloque fuera de rango."
|
||||
invalid-ore: "No se pudo encontrar el Ore \"%s\""
|
||||
geometry:
|
||||
main-menu:
|
||||
- "---------------Terra/geometry----------------"
|
||||
- "Various voxel geometry debugging commands"
|
||||
- "sphere - Generas un sphere"
|
||||
- "deformsphere - Generas un sphere deformado"
|
||||
- "tube - Generas un tube"
|
||||
deform:
|
||||
invalid-radius: "Radio invalido: \"%s\""
|
||||
invalid-deform: "Deform invalido: \"%s\""
|
||||
invalid-frequency: "Frequencia invalida: \"%s\""
|
||||
sphere:
|
||||
invalid-radius: "Radio invalido: \"%s\""
|
||||
tube:
|
||||
invalid-radius: "Radio invalido: \"%s\""
|
||||
image:
|
||||
main-menu:
|
||||
- "---------------Terra/image---------------"
|
||||
- "render - Renderiza una imagen con alto y ancho, y este después podrá ser importado como un mundo."
|
||||
- "gui - Abre el debug GUI.(Puede ser habilitado en la configuración)"
|
||||
gui:
|
||||
main-menu:
|
||||
- "-------------Terra/image/gui-------------"
|
||||
- "raw - Abre el GUI con la configuración del bioma sin procesar."
|
||||
- "step - Vuelve a renderizar la configuración para mostrar los límites más claro."
|
||||
debug: "El modo debug puede habilitarse para usar el debug GUI! LA CREACIÓN DEL DEBUG GUI NO PODRÍA SER SEGURA!"
|
||||
render:
|
||||
save: "Guarda una imagen como \"%s\""
|
||||
error: "Un error ha ocurrido mientras se generaba la imagen!"
|
||||
profile:
|
||||
main-menu:
|
||||
- "---------------Terra/profile---------------"
|
||||
- "start - Se incia la generación del Profiler."
|
||||
- "stop - Se detiene la generación del Profiler."
|
||||
- "query - Fetches profiler data"
|
||||
- "reset - Reinicia la configuración del Profiler."
|
||||
reset: "El Profiler ha sido reiniciado."
|
||||
start: "El Profiler se ha iniciado."
|
||||
stop: "El Profiler se ha detenido."
|
||||
structure:
|
||||
main-menu:
|
||||
- "---------------Terra/structure---------------"
|
||||
- "export - Exporta tus estructuras de Worldedit como estructuras Terra."
|
||||
- "load - Carga una estructura Terra."
|
||||
invalid-radius: "Radio invalido: \"%s\""
|
||||
invalid: "ID de la estructura es invalida: \"%s\""
|
||||
export: "Estructura guardada como \"%s\""
|
||||
world-config:
|
||||
loading: "Carga los parametros de configuración para el mundo %s..."
|
||||
not-found: "La configuración para el mundo \"%s\" no se puede encontrar. Copiando la configuración por defecto."
|
||||
using-image: "Carga el mundo a partir de una imagen."
|
||||
error: "No se pudo cargar la configuración para el mundo %s"
|
||||
done: "el mundo se ha cargado completamente. Tiempo transcurrido: %sms"
|
||||
config-pack:
|
||||
loaded: "Configuración %1$s fue cargada en %2$sms."
|
||||
config:
|
||||
loaded: "Cargado en %1$s desde el archivo %2$s"
|
||||
loaded-all: "Cargado en %1$s %2$s(s) en %3$sms."
|
||||
error:
|
||||
duplicate: "Una ID duplicada fué encontrado en el archivo: %s"
|
||||
file:
|
||||
- "Error de configuración para el objeto Terra. Archivo: %1$s"
|
||||
- "%2$s"
|
||||
- "Corrigelo antes de proseguir!"
|
||||
generic:
|
||||
- "Un error ha ocurrido mientras se cargaba las configuraciónes."
|
||||
- "Es recomendable reportar esto a Terra."
|
||||
warning:
|
||||
no-population: "No se cargaron fragmentos de población. Si es la primera vez que inicias tu servidor con Terra, esto es normal si estás creando un nuevo mundo."
|
||||
error:
|
||||
severe-config: "Un grave error de configuración ha impedido que Terra genere correctamente el terreno en las coordenadas: %1$s, %2$s. Compruebe si hay errores en su configuración. Cualquier error de configuración se habrá informado anteriormente."
|
||||
debug:
|
||||
data-save: "Datos de población guardados para el mundo \"%s\""
|
||||
121
common/implementation/base/src/main/resources/lang/it_it.yml
Normal file
121
common/implementation/base/src/main/resources/lang/it_it.yml
Normal file
@@ -0,0 +1,121 @@
|
||||
enable:
|
||||
- "Se ti piace Terra, per favore considera di sostenere il progetto su Patreon!"
|
||||
- "Avrai accesso a funzionalità sperimentali prima che vengano rilasciate!"
|
||||
- "Sostieni il progetto qui: https://www.patreon.com/dfsek"
|
||||
disable:
|
||||
- "Grazie per aver usato Terra!"
|
||||
command:
|
||||
debug-only: "Questo comando deve essere usato con la modalità debug attivata!"
|
||||
player-only: "Solo i giocatori possono eseguire questo comando!"
|
||||
invalid: "Comando invalido. (%1$s argomenti previsti, %2$s trovati)."
|
||||
players-only: "Solo i giocatori possono eseguire questo comando!"
|
||||
world: "Questo comando può solo essere eseguito in un mondo creato da Terra!"
|
||||
reload: "Configurazione Terra ricaricata."
|
||||
reload-error: "Si sono verificati errori durante il ricaricamento delle configurazioni Terra. Vedere i log per ulteriori informazioni."
|
||||
version: "Questo server sta usando la versione \"%1$s\" Terra, sulla piattaforma \"%2$s\""
|
||||
main-menu:
|
||||
- "--------------------Terra--------------------"
|
||||
- "reload - Ricarica i dati di configurazione"
|
||||
- "biome - Ottieni il bioma attuale"
|
||||
- "ore - Genera una vena minerale davanti a te (per fare debug)"
|
||||
- "save-data - Salva i dati sulla popolazione"
|
||||
- "structure - Carica ed esporta strutture"
|
||||
- "profile - Opzioni dell'analizzatore"
|
||||
- "image - Opzioni immagine / menu"
|
||||
biome:
|
||||
biome-found: "Trovato un bioma alle coordinate (%1$s, %2$s)"
|
||||
unable-to-locate: "Ricerca bioma fallita."
|
||||
invalid-radius: "Raggio invalido: \"%s\""
|
||||
invalid: "ID bioma invalido: \"%s\""
|
||||
in: "Tu sei nel bioma \"%s\""
|
||||
packs:
|
||||
main: "Pacchetti di configurazione installati:"
|
||||
pack: " - %1$s v%3$s (autore: %2$s)"
|
||||
none: "Nessun pacchetto di configurazione è installato."
|
||||
ore:
|
||||
main-menu:
|
||||
- "---------------Terra/ore---------------"
|
||||
- "Genera una vena di minerale nel blocco che stai guardando."
|
||||
out-of-range: "Blocco fuori portata"
|
||||
invalid-ore: "Ricerca minerale \"%s\" fallita!"
|
||||
geometry:
|
||||
main-menu:
|
||||
- "---------------Terra/geometry----------------"
|
||||
- "Vari comandi di debug della geometria voxel"
|
||||
- "sphere - Genera una sfera"
|
||||
- "deformsphere - Genera una sfera deformata"
|
||||
- "tube - Genera un tubo"
|
||||
deform:
|
||||
invalid-radius: "Raggio non valido: \"%s\""
|
||||
invalid-deform: "Deformazione non valida: \"%s\""
|
||||
invalid-frequency: "Frequenza non valida: \"%s\""
|
||||
sphere:
|
||||
invalid-radius: "Raggio non valido: \"%s\""
|
||||
tube:
|
||||
invalid-radius: "Raggio non valido: \"%s\""
|
||||
image:
|
||||
main-menu:
|
||||
- "---------------Terra/image---------------"
|
||||
- "render - Renderizza un'immagine con una data larghezza e altezza, che può essere successivamente importata come mondo."
|
||||
- "gui - Apri il menu di debug (deve essere abilitato nella configurazione)"
|
||||
gui:
|
||||
main-menu:
|
||||
- "-------------Terra/image/gui-------------"
|
||||
- "raw - Apri il menu con dati grezzi sui biomi"
|
||||
- "step - Riesegui il rendering dei dati per mostrare i bordi più chiaramente"
|
||||
debug: "La modalità di debug deve essere abilitata per utilizzare la GUI di debug! La GUI di debug NON È SICURA PER LA PRODUZIONE!"
|
||||
render:
|
||||
save: "Immagine salvata come \"%s\""
|
||||
error: "Si è verificato un errore durante la generazione dell'immagine!"
|
||||
profile:
|
||||
main-menu:
|
||||
- "---------------Terra/profile---------------"
|
||||
- "start - Inizia il profiler"
|
||||
- "stop - Ferma il profiler"
|
||||
- "query - Recupera i dati del profiler"
|
||||
- "reset - Resetta i dati del profiler"
|
||||
reset: "Il profiler è stato resettato."
|
||||
start: "Il profiler è stato avviato."
|
||||
stop: "Il profiler è stato fermato."
|
||||
structure:
|
||||
main-menu:
|
||||
- "---------------Terra/structure---------------"
|
||||
- "export - Esporta la tua selezione attuale di WorldEdit come struttura Terra."
|
||||
- "load - Carica una struttura Terra"
|
||||
invalid-radius: "Raggio invalido: \"%s\""
|
||||
invalid-rotation: "Rotazione invalida: \"%s\""
|
||||
invalid: "ID struttura invalido: \"%s\""
|
||||
export: "Struttura salvata come \"%s\""
|
||||
world-config:
|
||||
load: "Caricamento dei valori di configurazione per il mondo \"%s\"..."
|
||||
not-found: "Configurazione per il mondo \"%s\" non trovata. La configurazione predefinita sarà utilizzata."
|
||||
using-image: "Caricamento mondo da immagine."
|
||||
error: "Impossibile caricare la configurazione per il mondo \"%s\""
|
||||
done: "Caricamento del mondo \"%1$s\" completato. Tempo trascorso: %2$sms"
|
||||
config-pack:
|
||||
loaded: "Pacchetto di configurazione %1$s v%4$s (autore: %3$s) caricato in %2$sms."
|
||||
config:
|
||||
loaded: "Caricato %1$s dal file %2$s"
|
||||
loaded-all: "Caricato %1$s %2$s(s) in %3$sms."
|
||||
error:
|
||||
invalid-failover: "Tipo di failover non valido: \"%s\""
|
||||
duplicate: "ID duplicato trovato nel file: %s"
|
||||
file:
|
||||
- "Errore di configurazione Terra nel file: %1$s"
|
||||
- "%2$s"
|
||||
- "Correggilo prima di procedere!"
|
||||
generic:
|
||||
- "Si è verificato un errore durante il caricamento delle configurazioni."
|
||||
- "Per favore, segnalatelo a Terra."
|
||||
warning:
|
||||
no-population: "Non sono stati caricati chunk preesistenti. Se è la prima volta che avvii il tuo server con Terra, o se stai creando un nuovo mondo, è normale."
|
||||
error:
|
||||
severe-config: "Un grave errore di configurazione ha impedito a Terra di generare correttamente il terreno alle coordinate: %1$s, %2$s. Controlla la tua configurazione per errori. Eventuali errori di configurazione saranno stati segnalati sopra."
|
||||
debug:
|
||||
data-save: "Dati sulla popolazione salvati per il mondo \"%s\""
|
||||
use-paper:
|
||||
- "Sembra che tu stia usando Spigot/CraftBukkit."
|
||||
- "Nonostante Terra &ofunzioni&r su Spigot, delle funzionalità verranno perse. (Terra non è testato su CraftBukkit; nessun supporto verrà dato per la piattaforma CraftBukkit)."
|
||||
- "Inoltre, Paper offre enormi miglioramenti delle prestazioni rispetto a Spigot e tutti i plug-in di Spigot dovrebbero funzionare con Paper!"
|
||||
- "Per avere la migliore esperienza con Terra e tutti i tuoi plugin, usa Paper."
|
||||
- "Scopri di più sul sito web di Paper: https://papermc.io/"
|
||||
122
common/implementation/base/src/main/resources/lang/ja_jp.yml
Normal file
122
common/implementation/base/src/main/resources/lang/ja_jp.yml
Normal file
@@ -0,0 +1,122 @@
|
||||
enable:
|
||||
- "Terraを気に入っていただけたのであれば、Patreonでの支援をご検討ください!"
|
||||
- "リリース前の実験的な機能を使うことができます!"
|
||||
- "プロジェクトの支援はこちらから: https://www.patreon.com/dfsek"
|
||||
disable:
|
||||
- "Terraをご利用いただきありがとうございます!"
|
||||
command:
|
||||
debug-only: "このコマンドは、デバッグモードを有効にして使用する必要があります。"
|
||||
player-only: "このコマンドはプレイヤー専用です!"
|
||||
invalid: "Invalid command. (Expected %1$s arguments, found %2$s)."
|
||||
players-only: "コマンドはプレイヤー専用です。"
|
||||
world: "このコマンドはTerraのワールドで実行する必要があります!"
|
||||
reload: "Terraの設定を再読み込みしました。"
|
||||
reload-error: "Terraの設定の再ロード中にエラーが発生しました。詳細はログを参照してください。"
|
||||
version: "このサーバーでは Terraバージョン\"%1$s\" が実行されており、プラットフォームは \"%2$s\" です。"
|
||||
main-menu:
|
||||
- "--------------------Terra--------------------"
|
||||
- "reload - 設定データを再読み込み"
|
||||
- "biome - 現在のバイオームを取得"
|
||||
- "ore - 向いている場所に鉱石を生成する(デバッグ用)"
|
||||
- "save-data - データを保存"
|
||||
- "structure - ストラクチャーのロード及びエクスポート"
|
||||
- "profile - プロファイラ オプション"
|
||||
- "image - 画像/GUI オプション"
|
||||
biome:
|
||||
biome-found: "バイオームの座標 (%1$s, %2$s)"
|
||||
unable-to-locate: "バイオームが見つけられません。"
|
||||
invalid-radius: "無効な半径: \"%s\""
|
||||
invalid: "無効なバイオームID: \"%s\""
|
||||
in: "あなたは \"%s\" にいます。"
|
||||
packs:
|
||||
main: "現在インストールされているコンフィグパック:"
|
||||
pack: " - %1$s v%3$s by %2$s"
|
||||
none: "コンフィグパックはインストールされていません。"
|
||||
ore:
|
||||
main-menu:
|
||||
- "---------------Terra/ore---------------"
|
||||
- "見ているブロックに鉱石を生成します。"
|
||||
out-of-range: "範囲外のブロック"
|
||||
invalid-ore: "鉱石 \"%s\" が見つかりません。"
|
||||
geometry:
|
||||
main-menu:
|
||||
- "---------------Terra/geometry----------------"
|
||||
- "様々なボクセルジオメトリのデバッグコマンド"
|
||||
- "sphere - 球体を生成"
|
||||
- "deformsphere - 変形した球体を生成"
|
||||
- "tube - チューブを生成"
|
||||
deform:
|
||||
invalid-radius: "無効な半径: \"%s\""
|
||||
invalid-deform: "無効な変形: \"%s\""
|
||||
invalid-frequency: "無効な周波数: \"%s\""
|
||||
sphere:
|
||||
invalid-radius: "無効な半径: \"%s\""
|
||||
tube:
|
||||
invalid-radius: "無効な半径: \"%s\""
|
||||
image:
|
||||
main-menu:
|
||||
- "---------------Terra/image---------------"
|
||||
- "render - 指定された幅と高さの画像をレンダリングします。"
|
||||
- "gui - デバッグGUIを開く(設定で有効にする必要があります)"
|
||||
gui:
|
||||
main-menu:
|
||||
- "-------------Terra/image/gui-------------"
|
||||
- "raw - 生のBiomeデータを利用したGUIを開く"
|
||||
- "step - 境界線をより明確に表示するためにデータを再レンダリング"
|
||||
debug: "デバッグGUIを使用するには、デバッグモードを有効にする必要があります。デバッグGUIは安全ではありません!"
|
||||
render:
|
||||
save: "\"%s\" として画像を保存"
|
||||
error: "画像生成中にエラーが発生しました!"
|
||||
profile:
|
||||
main-menu:
|
||||
- "---------------Terra/profile---------------"
|
||||
- "start - プロファイラを起動"
|
||||
- "stop - プロファイラを停止"
|
||||
- "query - プロファイラデータを取得"
|
||||
- "reset - プロファイラのデータをリセット"
|
||||
reset: "プロファイラがリセットされました。"
|
||||
start: "プロファイラが起動しました。"
|
||||
stop: "プロファイラが停止しました。"
|
||||
structure:
|
||||
main-menu:
|
||||
- "---------------Terra/structure---------------"
|
||||
- "export - 現在のWorldEditの選択範囲をTerraストラクチャーとしてエクスポート"
|
||||
- "load - Terraストラクチャーを読み込む"
|
||||
invalid-radius: "無効な半径: \"%s\""
|
||||
invalid-rotation: "無効な回転: \"%s\""
|
||||
invalid: "無効なストラクチャーID: \"%s\""
|
||||
export: "\"%s\" にストラクチャーを保存"
|
||||
world-config:
|
||||
load: "ワールド \"%s\" のワールド設定値を読み込み中..."
|
||||
not-found: "ワールド \"%s\" の設定が見つかりませんでした。デフォルトの設定をコピーします。"
|
||||
using-image: "画像からワールドを読み込みます。"
|
||||
error: "ワールド %s の設定を読み込めませんでした"
|
||||
done: "ワールドの読み込みが完了しました。経過時間: %sms"
|
||||
config-pack:
|
||||
loaded: "%2$sms で設定 %1$s が読み込まれました。"
|
||||
config:
|
||||
loaded: "ファイル %2$s から %1$s を読み込まれました。"
|
||||
loaded-all: "%3$sms で %1$s %2$s で読み込まれました。"
|
||||
error:
|
||||
invalid-failover: "無効なフェイルオーバータイプ: \"%s\""
|
||||
duplicate: "ファイルに重複したIDが見つかりました: %s"
|
||||
file:
|
||||
- "Terraオブジェクトに設定エラーがあります。ファイル: %1$s"
|
||||
- "%2$s"
|
||||
- "先に進む前にこれを修正してください!"
|
||||
generic:
|
||||
- "設定の読み込み中にエラーが発生しました。"
|
||||
- "Terraに報告してください。"
|
||||
warning:
|
||||
no-population: "チャンクが読み込まれませんでした。初めてTerraでサーバーを起動した場合、または新しいワールドを作成した場合、これは正常です。"
|
||||
error:
|
||||
severe-config: "重大な設定エラーによりTerraが正しく地形を生成できません。座標: %1$s, %2$s エラーがないか設定をチェックしてください。設定エラーは上記で報告されています。"
|
||||
debug:
|
||||
data-save: "ワールド \"%s\" のデータを保存"
|
||||
use-paper:
|
||||
- "Spigot/CraftBukkitを使用していています。"
|
||||
- "TerraはSpigot上で&o動作します&rが、いくつかの機能は使用できません。(TerraはCraftBukkitではテストされていません。CraftBukkitはサポートされません)。"
|
||||
- "Terraを最大限活用するにはPaperに切り替えてください。"
|
||||
- "さらに、PaperはSpigotよりもパフォーマンスが大幅に向上しており、すべてのSpigotプラグインはPaperで動作するはずです。"
|
||||
- "Terraとすべてのプラグインで最高の体験をするためには、Paperをご利用ください。"
|
||||
- "詳細については、Paperのウェブサイトをご覧ください: https://papermc.io/"
|
||||
122
common/implementation/base/src/main/resources/lang/nl_NL.yml
Normal file
122
common/implementation/base/src/main/resources/lang/nl_NL.yml
Normal file
@@ -0,0 +1,122 @@
|
||||
enable:
|
||||
- "Als je Terra leuk vindt, overweeg dan om het project op Patreon te steunen!"
|
||||
- "Je krijgt toegang tot experimentele functies voordat ze uitgebracht worden!"
|
||||
- "Steun het project hier: https://www.patreon.com/dfsek"
|
||||
disable:
|
||||
- "Bedankt voor het gebruiken van Terra!"
|
||||
command:
|
||||
debug-only: "Dit commando moet worden gebruikt met debug-modus ingeschakeld!"
|
||||
player-only: "Dit commando is alleen voor spelers!"
|
||||
invalid: "Ongeldig commando. (Verwachte %1$s argumenten, vond er %2$s)."
|
||||
players-only: "Dit commando is alleen voor spelers."
|
||||
world: "Dit commando moet worden uitgevoerd in een Terra-wereld!"
|
||||
reload: "Terra configuratie herladen."
|
||||
reload-error: "Er zijn fouten opgetreden tijdens het herladen van de Terra-configuratie. Zie de logboeken voor meer informatie."
|
||||
version: "Deze server draait Terra versie \"%1$s\", op platform \"%2$s\""
|
||||
main-menu:
|
||||
- "--------------------Terra--------------------"
|
||||
- "reload - Herlaad de configuratie gegevens"
|
||||
- "biome - Find het huidige bioom (klimaatgebied)"
|
||||
- "ore - Genereer een ertsader op de locatie waar je heen kijkt (voor debuggen)"
|
||||
- "save-data - Sla populatie data op"
|
||||
- "structure - Laad en exporteer constructies"
|
||||
- "profile - Profiler opties"
|
||||
- "image - Afbeelding/GUI opties"
|
||||
biome:
|
||||
biome-found: "bioom (klimaatgebied) gevonden op (%1$s, %2$s)"
|
||||
unable-to-locate: "Geen bioom (klimaatgebied) kunnen vinden."
|
||||
invalid-radius: "Ongeldige straal: \"%s\""
|
||||
invalid: "Ongeldig bioom ID: \"%s\""
|
||||
in: "Je bent in \"%s\""
|
||||
packs:
|
||||
main: "Momenteel geïnstalleerde configuratiepakketten:"
|
||||
pack: " - %1$s v%3$s door %2$s"
|
||||
none: "Er zijn geen configuratiepakketten geïnstalleerd."
|
||||
ore:
|
||||
main-menu:
|
||||
- "---------------Terra/erts---------------"
|
||||
- "Genereer een ertsader bij het blok waar je naar kijkt."
|
||||
out-of-range: "Blok buiten bereik"
|
||||
invalid-ore: "Kan \"%s\" erts niet vinden"
|
||||
geometry:
|
||||
main-menu:
|
||||
- "---------------Terra/geometrie----------------"
|
||||
- "Diverse voxelgeometrie debug commando's"
|
||||
- "sphere - Genereer een bol"
|
||||
- "deformsphere - Genereer een vervormde bol"
|
||||
- "tube - Genereer een tube"
|
||||
deform:
|
||||
invalid-radius: "Ongeldige straal: \"%s\""
|
||||
invalid-deform: "Ongeldige vervorming: \"%s\""
|
||||
invalid-frequency: "Ongeldige frequentie: \"%s\""
|
||||
sphere:
|
||||
invalid-radius: "Ongeldige straal: \"%s\""
|
||||
tube:
|
||||
invalid-radius: "Ongeldige straal: \"%s\""
|
||||
image:
|
||||
main-menu:
|
||||
- "---------------Terra/afbeelding---------------"
|
||||
- "render - Genereer en beeld met een bepaalde breedte en hoogte, deze kan later als een wereld worden geïmporteerd."
|
||||
- "gui - Open debug GUI (moet worden ingeschakeld in de configuratie)."
|
||||
gui:
|
||||
main-menu:
|
||||
- "-------------Terra/afbeelding/gui-------------"
|
||||
- "raw - Open GUI met ruwe bioom (klimaatgebied) gegevens"
|
||||
- "step - Regenereer de gegevens om de grenzen duidelijker te laten zien""
|
||||
debug: "De debug-modus moet ingeschakeld zijn om de debug GUI te kunnen gebruiken! Gebruik de debug GUI alleen om te testen, HET IS NIET VEILIG OM TE GEBRUIKEN IN PRODUCTIE!"
|
||||
render:
|
||||
save: "Afbeelding opgeslagen als \"%s\""
|
||||
error: "Er is een fout opgetreden tijdens het genereren van het beeld!"
|
||||
profile:
|
||||
main-menu:
|
||||
- "---------------Terra/profile---------------"
|
||||
- "start - Start de profiler"
|
||||
- "stop - Stop de profiler"
|
||||
- "query - Haal profiler gegevens op"
|
||||
- "reset - Resets profiler gegevens"
|
||||
reset: "Profiler is gereset."
|
||||
start: "Profiler is gestart."
|
||||
stop: "Profiler is gestopt."
|
||||
structure:
|
||||
main-menu:
|
||||
- "---------------Terra/constructies---------------"
|
||||
- "export - Exporteer je huidige WorldEdit selectie als een Terra constructie."
|
||||
- "load - Laad een Terra constructie"
|
||||
invalid-radius: "Ongeldige straal: \"%s\""
|
||||
invalid-rotation: "Ongeldige rotatie: \"%s\""
|
||||
invalid: "Ongeldig constructie ID: \"%s\""
|
||||
export: "Constructie opgeslagen naar \"%s\""
|
||||
world-config:
|
||||
load: "Laden van configuratiewaarden voor wereld \"%s\"..."
|
||||
not-found: "Configuratie voor wereld \"%s\" niet gevonden. Standaard configuratie wordt gebruikt"
|
||||
using-image: "Laden van wereld uit een afbeelding."
|
||||
error: "Niet in staat om de configuratie voor wereld %s te laden"
|
||||
done: "Laden van wereld \"%1$s\" compleet. Tijd verstreken: %2$sms"
|
||||
config-pack:
|
||||
loaded: "Configuratiepakket %1$s v%4$s door %3$s geladen in %2$sms."
|
||||
config:
|
||||
loaded: "%1$s geladen van bestand %2$s"
|
||||
loaded-all: "%1$s %2$s(s) in %3$sms geladen."
|
||||
error:
|
||||
invalid-failover: "Ongeldig failover type: \"%s\""
|
||||
duplicate: "Duplicaat ID gevonden in bestand: %s"
|
||||
file:
|
||||
- "Configuratiefout voor Terra-object. Bestand: %1$s"
|
||||
- "%2$s"
|
||||
- "Corrigeer dit voordat je verder gaat!"
|
||||
generic:
|
||||
- "Er is een fout opgetreden tijdens het laden van de configuraties."
|
||||
- "Rapporteer dit alsjeblieft aan Terra."
|
||||
warning:
|
||||
no-population: "Geen populatie chunks kunnen laden. Als dit de eerste keer is dat de server met Terra gestart wordt is er niks aan de hand."
|
||||
error:
|
||||
severe-config: "Een ernstige configuratiefout heeft ervoor gezorgd dat Terra geen terrein op de coördinaten %1$s, %2$s heeft kunnen genereren. Controleer je configuratie op fouten. Eventuele configuratiefouten zullen hierboven zijn gemeld."
|
||||
debug:
|
||||
data-save: "Populatie gegevens voor wereld \"%s\" opgeslagen"
|
||||
use-paper:
|
||||
- "Het lijkt erop dat je Spigot/CraftBukkit gebruikt."
|
||||
- "Terra &owerkt&r op Spigot, maar sommige functionaliteit zal verloren gaan. (Terra is niet getest op CraftBukkit; er wordt dus ook geen ondersteuning voor gegeven)."
|
||||
- "Om het meeste uit Terra te halen, schakel dan over op Paper."
|
||||
- "Bovendien biedt Paper enorme prestatieverbeteringen ten opzichte van Spigot, en zelfs alle Spigot plugins zouden met Paper moeten werken!"
|
||||
- "Om de beste ervaring met Terra, en al je andere plugins, te hebben, gebruik dan Paper."
|
||||
- "Lees meer op de website van Paper: https://papermc.io/"
|
||||
117
common/implementation/base/src/main/resources/lang/pl.yml
Normal file
117
common/implementation/base/src/main/resources/lang/pl.yml
Normal file
@@ -0,0 +1,117 @@
|
||||
enable:
|
||||
- "Jezeli spodoba ci sie Terra, rozwaz wsparcie projektu na Patreon!"
|
||||
- "Otrzymasz dostep do eksperymentalnych funkcji przed ich premiera!"
|
||||
- "Wspieraj projekt na: https://www.patreon.com/dfsek"
|
||||
disable:
|
||||
- "Dziekuje za korzystanie z Terra!"
|
||||
command:
|
||||
debug-only: "Ta komenda musi byc uzyta z trybem debugowym wlaczonym!"
|
||||
player-only: "Ta komenda jest tylko dla graczy!"
|
||||
invalid: "Niepoprawna komenda. (Oczekiwane %1$s argumenty, znalezione %2$s)."
|
||||
players-only: "Komenda jest tylko dla graczy."
|
||||
world: "Ta komenda musi byc wpisana w swiecie Terra!"
|
||||
reload: "Przeladowano plik konfiguracyjny Terra."
|
||||
version: "Ten serwer korzysta z wersji Terra \"%s\""
|
||||
main-menu:
|
||||
- "--------------------Terra--------------------"
|
||||
- "reload - Przeladuj dane konfiguracyjne"
|
||||
- "biome - Otrzymaj informacje o obecnym biomie"
|
||||
- "ore - Wygeneruj zloze rud w strone w ktora patrzysz (Do debugowania)"
|
||||
- "save-data - Zapisz dane"
|
||||
- "structure - Zaladuj i wyeksportuj dane struktur"
|
||||
- "profile - Opcje profilera"
|
||||
- "image - Opcje obrazu/GUI"
|
||||
biome:
|
||||
biome-found: "Zlokalizowano biom na (%1$s, %2$s)"
|
||||
unable-to-locate: "Nie moglismy zlokalizowac biomu."
|
||||
invalid-radius: "Niepoprawny zakres: \"%s\""
|
||||
invalid: "Niepoprawne Biome ID: \"%s\""
|
||||
in: "Jestes na \"%s\""
|
||||
ore:
|
||||
main-menu:
|
||||
- "---------------Terra/rudy---------------"
|
||||
- "Generuje zloze rud w strone w ktora patrzysz."
|
||||
out-of-range: "Blok spoza zakresu"
|
||||
invalid-ore: "Niemoglismy znalezc Rudy \"%s\""
|
||||
geometry:
|
||||
main-menu:
|
||||
- "---------------Terra/geometria----------------"
|
||||
- "Zroznicowane komendy geometrii voxeli do debugowania"
|
||||
- "sphere - Generuje kule"
|
||||
- "deformsphere - Generuje zdeformowana kul"
|
||||
- "tube - Generaje tube"
|
||||
deform:
|
||||
invalid-radius: "Niepoprawny zakres: \"%s\""
|
||||
invalid-deform: "Niepoprawna deformacja: \"%s\""
|
||||
invalid-frequency: "Niepoprawna czestotliwosc: \"%s\""
|
||||
sphere:
|
||||
invalid-radius: "Niepoprawny zakres: \"%s\""
|
||||
tube:
|
||||
invalid-radius: "Niepoprawny zakres: \"%s\""
|
||||
image:
|
||||
main-menu:
|
||||
- "---------------Terra/obraz---------------"
|
||||
- "render - Renderuje obraz o podanej szerokosci i wysokosci, moze byc potem zaimportowane jako swiat."
|
||||
- "gui - Otwiera GUI debugowania (Musi byc wlaczone w pliku konfiguracyjnym)"
|
||||
gui:
|
||||
main-menu:
|
||||
- "-------------Terra/obraz/gui-------------"
|
||||
- "raw - Otwiera GUI z surowymi danymi Biomu"
|
||||
- "step - Przerenderowuje dane aby pokazac granice bardziej przejrzyscie"
|
||||
debug: "Tryb debugowania musi byc wlaczony aby debugowac za pomoca GUI! GUI debugowania NIE JEST STABILNE!"
|
||||
render:
|
||||
save: "Zapisano obraz jako \"%s\""
|
||||
error: "Wystapil error podczas generowania obrazu!"
|
||||
profile:
|
||||
main-menu:
|
||||
- "---------------Terra/profil---------------"
|
||||
- "start - Rozpoczyna dzialanie profilera"
|
||||
- "stop - Zatrzymuje dzialanie profilera"
|
||||
- "query - Wydobywa dane profilera"
|
||||
- "reset - Resetuje dane profilera"
|
||||
reset: "Profiler zostal zresetowany."
|
||||
start: "Profiler zostal wlaczony."
|
||||
stop: "Profiler zostal wylaczony."
|
||||
structure:
|
||||
main-menu:
|
||||
- "---------------Terra/struktury---------------"
|
||||
- "export - Wyeksportuj obecne zaznaczenie w WorldEdicie jako strukture Terra."
|
||||
- "load - Zaladuj strukture Terra"
|
||||
invalid-radius: "Niepoprawny zakres: \"%s\""
|
||||
invalid-rotation: "Niepoprawny zakres: \"%s\""
|
||||
invalid: "Niepoprawne ID Struktury: \"%s\""
|
||||
export: "Zapisano strukture jak \"%s\""
|
||||
world-config:
|
||||
loading: "Ladowanie wartosci konfiguracji dla swiata %s..."
|
||||
not-found: "Konfiguracja dla swiata \"%s\" nie zostala znaleziona. Kopiuje domyslny plik konfiguracyjny."
|
||||
using-image: "Ladowania swiata z obrazu."
|
||||
error: "Nie udalo sie zaladowac konfiguracji dla swiata %s"
|
||||
done: "Ladowanie swiata gotowe. Wykonano to w: %sms"
|
||||
config-pack:
|
||||
loaded: "Zaladowano plik konfiguracyjny %1$s w %2$sms."
|
||||
config:
|
||||
loaded: "Zaladowano %1$s z pliku %2$s"
|
||||
loaded-all: "Zaladowano %1$s %2$s(s) w %3$sms."
|
||||
error:
|
||||
invalid-failover: "Niepoprawny typ awaryjnego przelaczania: \"%s\""
|
||||
duplicate: "Zduplikowano ID znalezione w pliku: %s"
|
||||
file:
|
||||
- "Blad konfiguracji w objekcie Terra. Plik: %1$s"
|
||||
- "%2$s"
|
||||
- "Popraw to przed rozpoczeciem!"
|
||||
generic:
|
||||
- "Wystapil blad podczas ladowania konfiguracji."
|
||||
- "Prosze zglos to do Terra."
|
||||
warning:
|
||||
no-population: "Chunki populacyjne nie zostaly zaladowane. Jezeli to jest pierwszy raz kiedy wlaczasz serwer z Terra, lub tworzysz nowy swiat, to jest normalne."
|
||||
error:
|
||||
severe-config: "Powazne bledy konfiguracji zablokowaly generowanie terenu na koordynatach: %1$s, %2$s. Prosze sprawdz konfiguracyje w poszukiwaniu bledow. Wszelkie bledy konfiguracyjne zostaly zgloszone powyzej."
|
||||
debug:
|
||||
data-save: "Zapisane dane dla swiata \"%s\""
|
||||
use-paper:
|
||||
- "Wyglada na to ze dalej korzystasz z Spigot/CraftBukkit."
|
||||
- "Terra &odziala&r na Spigotcie, niektore funkcje moga byc stracone. (Terra nie jest przetestowana na CraftBukkit; wiec nie wspieramy CraftBukkit)."
|
||||
- "Aby wycisnac jak najwiecej z Terra, prosze przejdz na Paper."
|
||||
- "Ponadto, Paper oferuje ulepszona wydajnosc wzgledem Spigota, a wszystkie pluginy z Spigota powinny dzialac na Paperze!"
|
||||
- "Dla jak najlepszych doswiadczen z Terra, i wszystkimi twoimi pluginami, przejdz na Papera."
|
||||
- "Dowiedz sie wiecej o Paperze na ich stronie: https://papermc.io/"
|
||||
122
common/implementation/base/src/main/resources/lang/ru.yml
Normal file
122
common/implementation/base/src/main/resources/lang/ru.yml
Normal file
@@ -0,0 +1,122 @@
|
||||
enable:
|
||||
- "Если вам нравится Terra, пожалуйста, поддержите проект на Patreon!"
|
||||
- "Вы получите доступ к экспериментальным функциям ещё до их релиза!"
|
||||
- "Поддержите проект здесь: https://www.patreon.com/dfsek"
|
||||
disable:
|
||||
- "Благодарим за использование Terra!"
|
||||
command:
|
||||
debug-only: "Эта команда может быть введена только в режиме отладки!"
|
||||
player-only: "Эту команду могут вводить только игроки!"
|
||||
invalid: "Неверная команда. (Ожидался аргумент %1$s, найден %2$s)."
|
||||
players-only: "Команда только для игроков."
|
||||
world: "Эта команда может быть введена только в мире с Terra!"
|
||||
reload: "Конфигурации Terra перезагружена."
|
||||
reload-error: "Во время перезагрузки конфигураций Terra произошла ошибка. Просмотрите логи для более детальной информации."
|
||||
version: "This server is running Terra version \"%1$s\", on platform \"%2$s\""
|
||||
main-menu:
|
||||
- "--------------------Terra--------------------"
|
||||
- "reload - Перезагрузить конфигурации"
|
||||
- "biome - Узнать текущий биом"
|
||||
- "ore - Сгенерировать жилу руд на месте вашего взора (Для отладки)"
|
||||
- "save-data - Сохранить данные популяции"
|
||||
- "structure - Загрузить и экспортировать структуры"
|
||||
- "profile - Команды профайлера"
|
||||
- "image - Команды образа/интерфейса"
|
||||
biome:
|
||||
biome-found: "Биом найден на (%1$s, %2$s)"
|
||||
unable-to-locate: "Не получилось найти биом."
|
||||
invalid-radius: "Неверный радиус: \"%s\""
|
||||
invalid: "Неверный ID биома: \"%s\""
|
||||
in: "Вы находитесь в \"%s\""
|
||||
packs:
|
||||
main: "Установленные наборы конфигураций:"
|
||||
pack: " - %1$s вер.%3$s от %2$s"
|
||||
none: "Наборы конфигураций не установлены."
|
||||
ore:
|
||||
main-menu:
|
||||
- "---------------Terra/ore---------------"
|
||||
- "Генерирует жилу руд на месте вашего взора."
|
||||
out-of-range: "Блок слишком далеко"
|
||||
invalid-ore: "Не получилось найти руду \"%s\""
|
||||
geometry:
|
||||
main-menu:
|
||||
- "---------------Terra/geometry----------------"
|
||||
- "Различные команды отладки воксельной геометрии"
|
||||
- "sphere - Сгенерировать сферу"
|
||||
- "deformsphere - Сгенерировать деформированную сферу"
|
||||
- "tube - Сгенерировать трубу"
|
||||
deform:
|
||||
invalid-radius: "Неверный радиус: \"%s\""
|
||||
invalid-deform: "Неверная деформация: \"%s\""
|
||||
invalid-frequency: "Неверная частота: \"%s\""
|
||||
sphere:
|
||||
invalid-radius: "Неверный радиус: \"%s\""
|
||||
tube:
|
||||
invalid-radius: "Неверный радиус: \"%s\""
|
||||
image:
|
||||
main-menu:
|
||||
- "---------------Terra/image---------------"
|
||||
- "render - Прорендерить образ с указанными шириной и высотой, который позже может быть импортирован как мир."
|
||||
- "gui - Открыть интерфейс отладки (Должно быть включено в конфигурации)"
|
||||
gui:
|
||||
main-menu:
|
||||
- "-------------Terra/image/gui-------------"
|
||||
- "raw - Открыть интерфейс с сырыми данными биомов"
|
||||
- "step - Перерендерить данные для более ясного видения границ"
|
||||
debug: "Для использования этого интерфейса должен быть включен режим отладки! Режим отладки НЕБЕЗОПАСЕН ДЛЯ СЕРВЕРОВ!"
|
||||
render:
|
||||
save: "Образ сохранен как \"%s\""
|
||||
error: "Во время генерации образа произошла ошибка!"
|
||||
profile:
|
||||
main-menu:
|
||||
- "---------------Terra/profile---------------"
|
||||
- "start - Начать анализ профайлером"
|
||||
- "stop - Остановить анализ профайлером"
|
||||
- "query - Получить данные профайлера"
|
||||
- "reset - Обнулить данные профайлера"
|
||||
reset: "Данные профайлера были обнулены."
|
||||
start: "Анализ профайлером начат."
|
||||
stop: "Анализ профайлером остановлен."
|
||||
structure:
|
||||
main-menu:
|
||||
- "---------------Terra/structure---------------"
|
||||
- "export - Экспортировать выделение WorldEdit'а как структуру Terra"
|
||||
- "load - Загрузить структуру Terra"
|
||||
invalid-radius: "Неверный радиус: \"%s\""
|
||||
invalid-rotation: "Неверный поворот: \"%s\""
|
||||
invalid: "Неверный ID структуры: \"%s\""
|
||||
export: "Структура сохранена как \"%s\""
|
||||
world-config:
|
||||
load: "Значения конфигурации мира \"%s\" загружаются..."
|
||||
not-found: "Конфигурация мира \"%s\" не найдена. Копирование обычной."
|
||||
using-image: "Загрузка мира с образа."
|
||||
error: "Не получилось загрузить конфигурацию мира %s"
|
||||
done: "Загрузка мира \"%1$s\" завершена. Затрачено времени: %2$sмс"
|
||||
config-pack:
|
||||
loaded: "Набор конфигураций %1$s вер.%4$s от %3$s загружен за %2$sмс."
|
||||
config:
|
||||
loaded: "Загружен %1$s с файла %2$s"
|
||||
loaded-all: "Загружено %1$s %2$s за %3$sмс."
|
||||
error:
|
||||
invalid-failover: "Неверный тип аварийного переключения: \"%s\""
|
||||
duplicate: "Дублирующийся ID найден в файле: %s"
|
||||
file:
|
||||
- "Ошибка конфигурации объекта Terra. Файл: %1$s"
|
||||
- "%2$s"
|
||||
- "Прежде чем продолжить, исправьте это!"
|
||||
generic:
|
||||
- "Во время загрузки конфигураций произошла ошибка."
|
||||
- "Пожалуйста, сообщите об этом разработчикам Terra."
|
||||
warning:
|
||||
no-population: "Не было загружено популяторов чанков. Если вы впервые запускаете сервер с Terra или создаете новый мир, то всё в порядке."
|
||||
error:
|
||||
severe-config: "Несколько ошибок конфигруации не позволили Terra сгенерировать область нормально по этим координатам: %1$s, %2$s. Пожалуйста, проверьте свою конфигурацию на наличие ошибок. Все ошибки были показаны выше."
|
||||
debug:
|
||||
data-save: "Данные популяции мира \"%s\" сохранены"
|
||||
use-paper:
|
||||
- "Похоже, что вы используете Spigot/CraftBukkit."
|
||||
- "Пускай Terra и &oработает&r со Spigot, часть функционала плагина не работает. (Terra не тестировался с CraftBukkit; не ожидайте поддержки для CraftBukkit)."
|
||||
- "Чтобы получить весь функционал Terra, пожалуйста, используйте Paper."
|
||||
- "Кроме того, Paper намного производительнее, чем Spigot, а все плагины Spigot должны работать и на Paper!"
|
||||
- "Если вы хотите получить лучший опыт использования Terra и иных плагинов, пожалуйста, предпочтите Paper."
|
||||
- "Больше о Paper можно узнать на сайте: https://papermc.io/"
|
||||
107
common/implementation/base/src/main/resources/lang/zh_cn.yml
Normal file
107
common/implementation/base/src/main/resources/lang/zh_cn.yml
Normal file
@@ -0,0 +1,107 @@
|
||||
enable:
|
||||
- "如果你喜欢Terra,请考虑在Patreon上支持该项目!"
|
||||
- "你会在项目正式发布前获得实验性特性!"
|
||||
- "前往该网址支持我们:https://www.patreon.com/dfsek"
|
||||
disable:
|
||||
- "感谢使用Terra!"
|
||||
command:
|
||||
player-only: "该指令只能由玩家使用!"
|
||||
terra-world: "该指令只能在Terra世界内使用!"
|
||||
invalid: "无效的指令。(应有%1$s项参数,现在只有%2$s项)。"
|
||||
players-only: "指令只能由玩家使用。"
|
||||
world: "该指令只能在Terra世界内使用!"
|
||||
reload: "重载Terra配置。"
|
||||
main-menu:
|
||||
- "--------------------Terra--------------------"
|
||||
- "reload - 重载配置数据"
|
||||
- "biome - 查看所在群系"
|
||||
- "ore - 在你面朝的位置生成矿脉(用于调试)"
|
||||
- "save-data - 保存数据"
|
||||
- "structure - 加载和导出建筑"
|
||||
- "profile - 分析工具选项"
|
||||
- "image - 图像/GUI 选项"
|
||||
biome:
|
||||
biome-found: "群系位于(%1$s, %2$s)"
|
||||
unable-to-locate: "无法定位群系。"
|
||||
invalid-radius: "无效范围:\"%s\""
|
||||
invalid: "无效的群系ID: \"%s\""
|
||||
in: "你位于\"%s\""
|
||||
ore:
|
||||
main-menu:
|
||||
- "---------------Terra/矿物---------------"
|
||||
- "在你所视位置生成矿脉。"
|
||||
out-of-range: "所视方块超出范围"
|
||||
invalid-ore: "找不到矿物 \"%s\""
|
||||
geometry:
|
||||
main-menu:
|
||||
- "---------------Terra/几何----------------"
|
||||
- "各种几何调试指令"
|
||||
- "sphere - 生成球体"
|
||||
- "deformsphere - 生成变形球体"
|
||||
- "tube - 生成管形"
|
||||
deform:
|
||||
invalid-radius: "无效范围:\"%s\""
|
||||
invalid-deform: "无效变形:\"%s\""
|
||||
invalid-frequency: "无效频率:\"%s\""
|
||||
sphere:
|
||||
invalid-radius: "无效范围:\"%s\""
|
||||
tube:
|
||||
invalid-radius: "无效范围:\"%s\""
|
||||
image:
|
||||
main-menu:
|
||||
- "---------------Terra/图像---------------"
|
||||
- "render - 根据给定宽度和高度渲染图像,以便于之后导入到世界内。"
|
||||
- "gui - 打开调试GUI (必须先在配置内启用)"
|
||||
gui:
|
||||
main-menu:
|
||||
- "-------------Terra/图像/GUI-------------"
|
||||
- "raw - 打开纯群系数据的GUI"
|
||||
- "step - 重渲染数据以更清晰地显示边界"
|
||||
debug: "必须先启用调试模式才能使用GUI!调试GUI不适合在运行中的服务器里使用!"
|
||||
render:
|
||||
save: "已将图像保存为\"%s\""
|
||||
error: "生成图像时出错!"
|
||||
profile:
|
||||
main-menu:
|
||||
- "---------------Terra/分析---------------"
|
||||
- "start - 启动分析工具"
|
||||
- "stop - 关闭分析工具"
|
||||
- "query - 获取分析数据"
|
||||
- "reset - 重置分析数据"
|
||||
reset: "分析工具已重置。"
|
||||
start: "分析工具已启动。"
|
||||
stop: "分析工具已关闭。"
|
||||
structure:
|
||||
main-menu:
|
||||
- "---------------Terra/建筑---------------"
|
||||
- "export - 导出你当前的WorldEdit选区为Terra的建筑。"
|
||||
- "load - 加载Terra的建筑。"
|
||||
invalid-radius: "无效范围:\"%s\""
|
||||
invalid: "无效建筑ID:\"%s\""
|
||||
export: "已将建筑保存为\"%s\""
|
||||
world-config:
|
||||
loading: "正在加载世界%s配置数值……"
|
||||
not-found: "找不到世界\"%s\"的配置。正应用默认配置。"
|
||||
using-image: "加载图像中"
|
||||
error: "无法加载世界%s的配置"
|
||||
done: "加载世界完成。耗时:%sms"
|
||||
config-pack:
|
||||
loaded: "已加载配置%1$s,耗时%2$sms。"
|
||||
config:
|
||||
loaded: "已加载%1$s,源自文件%2$s"
|
||||
loaded-all: "已加载%1$s %2$s(s),耗时%3$sms。"
|
||||
error:
|
||||
duplicate: "该文件内的ID重复:%s"
|
||||
file:
|
||||
- "Terra目标的配置出错。文件:%1$s"
|
||||
- "%2$s"
|
||||
- "请先校正该配置!"
|
||||
generic:
|
||||
- "加载配置时出错。"
|
||||
- "请汇报该错误。"
|
||||
warning:
|
||||
no-population: "未加载区块。如果这是你第一次安装Terra后开服,或者你只是创建新世界,那么你看到这条消息很正常。"
|
||||
error:
|
||||
severe-config: "严重配置错误,该错误阻止Terra正常生成位于该坐标的地形:%1$s, %2$s。请检查你的配置。任何配置错误都会显示在上面。"
|
||||
debug:
|
||||
data-save: "已保存该世界的地形数据:\"%s\""
|
||||
133
common/implementation/base/src/test/java/MetaTest.java
Normal file
133
common/implementation/base/src/test/java/MetaTest.java
Normal file
@@ -0,0 +1,133 @@
|
||||
import com.dfsek.tectonic.annotations.Value;
|
||||
import com.dfsek.tectonic.config.ConfigTemplate;
|
||||
import com.dfsek.tectonic.config.Configuration;
|
||||
import com.dfsek.tectonic.loading.ConfigLoader;
|
||||
import com.dfsek.tectonic.yaml.YamlConfiguration;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.dfsek.terra.api.config.meta.Meta;
|
||||
import com.dfsek.terra.config.preprocessor.MetaListLikePreprocessor;
|
||||
import com.dfsek.terra.config.preprocessor.MetaMapPreprocessor;
|
||||
import com.dfsek.terra.config.preprocessor.MetaNumberPreprocessor;
|
||||
import com.dfsek.terra.config.preprocessor.MetaStringPreprocessor;
|
||||
import com.dfsek.terra.config.preprocessor.MetaValuePreprocessor;
|
||||
|
||||
|
||||
public class MetaTest {
|
||||
@Test
|
||||
public void testMetaList() {
|
||||
Configuration meta = new YamlConfiguration(MetaTest.class.getResourceAsStream("/meta.yml"), "meta.yml");
|
||||
Configuration metaTarget = new YamlConfiguration(MetaTest.class.getResourceAsStream("/metaTarget.yml"), "metaTarget.yml");
|
||||
|
||||
Map<String, Configuration> configurationMap = new HashMap<>();
|
||||
|
||||
configurationMap.put(meta.getName(), meta);
|
||||
configurationMap.put(metaTarget.getName(), metaTarget);
|
||||
|
||||
ConfigLoader loader = new ConfigLoader();
|
||||
loader.registerPreprocessor(Meta.class, new MetaStringPreprocessor(configurationMap));
|
||||
loader.registerPreprocessor(Meta.class, new MetaListLikePreprocessor(configurationMap));
|
||||
loader.registerPreprocessor(Meta.class, new MetaMapPreprocessor(configurationMap));
|
||||
loader.registerPreprocessor(Meta.class, new MetaNumberPreprocessor(configurationMap));
|
||||
|
||||
loader.registerPreprocessor(Meta.class, new MetaValuePreprocessor(configurationMap));
|
||||
|
||||
loader.load(new MetaListConfig(), meta).list.forEach(System.out::println);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMetaMap() {
|
||||
Configuration meta = new YamlConfiguration(MetaTest.class.getResourceAsStream("/meta.yml"), "meta.yml");
|
||||
Configuration metaTarget = new YamlConfiguration(MetaTest.class.getResourceAsStream("/metaTarget.yml"), "metaTarget.yml");
|
||||
|
||||
Map<String, Configuration> configurationMap = new HashMap<>();
|
||||
|
||||
configurationMap.put(meta.getName(), meta);
|
||||
configurationMap.put(metaTarget.getName(), metaTarget);
|
||||
|
||||
ConfigLoader loader = new ConfigLoader();
|
||||
loader.registerPreprocessor(Meta.class, new MetaStringPreprocessor(configurationMap));
|
||||
loader.registerPreprocessor(Meta.class, new MetaListLikePreprocessor(configurationMap));
|
||||
loader.registerPreprocessor(Meta.class, new MetaMapPreprocessor(configurationMap));
|
||||
loader.registerPreprocessor(Meta.class, new MetaNumberPreprocessor(configurationMap));
|
||||
|
||||
loader.registerPreprocessor(Meta.class, new MetaValuePreprocessor(configurationMap));
|
||||
|
||||
loader.load(new MetaMapConfig(), meta).map.forEach((k, v) -> System.out.println(k + ": " + v));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMetaString() {
|
||||
Configuration meta = new YamlConfiguration(MetaTest.class.getResourceAsStream("/meta.yml"), "meta.yml");
|
||||
Configuration metaTarget = new YamlConfiguration(MetaTest.class.getResourceAsStream("/metaTarget.yml"), "metaTarget.yml");
|
||||
|
||||
Map<String, Configuration> configurationMap = new HashMap<>();
|
||||
|
||||
configurationMap.put(meta.getName(), meta);
|
||||
configurationMap.put(metaTarget.getName(), metaTarget);
|
||||
|
||||
ConfigLoader loader = new ConfigLoader();
|
||||
|
||||
loader.registerPreprocessor(Meta.class, new MetaStringPreprocessor(configurationMap));
|
||||
loader.registerPreprocessor(Meta.class, new MetaListLikePreprocessor(configurationMap));
|
||||
loader.registerPreprocessor(Meta.class, new MetaMapPreprocessor(configurationMap));
|
||||
loader.registerPreprocessor(Meta.class, new MetaNumberPreprocessor(configurationMap));
|
||||
|
||||
loader.registerPreprocessor(Meta.class, new MetaValuePreprocessor(configurationMap));
|
||||
|
||||
System.out.println(loader.load(new MetaStringConfig(), meta).string);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMetaNumber() {
|
||||
Configuration meta = new YamlConfiguration(MetaTest.class.getResourceAsStream("/meta.yml"), "meta.yml");
|
||||
Configuration metaTarget = new YamlConfiguration(MetaTest.class.getResourceAsStream("/metaTarget.yml"), "metaTarget.yml");
|
||||
|
||||
Map<String, Configuration> configurationMap = new HashMap<>();
|
||||
|
||||
configurationMap.put(meta.getName(), meta);
|
||||
configurationMap.put(metaTarget.getName(), metaTarget);
|
||||
|
||||
ConfigLoader loader = new ConfigLoader();
|
||||
loader.registerPreprocessor(Meta.class, new MetaStringPreprocessor(configurationMap));
|
||||
loader.registerPreprocessor(Meta.class, new MetaListLikePreprocessor(configurationMap));
|
||||
loader.registerPreprocessor(Meta.class, new MetaMapPreprocessor(configurationMap));
|
||||
loader.registerPreprocessor(Meta.class, new MetaNumberPreprocessor(configurationMap));
|
||||
|
||||
loader.registerPreprocessor(Meta.class, new MetaValuePreprocessor(configurationMap));
|
||||
|
||||
System.out.println("int: " + loader.load(new MetaNumberConfig(), meta).integer);
|
||||
System.out.println("double: " + loader.load(new MetaNumberConfig(), meta).aDouble);
|
||||
}
|
||||
|
||||
|
||||
private static final class MetaListConfig implements ConfigTemplate {
|
||||
@Value("list")
|
||||
private @Meta List<@Meta String> list;
|
||||
}
|
||||
|
||||
|
||||
private static final class MetaMapConfig implements ConfigTemplate {
|
||||
@Value("map")
|
||||
private @Meta Map<@Meta String, @Meta String> map;
|
||||
}
|
||||
|
||||
|
||||
private static final class MetaStringConfig implements ConfigTemplate {
|
||||
@Value("string")
|
||||
private @Meta String string;
|
||||
}
|
||||
|
||||
|
||||
private static final class MetaNumberConfig implements ConfigTemplate {
|
||||
@Value("int")
|
||||
private @Meta int integer;
|
||||
|
||||
@Value("double")
|
||||
private @Meta double aDouble;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,259 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package command;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import com.dfsek.terra.api.command.CommandManager;
|
||||
import com.dfsek.terra.api.command.CommandTemplate;
|
||||
import com.dfsek.terra.api.command.annotation.Argument;
|
||||
import com.dfsek.terra.api.command.annotation.Command;
|
||||
import com.dfsek.terra.api.command.annotation.Subcommand;
|
||||
import com.dfsek.terra.api.command.annotation.Switch;
|
||||
import com.dfsek.terra.api.command.annotation.inject.ArgumentTarget;
|
||||
import com.dfsek.terra.api.command.annotation.inject.SwitchTarget;
|
||||
import com.dfsek.terra.api.command.arg.DoubleArgumentParser;
|
||||
import com.dfsek.terra.api.command.arg.IntegerArgumentParser;
|
||||
import com.dfsek.terra.api.command.exception.CommandException;
|
||||
import com.dfsek.terra.api.command.exception.InvalidArgumentsException;
|
||||
import com.dfsek.terra.api.command.exception.MalformedCommandException;
|
||||
import com.dfsek.terra.api.entity.CommandSender;
|
||||
import com.dfsek.terra.commands.TerraCommandManager;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
|
||||
public class CommandTest {
|
||||
@Test
|
||||
public void subcommand() throws CommandException {
|
||||
CommandManager manager = new TerraCommandManager(null);
|
||||
manager.register("test", DemoParentCommand.class);
|
||||
|
||||
manager.execute("test", null, Arrays.asList("subcommand1", "first", "2"));
|
||||
manager.execute("test", null, Arrays.asList("subcommand2", "first", "2"));
|
||||
manager.execute("test", null, Arrays.asList("s1", "first", "2", "3.4"));
|
||||
manager.execute("test", null, Arrays.asList("s2", "first", "2"));
|
||||
manager.execute("test", null, Arrays.asList("sub1", "first", "2", "3.4"));
|
||||
manager.execute("test", null, Arrays.asList("sub2", "first", "2"));
|
||||
manager.execute("test", null, Arrays.asList("first", "2")); // Parent command args
|
||||
|
||||
System.out.println("ARGS: " + manager.getMaxArgumentDepth());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void args() throws CommandException {
|
||||
CommandManager manager = new TerraCommandManager(null);
|
||||
manager.register("test", DemoCommand.class);
|
||||
|
||||
manager.execute("test", null, Arrays.asList("first", "2"));
|
||||
manager.execute("test", null, Arrays.asList("first", "2", "3.4"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void argsBeforeFlags() throws CommandException {
|
||||
CommandManager manager = new TerraCommandManager(null);
|
||||
manager.register("test", DemoCommand.class);
|
||||
|
||||
try {
|
||||
manager.execute("test", null, Arrays.asList("first", "-flag", "2"));
|
||||
fail();
|
||||
} catch(InvalidArgumentsException ignore) {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requiredArgsFirst() throws CommandException {
|
||||
CommandManager manager = new TerraCommandManager(null);
|
||||
manager.register("test", DemoInvalidCommand.class);
|
||||
|
||||
try {
|
||||
manager.execute("test", null, Arrays.asList("first", "2"));
|
||||
fail();
|
||||
} catch(MalformedCommandException ignore) {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void switches() throws CommandException {
|
||||
CommandManager manager = new TerraCommandManager(null);
|
||||
manager.register("test", DemoSwitchCommand.class);
|
||||
|
||||
manager.execute("test", null, Arrays.asList("first", "2"));
|
||||
manager.execute("test", null, Arrays.asList("first", "2", "3.4"));
|
||||
|
||||
manager.execute("test", null, Arrays.asList("first", "2", "-a"));
|
||||
manager.execute("test", null, Arrays.asList("first", "2", "3.4", "-b"));
|
||||
|
||||
manager.execute("test", null, Arrays.asList("first", "2", "-aSwitch"));
|
||||
manager.execute("test", null, Arrays.asList("first", "2", "3.4", "-bSwitch"));
|
||||
|
||||
manager.execute("test", null, Arrays.asList("first", "2", "-aSwitch", "-b"));
|
||||
manager.execute("test", null, Arrays.asList("first", "2", "3.4", "-bSwitch", "-a"));
|
||||
}
|
||||
|
||||
@Command(
|
||||
arguments = {
|
||||
@Argument("arg0"),
|
||||
@Argument(value = "arg1", argumentParser = IntegerArgumentParser.class),
|
||||
@Argument(value = "arg2", required = false, argumentParser = DoubleArgumentParser.class, defaultValue = "0")
|
||||
}
|
||||
)
|
||||
public static final class DemoCommand implements CommandTemplate {
|
||||
|
||||
@ArgumentTarget("arg0")
|
||||
private String arg0;
|
||||
|
||||
@ArgumentTarget("arg1")
|
||||
private Integer arg1;
|
||||
|
||||
@ArgumentTarget("arg2")
|
||||
private Double arg2;
|
||||
|
||||
|
||||
@Override
|
||||
public void execute(CommandSender sender) {
|
||||
System.out.println(arg0);
|
||||
System.out.println(arg1);
|
||||
System.out.println(arg2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Command(
|
||||
arguments = {
|
||||
@Argument("arg0"),
|
||||
@Argument("arg1"),
|
||||
@Argument(value = "arg2", required = false)
|
||||
},
|
||||
switches = {
|
||||
@Switch(value = "a", aliases = "aSwitch"),
|
||||
@Switch(value = "b", aliases = "bSwitch")
|
||||
}
|
||||
)
|
||||
public static final class DemoSwitchCommand implements CommandTemplate {
|
||||
@ArgumentTarget("arg0")
|
||||
private String arg0;
|
||||
|
||||
@ArgumentTarget("arg1")
|
||||
private String arg1;
|
||||
|
||||
@ArgumentTarget("arg2")
|
||||
private String arg2;
|
||||
|
||||
@SwitchTarget("a")
|
||||
private boolean a;
|
||||
|
||||
@SwitchTarget("b")
|
||||
private boolean b;
|
||||
|
||||
|
||||
@Override
|
||||
public void execute(CommandSender sender) {
|
||||
System.out.println(arg0);
|
||||
System.out.println(arg1);
|
||||
System.out.println(arg2);
|
||||
|
||||
System.out.println("A: " + a);
|
||||
System.out.println("B: " + b);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Command(
|
||||
arguments = {
|
||||
@Argument("arg0"),
|
||||
@Argument(value = "arg2", required = false), // optional arguments must be last. this command is invalid.
|
||||
@Argument("arg1")
|
||||
}
|
||||
)
|
||||
public static final class DemoInvalidCommand implements CommandTemplate {
|
||||
|
||||
@Override
|
||||
public void execute(CommandSender sender) {
|
||||
throw new Error("this should never be reached");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Command(
|
||||
arguments = {
|
||||
@Argument("arg0"),
|
||||
@Argument("arg1"),
|
||||
@Argument(value = "arg2", required = false),
|
||||
},
|
||||
subcommands = {
|
||||
@Subcommand(
|
||||
value = "subcommand1",
|
||||
aliases = { "s1", "sub1" },
|
||||
clazz = DemoChildCommand.class
|
||||
),
|
||||
@Subcommand(
|
||||
value = "subcommand2",
|
||||
aliases = { "s2", "sub2" },
|
||||
clazz = DemoChildCommand.class // Duplicate command intentional.
|
||||
)
|
||||
}
|
||||
)
|
||||
public static final class DemoParentCommand implements CommandTemplate {
|
||||
@ArgumentTarget("arg0")
|
||||
private String arg0;
|
||||
|
||||
@ArgumentTarget("arg1")
|
||||
private String arg1;
|
||||
|
||||
@ArgumentTarget("arg2")
|
||||
private String arg2;
|
||||
|
||||
|
||||
@Override
|
||||
public void execute(CommandSender sender) {
|
||||
System.out.println(arg0);
|
||||
System.out.println(arg1);
|
||||
System.out.println(arg2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Command(
|
||||
arguments = {
|
||||
@Argument("arg0"),
|
||||
@Argument("arg1"),
|
||||
@Argument(value = "arg2", required = false),
|
||||
}
|
||||
)
|
||||
public static final class DemoChildCommand implements CommandTemplate {
|
||||
@ArgumentTarget("arg0")
|
||||
private String arg0;
|
||||
|
||||
@ArgumentTarget("arg1")
|
||||
private String arg1;
|
||||
|
||||
@ArgumentTarget("arg2")
|
||||
private String arg2;
|
||||
|
||||
|
||||
@Override
|
||||
public void execute(CommandSender sender) {
|
||||
System.out.println(arg0);
|
||||
System.out.println(arg1);
|
||||
System.out.println(arg2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package profiler;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import com.dfsek.terra.api.profiler.Profiler;
|
||||
import com.dfsek.terra.profiler.ProfilerImpl;
|
||||
|
||||
|
||||
public class ProfilerTest {
|
||||
private static final Profiler PROFILER = new ProfilerImpl();
|
||||
|
||||
private static void doThing() throws InterruptedException {
|
||||
PROFILER.push("thing");
|
||||
Thread.sleep(1);
|
||||
doOtherThing();
|
||||
thing4();
|
||||
PROFILER.pop("thing");
|
||||
}
|
||||
|
||||
private static void doOtherThing() throws InterruptedException {
|
||||
PROFILER.push("thing2");
|
||||
Thread.sleep(2);
|
||||
doThirdOtherThing();
|
||||
thing4();
|
||||
PROFILER.pop("thing2");
|
||||
}
|
||||
|
||||
private static void doThirdOtherThing() throws InterruptedException {
|
||||
PROFILER.push("thing3");
|
||||
Thread.sleep(2);
|
||||
PROFILER.pop("thing3");
|
||||
}
|
||||
|
||||
private static void thing4() throws InterruptedException {
|
||||
PROFILER.push("thing4");
|
||||
Thread.sleep(2);
|
||||
PROFILER.pop("thing4");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProfiler() throws InterruptedException {
|
||||
//PROFILER.start();
|
||||
for(int i = 0; i < 100; i++) {
|
||||
doThing();
|
||||
}
|
||||
|
||||
for(int i = 0; i < 100; i++) {
|
||||
doThirdOtherThing();
|
||||
}
|
||||
|
||||
for(int i = 0; i < 100; i++) {
|
||||
doOtherThing();
|
||||
}
|
||||
PROFILER.stop();
|
||||
PROFILER.push("thing");
|
||||
PROFILER.push("thing2");
|
||||
PROFILER.start();
|
||||
PROFILER.pop("thing2");
|
||||
PROFILER.pop("thing");
|
||||
PROFILER.push("thing4");
|
||||
PROFILER.pop("thing4");
|
||||
|
||||
PROFILER.getTimings().forEach((id, timings) -> System.out.println(id + ": " + timings.toString()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package registry;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import com.dfsek.terra.api.registry.CheckedRegistry;
|
||||
import com.dfsek.terra.api.registry.OpenRegistry;
|
||||
import com.dfsek.terra.api.registry.exception.DuplicateEntryException;
|
||||
import com.dfsek.terra.registry.CheckedRegistryImpl;
|
||||
import com.dfsek.terra.registry.OpenRegistryImpl;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
|
||||
public class RegistryTest {
|
||||
@Test
|
||||
public void openRegistry() {
|
||||
OpenRegistry<String> test = new OpenRegistryImpl<>();
|
||||
|
||||
test.register("test", "bazinga");
|
||||
|
||||
assertEquals(test.get("test"), "bazinga");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void openRegistryChecked() {
|
||||
OpenRegistry<String> test = new OpenRegistryImpl<>();
|
||||
|
||||
test.registerChecked("test", "bazinga");
|
||||
|
||||
try {
|
||||
test.registerChecked("test", "bazinga2");
|
||||
fail("Shouldn't be able to re-register with #registerChecked!");
|
||||
} catch(DuplicateEntryException ignore) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkedRegistry() {
|
||||
CheckedRegistry<String> test = new CheckedRegistryImpl<>(new OpenRegistryImpl<>());
|
||||
|
||||
test.register("test", "bazinga");
|
||||
|
||||
assertEquals(test.get("test"), "bazinga");
|
||||
|
||||
try {
|
||||
test.register("test", "bazinga2");
|
||||
fail("Shouldn't be able to re-register in CheckedRegistry!");
|
||||
} catch(DuplicateEntryException ignore) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
10
common/implementation/base/src/test/resources/config.yml
Normal file
10
common/implementation/base/src/test/resources/config.yml
Normal file
@@ -0,0 +1,10 @@
|
||||
dimensions: 2
|
||||
type: Cellular
|
||||
frequency: 0.01
|
||||
cellular:
|
||||
return: Distance3Div
|
||||
normalize:
|
||||
type: LINEAR
|
||||
linear:
|
||||
min: -1
|
||||
max: 0
|
||||
BIN
common/implementation/base/src/test/resources/map.jpg
Normal file
BIN
common/implementation/base/src/test/resources/map.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 86 KiB |
18
common/implementation/base/src/test/resources/meta.yml
Normal file
18
common/implementation/base/src/test/resources/meta.yml
Normal file
@@ -0,0 +1,18 @@
|
||||
list:
|
||||
- ONE
|
||||
- "<< metaTarget.yml:list"
|
||||
- FOUR
|
||||
- FIVE
|
||||
- SIX
|
||||
- "<< metaTarget.yml:list2"
|
||||
- NINE
|
||||
- TEN
|
||||
map:
|
||||
"<<":
|
||||
- metaTarget.yml:map1
|
||||
- metaTarget.yml:map2
|
||||
one: ONE
|
||||
two: TWO
|
||||
string: "one-${metaTarget.yml:string.two}-${metaTarget.yml:string.three}-four-five-${metaTarget.yml:string.six}"
|
||||
int: 2 + 4
|
||||
double: ${metaTarget.yml:double} + 5.6
|
||||
17
common/implementation/base/src/test/resources/metaTarget.yml
Normal file
17
common/implementation/base/src/test/resources/metaTarget.yml
Normal file
@@ -0,0 +1,17 @@
|
||||
list:
|
||||
- TWO
|
||||
- THREE
|
||||
list2:
|
||||
- SEVEN
|
||||
- EIGHT
|
||||
map1:
|
||||
three: THREE
|
||||
four: FOUR
|
||||
five: FIVE
|
||||
map2:
|
||||
six: SIX
|
||||
string:
|
||||
two: two
|
||||
three: three
|
||||
six: six
|
||||
double: 1
|
||||
Reference in New Issue
Block a user