mirror of
https://github.com/GTNewHorizons/GTNHLib.git
synced 2026-11-14 01:14:15 +00:00
Merge branch 'master' into render-type
This commit is contained in:
11 files changed
+248
-11
No files matched your search
@@ -34,6 +34,7 @@ import com.gtnewhorizon.gtnhlib.network.PacketMessageAboveHotbar;
|
||||
import com.gtnewhorizon.gtnhlib.network.PacketViewDistance;
|
||||
import com.gtnewhorizon.gtnhlib.teams.TeamAdminCommand;
|
||||
import com.gtnewhorizon.gtnhlib.teams.TeamCommand;
|
||||
import com.gtnewhorizon.gtnhlib.test.block.BlockLightUnderStair;
|
||||
import com.gtnewhorizon.gtnhlib.test.block.BlockRngTest;
|
||||
import com.gtnewhorizon.gtnhlib.test.block.BlockTest;
|
||||
import com.gtnewhorizon.gtnhlib.test.block.BlockTestAo;
|
||||
@@ -74,6 +75,7 @@ public class CommonProxy {
|
||||
GTNHLib.info("GTNHLib version " + Tags.VERSION + " loaded.");
|
||||
|
||||
if (GTNHLibConfig.enableTestBlocks) {
|
||||
BlockLightUnderStair.register();
|
||||
BlockTest.register();
|
||||
BlockTestAo.register();
|
||||
BlockTestLectern.register();
|
||||
|
||||
@@ -8,21 +8,26 @@ import java.util.concurrent.ExecutionException;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import net.minecraft.command.CommandException;
|
||||
import net.minecraft.command.CommandNotFoundException;
|
||||
import net.minecraft.command.ICommand;
|
||||
import net.minecraft.command.ICommandSender;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.util.ChatComponentText;
|
||||
import net.minecraft.util.ChatComponentTranslation;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.gtnewhorizon.gtnhlib.util.CommandUtils;
|
||||
import com.mojang.brigadier.Command;
|
||||
import com.mojang.brigadier.CommandDispatcher;
|
||||
import com.mojang.brigadier.ParseResults;
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
|
||||
import com.mojang.brigadier.context.ParsedCommandNode;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import com.mojang.brigadier.suggestion.Suggestion;
|
||||
import com.mojang.brigadier.tree.CommandNode;
|
||||
@@ -32,6 +37,8 @@ import lombok.extern.log4j.Log4j2;
|
||||
@Log4j2
|
||||
public class BrigadierApi {
|
||||
|
||||
private static final int MAX_REPORTED_USAGES = 5;
|
||||
|
||||
@Nullable
|
||||
private static CommandDispatcher<ICommandSender> dispatcher = new CommandDispatcher<>();
|
||||
|
||||
@@ -81,11 +88,71 @@ public class BrigadierApi {
|
||||
* @return the result
|
||||
*/
|
||||
public static int executeCommand(ICommandSender sender, String command) {
|
||||
CommandDispatcher<ICommandSender> dispatcher = getCommandDispatcher();
|
||||
ParseResults<ICommandSender> parse = dispatcher.parse(command, sender);
|
||||
try {
|
||||
return getCommandDispatcher().execute(command, sender);
|
||||
return dispatcher.execute(parse);
|
||||
} catch (CommandSyntaxException e) {
|
||||
// TODO: make the exception message better
|
||||
throw new CommandException(e.getMessage());
|
||||
if (parse.getContext().getNodes().isEmpty()) {
|
||||
// nothing matched at all, let vanilla report it like any other unknown command
|
||||
throw new CommandNotFoundException();
|
||||
}
|
||||
reportSyntaxError(sender, parse, e);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Report a parse failure as what went wrong, where it went wrong and how the matched command is meant to be used.
|
||||
* Brigadier's own message is not a translation key, so it cannot be handed to a {@link CommandException}.
|
||||
*
|
||||
* @param sender the executor
|
||||
* @param parse the parse results the failure came from
|
||||
* @param e the failure
|
||||
*/
|
||||
private static void reportSyntaxError(ICommandSender sender, ParseResults<ICommandSender> parse,
|
||||
CommandSyntaxException e) {
|
||||
if (e.getType() == CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownCommand()) {
|
||||
// brigadier reports a command that parsed but has nothing to run as unknown
|
||||
CommandUtils.error(sender, "gtnhlib.chat.command.incomplete");
|
||||
} else {
|
||||
sender.addChatMessage(
|
||||
CommandUtils.colorChatComponent(EnumChatFormatting.RED, e.getRawMessage().getString()));
|
||||
}
|
||||
|
||||
String input = e.getInput();
|
||||
int cursor = e.getCursor();
|
||||
if (input != null && cursor >= 0 && cursor < input.length()) {
|
||||
ChatComponentText accepted = CommandUtils
|
||||
.colorChatComponent(EnumChatFormatting.GRAY, "/" + input.substring(0, cursor));
|
||||
ChatComponentText rejected = CommandUtils
|
||||
.colorChatComponent(EnumChatFormatting.RED, input.substring(cursor));
|
||||
rejected.getChatStyle().setUnderlined(true);
|
||||
sender.addChatMessage(accepted.appendSibling(rejected));
|
||||
}
|
||||
|
||||
List<ParsedCommandNode<ICommandSender>> nodes = parse.getContext().getNodes();
|
||||
if (nodes.isEmpty()) return;
|
||||
|
||||
StringBuilder path = new StringBuilder("/");
|
||||
for (ParsedCommandNode<ICommandSender> node : nodes) {
|
||||
path.append(node.getNode().getUsageText()).append(' ');
|
||||
}
|
||||
|
||||
String[] usages = getCommandDispatcher().getAllUsage(nodes.get(nodes.size() - 1).getNode(), sender, true);
|
||||
for (int i = 0; i < usages.length && i < MAX_REPORTED_USAGES; i++) {
|
||||
ChatComponentTranslation usage = new ChatComponentTranslation(
|
||||
"commands.generic.usage",
|
||||
(path + usages[i]).trim());
|
||||
usage.getChatStyle().setColor(EnumChatFormatting.GRAY);
|
||||
sender.addChatMessage(usage);
|
||||
}
|
||||
if (usages.length > MAX_REPORTED_USAGES) {
|
||||
ChatComponentTranslation more = new ChatComponentTranslation(
|
||||
"gtnhlib.chat.command.more_usages",
|
||||
usages.length - MAX_REPORTED_USAGES);
|
||||
more.getChatStyle().setColor(EnumChatFormatting.GRAY);
|
||||
sender.addChatMessage(more);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.gtnewhorizon.gtnhlib.client.model;
|
||||
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
|
||||
import com.gtnewhorizons.angelica.rendering.StateAwareTessellator;
|
||||
|
||||
class AngelicaHelper {
|
||||
|
||||
/// This method doesn't need to mess with [com.gtnewhorizons.angelica.api.ExtCeleritasRenderBlocks] because that
|
||||
/// only affects [net.minecraft.client.renderer.RenderBlocks] methods, which we don't use.
|
||||
static void initAngelicaLighting(Tessellator tesselator) {
|
||||
if (!(tesselator instanceof StateAwareTessellator saTess)) return;
|
||||
|
||||
saTess.angelica$setAppliedAo(true);
|
||||
}
|
||||
|
||||
static void quadAngelicaLighting(Tessellator tesselator, boolean ao, boolean noDirectionalShading) {
|
||||
if (!(tesselator instanceof StateAwareTessellator saTess)) return;
|
||||
|
||||
saTess.angelica$setAppliedAo(ao);
|
||||
saTess.angelica$setNoDirectionalShading(noDirectionalShading);
|
||||
}
|
||||
|
||||
static void resetAngelicaLighting(Tessellator tesselator) {
|
||||
if (!(tesselator instanceof StateAwareTessellator saTess)) return;
|
||||
|
||||
saTess.angelica$setAppliedAo(false);
|
||||
saTess.angelica$setNoDirectionalShading(false);
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import static com.gtnewhorizon.gtnhlib.client.renderer.cel.api.util.NormI8.unpac
|
||||
import static com.gtnewhorizon.gtnhlib.client.renderer.cel.api.util.NormI8.unpackZ;
|
||||
import static com.gtnewhorizon.gtnhlib.client.renderer.cel.model.quad.properties.ModelQuadFacing.DIRECTIONS;
|
||||
import static com.gtnewhorizon.gtnhlib.client.renderer.cel.model.quad.properties.ModelQuadFacing.VALUES;
|
||||
import static com.gtnewhorizon.gtnhlib.compat.Mods.ANGELICA;
|
||||
import static java.lang.Float.intBitsToFloat;
|
||||
import static java.lang.Math.max;
|
||||
import static net.minecraftforge.client.IItemRenderer.ItemRenderType.ENTITY;
|
||||
@@ -86,6 +87,8 @@ public class ModelISBRH implements ISimpleBlockRenderingHandler, IItemRenderer {
|
||||
worldContext.set(wrappedContext, x, y, z, RAND);
|
||||
final int meta = wrappedContext.getBlockMetadata(x, y, z);
|
||||
|
||||
if (ANGELICA) AngelicaHelper.initAngelicaLighting(tesselator);
|
||||
|
||||
final BakedModel model = ModelRegistry.getBakedModel(worldContext);
|
||||
int color = model.getColor(world, x, y, z, block, meta, RAND);
|
||||
|
||||
@@ -126,11 +129,26 @@ public class ModelISBRH implements ISimpleBlockRenderingHandler, IItemRenderer {
|
||||
final int lm = getLightMap(block, quad, quad.getLightFace(), world, x, y, z, renderer);
|
||||
tesselator.setBrightness(lm);
|
||||
|
||||
final float shade = quad.hasDirectionalShading() ? diffuseLight(quad.getComputedFaceNormal()) : 1;
|
||||
if (ANGELICA) {
|
||||
AngelicaHelper.quadAngelicaLighting(
|
||||
tesselator,
|
||||
quad.hasAmbientOcclusion(),
|
||||
!quad.hasDirectionalShading());
|
||||
}
|
||||
|
||||
final float shade;
|
||||
if (ANGELICA && quad.hasAmbientOcclusion()) {
|
||||
shade = 1;
|
||||
} else {
|
||||
shade = quad.hasDirectionalShading() ? diffuseLight(quad.getComputedFaceNormal()) : 1;
|
||||
}
|
||||
|
||||
tesselator.setColorOpaque_F(r * shade, g * shade, b * shade);
|
||||
renderQuad(quad, x, y, z, tesselator, renderer.overrideBlockTexture);
|
||||
}
|
||||
}
|
||||
|
||||
if (ANGELICA) AngelicaHelper.resetAngelicaLighting(tesselator);
|
||||
worldContext.reset();
|
||||
return rendered;
|
||||
}
|
||||
|
||||
+4
-5
@@ -67,11 +67,10 @@ public interface ModelQuadView extends ModelPrimitiveView {
|
||||
*/
|
||||
boolean isTransparent();
|
||||
|
||||
/**
|
||||
* Not to be confused with ambient occlusion AKA smooth lighting When true, allows this quad to multiply its
|
||||
* brightness based on the direction it's facing. When this is false, each face derives its brightness directly from
|
||||
* the light value it's facing without multiplying it.
|
||||
*/
|
||||
/// Not to be confused with ambient occlusion AKA smooth lighting. When true, allows this quad to multiply its
|
||||
/// brightness based on the direction it's facing. When this is false, each face derives its brightness directly
|
||||
/// from
|
||||
/// the light value it's facing without multiplying it.
|
||||
boolean hasDirectionalShading();
|
||||
|
||||
/**
|
||||
|
||||
@@ -31,11 +31,17 @@ public class MixinCommandHandler {
|
||||
cancellable = true)
|
||||
private void gtnhlib$fallbackToBrigadier(ICommandSender sender, String command,
|
||||
CallbackInfoReturnable<Integer> cir) {
|
||||
if (gtnhlib$isServerCommandManager()) {
|
||||
if (!gtnhlib$isServerCommandManager()) return;
|
||||
|
||||
// an empty console line or a lone slash is not a command, so do not report it as one
|
||||
if (command.trim().isEmpty()) {
|
||||
cir.setReturnValue(0);
|
||||
return;
|
||||
}
|
||||
|
||||
int value = BrigadierApi.executeCommand(sender, command);
|
||||
cir.setReturnValue(value);
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "getPossibleCommands(Lnet/minecraft/command/ICommandSender;Ljava/lang/String;)Ljava/util/List;",
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.gtnewhorizon.gtnhlib.test.block;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.util.ForgeDirection;
|
||||
|
||||
import com.gtnewhorizon.gtnhlib.blockstate.properties.DirectionBlockProperty;
|
||||
import com.gtnewhorizon.gtnhlib.blockstate.properties.DirectionBlockProperty.AbstractDirectionBlockProperty;
|
||||
import com.gtnewhorizon.gtnhlib.blockstate.registry.BlockPropertyRegistry;
|
||||
import com.gtnewhorizon.gtnhlib.util.DirectionUtil;
|
||||
|
||||
import cpw.mods.fml.common.registry.GameRegistry;
|
||||
|
||||
public class BlockLightUnderStair extends Block {
|
||||
|
||||
public final AbstractDirectionBlockProperty FACING_PROP = (AbstractDirectionBlockProperty) DirectionBlockProperty
|
||||
.facing();
|
||||
|
||||
public BlockLightUnderStair() {
|
||||
super(Material.wood);
|
||||
}
|
||||
|
||||
public static void register() {
|
||||
final var testBlock = new BlockLightUnderStair();
|
||||
testBlock.setBlockName("light_under_stair");
|
||||
GameRegistry.registerBlock(testBlock, "light_under_stair");
|
||||
|
||||
BlockPropertyRegistry.registerBlockItemProperty(testBlock, testBlock.FACING_PROP, ForgeDirection.EAST);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOpaqueCube() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBlockPlacedBy(World worldIn, int x, int y, int z, EntityLivingBase placer, ItemStack itemIn) {
|
||||
var dir = DirectionUtil.yawToDirection(placer.rotationYaw);
|
||||
|
||||
worldIn.setBlockMetadataWithNotify(x, y, z, FACING_PROP.getMeta(dir, 0), 2);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"variants": {
|
||||
"facing=north": { "model": "gtnhlib:blocks/light_test_stairs", "y": 270, "uvlock": true },
|
||||
"facing=south": { "model": "gtnhlib:blocks/light_test_stairs", "y": 90, "uvlock": true },
|
||||
"facing=west": { "model": "gtnhlib:blocks/light_test_stairs", "y": 0, "uvlock": true },
|
||||
"facing=east": { "model": "gtnhlib:blocks/light_test_stairs", "y": 180, "uvlock": true }
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
# Test block names
|
||||
tile.light_under_stair.name=Directional Shading Test Block
|
||||
tile.model_test.name=Test Block
|
||||
tile.model_test_tint.name=Test Block (Tint)
|
||||
tile.model_test_tint_mul.name=Test Block (Tint Mul)
|
||||
@@ -295,3 +296,7 @@ commands.title.show.title.single=Showed title to %s
|
||||
commands.title.show.subtitle.single=Showed subtitle to %s
|
||||
commands.title.times.single=Changed title display times for %s
|
||||
commands.title.icon.single=Changed title icon for %s
|
||||
|
||||
# Brigadier command errors
|
||||
gtnhlib.chat.command.incomplete=Incomplete command
|
||||
gtnhlib.chat.command.more_usages=... and %s more
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"parent": "gtnhlib:blocks/light_under_stair",
|
||||
"textures": {
|
||||
"bottom": "minecraft:planks_oak",
|
||||
"side": "minecraft:planks_oak",
|
||||
"top": "minecraft:planks_oak"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"parent": "block/block",
|
||||
"display": {
|
||||
"gui": {
|
||||
"rotation": [ 30, 135, 0 ],
|
||||
"translation": [ 0, 0, 0],
|
||||
"scale":[ 0.625, 0.625, 0.625 ]
|
||||
},
|
||||
"head": {
|
||||
"rotation": [ 0, -90, 0 ],
|
||||
"translation": [ 0, 0, 0 ],
|
||||
"scale": [ 1, 1, 1 ]
|
||||
},
|
||||
"thirdperson_lefthand": {
|
||||
"rotation": [ 75, -135, 0 ],
|
||||
"translation": [ 0, 2.5, 0],
|
||||
"scale": [ 0.375, 0.375, 0.375 ]
|
||||
}
|
||||
},
|
||||
"textures": {
|
||||
"particle": "#side"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"from": [ 0, 0, 0 ],
|
||||
"to": [ 16, 8, 16 ],
|
||||
"faces": {
|
||||
"down": { "uv": [ 0, 0, 16, 16 ], "texture": "#bottom", "cullface": "down" },
|
||||
"up": { "uv": [ 0, 0, 16, 16 ], "texture": "#top" },
|
||||
"north": { "uv": [ 0, 8, 16, 16 ], "texture": "#side", "cullface": "north" },
|
||||
"south": { "uv": [ 0, 8, 16, 16 ], "texture": "#side", "cullface": "south" },
|
||||
"west": { "uv": [ 0, 8, 16, 16 ], "texture": "#side", "cullface": "west" },
|
||||
"east": { "uv": [ 0, 8, 16, 16 ], "texture": "#side", "cullface": "east" }
|
||||
},
|
||||
"shade": false
|
||||
},
|
||||
{
|
||||
"from": [ 8, 8, 0 ],
|
||||
"to": [ 16, 16, 16 ],
|
||||
"faces": {
|
||||
"up": { "uv": [ 8, 0, 16, 16 ], "texture": "#top", "cullface": "up" },
|
||||
"north": { "uv": [ 0, 0, 8, 8 ], "texture": "#side", "cullface": "north" },
|
||||
"south": { "uv": [ 8, 0, 16, 8 ], "texture": "#side", "cullface": "south" },
|
||||
"west": { "uv": [ 0, 0, 16, 8 ], "texture": "#side" },
|
||||
"east": { "uv": [ 0, 0, 16, 8 ], "texture": "#side", "cullface": "east" }
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in new issue
Block a user