mirror of
https://github.com/GTNewHorizons/StructureLib.git
synced 2026-11-09 15:04:56 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
287e8317c9 | ||
|
|
95d1533342 | ||
|
|
19179ec894 |
No files matched your search
@@ -57,11 +57,13 @@ public interface IStructureElement<T> {
|
||||
* {@code StatCollector.translateToLocal()}. If a key has no matching translation, {@code translateToLocal} returns
|
||||
* the input string unchanged, so pre-translated fallback strings also work.
|
||||
*
|
||||
* @param context the context object (e.g. the multiblock controller), used to determine state-dependent
|
||||
* descriptions
|
||||
* @return a list of accepted block descriptions as lang keys (or display names as fallback), or null if no
|
||||
* description is available
|
||||
*/
|
||||
@Nullable
|
||||
default List<String> getDescription() {
|
||||
default List<String> getDescription(T context) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -94,7 +96,7 @@ public interface IStructureElement<T> {
|
||||
"Default implementation of survivalPlaceBlock hit! Things aren't going to work well! IStructureElement class: {}",
|
||||
getClass().getName());
|
||||
if (!StructureLibAPI.isBlockTriviallyReplaceable(world, x, y, z, actor)) return PlaceResult.REJECT;
|
||||
return PlaceResult.SKIP;
|
||||
return PlaceResult.REJECT_CONTINUE;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -204,7 +206,7 @@ public interface IStructureElement<T> {
|
||||
if (StructureLibAPI.isDebugEnabled()) LOGGER.info(
|
||||
"Fallback shim code of survivalPlaceBlock hit! Things aren't going to work well! IStructureElement class: {}",
|
||||
getClass().getName());
|
||||
return PlaceResult.SKIP;
|
||||
return PlaceResult.REJECT_CONTINUE;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -230,8 +232,8 @@ public interface IStructureElement<T> {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public List<String> getDescription() {
|
||||
return IStructureElement.this.getDescription();
|
||||
public List<String> getDescription(T context) {
|
||||
return IStructureElement.this.getDescription(context);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -266,16 +268,21 @@ public interface IStructureElement<T> {
|
||||
|
||||
enum PlaceResult {
|
||||
/**
|
||||
* This element either exists already, or does not yet have an implementation for survivalPlaceBlock, or some
|
||||
* other unforeseen situations. TODO this definition doesn't seem right. Should we separate SKIP from EXISTS, or
|
||||
* SKIP from ERROR?
|
||||
* The element's check passed, the position is already valid. No placement is needed. In the walker: continue
|
||||
* iteration (no error, not counted as placed). In ofChain: short-circuits, remaining alternatives are skipped.
|
||||
*/
|
||||
SKIP,
|
||||
/**
|
||||
* This element's space is occupied by other stuff and require player attention, or player missing required
|
||||
* resource, or the block cannot be placed due to obscure mechanisms, or some other unforeseen situations.
|
||||
* The element cannot handle this position (occupied, missing resources, etc.). In the walker: stop iteration
|
||||
* with error particles. In ofChain: try next alternative.
|
||||
*/
|
||||
REJECT,
|
||||
/**
|
||||
* This element has no survivalPlaceBlock implementation (default fallback), or otherwise cannot place but is
|
||||
* not an error condition. In the walker: continue iteration silently (like SKIP). In ofChain: try next
|
||||
* alternative (like REJECT), so a better-suited element can handle it.
|
||||
*/
|
||||
REJECT_CONTINUE,
|
||||
/**
|
||||
* Autoplace cannot proceed within this tick. To proceed further would require stopping the placement and wait
|
||||
* for next round.
|
||||
|
||||
@@ -65,10 +65,10 @@ public interface IStructureElementChain<T> extends IStructureElement<T> {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
default List<String> getDescription() {
|
||||
default List<String> getDescription(T context) {
|
||||
Set<String> descriptions = new LinkedHashSet<>();
|
||||
for (IStructureElement<T> fallback : fallbacks()) {
|
||||
List<String> desc = fallback.getDescription();
|
||||
List<String> desc = fallback.getDescription(context);
|
||||
if (desc != null) {
|
||||
descriptions.addAll(desc);
|
||||
}
|
||||
@@ -97,47 +97,51 @@ public interface IStructureElementChain<T> extends IStructureElement<T> {
|
||||
@Override
|
||||
default PlaceResult survivalPlaceBlock(T t, World world, int x, int y, int z, ItemStack trigger, IItemSource s,
|
||||
EntityPlayerMP actor, Consumer<IChatComponent> chatter) {
|
||||
boolean haveSkip = false;
|
||||
boolean allContinue = true;
|
||||
List<IChatComponent> bufferedNoise = new ArrayList<>();
|
||||
for (IStructureElement<T> fallback : fallbacks()) {
|
||||
PlaceResult result = fallback.survivalPlaceBlock(t, world, x, y, z, trigger, s, actor, bufferedNoise::add);
|
||||
switch (result) {
|
||||
case REJECT_CONTINUE:
|
||||
break;
|
||||
case REJECT:
|
||||
allContinue = false;
|
||||
break;
|
||||
case SKIP:
|
||||
haveSkip = true;
|
||||
break;
|
||||
bufferedNoise.forEach(chatter);
|
||||
return PlaceResult.SKIP;
|
||||
default:
|
||||
return result;
|
||||
}
|
||||
}
|
||||
// dump all that noise back into upstream
|
||||
bufferedNoise.forEach(chatter);
|
||||
// TODO need reconsider to ensure this is the right course of action
|
||||
return haveSkip ? PlaceResult.SKIP : PlaceResult.REJECT;
|
||||
return allContinue ? PlaceResult.REJECT_CONTINUE : PlaceResult.REJECT;
|
||||
}
|
||||
|
||||
@Override
|
||||
default PlaceResult survivalPlaceBlock(T t, World world, int x, int y, int z, ItemStack trigger,
|
||||
AutoPlaceEnvironment env) {
|
||||
boolean haveSkip = false;
|
||||
boolean allContinue = true;
|
||||
List<IChatComponent> bufferedNoise = new ArrayList<>();
|
||||
for (IStructureElement<T> fallback : fallbacks()) {
|
||||
PlaceResult result = fallback
|
||||
.survivalPlaceBlock(t, world, x, y, z, trigger, env.withChatter(bufferedNoise::add));
|
||||
switch (result) {
|
||||
case REJECT_CONTINUE:
|
||||
break;
|
||||
case REJECT:
|
||||
allContinue = false;
|
||||
break;
|
||||
case SKIP:
|
||||
haveSkip = true;
|
||||
break;
|
||||
bufferedNoise.forEach(env.getChatter());
|
||||
return PlaceResult.SKIP;
|
||||
default:
|
||||
return result;
|
||||
}
|
||||
}
|
||||
// dump all that noise back into upstream
|
||||
bufferedNoise.forEach(env.getChatter());
|
||||
// TODO need reconsider to ensure this is the right course of action
|
||||
return haveSkip ? PlaceResult.SKIP : PlaceResult.REJECT;
|
||||
return allContinue ? PlaceResult.REJECT_CONTINUE : PlaceResult.REJECT;
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -27,12 +27,12 @@ public interface IStructureElementCheckOnly<T> extends IStructureElement<T> {
|
||||
@Override
|
||||
default PlaceResult survivalPlaceBlock(T t, World world, int x, int y, int z, ItemStack trigger, IItemSource s,
|
||||
EntityPlayerMP actor, Consumer<IChatComponent> chatter) {
|
||||
return PlaceResult.SKIP;
|
||||
return PlaceResult.REJECT_CONTINUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
default PlaceResult survivalPlaceBlock(T t, World world, int x, int y, int z, ItemStack trigger,
|
||||
AutoPlaceEnvironment env) {
|
||||
return PlaceResult.SKIP;
|
||||
return PlaceResult.REJECT_CONTINUE;
|
||||
}
|
||||
}
|
||||
@@ -69,7 +69,7 @@ class LazyStructureElement<T> implements IStructureElementDeferred<T> {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public List<String> getDescription() {
|
||||
return elem != null ? elem.getDescription() : null;
|
||||
public List<String> getDescription(T context) {
|
||||
return elem != null ? elem.getDescription(context) : null;
|
||||
}
|
||||
}
|
||||
@@ -707,12 +707,22 @@ public class StructureUtility {
|
||||
public static <T, TIER> IStructureElement<T> ofBlocksTiered(ITierConverter<TIER> tierExtractor,
|
||||
@Nullable List<Pair<Block, Integer>> allKnownTiers, @Nullable TIER notSet, BiConsumer<T, TIER> setter,
|
||||
Function<T, TIER> getter) {
|
||||
return ofBlocksTiered(tierExtractor, allKnownTiers, notSet, setter, getter, null);
|
||||
List<String> descriptions = null;
|
||||
if (allKnownTiers != null) {
|
||||
descriptions = new java.util.ArrayList<>();
|
||||
for (Pair<Block, Integer> tier : allKnownTiers) {
|
||||
Item item = Item.getItemFromBlock(tier.getLeft());
|
||||
if (item != null) {
|
||||
descriptions.add(new ItemStack(item, 1, tier.getRight()).getUnlocalizedName() + ".name");
|
||||
}
|
||||
}
|
||||
}
|
||||
return ofBlocksTiered(tierExtractor, allKnownTiers, notSet, setter, getter, descriptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Like {@link #ofBlocksTiered(ITierConverter, List, Object, BiConsumer, Function)}, but with an explicit
|
||||
* description that will be returned by {@link IStructureElement#getDescription()}.
|
||||
* description that will be returned by {@link IStructureElement#getDescription(Object)}.
|
||||
*
|
||||
* @param description the description lang keys to attach to this element, or null for no description
|
||||
* @see #ofBlocksTiered(ITierConverter, List, Object, BiConsumer, Function)
|
||||
@@ -781,7 +791,7 @@ public class StructureUtility {
|
||||
public PlaceResult survivalPlaceBlock(T t, World world, int x, int y, int z, ItemStack trigger,
|
||||
AutoPlaceEnvironment env) {
|
||||
Pair<Block, Integer> hint = getHint(trigger);
|
||||
if (hint == null) return PlaceResult.REJECT; // TODO or SKIP?
|
||||
if (hint == null) return PlaceResult.REJECT;
|
||||
Block block = world.getBlock(x, y, z);
|
||||
int meta = world.getBlockMetadata(x, y, z);
|
||||
TIER tier = tierExtractor.convert(block, meta);
|
||||
@@ -801,7 +811,18 @@ public class StructureUtility {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public List<String> getDescription() {
|
||||
public List<String> getDescription(T context) {
|
||||
TIER currentTier = getter.apply(context);
|
||||
if (Objects.equals(currentTier, notSet)) return description;
|
||||
|
||||
for (Pair<Block, Integer> pair : hints) {
|
||||
TIER pairTier = tierExtractor.convert(pair.getKey(), pair.getValue());
|
||||
if (!Objects.equals(pairTier, currentTier)) continue;
|
||||
Item item = Item.getItemFromBlock(pair.getKey());
|
||||
if (item == null) continue;
|
||||
return Collections
|
||||
.singletonList(new ItemStack(item, 1, pair.getValue()).getUnlocalizedName() + ".name");
|
||||
}
|
||||
return description;
|
||||
}
|
||||
|
||||
@@ -1431,7 +1452,7 @@ public class StructureUtility {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public List<String> getDescription() {
|
||||
public List<String> getDescription(T context) {
|
||||
Item item = Item.getItemFromBlock(block);
|
||||
if (item == null) return null;
|
||||
return Collections.singletonList(new ItemStack(item, 1, meta).getUnlocalizedName() + ".name");
|
||||
@@ -1518,7 +1539,7 @@ public class StructureUtility {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public List<String> getDescription() {
|
||||
public List<String> getDescription(T context) {
|
||||
Item item = Item.getItemFromBlock(block);
|
||||
if (item == null) return null;
|
||||
return Collections.singletonList(new ItemStack(item, 1, meta).getUnlocalizedName() + ".name");
|
||||
@@ -1568,7 +1589,7 @@ public class StructureUtility {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public List<String> getDescription() {
|
||||
public List<String> getDescription(T context) {
|
||||
Item item = Item.getItemFromBlock(block);
|
||||
if (item == null) return null;
|
||||
return Collections.singletonList(new ItemStack(item, 1, 0).getUnlocalizedName() + ".name");
|
||||
@@ -1608,7 +1629,7 @@ public class StructureUtility {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public List<String> getDescription() {
|
||||
public List<String> getDescription(T context) {
|
||||
Item item = Item.getItemFromBlock(block);
|
||||
if (item == null) return null;
|
||||
return Collections.singletonList(new ItemStack(item, 1, 0).getUnlocalizedName() + ".name");
|
||||
@@ -1879,8 +1900,8 @@ public class StructureUtility {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public List<String> getDescription() {
|
||||
return element.getDescription();
|
||||
public List<String> getDescription(T context) {
|
||||
return element.getDescription(context);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -1938,7 +1959,7 @@ public class StructureUtility {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public List<String> getDescription() {
|
||||
public List<String> getDescription(T context) {
|
||||
return description;
|
||||
}
|
||||
};
|
||||
@@ -2000,8 +2021,8 @@ public class StructureUtility {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public List<String> getDescription() {
|
||||
return element.getDescription();
|
||||
public List<String> getDescription(T context) {
|
||||
return element.getDescription(context);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -2011,11 +2032,11 @@ public class StructureUtility {
|
||||
/**
|
||||
* Enable this structure element only if given predicate returns true.
|
||||
* <p>
|
||||
* Return SKIP when survival auto place if given predicate returns false.
|
||||
* Return REJECT_CONTINUE when survival auto place if given predicate returns false.
|
||||
*/
|
||||
public static <T> IStructureElement<T> onlyIf(Predicate<? super T> predicate,
|
||||
IStructureElement<? super T> downstream) {
|
||||
return onlyIf(predicate, downstream, PlaceResult.SKIP);
|
||||
return onlyIf(predicate, downstream, PlaceResult.REJECT_CONTINUE);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2075,8 +2096,8 @@ public class StructureUtility {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public List<String> getDescription() {
|
||||
return downstream.getDescription();
|
||||
public List<String> getDescription(T context) {
|
||||
return downstream.getDescription(context);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -2090,10 +2111,10 @@ public class StructureUtility {
|
||||
* using {@link #isAir()}. It will not attempt to capture any errors though, so next one will not be tried if
|
||||
* previous one would crash.
|
||||
* <p>
|
||||
* (*): For survival auto place, it will * REJECT, if all structure element REJECT * SKIP, if 1 or more structure
|
||||
* element SKIP and the rest structure element (0 or more) REJECT * any other result, **immediately** upon any
|
||||
* structure element returns these other results. This behavior is not 100% fixed and might change later on, but we
|
||||
* will send the notice on a best effort basis.
|
||||
* (*): For survival auto place, it will: REJECT, if any structure element returns REJECT (and none returned ACCEPT,
|
||||
* STOP, ACCEPT_STOP, or SKIP); REJECT_CONTINUE, if all structure elements return REJECT_CONTINUE (none returned
|
||||
* REJECT); SKIP, as soon as any structure element returns SKIP; any other result, immediately upon any structure
|
||||
* element returning those.
|
||||
* <p>
|
||||
* Take care while chaining, as it will try to call every structure element until it returns true. If none does it
|
||||
* will finally return false.
|
||||
@@ -2178,8 +2199,8 @@ public class StructureUtility {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public List<String> getDescription() {
|
||||
return elem.getDescription();
|
||||
public List<String> getDescription(T context) {
|
||||
return elem.getDescription(context.getCurrentContext());
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -3021,8 +3042,8 @@ public class StructureUtility {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public List<String> getDescription() {
|
||||
return backing.getDescription();
|
||||
public List<String> getDescription(T context) {
|
||||
return backing.getDescription(context);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
+2
-1
@@ -43,9 +43,10 @@ class SurvivalBuildStructureWalker<T> implements IStructureWalker<T> {
|
||||
env.offsetABC[2] = c;
|
||||
env.setSource(params.getSource());
|
||||
PlaceResult placeResult = element.survivalPlaceBlock(object, world, x, y, z, trigger, env);
|
||||
if (placeResult != PlaceResult.SKIP && built == -1) built = 0;
|
||||
if (placeResult != PlaceResult.SKIP && placeResult != PlaceResult.REJECT_CONTINUE && built == -1) built = 0;
|
||||
switch (placeResult) {
|
||||
case SKIP:
|
||||
case REJECT_CONTINUE:
|
||||
return true;
|
||||
case ACCEPT:
|
||||
if (check) element.check(object, world, x, y, z);
|
||||
|
||||
Reference in new issue
Block a user