Compare commits

...
2 Commits
Author SHA1 Message Date
1820982382 177ef6c551 v2.2.8 2026-08-22 17:07:18 +08:00
1820982382 c83e34c1d6 v2.2.7 2026-08-22 16:59:38 +08:00
33 changed files with 1146 additions and 22 deletions
+20 -6
View File
@@ -73,10 +73,24 @@ processResources {
jar { duplicatesStrategy = DuplicatesStrategy.EXCLUDE }
// 获取git提交总数
def gitCommitCount = providers.exec {
commandLine 'git', 'rev-list', '--count', 'HEAD'
}.standardOutput.asText.map { it.trim() }
// 最终完整版本 = 主版本+构建号
version = "${mod_version}.${gitCommitCount.get()}-alpha"
def gitVersion() {
def describe = providers.exec {
commandLine 'git', 'describe', '--tags', '--always'
}.standardOutput.asText.map { it.trim() }.get()
// 支持 "2.2" / "v2.2.0" / "2.2-3-gabc1234" / "abc1234"(无tag时)
// 版本 = tag 的 X.Y + 提交数:tag 2.2 + 2 提交 → 2.2.2
// find() 只匹配开头,忽略尾部 commit hash(-gabc1234)
def m = describe =~ /^v?(\d+\.\d+)(?:\.\d+)?(?:-(\d+))?/
if (m.find()) {
def xy = m.group(1) // 2.2
def count = m.group(2) ? m.group(2) : '0' // tag 后提交数
return "${xy}.${count}-alpha" // 2.2.2-alpha
}
// 兜底(从未打 tag):mod_version + 总提交数
def count = providers.exec {
commandLine 'git', 'rev-list', '--count', 'HEAD'
}.standardOutput.asText.map { it.trim() }.get()
return "${mod_version}.${count}-alpha"
}
version = gitVersion()
+1 -5
View File
@@ -25,8 +25,4 @@ org.gradle.configuration-cache=true
minecraft_version_range=[1.21.1,1.22)
neoforge_version_range=[21,)
loader_version_range=[4,)
systemProp.http.proxyHost=127.0.0.1
systemProp.http.proxyPort=7890
systemProp.https.proxyHost=127.0.0.1
systemProp.https.proxyPort=7890
systemProp.http.nonProxyHosts=localhost|127.*
@@ -52,6 +52,10 @@ public final class RecipeRegistration {
public static ShapelessArcaneRecipe ARCANE_CRAFTING_TERMINAL;
public static ShapelessArcaneRecipe VIS_INTERFACE;
public static ShapelessArcaneRecipe ESSENTIA_VIBRATION_CHAMBER;
/** 源质无线接收器(无序奥术)。 */
public static ShapelessArcaneRecipe ESSENTIA_PROVIDER_CONNECTION;
/** 源质无线绑定工具(无序奥术)。 */
public static ShapelessArcaneRecipe WIRELESS_CONNECTOR;
/** 赛特斯石英复制(坩埚炼金配方——研究页关联)。 */
public static CrucibleRecipe CERTUS_DUPE_RECIPE;
@@ -265,6 +269,22 @@ public final class RecipeRegistration {
tc("jar_of_essentia"),
stack(ModItems.COALESCENCE_CORE));
// 8. 源质无线接收器(无序奥术,研究:源质供应器)
ESSENTIA_PROVIDER_CONNECTION = ThaumcraftApi.addShapelessArcaneCraftingRecipe("ESSENTIAPROVIDER",
new ItemStack(ModBlocks.ESSENTIA_PROVIDER_CONNECTION.get(), 2),
new AspectList().add(Aspect.ORDER, 8).add(Aspect.AIR, 6).add(Aspect.FIRE, 3),
stack(ModItems.COALESCENCE_CORE),
stack(ModItems.DIFFUSION_CORE),
ae("wireless_receiver"),
tc("balanced_shard"));
// 9. 源质无线绑定工具(无序奥术,研究:源质供应器)
WIRELESS_CONNECTOR = ThaumcraftApi.addShapelessArcaneCraftingRecipe("ESSENTIAPROVIDER",
stack(ModItems.WIRELESS_CONNECTOR),
new AspectList().add(Aspect.ORDER, 5).add(Aspect.ENTROPY, 5),
ae("certus_quartz_wrench"),
tc("balanced_shard"));
}
@@ -282,9 +282,15 @@ public final class ThEThaumcraft {
-2, -4, 3, new ItemStack(ModItems.ESSENTIA_PROVIDER_ITEM.get()))
.setRound().setParents("ESSENTIABUSES")
.setPages(
// 源质供应器:介绍+用法 / 配方
new ResearchPage("tc.research_text.ESSENTIAPROVIDER.stage.1"),
new ResearchPage(RecipeRegistration.ESSENTIA_PROVIDER),
new ResearchPage("tc.research_text.ESSENTIAPROVIDER.stage.2"))
// 源质无线接收器:介绍+用法 / 配方
new ResearchPage("tc.research_text.ESSENTIAPROVIDER.connection.stage.1"),
new ResearchPage(RecipeRegistration.ESSENTIA_PROVIDER_CONNECTION),
// 源质无线绑定工具:介绍+用法 / 配方
new ResearchPage("tc.research_text.ESSENTIAPROVIDER.tool.stage.1"),
new ResearchPage(RecipeRegistration.WIRELESS_CONNECTOR))
.registerResearchItem();
}
@@ -0,0 +1,161 @@
package thaumicenergistics.common.items;
import net.minecraft.core.BlockPos;
import net.minecraft.core.component.DataComponents;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import thaumicenergistics.common.tiles.TileEssentiaProvider;
import thaumicenergistics.common.tiles.TileEssentiaProviderConnection;
import thaumicenergistics.init.ModBlocks;
/**
* 源质无线绑定工具:
* - Shift+右键:绑定/断开(未连接的接收器=选中;供应器=绑定选中的接收器;已连接的接收器=断开)
* - 右键:显示连接信息(聊天栏,坐标可复制)
*/
public class WirelessConnectorItem extends Item {
private static final String KEY_SELECTED_RECEIVER = "SelectedReceiver";
private static final String KEY_SELECTED_PROVIDER = "SelectedProvider";
public WirelessConnectorItem(Properties properties) {
super(properties);
}
private static CompoundTag getSelectionTag(ItemStack stack) {
return stack.getOrDefault(DataComponents.CUSTOM_DATA, net.minecraft.world.item.component.CustomData.EMPTY).copyTag();
}
private static void setSelectionTag(ItemStack stack, CompoundTag tag) {
stack.set(DataComponents.CUSTOM_DATA, net.minecraft.world.item.component.CustomData.of(tag));
}
private static void clearSelection(ItemStack stack) {
stack.remove(DataComponents.CUSTOM_DATA);
}
private static void showReceiverInfo(Player player, TileEssentiaProviderConnection receiver) {
BlockPos lp = receiver.getLinkedProviderPos();
if (lp != null) {
player.sendSystemMessage(Component.literal("§7[源质无线接收器] 已连接供应器: §a[" + lp.getX() + ", " + lp.getY() + ", " + lp.getZ() + "]"));
} else {
player.sendSystemMessage(Component.literal("§7[源质无线接收器] 未连接任何供应器"));
}
}
private static void showProviderInfo(Player player, TileEssentiaProvider provider) {
var list = provider.getLinkedReceivers();
player.sendSystemMessage(Component.literal("§7[源质供应器] 已连接接收器 (" + list.size() + "/" + TileEssentiaProvider.MAX_LINKED_RECEIVERS + "):"));
if (list.isEmpty()) {
player.sendSystemMessage(Component.literal("§7 (无)"));
} else {
for (BlockPos rp : list) {
player.sendSystemMessage(Component.literal("§a [" + rp.getX() + ", " + rp.getY() + ", " + rp.getZ() + "]"));
}
}
}
@Override
public InteractionResult useOn(UseOnContext context) {
Level level = context.getLevel();
BlockPos pos = context.getClickedPos();
Player player = context.getPlayer();
ItemStack stack = context.getItemInHand();
if (level.isClientSide() || player == null) {
return InteractionResult.SUCCESS;
}
BlockState state = level.getBlockState(pos);
BlockEntity be = level.getBlockEntity(pos);
// ===== Shift+右键:绑定 / 断开(顺序不限,第二步完成绑定) =====
if (player.isShiftKeyDown()) {
if (be instanceof TileEssentiaProviderConnection receiver) {
if (receiver.getLinkedProviderPos() != null) {
// 已连接 → 断开
receiver.clearLink();
player.sendSystemMessage(Component.literal("§e已断开该源质无线接收器的连接"));
return InteractionResult.SUCCESS;
}
CompoundTag tag = getSelectionTag(stack);
if (tag.contains(KEY_SELECTED_PROVIDER)) {
// 已选中供应器 → 绑定到它
BlockPos providerPos = BlockPos.of(tag.getLong(KEY_SELECTED_PROVIDER));
String error = receiver.setLinkedProvider(providerPos);
if (error == null) {
player.sendSystemMessage(Component.literal("§a绑定成功!无线接收器已连接至源质供应器"));
} else {
player.sendSystemMessage(Component.literal(error));
}
clearSelection(stack);
} else if (tag.contains(KEY_SELECTED_RECEIVER)) {
player.sendSystemMessage(Component.literal("§c接收器不能互相绑定,只能绑定到源质供应器"));
} else {
// 未选中 → 选中该接收器
tag.putLong(KEY_SELECTED_RECEIVER, pos.asLong());
setSelectionTag(stack, tag);
player.sendSystemMessage(Component.literal("§a已选中源质无线接收器,请 shift+右键 源质供应器完成绑定"));
}
return InteractionResult.SUCCESS;
}
if (be instanceof TileEssentiaProvider) {
CompoundTag tag = getSelectionTag(stack);
if (tag.contains(KEY_SELECTED_RECEIVER)) {
// 已选中接收器 → 绑定到本供应器
BlockPos receiverPos = BlockPos.of(tag.getLong(KEY_SELECTED_RECEIVER));
if (level.getBlockEntity(receiverPos) instanceof TileEssentiaProviderConnection receiver) {
String error = receiver.setLinkedProvider(pos);
if (error == null) {
player.sendSystemMessage(Component.literal("§a绑定成功!无线接收器已连接至源质供应器"));
} else {
player.sendSystemMessage(Component.literal(error));
}
} else {
player.sendSystemMessage(Component.literal("§c选中的源质无线接收器不存在或已被移除"));
}
clearSelection(stack);
} else {
// 未选中 → 选中该供应器
tag.putLong(KEY_SELECTED_PROVIDER, pos.asLong());
setSelectionTag(stack, tag);
player.sendSystemMessage(Component.literal("§a已选中源质供应器,请 shift+右键 源质无线接收器完成绑定"));
}
return InteractionResult.SUCCESS;
}
// 其他方块:清除选中
if (getSelectionTag(stack).contains(KEY_SELECTED_RECEIVER)
|| getSelectionTag(stack).contains(KEY_SELECTED_PROVIDER)) {
clearSelection(stack);
player.sendSystemMessage(Component.literal("§7已清除选中"));
return InteractionResult.SUCCESS;
}
return InteractionResult.PASS;
}
// ===== 右键:显示连接信息(复制显示) =====
if (be instanceof TileEssentiaProviderConnection receiver) {
showReceiverInfo(player, receiver);
return InteractionResult.SUCCESS;
}
if (be instanceof TileEssentiaProvider provider) {
showProviderInfo(player, provider);
return InteractionResult.SUCCESS;
}
// 其他方块:清除选中
if (getSelectionTag(stack).contains(KEY_SELECTED_RECEIVER)
|| getSelectionTag(stack).contains(KEY_SELECTED_PROVIDER)) {
clearSelection(stack);
player.sendSystemMessage(Component.literal("§7已清除选中"));
return InteractionResult.SUCCESS;
}
return InteractionResult.PASS;
}
}
@@ -33,7 +33,64 @@ public class TileEssentiaProvider extends TileProviderBase implements IEssentiaT
@Override
protected double getIdlePowerUsage() {
return 3.0;
// 基础 3 + 每连接 1 个接收器 +5
return 3.0 + 5.0 * getLinkedReceiverCount();
}
// ===== 无线接收器连接管理 =====
/** 最多连接的接收器数量。 */
public static final int MAX_LINKED_RECEIVERS = 8;
/** 最大连接距离(格)。 */
public static final int MAX_LINK_DISTANCE = 32;
private List<BlockPos> linkedReceivers = new java.util.ArrayList<>();
public java.util.List<BlockPos> getLinkedReceivers() {
return linkedReceivers;
}
public int getLinkedReceiverCount() {
return linkedReceivers.size();
}
/** 注册一个接收器连接(校验数量与距离,失败返回原因文案;成功返回 null)。 */
public String addLinkedReceiver(BlockPos receiverPos) {
if (linkedReceivers.contains(receiverPos)) return null; // 已连接
if (linkedReceivers.size() >= MAX_LINKED_RECEIVERS) {
return "§c该源质供应器已连接满 " + MAX_LINKED_RECEIVERS + " 个接收器";
}
double dist = Math.sqrt(worldPosition.distSqr(receiverPos));
if (dist > MAX_LINK_DISTANCE) {
return "§c距离过远(" + (int) Math.ceil(dist) + " 格 > " + MAX_LINK_DISTANCE + " 格上限)";
}
linkedReceivers.add(receiverPos);
setChanged();
updatePower();
return null;
}
public void removeLinkedReceiver(BlockPos receiverPos) {
if (linkedReceivers.remove(receiverPos)) {
setChanged();
updatePower();
}
}
/** 周期校验:清除已失效的接收器连接(方块被拆除)。 */
public void validateLinkedReceivers() {
if (level == null || linkedReceivers.isEmpty()) return;
linkedReceivers.removeIf(pos -> {
boolean gone = !(level.getBlockEntity(pos) instanceof TileEssentiaProviderConnection);
if (gone) setChanged();
return gone;
});
updatePower();
}
private void updatePower() {
if (mainNode != null) {
mainNode.setIdlePowerUsage(getIdlePowerUsage());
}
}
/** getEssentiaList 短时缓存:TC 管道 suction 每 tick 调 getEssentiaType,避免每 tick 全量遍历。 */
@@ -55,6 +112,12 @@ public class TileEssentiaProvider extends TileProviderBase implements IEssentiaT
if (essentiaListCacheTimer > 0) essentiaListCacheTimer--;
// 周期校验无线接收器连接(约每 2 秒)
if (++validateCounter >= 40) {
validateCounter = 0;
validateLinkedReceivers();
}
if (++tickCount >= tickRate) {
tickCount = 0;
tickRate = TICK_RATE_IDLE;
@@ -62,6 +125,8 @@ public class TileEssentiaProvider extends TileProviderBase implements IEssentiaT
}
}
private int validateCounter = 0;
// ===== IEssentiaTransport =====
@Override
@@ -151,6 +216,36 @@ public class TileEssentiaProvider extends TileProviderBase implements IEssentiaT
return 1;
}
// ===== 供源质无线接收器转发的公开方法 =====
public boolean thE_isActive() {
return mainNode.isActive();
}
public long thE_queryAmount(Aspect aspect) {
return getAspectAmountInNetwork(aspect);
}
public long thE_extract(Aspect aspect, long amount, boolean simulate) {
return extractEssentiaFromNetwork(aspect, amount, simulate);
}
public long thE_inject(Aspect aspect, long amount, boolean simulate) {
return injectEssentiaToNetwork(aspect, amount, simulate);
}
/** 网络中第一种有存量的源质(供接收器无特定需求时兜底)。 */
public Aspect thE_firstAvailable() {
if (essentiaGrid != null) {
for (var stack : getCachedEssentiaList()) {
if (stack.amount() > 0) {
return Aspect.getAspect(stack.aspectId().getPath());
}
}
}
return null;
}
@Override
public boolean renderExtendedTube() {
return false;
@@ -199,4 +294,27 @@ public class TileEssentiaProvider extends TileProviderBase implements IEssentiaT
}
}
}
// ===== NBT =====
@Override
protected void saveAdditional(net.minecraft.nbt.CompoundTag tag, net.minecraft.core.HolderLookup.Provider registries) {
super.saveAdditional(tag, registries);
net.minecraft.nbt.ListTag list = new net.minecraft.nbt.ListTag();
for (BlockPos pos : linkedReceivers) {
list.add(net.minecraft.nbt.LongTag.valueOf(pos.asLong()));
}
tag.put("LinkedReceivers", list);
}
@Override
protected void loadAdditional(net.minecraft.nbt.CompoundTag tag, net.minecraft.core.HolderLookup.Provider registries) {
super.loadAdditional(tag, registries);
linkedReceivers.clear();
if (tag.contains("LinkedReceivers")) {
for (net.minecraft.nbt.Tag t : tag.getList("LinkedReceivers", net.minecraft.nbt.Tag.TAG_LONG)) {
linkedReceivers.add(BlockPos.of(((net.minecraft.nbt.LongTag) t).getAsLong()));
}
}
}
}
@@ -0,0 +1,262 @@
package thaumicenergistics.common.tiles;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.HolderLookup;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import thaumcraft.api.aspects.Aspect;
import thaumcraft.api.aspects.IEssentiaTransport;
import thaumcraft.common.essentia.EssentiaTransport;
import thaumicenergistics.init.ModBlockEntities;
import thaumicenergistics.init.ModBlocks;
/**
* 源质无线接收器:通过无线连接器与源质供应器建立连接后,
* 作为纯中继(无 AE 节点),把 TC 管道/炼金塔的取源质请求转发到连接的供应器。
*/
public class TileEssentiaProviderConnection extends BlockEntity implements IEssentiaTransport, EssentiaTransport {
/** 连接的源质供应器坐标(null = 未连接)。 */
private BlockPos linkedProviderPos;
/** 接收器每次输入/输出源质上限。 */
public static final int TRANSFER_LIMIT = 16;
private int linkCheckCounter = 0;
private int pullCounter = 0;
private static final int PULL_INTERVAL = 10;
/** 模拟管道的最大扫描距离(格):接收器可隔空拉取该距离内的源质源。 */
private static final int PIPE_SCAN_RANGE = 16;
/** 服务端 tick:周期校验连接 + 主动沿模拟管道拉取源质(蒸馏器/罐/管道不主动推,需接收器拉)。 */
public static void serverTick(net.minecraft.world.level.Level level, BlockPos pos, BlockState state, TileEssentiaProviderConnection be) {
if (level.isClientSide()) return;
if (be.linkedProviderPos != null && ++be.linkCheckCounter >= 40) {
be.linkCheckCounter = 0;
be.getLinkedProvider(); // 无效连接会被清除
}
if (++be.pullCounter >= PULL_INTERVAL) {
be.pullCounter = 0;
be.takeEssentiaFromNeighbors();
}
}
/** 模拟管道:沿 6 个方向扫描,最近的有效源质源(蒸馏器/罐/管道)隔空拉取,经连接供应器注入 AE 网络。 */
private void takeEssentiaFromNeighbors() {
if (level == null || level.isClientSide()) return;
TileEssentiaProvider provider = getLinkedProvider();
if (provider == null || !provider.thE_isActive()) return;
for (Direction side : Direction.values()) {
if (!canInputFrom(side)) continue;
// 沿方向行走:非传输方块 = 管道断;空管道 = 继续;有源质 = 拉取
for (int d = 1; d <= PIPE_SCAN_RANGE; d++) {
BlockPos sourcePos = worldPosition.relative(side, d);
if (!level.isLoaded(sourcePos)) break;
BlockEntity sourceTile = level.getBlockEntity(sourcePos);
if (sourceTile == this) break;
if (sourceTile instanceof TileEssentiaProvider) break; // 到供应器本体,防循环
if (!(sourceTile instanceof IEssentiaTransport source)) break; // 非传输方块 = 管道断
Direction sourceSide = side.getOpposite();
if (!source.canOutputTo(sourceSide)) break; // 不能向接收器方向输出 = 断
int srcAmount = source.getEssentiaAmount(sourceSide);
if (srcAmount <= 0) continue; // 空管道/空源 → 继续走
int dSuck = getSuctionAmount(side);
if (dSuck < source.getMinimumSuction() || dSuck < source.getSuctionAmount(sourceSide)) {
break;
}
Aspect sourceAspect = source.getEssentiaType(sourceSide);
if (sourceAspect == null) break;
// 直接拉取并注入(injectEssentia 返回 0 = 全部接受,无需模拟预检)
int want = Math.min(Math.max(srcAmount, 1), TRANSFER_LIMIT);
int taken = source.takeEssentia(sourceAspect, want, sourceSide);
if (taken > 0) {
provider.thE_inject(sourceAspect, taken, false);
}
break; // 拉到即停
}
}
}
public TileEssentiaProviderConnection(BlockPos pos, BlockState state) {
super(ModBlockEntities.ESSENTIA_PROVIDER_CONNECTION.get(), pos, state);
}
// ===== 连接管理 =====
public BlockPos getLinkedProviderPos() {
return linkedProviderPos;
}
public boolean isLinked() {
return linkedProviderPos != null && getLinkedProvider() != null;
}
/** 设置连接(无线连接器右键供应器时调用)。返回 null = 成功;否则返回失败原因文案。 */
public String setLinkedProvider(BlockPos providerPos) {
// 在供应器侧注册(校验数量/距离)
if (level != null && !level.isClientSide()) {
if (level.getBlockEntity(providerPos) instanceof TileEssentiaProvider provider) {
String error = provider.addLinkedReceiver(worldPosition);
if (error != null) {
return error; // 超限/超距,不建立连接
}
} else {
return "§c目标不是有效的源质供应器";
}
}
this.linkedProviderPos = providerPos;
setChanged();
updateConnectedState();
return null;
}
public void clearLink() {
// 从供应器侧注销
if (level != null && !level.isClientSide() && linkedProviderPos != null
&& level.getBlockEntity(linkedProviderPos) instanceof TileEssentiaProvider provider) {
provider.removeLinkedReceiver(worldPosition);
}
this.linkedProviderPos = null;
setChanged();
updateConnectedState();
}
private void updateConnectedState() {
if (level == null || level.isClientSide()) return;
boolean connected = linkedProviderPos != null;
BlockState st = getBlockState();
if (st.getValue(ModBlocks.CONNECTED) != connected) {
level.setBlock(worldPosition, st.setValue(ModBlocks.CONNECTED, connected), 3);
BlockEntity be = level.getBlockEntity(worldPosition);
if (be != null && be != this) {
be.setChanged();
}
}
}
/** 查找连接的供应器 tile。 */
public TileEssentiaProvider getLinkedProvider() {
if (level == null || level.isClientSide() || linkedProviderPos == null) return null;
if (level.getBlockEntity(linkedProviderPos) instanceof TileEssentiaProvider provider) {
// 自愈:供应器列表缺本接收器时补注册(修复旧存档/列表丢失导致的状态不一致)
if (!provider.getLinkedReceivers().contains(worldPosition)) {
provider.addLinkedReceiver(worldPosition);
}
return provider;
}
// 供应器被移除 → 清除连接
linkedProviderPos = null;
setChanged();
updateConnectedState();
return null;
}
// ===== IEssentiaTransport(转发到连接供应器) =====
@Override
public boolean isConnectable(Direction side) {
return true;
}
@Override
public boolean canInputFrom(Direction side) {
return true; // 支持输入源质到 AE 网络
}
@Override
public boolean canOutputTo(Direction side) {
return true;
}
@Override
public void setSuction(Aspect aspect, int amount) {
}
@Override
public Aspect getSuctionType(Direction side) {
return null;
}
@Override
public int getSuctionAmount(Direction side) {
// 与源质供应器一致:有吸力才能被蒸馏器等设施注入源质(输入功能)
return 8;
}
@Override
public int takeEssentia(Aspect aspect, int amount, Direction side) {
TileEssentiaProvider provider = getLinkedProvider();
if (provider == null || !provider.thE_isActive() || aspect == null || amount <= 0) return 0;
return (int) provider.thE_extract(aspect, Math.min(amount, TRANSFER_LIMIT), false);
}
@Override
public int addEssentia(Aspect aspect, int amount, Direction side) {
// 无线输入:转发到连接供应器注入 AE 网络,每次上限 16
TileEssentiaProvider provider = getLinkedProvider();
if (provider == null || !provider.thE_isActive() || aspect == null || amount <= 0) return 0;
return (int) provider.thE_inject(aspect, Math.min(amount, TRANSFER_LIMIT), false);
}
@Override
public int getEssentiaAmount(Direction side) {
TileEssentiaProvider provider = getLinkedProvider();
if (provider == null || !provider.thE_isActive()) return 0;
Aspect wanted = getNeighborWantedAspect(side);
if (wanted != null) {
return (int) Math.min(provider.thE_queryAmount(wanted), Integer.MAX_VALUE);
}
return 0;
}
@Override
public Aspect getEssentiaType(Direction side) {
TileEssentiaProvider provider = getLinkedProvider();
if (provider == null || !provider.thE_isActive()) return null;
Aspect wanted = getNeighborWantedAspect(side);
if (wanted != null && provider.thE_queryAmount(wanted) > 0) {
return wanted;
}
return provider.thE_firstAvailable();
}
@Override
public int getMinimumSuction() {
return 0;
}
@Override
public boolean renderExtendedTube() {
return false;
}
private Aspect getNeighborWantedAspect(Direction side) {
BlockPos neighborPos = worldPosition.relative(side);
if (level.getBlockEntity(neighborPos) instanceof IEssentiaTransport transport) {
return transport.getSuctionType(side.getOpposite());
}
return null;
}
// ===== NBT =====
@Override
protected void saveAdditional(CompoundTag tag, HolderLookup.Provider registries) {
super.saveAdditional(tag, registries);
if (linkedProviderPos != null) {
tag.putLong("LinkedProvider", linkedProviderPos.asLong());
}
}
@Override
protected void loadAdditional(CompoundTag tag, HolderLookup.Provider registries) {
super.loadAdditional(tag, registries);
if (tag.contains("LinkedProvider")) {
linkedProviderPos = BlockPos.of(tag.getLong("LinkedProvider"));
} else {
linkedProviderPos = null;
}
}
}
@@ -232,7 +232,7 @@ public class TileInfusionMonitor extends ThETileBase implements IInWorldGridNode
if (bubble != null) return;
bubble = EntityType.TEXT_DISPLAY.create(level);
if (bubble == null) return;
bubble.setPos(worldPosition.getX() + 0.5, worldPosition.getY() + 1.4, worldPosition.getZ() + 0.5);
bubble.setPos(worldPosition.getX() + 0.5, worldPosition.getY() + 1.2, worldPosition.getZ() + 0.5);
// 1.21.1 TextDisplay 配置 API 均为 private/protected:反射调用 readAdditionalSaveData
// 用 summon 命令同款 NBT 一次配置全部字段(text/background/billboard/shadow/see_through 等)。
applyBubbleNbt(buildBubbleText(cachedRisk));
@@ -304,7 +304,7 @@ public class TileInfusionMonitor extends ThETileBase implements IInWorldGridNode
bubble = null;
}
/** 风险数据 → 气泡多行文本(2 行:注魔风险/不稳定度;描述改由右键在聊天框显示)。 */
/** 风险数据 → 气泡多行文本(2 行:注魔风险/不稳定度;不显示基础+祭坛细分,细分在聊天栏)。 */
private static Component buildBubbleText(RiskData risk) {
// 内边距必须用不间断空格(\u00A0):普通空格在行尾会被字体布局裁剪,
// 导致背景只包住左侧、右侧贴边。NBSP 有真实字形,两侧都保留。
@@ -313,8 +313,7 @@ public class TileInfusionMonitor extends ThETileBase implements IInWorldGridNode
Component line1 = Component.literal(pad + "注魔风险: " + tierWord + pad)
.withStyle(style -> style.withColor(tierColor(risk.tier())));
Component line2 = Component.literal(pad + "不稳定度: " + risk.instability()
+ " (基础 " + risk.recipeInstability() + " + 祭坛 " + risk.symmetry() + ")" + pad)
Component line2 = Component.literal(pad + "不稳定度: " + risk.instability() + pad)
.withStyle(style -> style.withColor(0xFFFFFFFF));
// 上下各留一个空行(垂直内边距)
@@ -383,19 +382,35 @@ public class TileInfusionMonitor extends ThETileBase implements IInWorldGridNode
}
}
/** 右键:在玩家聊天框显示当前风险档位 + 描述。 */
/** 右键:聊天框提示。需手册 + 联网才显示详细风险;否则提示缺失项。 */
public void showDescriptionInChat(Player player) {
if (level == null || level.isClientSide()) return;
boolean hasBook = getBlockState().getValue(ModBlocks.BOOK);
boolean hasNetwork = getBlockState().getValue(ModBlocks.NETWORK);
if (!hasBook && !hasNetwork) {
player.sendSystemMessage(Component.literal("§7韵魔观测器: 缺少引导的书籍与网络能量(魔导手册与 AE 网络)"));
return;
}
if (!hasBook) {
player.sendSystemMessage(Component.literal("§7韵魔观测器: 需要放置魔导手册作为引导"));
return;
}
if (!hasNetwork) {
player.sendSystemMessage(Component.literal("§7韵魔观测器: 需要接入 AE 网络供能"));
return;
}
if (!cachedRisk.found()) {
player.sendSystemMessage(Component.literal("§7韵魔观测器: 未检测到注魔祭坛"));
return;
}
String tierWord = tierWord(cachedRisk.tier());
String desc = tierDesc(cachedRisk.tier());
// 档位行用档位颜色
Component msg = Component.literal("注魔风险: ")
.withStyle(style -> style.withColor(tierColor(cachedRisk.tier())))
.append(Component.literal(tierWord + " §f—— " + desc));
.append(Component.literal(tierWord + "§7"))
.append(Component.literal("\n不稳定度: " + cachedRisk.instability()
+ " (基础 " + cachedRisk.recipeInstability() + " + 祭坛 " + cachedRisk.symmetry() + ")§f\n"))
.append(Component.literal(desc));
player.sendSystemMessage(msg);
}
@@ -45,6 +45,10 @@ public final class ModBlockEntities {
REGISTRY.register("infusion_monitor",
() -> BlockEntityType.Builder.of(TileInfusionMonitor::new, ModBlocks.INFUSION_MONITOR.get()).build(null));
public static final Supplier<BlockEntityType<TileEssentiaProviderConnection>> ESSENTIA_PROVIDER_CONNECTION =
REGISTRY.register("essentia_provider_connection",
() -> BlockEntityType.Builder.of(TileEssentiaProviderConnection::new, ModBlocks.ESSENTIA_PROVIDER_CONNECTION.get()).build(null));
/**
* 虚拟的 Thaumcraft vis 源,供 vis 接口的提供端使用。
* 不作为真实方块放置;由 {@link thaumicenergistics.common.parts.VisInterfacePart}
@@ -297,4 +297,64 @@ public final class ModBlocks {
return java.util.List.of(new ItemStack(ModItems.ALKUSURE86_FUMO_ITEM.get()));
}
});
// ==================== 源质无线接收器 ====================
/** 是否已连接源质供应器(off/on 模型切换)。 */
public static final net.minecraft.world.level.block.state.properties.BooleanProperty CONNECTED =
net.minecraft.world.level.block.state.properties.BooleanProperty.create("connected");
/** 接收器六向贴放(贴墙/立地/挂顶)。 */
public static final net.minecraft.world.level.block.state.properties.DirectionProperty FACING_ALL =
net.minecraft.world.level.block.state.properties.BlockStateProperties.FACING;
/** 接收器专用:低硬度 → 镐子可快速挖掘。 */
private static final BlockBehaviour.Properties PC =
BlockBehaviour.Properties.of().mapColor(MapColor.STONE).strength(1.0f).sound(SoundType.STONE);
public static final DeferredBlock<Block> ESSENTIA_PROVIDER_CONNECTION = REGISTRY.register("essentia_provider_connection", () -> new ThEBaseEntityBlock(PC) {
@Override
public net.minecraft.world.level.block.entity.BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
return new TileEssentiaProviderConnection(pos, state);
}
@Override
public <T extends net.minecraft.world.level.block.entity.BlockEntity> net.minecraft.world.level.block.entity.BlockEntityTicker<T> getTicker(net.minecraft.world.level.Level level, BlockState state, net.minecraft.world.level.block.entity.BlockEntityType<T> type) {
if (!level.isClientSide() && type == ModBlockEntities.ESSENTIA_PROVIDER_CONNECTION.get()) {
return (lvl, pos, st, be) -> TileEssentiaProviderConnection.serverTick(lvl, pos, st, (TileEssentiaProviderConnection) be);
}
return null;
}
@Override
protected void createBlockStateDefinition(net.minecraft.world.level.block.state.StateDefinition.Builder<Block, BlockState> builder) {
builder.add(CONNECTED, FACING_ALL);
}
@Override
public BlockState getStateForPlacement(net.minecraft.world.item.context.BlockPlaceContext context) {
// 正面朝外 = 点击面的方向(贴墙/立地/挂顶)
return this.defaultBlockState()
.setValue(FACING_ALL, context.getClickedFace())
.setValue(CONNECTED, false);
}
@Override
public net.minecraft.world.phys.shapes.VoxelShape getShape(BlockState state, net.minecraft.world.level.BlockGetter level, BlockPos pos, net.minecraft.world.phys.shapes.CollisionContext context) {
// 薄碰撞箱(贴墙/立地/挂顶),不遮挡光线;UP=立地(底部) DOWN=挂顶(顶部)
return switch (state.getValue(FACING_ALL)) {
case NORTH -> net.minecraft.world.phys.shapes.Shapes.box(0.25, 0.25, 0.75, 0.75, 0.75, 1.0);
case SOUTH -> net.minecraft.world.phys.shapes.Shapes.box(0.25, 0.25, 0.0, 0.75, 0.75, 0.25);
case EAST -> net.minecraft.world.phys.shapes.Shapes.box(0.0, 0.25, 0.25, 0.25, 0.75, 0.75);
case WEST -> net.minecraft.world.phys.shapes.Shapes.box(0.75, 0.25, 0.25, 1.0, 0.75, 0.75);
case UP -> net.minecraft.world.phys.shapes.Shapes.box(0.25, 0.0, 0.25, 0.75, 0.25, 0.75); // 立地:碰撞箱在底部
case DOWN -> net.minecraft.world.phys.shapes.Shapes.box(0.25, 0.75, 0.25, 0.75, 1.0, 0.75); // 挂顶:碰撞箱在顶部
};
}
@Override
public int getLightBlock(BlockState state, net.minecraft.world.level.BlockGetter level, BlockPos pos) {
return 0; // 不遮挡光线
}
});
}
@@ -39,6 +39,7 @@ public final class ModCreativeTab {
output.accept(ModItems.KNOWLEDGE_INSCRIBER_ITEM.get()); output.accept(ModItems.ESSENTIA_CELL_WORKBENCH_ITEM.get());
output.accept(ModItems.DISTILLATION_ENCODER_ITEM.get());
output.accept(ModItems.INFUSION_MONITOR_ITEM.get());
output.accept(ModItems.ESSENTIA_PROVIDER_CONNECTION_ITEM.get()); output.accept(ModItems.WIRELESS_CONNECTOR.get());
// 玩偶不进创造物品栏:需 /give @p thaumicenergistics:alkusure86fumo 手动获取
// output.accept(ModItems.ALKUSURE86_FUMO_ITEM.get());
@@ -80,4 +80,11 @@ public final class ModItems {
public static final DeferredItem<BlockItem> DISTILLATION_ENCODER_ITEM = REGISTRY.registerSimpleBlockItem(ModBlocks.DISTILLATION_ENCODER);
public static final DeferredItem<BlockItem> INFUSION_MONITOR_ITEM = REGISTRY.registerSimpleBlockItem(ModBlocks.INFUSION_MONITOR);
public static final DeferredItem<BlockItem> ALKUSURE86_FUMO_ITEM = REGISTRY.registerSimpleBlockItem(ModBlocks.ALKUSURE86_FUMO);
public static final DeferredItem<BlockItem> ESSENTIA_PROVIDER_CONNECTION_ITEM =
REGISTRY.registerSimpleBlockItem(ModBlocks.ESSENTIA_PROVIDER_CONNECTION);
/** 无线连接器:右键接收器选中,再右键源质供应器建立连接。 */
public static final DeferredItem<net.minecraft.world.item.Item> WIRELESS_CONNECTOR =
REGISTRY.register("wireless_connector",
() -> new thaumicenergistics.common.items.WirelessConnectorItem(new net.minecraft.world.item.Item.Properties()));
}
@@ -0,0 +1,22 @@
{
"multipart": [
{ "when": { "facing": "down" }, "apply": { "model": "thaumicenergistics:block/essentia_provider_connection_model", "x": 90 } },
{ "when": { "facing": "up" }, "apply": { "model": "thaumicenergistics:block/essentia_provider_connection_model", "x": -90 } },
{ "when": { "facing": "north" }, "apply": { "model": "thaumicenergistics:block/essentia_provider_connection_model", "y": 0 } },
{ "when": { "facing": "south" }, "apply": { "model": "thaumicenergistics:block/essentia_provider_connection_model", "y": 180 } },
{ "when": { "facing": "east" }, "apply": { "model": "thaumicenergistics:block/essentia_provider_connection_model", "y": 90 } },
{ "when": { "facing": "west" }, "apply": { "model": "thaumicenergistics:block/essentia_provider_connection_model", "y": 270 } },
{ "when": { "facing": "down", "connected": "false" }, "apply": { "model": "thaumicenergistics:block/essentia_provider_connection_off", "x": 90 } },
{ "when": { "facing": "up", "connected": "false" }, "apply": { "model": "thaumicenergistics:block/essentia_provider_connection_off", "x": -90 } },
{ "when": { "facing": "north", "connected": "false" }, "apply": { "model": "thaumicenergistics:block/essentia_provider_connection_off", "y": 0 } },
{ "when": { "facing": "south", "connected": "false" }, "apply": { "model": "thaumicenergistics:block/essentia_provider_connection_off", "y": 180 } },
{ "when": { "facing": "east", "connected": "false" }, "apply": { "model": "thaumicenergistics:block/essentia_provider_connection_off", "y": 90 } },
{ "when": { "facing": "west", "connected": "false" }, "apply": { "model": "thaumicenergistics:block/essentia_provider_connection_off", "y": 270 } },
{ "when": { "facing": "down", "connected": "true" }, "apply": { "model": "thaumicenergistics:block/essentia_provider_connection_on", "x": 90 } },
{ "when": { "facing": "up", "connected": "true" }, "apply": { "model": "thaumicenergistics:block/essentia_provider_connection_on", "x": -90 } },
{ "when": { "facing": "north", "connected": "true" }, "apply": { "model": "thaumicenergistics:block/essentia_provider_connection_on", "y": 0 } },
{ "when": { "facing": "south", "connected": "true" }, "apply": { "model": "thaumicenergistics:block/essentia_provider_connection_on", "y": 180 } },
{ "when": { "facing": "east", "connected": "true" }, "apply": { "model": "thaumicenergistics:block/essentia_provider_connection_on", "y": 90 } },
{ "when": { "facing": "west", "connected": "true" }, "apply": { "model": "thaumicenergistics:block/essentia_provider_connection_on", "y": 270 } }
]
}
@@ -129,5 +129,9 @@
"tc.research_text.INFUSIONMONITOR.stage.2": "The Infusion Monitor takes the Thaumonomicon as its key and the network as its sight. Place the tome and connect to the network, and it shall hover above the void, truthfully telling the risk of the ritual — and on right-click, it whispers its deeper warnings.",
"tc.research_name.INFUSIONMONITOR": "Infusion Monitor",
"tc.research_name.GOLEMWIFIBACKPACK": "Golem WiFi Backpack"
"tc.research_name.GOLEMWIFIBACKPACK": "Golem WiFi Backpack",
"block.thaumicenergistics.essentia_provider_connection": "Wireless Essentia Receiver",
"item.thaumicenergistics.wireless_connector": "Wireless Connector",
"tc.research_text.ESSENTIAPROVIDER.connection.stage.1": "The Wireless Essentia Receiver can be mounted on any surface. Use the Wireless Essentia Binding Tool to link it to an Essentia Provider, relaying essentia to alchemy towers and stills at a distance. Each provider serves up to eight receivers within thirty-two blocks; each additional receiver costs five extra AE/t. The receiver can also feed essentia back into the network, up to sixteen per transfer.",
"tc.research_text.ESSENTIAPROVIDER.tool.stage.1": "The Wireless Essentia Binding Tool creates and breaks wireless links: sneak-right-click an unlinked receiver to select it, then sneak-right-click an Essentia Provider to bind; sneak-right-click a linked receiver to disconnect. A normal right-click shows the connection coordinates of either device."
}
@@ -145,5 +145,9 @@
"tc.research_text.INFUSIONMONITOR.stage.1": "观测即是驾驭。你将魔导手册置于祭坛之侧,以侦测器窥探注魔的每一次脉动——灵光、裂隙、咒波的先兆,尽收眼底。当它与 ME 网络相连,观测者便真正睁开眼。",
"tc.research_text.INFUSIONMONITOR.stage.2": "韵魔观测器以魔导手册为钥、以网络为眼。放上手册并接入网络,它便会悬浮于虚空之中,如实告知你注魔之仪的风险——而按住右键,它将低语出更深层的告诫。",
"tc.research_name.INFUSIONMONITOR": "韵魔观测器",
"tc.research_name.GOLEMWIFIBACKPACK": "傀儡WiFi背包"
"tc.research_name.GOLEMWIFIBACKPACK": "傀儡WiFi背包",
"block.thaumicenergistics.essentia_provider_connection": "源质无线接收器",
"item.thaumicenergistics.wireless_connector": "源质无线绑定工具",
"tc.research_text.ESSENTIAPROVIDER.connection.stage.1": "源质无线接收器可挂置于任意表面,以源质无线绑定工具与源质供应器建立无线连接,将源质远程输送至炼金塔、蒸馏器等设施。每台供应器最多服务八台接收器,距离不得超过三十二格;每多一台接收器,供应器功耗上升五点。接收器亦可向网络回输源质,每次上限十六点。",
"tc.research_text.ESSENTIAPROVIDER.tool.stage.1": "源质无线绑定工具用于建立与解除无线连接:按住 Shift 右键未连接的接收器将其选中,再 Shift 右键源质供应器完成绑定;Shift 右键已连接的接收器可断开连接;普通右键则可查看双方连接坐标。"
}
@@ -0,0 +1,112 @@
{
"format_version": "1.9.0",
"credit": "Made with _leng",
"textures": {
"particle": "thaumicenergistics:block/essentia_provider_connection"
},
"elements": [
{
"from": [5, 5, 14],
"to": [11, 11, 16],
"faces": {
"north": {"uv": [0, 0, 6, 6], "texture": "#particle"},
"east": {"uv": [6, 6, 8, 0], "texture": "#particle"},
"south": {"uv": [0, 6, 6, 12], "texture": "#particle"},
"west": {"uv": [8, 0, 6, 6], "texture": "#particle"},
"up": {"uv": [6, 0, 8, 6], "rotation": 270, "texture": "#particle"},
"down": {"uv": [6, 0, 8, 6], "rotation": 90, "texture": "#particle"}
}
},
{
"from": [6.5, 6.5, 12],
"to": [9.5, 9.5, 12],
"faces": {
"north": {"uv": [6, 6, 9, 9], "texture": "#particle"}
}
},
{
"from": [6.25912, 7, 12.151],
"to": [7.25912, 9, 14.321],
"rotation": {"angle": -22.5, "axis": "y", "origin": [6.75912, 6.5, 12.681]},
"faces": {
"west": {"uv": [8, 0, 10, 2], "texture": "#particle"},
"up": {"uv": [10, 9, 9, 7], "texture": "#particle"},
"down": {"uv": [9, 9, 8, 11], "texture": "#particle"}
}
},
{
"from": [8.74088, 7, 12.151],
"to": [9.74088, 9, 14.321],
"rotation": {"angle": 22.5, "axis": "y", "origin": [9.24088, 7.5, 12.681]},
"faces": {
"east": {"uv": [10, 0, 8, 2], "rotation": 270, "texture": "#particle"},
"up": {"uv": [8, 11, 9, 9], "texture": "#particle"},
"down": {"uv": [10, 7, 9, 9], "texture": "#particle"}
}
},
{
"from": [7, 5.83434, 12.0665],
"to": [9, 6.83434, 14.3065],
"rotation": {"angle": 22.5, "axis": "x", "origin": [8.4, 6.33434, 13.7065]},
"faces": {
"east": {"uv": [9, 11, 8, 9], "texture": "#particle"},
"west": {"uv": [10, 9, 9, 7], "texture": "#particle"},
"down": {"uv": [10, 0, 8, 2], "texture": "#particle"}
}
},
{
"from": [7, 9.16566, 12.0665],
"to": [9, 10.16566, 14.2365],
"rotation": {"angle": -22.5, "axis": "x", "origin": [8.4, 9.66566, 13.7065]},
"faces": {
"east": {"uv": [9, 7, 10, 9], "texture": "#particle"},
"west": {"uv": [8, 9, 9, 11], "texture": "#particle"},
"up": {"uv": [8, 0, 10, 2], "rotation": 90, "texture": "#particle"}
}
},
{
"from": [6, 6, 11.5],
"to": [7, 7, 14],
"faces": {
"north": {"uv": [10, 0, 11, 1], "texture": "#particle"},
"east": {"uv": [9, 6, 12, 7], "texture": "#particle"},
"west": {"uv": [9, 7, 12, 6], "rotation": 180, "texture": "#particle"},
"up": {"uv": [12, 6, 9, 7], "rotation": 90, "texture": "#particle"},
"down": {"uv": [12, 6, 9, 7], "rotation": 270, "texture": "#particle"}
}
},
{
"from": [6, 9, 11.5],
"to": [7, 10, 14],
"faces": {
"north": {"uv": [10, 0, 11, 1], "texture": "#particle"},
"east": {"uv": [9, 6, 12, 7], "texture": "#particle"},
"west": {"uv": [9, 7, 12, 6], "rotation": 180, "texture": "#particle"},
"up": {"uv": [12, 6, 9, 7], "rotation": 90, "texture": "#particle"},
"down": {"uv": [12, 6, 9, 7], "rotation": 270, "texture": "#particle"}
}
},
{
"from": [9, 6, 11.5],
"to": [10, 7, 14],
"faces": {
"north": {"uv": [10, 0, 11, 1], "texture": "#particle"},
"east": {"uv": [9, 6, 12, 7], "texture": "#particle"},
"west": {"uv": [9, 7, 12, 6], "rotation": 180, "texture": "#particle"},
"up": {"uv": [12, 6, 9, 7], "rotation": 90, "texture": "#particle"},
"down": {"uv": [12, 6, 9, 7], "rotation": 270, "texture": "#particle"}
}
},
{
"from": [9, 9, 11.5],
"to": [10, 10, 14],
"faces": {
"north": {"uv": [10, 0, 11, 1], "texture": "#particle"},
"east": {"uv": [9, 6, 12, 7], "texture": "#particle"},
"west": {"uv": [12, 7, 9, 6], "texture": "#particle"},
"up": {"uv": [12, 6, 9, 7], "rotation": 90, "texture": "#particle"},
"down": {"uv": [9, 6, 12, 7], "rotation": 90, "texture": "#particle"}
}
}
]
}
@@ -0,0 +1,46 @@
{
"format_version": "1.9.0",
"credit": "Made with _leng",
"textures": {
"particle": "thaumicenergistics:block/essentia_provider_connection"
},
"elements": [
{
"from": [7.5, 7.5, 11],
"to": [8.5, 8.5, 12],
"faces": {
"east": {"uv": [9, 9, 10, 10], "texture": "#particle"},
"west": {"uv": [9, 9, 10, 10], "texture": "#particle"},
"up": {"uv": [9, 9, 10, 10], "texture": "#particle"},
"down": {"uv": [9, 9, 10, 10], "texture": "#particle"}
}
},
{
"from": [7.1, 7.1, 9.2],
"to": [8.9, 8.9, 11],
"rotation": {"angle": 45, "axis": "z", "origin": [8, 8, 10.1]},
"faces": {
"north": {"uv": [8, 2, 10, 4], "texture": "#particle"},
"east": {"uv": [10, 2, 8, 4], "texture": "#particle"},
"south": {"uv": [8, 4, 10, 6], "texture": "#particle"},
"west": {"uv": [8, 4, 10, 6], "rotation": 90, "texture": "#particle"},
"up": {"uv": [8, 4, 10, 2], "rotation": 180, "texture": "#particle"},
"down": {"uv": [10, 4, 8, 6], "texture": "#particle"}
}
},
{
"name": "cube_outline",
"from": [9.1, 9.1, 11.2],
"to": [6.9, 6.9, 9],
"rotation": {"angle": 45, "axis": "z", "origin": [8, 8, 10.1]},
"faces": {
"north": {"uv": [6, 9, 8, 11], "texture": "#particle"},
"east": {"uv": [6, 9, 8, 11], "texture": "#particle"},
"south": {"uv": [6, 9, 8, 11], "texture": "#particle"},
"west": {"uv": [8, 9, 6, 11], "texture": "#particle"},
"up": {"uv": [8, 11, 6, 9], "texture": "#particle"},
"down": {"uv": [6, 9, 8, 11], "texture": "#particle"}
}
}
]
}
@@ -0,0 +1,77 @@
{
"format_version": "1.9.0",
"credit": "Made with _leng",
"textures": {
"particle": "thaumicenergistics:block/essentia_provider_connection"
},
"elements": [
{
"from": [7.5, 7.5, 11],
"to": [8.5, 8.5, 12],
"faces": {
"east": {"uv": [9, 9, 10, 10], "texture": "#particle"},
"west": {"uv": [9, 9, 10, 10], "texture": "#particle"},
"up": {"uv": [9, 9, 10, 10], "texture": "#particle"},
"down": {"uv": [9, 9, 10, 10], "texture": "#particle"}
}
},
{
"from": [7.1, 7.1, 9.2],
"to": [8.9, 8.9, 11],
"rotation": {"angle": 45, "axis": "z", "origin": [8, 8, 10.1]},
"faces": {
"north": {"uv": [10, 4, 12, 6], "texture": "#particle"},
"east": {"uv": [12, 4, 10, 6], "texture": "#particle"},
"south": {"uv": [10, 2, 12, 4], "rotation": 90, "texture": "#particle"},
"west": {"uv": [10, 2, 12, 4], "texture": "#particle"},
"up": {"uv": [10, 6, 12, 4], "rotation": 180, "texture": "#particle"},
"down": {"uv": [10, 4, 12, 2], "rotation": 90, "texture": "#particle"}
}
},
{
"name": "cube_outline",
"from": [9.1, 9.1, 11.2],
"to": [6.9, 6.9, 9],
"rotation": {"angle": 45, "axis": "z", "origin": [8, 8, 10.1]},
"faces": {
"north": {"uv": [10, 4, 11, 5], "texture": "#particle"},
"east": {"uv": [10, 4, 11, 5], "texture": "#particle"},
"south": {"uv": [10, 4, 11, 5], "texture": "#particle"},
"west": {"uv": [11, 4, 10, 5], "texture": "#particle"},
"up": {"uv": [11, 5, 10, 4], "texture": "#particle"},
"down": {"uv": [10, 4, 11, 5], "texture": "#particle"}
}
}
],
"display": {
"thirdperson_righthand": {
"rotation": [137.73, -0.85, -90.28],
"translation": [0, 2, 1.5],
"scale": [0.375, 0.375, 0.375]
},
"thirdperson_lefthand": {
"rotation": [75, 45, 0],
"translation": [0, 2.5, 0],
"scale": [0.375, 0.375, 0.375]
},
"firstperson_righthand": {
"rotation": [0, 45, 0],
"scale": [0.4, 0.4, 0.4]
},
"firstperson_lefthand": {
"rotation": [0, -135, 0],
"scale": [0.4, 0.4, 0.4]
},
"ground": {
"translation": [0, 3, 0],
"scale": [0.25, 0.25, 0.25]
},
"gui": {
"rotation": [30, -135, 0],
"scale": [0.625, 0.625, 0.625]
},
"fixed": {
"scale": [0.5, 0.5, 0.5]
}
}
}
@@ -0,0 +1,188 @@
{
"format_version": "1.9.0",
"credit": "Made with _leng",
"textures": {
"particle": "thaumicenergistics:block/essentia_provider_connection"
},
"elements": [
{
"from": [5, 5, 14],
"to": [11, 11, 16],
"faces": {
"north": {"uv": [0, 0, 6, 6], "texture": "#particle"},
"east": {"uv": [6, 6, 8, 0], "texture": "#particle"},
"south": {"uv": [0, 6, 6, 12], "texture": "#particle"},
"west": {"uv": [8, 0, 6, 6], "texture": "#particle"},
"up": {"uv": [6, 0, 8, 6], "rotation": 270, "texture": "#particle"},
"down": {"uv": [6, 0, 8, 6], "rotation": 90, "texture": "#particle"}
}
},
{
"from": [6.5, 6.5, 12],
"to": [9.5, 9.5, 12],
"faces": {
"north": {"uv": [6, 6, 9, 9], "texture": "#particle"}
}
},
{
"from": [6.25912, 7, 12.151],
"to": [7.25912, 9, 14.321],
"rotation": {"angle": -22.5, "axis": "y", "origin": [6.75912, 6.5, 12.681]},
"faces": {
"west": {"uv": [8, 0, 10, 2], "texture": "#particle"},
"up": {"uv": [10, 9, 9, 7], "texture": "#particle"},
"down": {"uv": [9, 9, 8, 11], "texture": "#particle"}
}
},
{
"from": [8.74088, 7, 12.151],
"to": [9.74088, 9, 14.321],
"rotation": {"angle": 22.5, "axis": "y", "origin": [9.24088, 7.5, 12.681]},
"faces": {
"east": {"uv": [10, 0, 8, 2], "rotation": 270, "texture": "#particle"},
"up": {"uv": [8, 11, 9, 9], "texture": "#particle"},
"down": {"uv": [10, 7, 9, 9], "texture": "#particle"}
}
},
{
"from": [7, 5.83434, 12.0665],
"to": [9, 6.83434, 14.3065],
"rotation": {"angle": 22.5, "axis": "x", "origin": [8.4, 6.33434, 13.7065]},
"faces": {
"east": {"uv": [9, 11, 8, 9], "texture": "#particle"},
"west": {"uv": [10, 9, 9, 7], "texture": "#particle"},
"down": {"uv": [10, 0, 8, 2], "texture": "#particle"}
}
},
{
"from": [7, 9.16566, 12.0665],
"to": [9, 10.16566, 14.2365],
"rotation": {"angle": -22.5, "axis": "x", "origin": [8.4, 9.66566, 13.7065]},
"faces": {
"east": {"uv": [9, 7, 10, 9], "texture": "#particle"},
"west": {"uv": [8, 9, 9, 11], "texture": "#particle"},
"up": {"uv": [8, 0, 10, 2], "rotation": 90, "texture": "#particle"}
}
},
{
"from": [6, 6, 11.5],
"to": [7, 7, 14],
"faces": {
"north": {"uv": [10, 0, 11, 1], "texture": "#particle"},
"east": {"uv": [9, 6, 12, 7], "texture": "#particle"},
"west": {"uv": [9, 7, 12, 6], "rotation": 180, "texture": "#particle"},
"up": {"uv": [12, 6, 9, 7], "rotation": 90, "texture": "#particle"},
"down": {"uv": [12, 6, 9, 7], "rotation": 270, "texture": "#particle"}
}
},
{
"from": [6, 9, 11.5],
"to": [7, 10, 14],
"faces": {
"north": {"uv": [10, 0, 11, 1], "texture": "#particle"},
"east": {"uv": [9, 6, 12, 7], "texture": "#particle"},
"west": {"uv": [9, 7, 12, 6], "rotation": 180, "texture": "#particle"},
"up": {"uv": [12, 6, 9, 7], "rotation": 90, "texture": "#particle"},
"down": {"uv": [12, 6, 9, 7], "rotation": 270, "texture": "#particle"}
}
},
{
"from": [9, 6, 11.5],
"to": [10, 7, 14],
"faces": {
"north": {"uv": [10, 0, 11, 1], "texture": "#particle"},
"east": {"uv": [9, 6, 12, 7], "texture": "#particle"},
"west": {"uv": [9, 7, 12, 6], "rotation": 180, "texture": "#particle"},
"up": {"uv": [12, 6, 9, 7], "rotation": 90, "texture": "#particle"},
"down": {"uv": [12, 6, 9, 7], "rotation": 270, "texture": "#particle"}
}
},
{
"from": [9, 9, 11.5],
"to": [10, 10, 14],
"faces": {
"north": {"uv": [10, 0, 11, 1], "texture": "#particle"},
"east": {"uv": [9, 6, 12, 7], "texture": "#particle"},
"west": {"uv": [12, 7, 9, 6], "texture": "#particle"},
"up": {"uv": [12, 6, 9, 7], "rotation": 90, "texture": "#particle"},
"down": {"uv": [9, 6, 12, 7], "rotation": 90, "texture": "#particle"}
}
},
{
"from": [7.5, 7.5, 11],
"to": [8.5, 8.5, 12],
"faces": {
"east": {"uv": [9, 9, 10, 10], "texture": "#particle"},
"west": {"uv": [9, 9, 10, 10], "texture": "#particle"},
"up": {"uv": [9, 9, 10, 10], "texture": "#particle"},
"down": {"uv": [9, 9, 10, 10], "texture": "#particle"}
}
},
{
"from": [7.1, 7.1, 9.2],
"to": [8.9, 8.9, 11],
"rotation": {"angle": 45, "axis": "z", "origin": [8, 8, 10.1]},
"faces": {
"north": {"uv": [8, 2, 10, 4], "texture": "#particle"},
"east": {"uv": [10, 2, 8, 4], "texture": "#particle"},
"south": {"uv": [8, 4, 10, 6], "texture": "#particle"},
"west": {"uv": [8, 4, 10, 6], "rotation": 90, "texture": "#particle"},
"up": {"uv": [8, 4, 10, 2], "rotation": 180, "texture": "#particle"},
"down": {"uv": [10, 4, 8, 6], "texture": "#particle"}
}
},
{
"name": "cube_outline",
"from": [9.1, 9.1, 11.2],
"to": [6.9, 6.9, 9],
"rotation": {"angle": 45, "axis": "z", "origin": [8, 8, 10.1]},
"faces": {
"north": {"uv": [6, 9, 8, 11], "texture": "#particle"},
"east": {"uv": [6, 9, 8, 11], "texture": "#particle"},
"south": {"uv": [6, 9, 8, 11], "texture": "#particle"},
"west": {"uv": [8, 9, 6, 11], "texture": "#particle"},
"up": {"uv": [8, 11, 6, 9], "texture": "#particle"},
"down": {"uv": [6, 9, 8, 11], "texture": "#particle"}
}
}
],
"display": {
"thirdperson_righthand": {
"rotation": [141.59, -0.2, -55.02],
"translation": [0, 2, 1],
"scale": [0.375, 0.375, 0.375]
},
"thirdperson_lefthand": {
"rotation": [139.56, -0.16, -44.95],
"translation": [0, 1.75, 0.75],
"scale": [0.375, 0.375, 0.375]
},
"firstperson_righthand": {
"rotation": [68.36, 3.03, 5.76],
"translation": [-1, 4, 1.75],
"scale": [0.4, 0.4, 0.4]
},
"firstperson_lefthand": {
"rotation": [65.1, 1.97, 105.08],
"translation": [-0.5, 3.5, 1],
"scale": [0.4, 0.4, 0.4]
},
"ground": {
"rotation": [90, 0, 0],
"translation": [0, 4.5, 0]
},
"gui": {
"rotation": [108.74, -0.07, -58.99],
"translation": [0, 1.5, 0],
"scale": [1.005, 1.005, 1.005]
},
"head": {
"rotation": [90, 0, 0],
"translation": [0, 14.5, 0]
},
"fixed": {
"rotation": [90, 0, 0],
"translation": [0, 4, -0.75]
}
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "thaumicenergistics:item/wireless_connector"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 493 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 504 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

@@ -9,6 +9,7 @@
"thaumicenergistics:essentia_cell_workbench",
"thaumicenergistics:distillation_encoder",
"thaumicenergistics:infusion_monitor",
"thaumicenergistics:essentia_provider_connection",
"thaumicenergistics:alkusure86fumo"
]
}