Skip to content

Commit

Permalink
Merge pull request #31 from teaconmc/feature/report-and-ban
Browse files Browse the repository at this point in the history
Report & Ban Update
  • Loading branch information
ustc-zzzz committed Apr 9, 2023
2 parents 7785834 + 554c19a commit 0bebd1d
Show file tree
Hide file tree
Showing 13 changed files with 441 additions and 140 deletions.
7 changes: 7 additions & 0 deletions src/main/java/org/teacon/slides/ModRegistries.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import net.minecraftforge.registries.RegistryObject;
import org.teacon.slides.network.ProjectorURLPrefetchPacket;
import org.teacon.slides.network.ProjectorURLRequestPacket;
import org.teacon.slides.network.ProjectorURLSummaryPacket;
import org.teacon.slides.network.ProjectorUpdatePacket;
import org.teacon.slides.url.ProjectorURLArgument;
import org.teacon.slides.projector.*;
Expand Down Expand Up @@ -90,6 +91,12 @@ public static void setupCommon(final FMLCommonSetupEvent event) {
ProjectorURLRequestPacket::new,
ProjectorURLRequestPacket::handle,
Optional.of(NetworkDirection.PLAY_TO_SERVER));
CHANNEL.registerMessage(index++,
ProjectorURLSummaryPacket.class,
ProjectorURLSummaryPacket::write,
ProjectorURLSummaryPacket::new,
ProjectorURLSummaryPacket::handle,
Optional.of(NetworkDirection.PLAY_TO_CLIENT));
SlideShow.LOGGER.info("Registered {} network packages (version {})", index, NETWORK_VERSION);
}
}
53 changes: 31 additions & 22 deletions src/main/java/org/teacon/slides/admin/SlideCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.exceptions.DynamicCommandExceptionType;
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
import com.mojang.datafixers.util.Either;
import net.minecraft.ChatFormatting;
import net.minecraft.FieldsAreNonnullByDefault;
Expand Down Expand Up @@ -39,6 +40,8 @@
public class SlideCommand {
private static final DynamicCommandExceptionType URL_NOT_EXIST = new DynamicCommandExceptionType(v -> Component.translatable("command.slide_show.failed.url_not_exist", v));

private static final SimpleCommandExceptionType PERM_NOT_EXIST = new SimpleCommandExceptionType(Component.translatable("command.slide_show.failed.perm_not_exist").withStyle(ChatFormatting.RED));

@SubscribeEvent
public static void onCommandsRegister(RegisterCommandsEvent event) {
var node = event.getDispatcher().register(command(SlideShow.ID.replace('_', '-')));
Expand Down Expand Up @@ -74,35 +77,41 @@ private static int prefetchProjectorUrl(CommandContext<CommandSourceStack> ctx)
}

private static int blockByProjectorUrl(CommandContext<CommandSourceStack> ctx) throws CommandSyntaxException {
var data = ProjectorURLSavedData.get(ctx.getSource().getLevel());
var arg = ProjectorURLArgument.getUrl(ctx, "url");
var pairOptional = toPairOpt(data, arg);
if (pairOptional.isPresent()) {
var pair = pairOptional.get();
var text = toText(pair.getKey(), pair.getValue());
if (data.setBlockedStatusByCommand(pair.getKey(), pair.getValue(), ctx.getSource(), true)) {
var msg = Component.translatable("command.slide_show.block_projector_url.success", text);
ctx.getSource().sendSuccess(msg.withStyle(ChatFormatting.GREEN), true);
return Command.SINGLE_SUCCESS;
if (SlidePermission.canBlockUrl(ctx.getSource().source)) {
var data = ProjectorURLSavedData.get(ctx.getSource().getLevel());
var arg = ProjectorURLArgument.getUrl(ctx, "url");
var pairOptional = toPairOpt(data, arg);
if (pairOptional.isPresent()) {
var pair = pairOptional.get();
var text = toText(pair.getKey(), pair.getValue());
if (data.setBlockedStatusByCommand(pair.getKey(), pair.getValue(), ctx.getSource(), true)) {
var msg = Component.translatable("command.slide_show.block_projector_url.success", text);
ctx.getSource().sendSuccess(msg.withStyle(ChatFormatting.GREEN), true);
return Command.SINGLE_SUCCESS;
}
}
throw URL_NOT_EXIST.create(arg.map(SlideCommand::toText, SlideCommand::toText));
}
throw URL_NOT_EXIST.create(arg.map(SlideCommand::toText, SlideCommand::toText));
throw PERM_NOT_EXIST.create();
}

private static int unblockByProjectorUrl(CommandContext<CommandSourceStack> ctx) throws CommandSyntaxException {
var data = ProjectorURLSavedData.get(ctx.getSource().getLevel());
var arg = ProjectorURLArgument.getUrl(ctx, "url");
var pairOptional = toPairOpt(data, arg);
if (pairOptional.isPresent()) {
var pair = pairOptional.get();
var text = toText(pair.getKey(), pair.getValue());
if (data.setBlockedStatusByCommand(pair.getKey(), pair.getValue(), ctx.getSource(), false)) {
var msg = Component.translatable("command.slide_show.unblock_projector_url.success", text);
ctx.getSource().sendSuccess(msg.withStyle(ChatFormatting.GREEN), true);
return Command.SINGLE_SUCCESS;
if (SlidePermission.canUnblockUrl(ctx.getSource().source)) {
var data = ProjectorURLSavedData.get(ctx.getSource().getLevel());
var arg = ProjectorURLArgument.getUrl(ctx, "url");
var pairOptional = toPairOpt(data, arg);
if (pairOptional.isPresent()) {
var pair = pairOptional.get();
var text = toText(pair.getKey(), pair.getValue());
if (data.setBlockedStatusByCommand(pair.getKey(), pair.getValue(), ctx.getSource(), false)) {
var msg = Component.translatable("command.slide_show.unblock_projector_url.success", text);
ctx.getSource().sendSuccess(msg.withStyle(ChatFormatting.GREEN), true);
return Command.SINGLE_SUCCESS;
}
}
throw URL_NOT_EXIST.create(arg.map(SlideCommand::toText, SlideCommand::toText));
}
throw URL_NOT_EXIST.create(arg.map(SlideCommand::toText, SlideCommand::toText));
throw PERM_NOT_EXIST.create();
}

private static Optional<Map.Entry<UUID, ProjectorURL>> toPairOpt(ProjectorURLSavedData data,
Expand Down
59 changes: 55 additions & 4 deletions src/main/java/org/teacon/slides/admin/SlidePermission.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,86 @@

import net.minecraft.FieldsAreNonnullByDefault;
import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.commands.CommandSource;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.player.Player;
import net.minecraft.server.rcon.RconConsoleSource;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.server.permission.PermissionAPI;
import net.minecraftforge.server.permission.events.PermissionGatherEvent;
import net.minecraftforge.server.permission.nodes.PermissionDynamicContext;
import net.minecraftforge.server.permission.nodes.PermissionNode;
import net.minecraftforge.server.permission.nodes.PermissionTypes;
import org.teacon.slides.SlideShow;

import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.Objects;
import java.util.UUID;

@FieldsAreNonnullByDefault
@MethodsReturnNonnullByDefault
@ParametersAreNonnullByDefault
@Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.FORGE)
public final class SlidePermission {
private static @Nullable PermissionNode<Boolean> INTERACT_CREATE_PERM;
private static @Nullable PermissionNode<Boolean> INTERACT_PERM;
private static @Nullable PermissionNode<Boolean> BLOCK_PERM;
private static @Nullable PermissionNode<Boolean> UNBLOCK_PERM;

@SubscribeEvent
public static void gatherPermNodes(PermissionGatherEvent.Nodes event) {
// FIXME: permission resolving
event.addNodes(INTERACT_PERM = new PermissionNode<>(SlideShow.ID,
"interact.projector", PermissionTypes.BOOLEAN, (player, playerUUID, context) -> true));
"interact.projector", PermissionTypes.BOOLEAN, SlidePermission::everyone));
event.addNodes(INTERACT_CREATE_PERM = new PermissionNode<>(SlideShow.ID,
"interact.projector.create_url", PermissionTypes.BOOLEAN, SlidePermission::everyone));
event.addNodes(BLOCK_PERM = new PermissionNode<>(SlideShow.ID,
"interact_url.block", PermissionTypes.BOOLEAN, SlidePermission::operator));
event.addNodes(UNBLOCK_PERM = new PermissionNode<>(SlideShow.ID,
"interact_url.unblock", PermissionTypes.BOOLEAN, SlidePermission::operator));
}

public static boolean canInteract(Player p) {
return p instanceof ServerPlayer sp && PermissionAPI.getPermission(sp, Objects.requireNonNull(INTERACT_PERM));
public static boolean canInteract(@Nullable CommandSource source) {
if (source instanceof ServerPlayer sp) {
return PermissionAPI.getPermission(sp, Objects.requireNonNull(INTERACT_PERM));
}
return false;
}

public static boolean canInteractCreateUrl(@Nullable CommandSource source) {
if (source instanceof ServerPlayer serverPlayer) {
return PermissionAPI.getPermission(serverPlayer, Objects.requireNonNull(INTERACT_CREATE_PERM));
}
return false;
}

public static boolean canBlockUrl(@Nullable CommandSource source) {
if (source instanceof MinecraftServer || source instanceof RconConsoleSource) {
return true;
}
if (source instanceof ServerPlayer serverPlayer) {
return PermissionAPI.getPermission(serverPlayer, Objects.requireNonNull(BLOCK_PERM));
}
return false;
}

public static boolean canUnblockUrl(@Nullable CommandSource source) {
if (source instanceof MinecraftServer || source instanceof RconConsoleSource) {
return true;
}
if (source instanceof ServerPlayer serverPlayer) {
return PermissionAPI.getPermission(serverPlayer, Objects.requireNonNull(UNBLOCK_PERM));
}
return false;
}

private static boolean everyone(@Nullable ServerPlayer player, UUID uuid, PermissionDynamicContext<?>... context) {
return true;
}

private static boolean operator(@Nullable ServerPlayer player, UUID uuid, PermissionDynamicContext<?>... context) {
return player != null && player.hasPermissions(2);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.server.level.ServerPlayer;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.network.NetworkEvent;
import net.minecraftforge.network.PacketDistributor;
import org.teacon.slides.ModRegistries;
Expand All @@ -14,67 +16,50 @@
import org.teacon.slides.url.ProjectorURLSavedData;

import javax.annotation.ParametersAreNonnullByDefault;
import java.util.Set;
import java.util.UUID;
import java.util.*;
import java.util.function.Supplier;

@FieldsAreNonnullByDefault
@MethodsReturnNonnullByDefault
@ParametersAreNonnullByDefault
public final class ProjectorURLPrefetchPacket {
private final ImmutableSet<UUID> blockedIdSet;

private final ImmutableSet<UUID> nonExistentIdSet;

private final ImmutableMap<UUID, ProjectorURL> unblockedIdMap;
private final ImmutableMap<UUID, ProjectorURL> existentIdMap;

private enum Status {
END, BLOCKED, NON_EXISTENT, UNBLOCKED
END, EXISTENT, NON_EXISTENT
}

public ProjectorURLPrefetchPacket(Set<UUID> idSet, ProjectorURLSavedData data) {
var blockedIdSetBuilder = ImmutableSet.<UUID>builder();
var nonExistentIdSetBuilder = ImmutableSet.<UUID>builder();
var unblockedIdMapBuilder = ImmutableMap.<UUID, ProjectorURL>builder();
var nonExistentBuilder = ImmutableSet.<UUID>builder();
var existentBuilder = ImmutableMap.<UUID, ProjectorURL>builder();
for (var id : idSet) {
var url = data.getUrlById(id);
var isBlocked = data.isUrlBlocked(id);
if (isBlocked) {
blockedIdSetBuilder.add(id);
} else if (url.isEmpty()) {
nonExistentIdSetBuilder.add(id);
} else {
unblockedIdMapBuilder.put(id, url.get());
}
data.getUrlById(id).ifPresentOrElse(u -> existentBuilder.put(id, u), () -> nonExistentBuilder.add(id));
}
this.blockedIdSet = blockedIdSetBuilder.build();
this.nonExistentIdSet = nonExistentIdSetBuilder.build();
this.unblockedIdMap = unblockedIdMapBuilder.build();
this.nonExistentIdSet = nonExistentBuilder.build();
this.existentIdMap = existentBuilder.build();
}

public ProjectorURLPrefetchPacket(FriendlyByteBuf buf) {
var blockedIdSetBuilder = ImmutableSet.<UUID>builder();
var nonExistentIdSetBuilder = ImmutableSet.<UUID>builder();
var unblockedIdMapBuilder = ImmutableMap.<UUID, ProjectorURL>builder();
var nonExistentBuilder = ImmutableSet.<UUID>builder();
var existentBuilder = ImmutableMap.<UUID, ProjectorURL>builder();
while (true) {
switch (buf.readEnum(Status.class)) {
case END -> {
this.blockedIdSet = blockedIdSetBuilder.build();
this.nonExistentIdSet = nonExistentIdSetBuilder.build();
this.unblockedIdMap = unblockedIdMapBuilder.build();
this.nonExistentIdSet = nonExistentBuilder.build();
this.existentIdMap = existentBuilder.build();
return;
}
case BLOCKED -> blockedIdSetBuilder.add(buf.readUUID());
case NON_EXISTENT -> nonExistentIdSetBuilder.add(buf.readUUID());
case UNBLOCKED -> unblockedIdMapBuilder.put(buf.readUUID(), new ProjectorURL(buf.readUtf()));
case NON_EXISTENT -> nonExistentBuilder.add(buf.readUUID());
case EXISTENT -> existentBuilder.put(buf.readUUID(), new ProjectorURL(buf.readUtf()));
}
}
}

public void write(FriendlyByteBuf buf) {
this.blockedIdSet.forEach(uuid -> buf.writeEnum(Status.BLOCKED).writeUUID(uuid));
this.existentIdMap.forEach((uuid, url) -> buf.writeEnum(Status.EXISTENT).writeUUID(uuid).writeUtf(url.toUrl().toString()));
this.nonExistentIdSet.forEach(uuid -> buf.writeEnum(Status.NON_EXISTENT).writeUUID(uuid));
this.unblockedIdMap.forEach((uuid, url) -> buf.writeEnum(Status.UNBLOCKED).writeUUID(uuid).writeUtf(url.toUrl().toString()));
buf.writeEnum(Status.END);
}

Expand All @@ -87,7 +72,10 @@ public void sendToClient(ServerPlayer player) {
}

public void handle(Supplier<NetworkEvent.Context> context) {
context.get().enqueueWork(() -> SlideState.applyPrefetch(this.blockedIdSet, this.nonExistentIdSet, this.unblockedIdMap));
context.get().enqueueWork(() -> {
var applyPrefetch = DistExecutor.safeCallWhenOn(Dist.CLIENT, () -> SlideState::getApplyPrefetch);
Objects.requireNonNull(applyPrefetch).accept(this.nonExistentIdSet, this.existentIdMap);
});
context.get().setPacketHandled(true);
}
}
Loading

0 comments on commit 0bebd1d

Please sign in to comment.