Compare commits

..
Author SHA1 Message Date
nicksitnikov 2e3aefd9fd Delete duplicate copy of class 2026-08-01 03:25:02 -05:00
nicksitnikov c4b091888b Un-generic-ify IStructureNavigate 2026-08-01 03:25:02 -05:00
nicksitnikov 68fbdf8a81 Mark internal functions as internal 2026-08-01 03:25:01 -05:00
nicksitnikov f3bf5fc1ea Apply spotless 2026-08-01 03:24:56 -05:00
nicksitnikov 9f9ab7acd9 Fix minor error 2026-08-01 03:23:47 -05:00
nicksitnikov 0fe5a74863 Apply variance to StructureUtility. Bleargh, give me JEP 300 any day. 2026-08-01 03:23:39 -05:00
nicksitnikov d650c173bf Make IStructureElement contravariant. 2026-08-01 03:21:27 -05:00
Martin Robertz 137f651486 update deps 2026-07-03 19:22:22 +02:00
attempt0andgithub-actions[bot] ff88cbf2d7 Read channel in getBlocksToPlace (#68)
## Summary
This causes inconsistency in the API and should be addressed. The
primary consumer of the API is NEI preview and the preview does show
wrong block with glass tier set, not sure if this is the cause
<img width="1088" height="491" alt="image"
src="https://github.com/user-attachments/assets/fff146d8-6d8e-44d9-842e-1677691271d2"
/>

## Checklist
- [ ] I have tested this PR in DevEnv
- [ ] I have tested this PR in Fullpack
- [x] This PR is in compliance with the [GTNH AI
Policy](https://github.com/GTNewHorizons/GTNH-Dev-Doc/blob/master/AI_POLICY.md)
- [ ] This PR requires another PR in order to merge

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-03 23:33:08 +08:00
DylanTaylor1 4922760b46 Change subchannel color to match tooltips (#67)
Changes subchannel color from orange to aqua to match tooltips from the
Construction Tooltips Overhaul
(https://github.com/GTNewHorizons/GT5-Unofficial/pull/7299)
2026-07-02 21:12:20 -04:00
Eldrinn-Elantey 45bd25401f Add confirmation step to Clear button in channel GUI (#66) 2026-06-21 16:57:58 +02:00
15 changed files with 532 additions and 367 deletions

No files matched your search

+2 -2
View File
@@ -1,8 +1,8 @@
// Add your dependencies here
dependencies {
api("com.github.GTNewHorizons:GTNHLib:0.11.18:dev")
implementation("com.github.GTNewHorizons:NotEnoughItems:2.8.104-GTNH:dev")
api("com.github.GTNewHorizons:GTNHLib:0.11.21:dev")
implementation("com.github.GTNewHorizons:NotEnoughItems:2.8.110-GTNH:dev")
testImplementation(platform('org.junit:junit-bom:5.9.2'))
testImplementation('org.junit.jupiter:junit-jupiter')
@@ -64,6 +64,9 @@ public class GuiScreenConfigureChannels extends GuiContainer implements IGuiScre
private GuiTextField key, value;
protected int guiTop, guiLeft;
private List<String> info;
private boolean wipePending = false;
private long wipePendingTime = 0;
private static final long WIPE_CONFIRM_TIMEOUT_MS = 3000;
public GuiScreenConfigureChannels(Container container, ItemStack trigger) {
super(container);
@@ -346,9 +349,17 @@ public class GuiScreenConfigureChannels extends GuiContainer implements IGuiScre
ChannelDataAccessor.unsetChannelData(trigger, key.getText());
break;
case WIPE_BTN:
ChannelDataAccessor.wipeChannelData(trigger);
key.setText("");
this.value.setText("");
if (!wipePending) {
wipePending = true;
wipePendingTime = System.currentTimeMillis();
btn.displayString = I18n.format(I18N_PREFIX + "wipe.confirm");
} else {
wipePending = false;
btn.displayString = I18n.format(I18N_PREFIX + "wipe");
ChannelDataAccessor.wipeChannelData(trigger);
key.setText("");
this.value.setText("");
}
break;
}
@@ -369,6 +380,10 @@ public class GuiScreenConfigureChannels extends GuiContainer implements IGuiScre
super.updateScreen();
key.updateCursorCounter();
value.updateCursorCounter();
if (wipePending && System.currentTimeMillis() - wipePendingTime > WIPE_CONFIRM_TIMEOUT_MS) {
wipePending = false;
getButtonList().get(WIPE_BTN).displayString = I18n.format(I18N_PREFIX + "wipe");
}
}
@Override
@@ -67,7 +67,7 @@ public interface IStructureDefinition<T> {
* @throws java.util.NoSuchElementException if the given structure piece is not found and the moon phase perfectly
* matches
*/
IStructureElement<T>[] getStructureFor(String name);
IStructureElement<? super T>[] getStructureFor(String name);
boolean isContainedInStructure(String name, int offsetA, int offsetB, int offsetC);
@@ -356,7 +356,7 @@ public interface IStructureDefinition<T> {
* @return true if iteration completed successfully.
* @param <T> type of context object.
*/
static <T> boolean iterate(T object, ItemStack trigger, IStructureElement<T>[] elements, World world,
static <T> boolean iterate(T object, ItemStack trigger, IStructureElement<? super T>[] elements, World world,
ExtendedFacing extendedFacing, int basePositionX, int basePositionY, int basePositionZ, int basePositionA,
int basePositionB, int basePositionC, boolean hintsOnly, Boolean checkBlocksIfNotNullForceCheckAllIfTrue) {
if (!world.isRemote && hintsOnly) {
@@ -28,6 +28,9 @@ import com.gtnewhorizon.structurelib.util.ItemStackPredicate.NBTMode;
/**
* Use StructureUtility to instantiate. These are the building blocks for your {@link IStructureDefinition}. It
* represents what a particular element can be and how this particular element should be autoplaced.
*
* @param <T> Type of the context object. {@link IStructureElement} is contravariant over T, so parameters and fields of
* type {@link IStructureElement} should be declared as {@code IStructureElement<? super T>}
*/
public interface IStructureElement<T> {
@@ -213,7 +216,7 @@ public interface IStructureElement<T> {
* Forget the messed up class dependency graph for now. this is just so convenient.
*/
default IStructureElementNoPlacement<T> noPlacement() {
return new IStructureElementNoPlacement<T>() {
return new IStructureElementNoPlacement<>() {
@Override
public boolean check(T t, World world, int x, int y, int z) {
@@ -21,11 +21,11 @@ import com.google.common.collect.Iterables;
*/
public interface IStructureElementChain<T> extends IStructureElement<T> {
IStructureElement<T>[] fallbacks();
IStructureElement<? super T>[] fallbacks();
@Override
default boolean check(T t, World world, int x, int y, int z) {
for (IStructureElement<T> fallback : fallbacks()) {
for (IStructureElement<? super T> fallback : fallbacks()) {
if (fallback.check(t, world, x, y, z)) {
return true;
}
@@ -35,7 +35,7 @@ public interface IStructureElementChain<T> extends IStructureElement<T> {
@Override
default boolean couldBeValid(T t, World world, int x, int y, int z, ItemStack trigger) {
for (IStructureElement<T> fallback : fallbacks()) {
for (IStructureElement<? super T> fallback : fallbacks()) {
if (fallback.couldBeValid(t, world, x, y, z, trigger)) {
return true;
}
@@ -45,7 +45,7 @@ public interface IStructureElementChain<T> extends IStructureElement<T> {
@Override
default boolean spawnHint(T t, World world, int x, int y, int z, ItemStack trigger) {
for (IStructureElement<T> fallback : fallbacks()) {
for (IStructureElement<? super T> fallback : fallbacks()) {
if (fallback.spawnHint(t, world, x, y, z, trigger)) {
return true;
}
@@ -55,7 +55,7 @@ public interface IStructureElementChain<T> extends IStructureElement<T> {
@Override
default boolean placeBlock(T t, World world, int x, int y, int z, ItemStack trigger) {
for (IStructureElement<T> fallback : fallbacks()) {
for (IStructureElement<? super T> fallback : fallbacks()) {
if (fallback.placeBlock(t, world, x, y, z, trigger)) {
return true;
}
@@ -67,7 +67,7 @@ public interface IStructureElementChain<T> extends IStructureElement<T> {
@Override
default List<String> getDescription(T context) {
Set<String> descriptions = new LinkedHashSet<>();
for (IStructureElement<T> fallback : fallbacks()) {
for (IStructureElement<? super T> fallback : fallbacks()) {
List<String> desc = fallback.getDescription(context);
if (desc != null) {
descriptions.addAll(desc);
@@ -82,7 +82,7 @@ public interface IStructureElementChain<T> extends IStructureElement<T> {
AutoPlaceEnvironment env) {
Predicate<ItemStack> predicate = null;
List<Iterable<ItemStack>> is = new ArrayList<>();
for (IStructureElement<T> fallback : fallbacks()) {
for (IStructureElement<? super T> fallback : fallbacks()) {
BlocksToPlace e = fallback.getBlocksToPlace(t, world, x, y, z, trigger, env);
if (e == null) continue;
if (predicate == null) predicate = e.getPredicate();
@@ -99,7 +99,7 @@ public interface IStructureElementChain<T> extends IStructureElement<T> {
EntityPlayerMP actor, Consumer<IChatComponent> chatter) {
boolean allContinue = true;
List<IChatComponent> bufferedNoise = new ArrayList<>();
for (IStructureElement<T> fallback : fallbacks()) {
for (IStructureElement<? super T> fallback : fallbacks()) {
PlaceResult result = fallback.survivalPlaceBlock(t, world, x, y, z, trigger, s, actor, bufferedNoise::add);
switch (result) {
case REJECT_CONTINUE:
@@ -124,7 +124,7 @@ public interface IStructureElementChain<T> extends IStructureElement<T> {
AutoPlaceEnvironment env) {
boolean allContinue = true;
List<IChatComponent> bufferedNoise = new ArrayList<>();
for (IStructureElement<T> fallback : fallbacks()) {
for (IStructureElement<? super T> fallback : fallbacks()) {
PlaceResult result = fallback
.survivalPlaceBlock(t, world, x, y, z, trigger, env.withChatter(bufferedNoise::add));
switch (result) {
@@ -10,36 +10,36 @@ import net.minecraft.world.World;
/**
* Use StructureUtility to instantiate
*/
interface IStructureNavigate<T> extends IStructureElement<T> {
interface IStructureNavigate extends IStructureElement<Object> {
@Override
default boolean check(T t, World world, int x, int y, int z) {
default boolean check(Object t, World world, int x, int y, int z) {
return true;
}
@Override
default boolean couldBeValid(T t, World world, int x, int y, int z, ItemStack trigger) {
default boolean couldBeValid(Object t, World world, int x, int y, int z, ItemStack trigger) {
return true;
}
@Override
default boolean spawnHint(T t, World world, int x, int y, int z, ItemStack trigger) {
default boolean spawnHint(Object t, World world, int x, int y, int z, ItemStack trigger) {
return true;
}
@Override
default boolean placeBlock(T t, World world, int x, int y, int z, ItemStack trigger) {
default boolean placeBlock(Object t, World world, int x, int y, int z, ItemStack trigger) {
return true;
}
@Override
default PlaceResult survivalPlaceBlock(T t, World world, int x, int y, int z, ItemStack trigger, IItemSource s,
default PlaceResult survivalPlaceBlock(Object t, World world, int x, int y, int z, ItemStack trigger, IItemSource s,
EntityPlayerMP actor, Consumer<IChatComponent> chatter) {
return PlaceResult.SKIP;
}
@Override
default PlaceResult survivalPlaceBlock(T t, World world, int x, int y, int z, ItemStack trigger,
default PlaceResult survivalPlaceBlock(Object t, World world, int x, int y, int z, ItemStack trigger,
AutoPlaceEnvironment env) {
return PlaceResult.SKIP;
}
@@ -21,40 +21,42 @@ public interface IStructureWalker<T> {
* @param c The relative C position of the element in structure-local coordinates (pre transform)
* @return False to stop iterating, true to continue.
*/
boolean visit(IStructureElement<T> element, World world, int x, int y, int z, int a, int b, int c);
boolean visit(IStructureElement<? super T> element, World world, int x, int y, int z, int a, int b, int c);
default boolean blockNotLoaded(IStructureElement<T> element, World world, int x, int y, int z, int a, int b,
default boolean blockNotLoaded(IStructureElement<? super T> element, World world, int x, int y, int z, int a, int b,
int c) {
return false;
}
static <T> IStructureWalker<T> ignoreBlockUnloaded(IStructureWalker<T> walker) {
return new IStructureWalker<T>() {
return new IStructureWalker<>() {
@Override
public boolean visit(IStructureElement<T> element, World world, int x, int y, int z, int a, int b, int c) {
public boolean visit(IStructureElement<? super T> element, World world, int x, int y, int z, int a, int b,
int c) {
return walker.visit(element, world, x, y, z, a, b, c);
}
@Override
public boolean blockNotLoaded(IStructureElement<T> element, World world, int x, int y, int z, int a, int b,
int c) {
public boolean blockNotLoaded(IStructureElement<? super T> element, World world, int x, int y, int z, int a,
int b, int c) {
return walker.visit(element, world, x, y, z, a, b, c);
}
};
}
static <T> IStructureWalker<T> skipBlockUnloaded(IStructureWalker<T> walker) {
return new IStructureWalker<T>() {
return new IStructureWalker<>() {
@Override
public boolean visit(IStructureElement<T> element, World world, int x, int y, int z, int a, int b, int c) {
public boolean visit(IStructureElement<? super T> element, World world, int x, int y, int z, int a, int b,
int c) {
return walker.visit(element, world, x, y, z, a, b, c);
}
@Override
public boolean blockNotLoaded(IStructureElement<T> element, World world, int x, int y, int z, int a, int b,
int c) {
public boolean blockNotLoaded(IStructureElement<? super T> element, World world, int x, int y, int z, int a,
int b, int c) {
return true;
}
};
@@ -13,14 +13,14 @@ import net.minecraft.world.World;
class LazyStructureElement<T> implements IStructureElementDeferred<T> {
private Function<T, IStructureElement<T>> to;
private IStructureElement<T> elem;
private Function<? super T, ? extends IStructureElement<? super T>> to;
private IStructureElement<? super T> elem;
public LazyStructureElement(Function<T, IStructureElement<T>> to) {
public LazyStructureElement(Function<? super T, ? extends IStructureElement<? super T>> to) {
this.to = to;
}
private IStructureElement<T> get(T t) {
private IStructureElement<? super T> get(T t) {
if (to != null) {
elem = to.apply(t);
to = null;
@@ -16,17 +16,17 @@ import com.gtnewhorizon.structurelib.util.Vec3Impl;
public class StructureDefinition<T> implements IStructureDefinition<T> {
private final Map<Character, IStructureElement<T>> elements;
private final Map<Character, IStructureElement<? super T>> elements;
private final Map<String, String> shapes;
private final Map<String, IStructureElement<T>[]> structures;
private final Map<String, IStructureElement<? super T>[]> structures;
private final Map<String, Set<Vec3Impl>> occupiedSpaces;
public static <B> Builder<B> builder() {
return new Builder<>();
}
private StructureDefinition(Map<Character, IStructureElement<T>> elements, Map<String, String> shapes,
Map<String, IStructureElement<T>[]> structures, Map<String, Set<Vec3Impl>> occupiedSpaces) {
private StructureDefinition(Map<Character, IStructureElement<? super T>> elements, Map<String, String> shapes,
Map<String, IStructureElement<? super T>[]> structures, Map<String, Set<Vec3Impl>> occupiedSpaces) {
this.elements = elements;
this.shapes = shapes;
this.structures = structures;
@@ -40,7 +40,7 @@ public class StructureDefinition<T> implements IStructureDefinition<T> {
private static final char C = '\uC000';
private char d = '\uD000';
private final Map<Vec3Impl, Character> navigates;
private final Map<Character, IStructureElement<T>> elements;
private final Map<Character, IStructureElement<? super T>> elements;
private final Map<String, String> shapes;
private final Map<String, Set<Vec3Impl>> occupiedSpaces;
@@ -51,7 +51,7 @@ public class StructureDefinition<T> implements IStructureDefinition<T> {
occupiedSpaces = new HashMap<>();
}
public Map<Character, IStructureElement<T>> getElements() {
public Map<Character, IStructureElement<? super T>> getElements() {
return elements;
}
@@ -181,18 +181,18 @@ public class StructureDefinition<T> implements IStructureDefinition<T> {
* @deprecated use the unboxed version
*/
@Deprecated
public Builder<T> addElement(Character name, IStructureElement<T> structurePiece) {
public Builder<T> addElement(Character name, IStructureElement<? super T> structurePiece) {
elements.putIfAbsent(name, structurePiece);
return this;
}
public Builder<T> addElement(char name, IStructureElement<T> structurePiece) {
public Builder<T> addElement(char name, IStructureElement<? super T> structurePiece) {
elements.putIfAbsent(name, structurePiece);
return this;
}
public IStructureDefinition<T> build() {
Map<String, IStructureElement<T>[]> structures = compileStructureMap();
Map<String, IStructureElement<? super T>[]> structures = compileStructureMap();
return new StructureDefinition<>(
new HashMap<>(elements),
new HashMap<>(shapes),
@@ -201,7 +201,7 @@ public class StructureDefinition<T> implements IStructureDefinition<T> {
}
@SuppressWarnings("unchecked")
private Map<String, IStructureElement<T>[]> compileElementSetMap() {
private Map<String, IStructureElement<? super T>[]> compileElementSetMap() {
Set<Integer> missing = findMissing();
if (missing.isEmpty()) {
return shapes.entrySet().stream().collect(
@@ -217,7 +217,7 @@ public class StructureDefinition<T> implements IStructureDefinition<T> {
}
@SuppressWarnings("unchecked")
private Map<String, IStructureElement<T>[]> compileStructureMap() {
private Map<String, IStructureElement<? super T>[]> compileStructureMap() {
Set<Integer> missing = findMissing();
if (missing.isEmpty()) {
return shapes.entrySet().stream().collect(
@@ -238,7 +238,7 @@ public class StructureDefinition<T> implements IStructureDefinition<T> {
}
}
public Map<Character, IStructureElement<T>> getElements() {
public Map<Character, IStructureElement<? super T>> getElements() {
return elements;
}
@@ -246,13 +246,13 @@ public class StructureDefinition<T> implements IStructureDefinition<T> {
return shapes;
}
public Map<String, IStructureElement<T>[]> getStructures() {
public Map<String, IStructureElement<? super T>[]> getStructures() {
return structures;
}
@Override
public IStructureElement<T>[] getStructureFor(String name) {
IStructureElement<T>[] elements = structures.get(name);
public IStructureElement<? super T>[] getStructureFor(String name) {
IStructureElement<? super T>[] elements = structures.get(name);
if (elements == null) throw new NoSuchElementException(name);
return elements;
}
File diff suppressed because it is too large. Load diff
@@ -37,7 +37,7 @@ class SurvivalBuildStructureWalker<T> implements IStructureWalker<T> {
}
@Override
public boolean visit(IStructureElement<T> element, World world, int x, int y, int z, int a, int b, int c) {
public boolean visit(IStructureElement<? super T> element, World world, int x, int y, int z, int a, int b, int c) {
env.offsetABC[0] = a;
env.offsetABC[1] = b;
env.offsetABC[2] = c;
@@ -1,64 +0,0 @@
package com.gtnewhorizon.structurelib.util;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.NavigableMap;
import java.util.Spliterator;
import java.util.TreeMap;
import java.util.function.Consumer;
public class SortedRegistry<V> implements Iterable<V> {
private final NavigableMap<String, V> store = new TreeMap<>();
/**
* Store stuff in an array for faster iteration access than a red black tree
*/
private List<V> baked = Collections.emptyList();
public void register(String key, V val) {
if (key == null || val == null) throw new NullPointerException();
V old = store.putIfAbsent(key, val);
if (old != null) {
throw new IllegalArgumentException("Duplicate key: " + key);
}
// TODO allow a user to edit the order with a configuration file
baked = new ArrayList<>(store.values());
}
public int size() {
return store.size();
}
public boolean isEmpty() {
return store.isEmpty();
}
public boolean containsKey(String key) {
return store.containsKey(key);
}
public boolean containsValue(V value) {
return store.containsValue(value);
}
public V get(String key) {
return store.get(key);
}
@Override
public Iterator<V> iterator() {
return baked.iterator();
}
@Override
public void forEach(Consumer<? super V> action) {
baked.forEach(action);
}
@Override
public Spliterator<V> spliterator() {
return baked.spliterator();
}
}
@@ -37,12 +37,13 @@ item.structurelib.constructableTrigger.gui.add=Add
item.structurelib.constructableTrigger.gui.set=Update
item.structurelib.constructableTrigger.gui.unset=Remove
item.structurelib.constructableTrigger.gui.wipe=§4Clear
item.structurelib.constructableTrigger.gui.wipe.confirm=§4Sure?
item.structurelib.constructableTrigger.gui.channels.from=§rMod: §9§o%s
item.structurelib.constructableTrigger.gui.info=Many multiblocks support some degree of variation in their structure and a sub channel allows indication of which variant to use.\n All sub channels have a sequence of lowercase characters as key and a positive integer as value. Most known sub channels should be available as typeahead completions.\n You can also drag and drop items from NEI to set the corresponding sub channel value. These items all have a tooltip of "§oIndicates§r §ovalue§r §oX§r §ofor§r §osub§r §ochannel§r §oY§r".
channels.structurelib.show_errors=When set, will highlight parts of the multiblock that is definitely wrong
structurelib.tooltip.channelvalue=§7Indicates value §6%d§r§7 for sub channel §6%s
structurelib.tooltip.channelvalue=§7Value §b%d§r§7 for subchannel §b%s
structurelib.tooltip.indicator_dnd=Drop into GUI to select this value for this channel
structurelib.autoplace.built_stat=Built %s blocks
@@ -0,0 +1,200 @@
tile.structurelib.blockhint.name=Подсказка
tile.structurelib.blockhint.0.name=Подсказка 1 точка
tile.structurelib.blockhint.1.name=Подсказка 2 точки
tile.structurelib.blockhint.2.name=Подсказка 3 точки
tile.structurelib.blockhint.3.name=Подсказка 4 точки
tile.structurelib.blockhint.4.name=Подсказка 5 точек
tile.structurelib.blockhint.5.name=Подсказка 6 точек
tile.structurelib.blockhint.6.name=Подсказка 7 точек
tile.structurelib.blockhint.7.name=Подсказка 8 точек
tile.structurelib.blockhint.8.name=Подсказка 9 точек
tile.structurelib.blockhint.9.name=Подсказка 10 точек
tile.structurelib.blockhint.10.name=Подсказка 11 точек
tile.structurelib.blockhint.11.name=Подсказка 12 точек
tile.structurelib.blockhint.12.name=Общая подсказка
tile.structurelib.blockhint.13.name=Подсказка воздух
tile.structurelib.blockhint.14.name=Подсказка нет воздуха
tile.structurelib.blockhint.15.name=Подсказка ошибка
item.structurelib.frontRotationTool.name=Инструмент для поворота (Автономный)
item.structurelib.frontRotationTool.desc.0=Открывает интерфейс поворота лицевой стороны
item.structurelib.frontRotationTool.desc.1=Поворачивает только лицевую сторону,
item.structurelib.frontRotationTool.desc.2=что позволяет повернуть всю структуру.
item.structurelib.constructableTrigger.name=Голограммный проектор мультиблоковой структуры
item.structurelib.constructableTrigger.desc.0=Используется по интерфейсу контроллера
item.structurelib.constructableTrigger.desc.1=Показывает схему постройки мультиблочной структуры,
item.structurelib.constructableTrigger.desc.2=используется при нажатии по контроллеру
item.structurelib.constructableTrigger.desc.3=(Shift+ПКМ для автоматической постройки)
item.structurelib.constructableTrigger.desc.4=Количество проекторов в одном слоте влияет на тир/режим/тип постройки, если он не задан в GUI проектора
item.structurelib.constructableTrigger.desc.5=Удерживайте §l[LSHIFT]§r для отображения данных канала
item.structurelib.constructableTrigger.desc.lshift.0=Содержит %d подканал
item.structurelib.constructableTrigger.too_fast=Подождите %d миллисекунд перед очередным автозаполнением...
item.structurelib.constructableTrigger.gui.title=Подканалы
item.structurelib.constructableTrigger.gui.key=Ключ:
item.structurelib.constructableTrigger.gui.value=Значение:
item.structurelib.constructableTrigger.gui.add=Добавить
item.structurelib.constructableTrigger.gui.set=Обновить
item.structurelib.constructableTrigger.gui.unset=Удалить
item.structurelib.constructableTrigger.gui.wipe=§4Очистить
item.structurelib.constructableTrigger.gui.wipe.confirm=§4Уверен?
item.structurelib.constructableTrigger.gui.channels.from=§rМод: §9§o%s
item.structurelib.constructableTrigger.gui.info=Многие мультиблоки поддерживают различные вариации структуры. Субканал позволяет указать, какой именно вариант использовать.\nВсе субканалы в качестве ключа используют строку из строчных букв, а в качестве значения - положительное целое число. Для большинства известных субканалов доступно автодополнение при вводе.\nВы также можете перетаскивать предметы из NEI, чтобы задать значение соответствующего субканала. Все эти предметы имеют подсказку: "§oЗадаёт§r §oзначение§r §oX§r §oдля§r §oсубканала§r §oY§r"
channels.structurelib.show_errors=Если включено, подсвечивает элементы мультиблока с явными ошибками
structurelib.tooltip.channelvalue=§7Указывает значение §b%d§r§7 для подканала §b%s
structurelib.tooltip.indicator_dnd=Перейдите в GUI, чтобы выбрать это значение для этого канала.
structurelib.autoplace.built_stat=Построено %s блоков
structurelib.autoplace.complete=§aЭтот мультиблок собран!
structurelib.autoplace.error.not_enabled=§cЭтот мультиблок не поддерживает автозаполнение в выживании!
structurelib.autoplace.error.no_simple_block=§cПредлагалось разместить §r%s§c но ничего не нашлось
structurelib.autoplace.error.no_item_stack=§cПредлагалось разместить блок используя §r%s§c но ничего не нашлось
structurelib.autoplace.warning.no_explicit_channel=§6Эта структура зависит от несуществующего подканала §r%s§6. Вместо этого используйте главный канал.
structurelib.blockhint.desc.0=Помогает при постройке
structurelib.blockhint.0.name=Подсказка 1 точка
structurelib.blockhint.1.name=Подсказка 2 точки
structurelib.blockhint.2.name=Подсказка 3 точки
structurelib.blockhint.3.name=Подсказка 4 точки
structurelib.blockhint.4.name=Подсказка 5 точек
structurelib.blockhint.5.name=Подсказка 6 точек
structurelib.blockhint.6.name=Подсказка 7 точек
structurelib.blockhint.7.name=Подсказка 8 точек
structurelib.blockhint.8.name=Подсказка 9 точек
structurelib.blockhint.9.name=Подсказка 10 точек
structurelib.blockhint.10.name=Подсказка 11 точек
structurelib.blockhint.11.name=Подсказка 12 точек
structurelib.blockhint.desc.1=Заполнитель конкретной группы.
structurelib.blockhint.12.name=Общая подсказка
structurelib.blockhint.desc.2=Общий заполнитель.
structurelib.blockhint.13.name=Подсказка воздух
structurelib.blockhint.desc.3=Убедитесь, что это содержит воздух.
structurelib.blockhint.14.name=Подсказка нет воздуха
structurelib.blockhint.desc.4=Убедитесь, что это не содержит воздух.
structurelib.blockhint.15.name=Подсказка ошибка
structurelib.blockhint.desc.5=ОШИБКА (а что вы ожидали?)
itemGroup.structurelib=StructureLib
structurelib.facing.0=вниз нормальный нет
structurelib.facing.1=вниз нормальный по горизонтали
structurelib.facing.2=вниз нормальный по вертикали
structurelib.facing.3=вниз нормальный оба
structurelib.facing.4=вниз по часовой стрелке нет
structurelib.facing.5=вниз по часовой стрелке по горизонтали
structurelib.facing.6=вниз по часовой стрелке по вертикали
structurelib.facing.7=вниз по часовой стрелке оба
structurelib.facing.8=вниз перевернутый
structurelib.facing.9=вниз перевернутый
structurelib.facing.10=вниз перевернутый
structurelib.facing.11=вниз перевернутый
structurelib.facing.12=вниз против часовой стрелки
structurelib.facing.13=вниз против часовой стрелки
structurelib.facing.14=вниз против часовой стрелки
structurelib.facing.15=вниз против часовой стрелки
structurelib.facing.16=вверх нормальный нет
structurelib.facing.17=вверх нормальный по горизонтали
structurelib.facing.18=вверх нормальный по вертикали
structurelib.facing.19=вверх нормальный оба
structurelib.facing.20=вверх по часовой стрелке нет
structurelib.facing.21=вверх по часовой стрелке по горизонтали
structurelib.facing.22=вверх по часовой стрелке по вертикали
structurelib.facing.23=вверх по часовой стрелке оба
structurelib.facing.24=вверх перевернутый
structurelib.facing.25=вверх перевернутый
structurelib.facing.26=вверх перевернутый
structurelib.facing.27=вверх перевернутый
structurelib.facing.28=вверх против часовой стрелки
structurelib.facing.29=вверх против часовой стрелки
structurelib.facing.30=вверх против часовой стрелки
structurelib.facing.31=вверх против часовой стрелки
structurelib.facing.32=север нормальный нет
structurelib.facing.33=север нормальный по горизонтали
structurelib.facing.34=север нормальный по вертикали
structurelib.facing.35=север нормальный оба
structurelib.facing.36=север по часовой стрелке нет
structurelib.facing.37=север по часовой стрелке по горизонтали
structurelib.facing.38=север по часовой стрелке по вертикали
structurelib.facing.39=север по часовой стрелке оба
structurelib.facing.40=север перевернутый
structurelib.facing.41=север перевернутый
structurelib.facing.42=север перевернутый
structurelib.facing.43=север перевернутый
structurelib.facing.44=север против часовой стрелки
structurelib.facing.45=север против часовой стрелки
structurelib.facing.46=север против часовой стрелки
structurelib.facing.47=север против часовой стрелки
structurelib.facing.48=юг нормальный нет
structurelib.facing.49=юг нормальный по горизонтали
structurelib.facing.50=юг нормальный по вертикали
structurelib.facing.51=юг нормальный оба
structurelib.facing.52=юг по часовой стрелке нет
structurelib.facing.53=юг по часовой стрелке по горизонтали
structurelib.facing.54=юг по часовой стрелке по вертикали
structurelib.facing.55=юг по часовой стрелке оба
structurelib.facing.56=юг перевернутый
structurelib.facing.57=юг перевернутый
structurelib.facing.58=юг перевернутый
structurelib.facing.59=юг перевернутый
structurelib.facing.60=юг против часовой стрелки
structurelib.facing.61=юг против часовой стрелки
structurelib.facing.62=юг против часовой стрелки
structurelib.facing.63=юг против часовой стрелки
structurelib.facing.64=запад нормальный нет
structurelib.facing.65=запад нормальный по горизонтали
structurelib.facing.66=запад нормальный по вертикали
structurelib.facing.67=запад нормальный оба
structurelib.facing.68=запад по часовой стрелке нет
structurelib.facing.69=запад по часовой стрелке по горизонтали
structurelib.facing.70=запад по часовой стрелке по вертикали
structurelib.facing.71=запад по часовой стрелке оба
structurelib.facing.72=запад перевернутый
structurelib.facing.73=запад перевернутый
structurelib.facing.74=запад перевернутый
structurelib.facing.75=запад перевернутый
structurelib.facing.76=запад против часовой стрелки
structurelib.facing.77=запад против часовой стрелки
structurelib.facing.78=запад против часовой стрелки
structurelib.facing.79=запад против часовой стрелки
structurelib.facing.80=восток нормальный нет
structurelib.facing.81=восток нормальный по горизонтали
structurelib.facing.82=восток нормальный по вертикали
structurelib.facing.83=восток нормальный оба
structurelib.facing.84=восток по часовой стрелке нет
structurelib.facing.85=восток по часовой стрелке по горизонтали
structurelib.facing.86=восток по часовой стрелке по вертикали
structurelib.facing.87=восток по часовой стрелке оба
structurelib.facing.88=восток перевернутый
structurelib.facing.89=восток перевернутый
structurelib.facing.90=восток перевернутый
structurelib.facing.91=восток перевернутый
structurelib.facing.92=восток против часовой стрелки
structurelib.facing.93=восток против часовой стрелки
structurelib.facing.94=восток против часовой стрелки
structurelib.facing.95=восток против часовой стрелки
structurelib.config.client=Настройки клиента
structurelib.config.client.tooltip=Настройки, которые изменяют только внешний вид игры, но не то, как она функционирует.
structurelib.config.client.hologram=Голограммные настройки
structurelib.config.client.hologram.tooltip=Настройки, которые по умолчанию меняют способ проецирования голограммы в мир.
structurelib.config.client.hologram.maxCoexisting=Макс. сосуществующих голограмм
structurelib.config.client.hologram.maxCoexisting.tooltip=Количество голограмм, которые могут сосуществовать. Обычно все подсказки, сгенерированные одним щелчком ПКМ, принадлежат одной голограмме. Будет предпринята попытка удаления старой голограммы, когда будет проецироваться новая голограмма и этот лимит будет превышен.
structurelib.config.client.hologram.removeColliding=Удалить сталкивающиеся голограммы
structurelib.config.client.hologram.removeColliding.tooltip=Whether an attempt will be made to remove any existing hologram that collides with a new hologram.
structurelib.config.registries=Sorted Registries
structurelib.config.registries.tooltip=Sorted Registry is how StructureLib internally keep track of certain features. Each individual elements may be reordered, disabled and enabled at user's command. Changes will be synced to server if needed.\nThis gui can also be accessed in game by shift right clicking air with Multiblock Structure Hologram Projector.
structurelib.config.registries.stackextractors=Stack Extractors
structurelib.config.registries.stackextractors.tooltip=Controls which inventory-from-stack functions are enabled during survival autoplace
structurelib.config.registries.inventoryproviders=Источники инвентарей
structurelib.config.registries.inventoryproviders.tooltip=Controls which inventories functions are enabled during survival autoplace
structurelib.configgui.enabled=Включённый элемент
structurelib.configgui.disabled=Отключённый элемент
structurelib.configgui.drag.tooltip=Перетащите эту кнопку, чтобы изменить порядок этого элемента.
structurelib.sortedregistry.inventoryproviders.5000-main-inventory=Основной инвентарь игрока
structurelib.sortedregistry.inventoryproviders.5000-main-inventory.tooltip=36 ячеек для предметов в вашем основном инвентаре. Слоты для брони исключены.
structurelib.sortedregistry.inventoryproviders.7000-ender-inventory=Инвентарь сундука Эндера
structurelib.sortedregistry.inventoryproviders.7000-ender-inventory.tooltip=Соединяет на ваш инвентарь из ванильного сундука Эндера. Требуется не менее один "похожий на рюкзак Эндера" предмет в основном инвентаре для работы.
@@ -42,7 +42,7 @@ item.structurelib.constructableTrigger.gui.info=许多多方块的结构都是
channels.structurelib.show_errors=添加后,在投影时会高亮标出必然错误的部分
structurelib.tooltip.channelvalue=§7表示子信道 §6%2$s§r§7 为 §6%d§r
structurelib.tooltip.channelvalue=§7表示子信道 §b%2$s§r§7 为 §b%d§r
structurelib.tooltip.indicator_dnd=拖入GUI中来选择该值
structurelib.autoplace.built_stat=已放置 %s 个方块