Skip to content

Commit

Permalink
Add create url permissions
Browse files Browse the repository at this point in the history
  • Loading branch information
ustc-zzzz committed Apr 9, 2023
1 parent 2c24b3c commit 554c19a
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 48 deletions.
10 changes: 10 additions & 0 deletions src/main/java/org/teacon/slides/admin/SlidePermission.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
@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;
Expand All @@ -34,6 +35,8 @@ public static void gatherPermNodes(PermissionGatherEvent.Nodes event) {
// FIXME: permission resolving
event.addNodes(INTERACT_PERM = new PermissionNode<>(SlideShow.ID,
"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,
Expand All @@ -47,6 +50,13 @@ public static boolean canInteract(@Nullable CommandSource source) {
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;
Expand Down
59 changes: 37 additions & 22 deletions src/main/java/org/teacon/slides/network/ProjectorUpdatePacket.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.teacon.slides.network;

import com.machinezoo.noexception.optional.OptionalFunction;
import net.minecraft.FieldsAreNonnullByDefault;
import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.core.BlockPos;
Expand Down Expand Up @@ -49,26 +50,28 @@ public final class ProjectorUpdatePacket {
public final float slideOffsetZ;
public final boolean doubleSided;
public final boolean keepAspectRatio;
public final boolean hasCreatePermission;
public final @Nullable ProjectorURL imgUrl;
public final @Nullable Log lastOperationLog;

public ProjectorUpdatePacket(ProjectorBlockEntity entity,
@Nullable ProjectorURL imgUrlFallback,
@Nullable Log lastOpFallback) {
boolean canCreateNewProjectorUrl,
OptionalFunction<UUID, ProjectorURL> uuidToUrl) {
this.pos = entity.getBlockPos();
this.imgId = entity.getImageLocation();
var imgUrlOptional = Optional.<ProjectorURL>empty();
var lastOpOptional = Optional.<Log>empty();
if (entity.getLevel() instanceof ServerLevel serverLevel) {
var data = ProjectorURLSavedData.get(serverLevel);
var globalPos = GlobalPos.of(serverLevel.dimension(), this.pos);
imgUrlOptional = data.getUrlById(this.imgId);
lastOpOptional = imgUrlOptional.flatMap(u -> data
.getLatestLog(u, globalPos, Set.of(LogType.BLOCK, LogType.UNBLOCK))
.or(() -> data.getLatestLog(u, globalPos, Set.of(LogType.values()))));
}
var imgLocation = entity.getImageLocation();
var dimension = entity.getDimension();
var slideOffset = entity.getSlideOffset();
var imgUrlOptional = uuidToUrl.apply(imgLocation);
var lastOperationOptional = imgUrlOptional.flatMap(uuid -> {
if (entity.getLevel() instanceof ServerLevel serverLevel) {
var data = ProjectorURLSavedData.get(serverLevel);
var globalPos = GlobalPos.of(serverLevel.dimension(), this.pos);
return data.getLatestLog(uuid, globalPos, Set.of(LogType.BLOCK, LogType.UNBLOCK))
.or(() -> data.getLatestLog(uuid, globalPos, Set.of(LogType.values())));
}
return Optional.empty();
});
this.imgId = imgLocation;
this.rotation = entity.getBlockState().getValue(ProjectorBlock.ROTATION);
this.color = entity.getColorARGB();
this.dimensionX = dimension.x();
Expand All @@ -78,8 +81,9 @@ public ProjectorUpdatePacket(ProjectorBlockEntity entity,
this.slideOffsetZ = slideOffset.z();
this.doubleSided = entity.getDoubleSided();
this.keepAspectRatio = entity.getKeepAspectRatio();
this.imgUrl = imgUrlOptional.orElse(imgUrlFallback);
this.lastOperationLog = lastOpOptional.orElse(lastOpFallback);
this.hasCreatePermission = canCreateNewProjectorUrl;
this.imgUrl = imgUrlOptional.orElse(null);
this.lastOperationLog = lastOperationOptional.orElse(null);
}

public ProjectorUpdatePacket(FriendlyByteBuf buf) {
Expand All @@ -94,6 +98,7 @@ public ProjectorUpdatePacket(FriendlyByteBuf buf) {
this.slideOffsetZ = buf.readFloat();
this.doubleSided = buf.readBoolean();
this.keepAspectRatio = buf.readBoolean();
this.hasCreatePermission = buf.readBoolean();
this.imgUrl = Optional.of(buf.readUtf()).filter(s -> !s.isEmpty()).map(ProjectorURL::new).orElse(null);
this.lastOperationLog = Optional.ofNullable(buf.readNbt()).map(c -> Log.readTag(c).getValue()).orElse(null);
}
Expand All @@ -102,7 +107,7 @@ public void write(FriendlyByteBuf buf) {
buf.writeBlockPos(this.pos).writeUUID(this.imgId);
buf.writeEnum(this.rotation).writeInt(this.color).writeFloat(this.dimensionX).writeFloat(this.dimensionY);
buf.writeFloat(this.slideOffsetX).writeFloat(this.slideOffsetY).writeFloat(this.slideOffsetZ);
buf.writeBoolean(this.doubleSided).writeBoolean(this.keepAspectRatio);
buf.writeBoolean(this.doubleSided).writeBoolean(this.keepAspectRatio).writeBoolean(this.hasCreatePermission);
buf.writeUtf(this.imgUrl == null ? "" : this.imgUrl.toUrl().toString());
buf.writeNbt(this.lastOperationLog == null ? null : this.lastOperationLog.writeTag());
}
Expand All @@ -121,14 +126,24 @@ public void handle(Supplier<NetworkEvent.Context> context) {
// prevent remote chunk loading
if (level.isLoaded(this.pos) && level.getBlockEntity(this.pos) instanceof ProjectorBlockEntity tile) {
// update image locations
var data = ProjectorURLSavedData.get(level);
var oldId = tile.getImageLocation();
var newId = UUID.randomUUID();
if (this.imgUrl != null) {
newId = data.getOrCreateIdByProjector(this.imgUrl, player, globalPos);
var data = ProjectorURLSavedData.get(level);
var newId = data.getUrlById(this.imgId).map(u -> this.imgId).orElseGet(() -> {
if (this.imgUrl != null) {
if (this.hasCreatePermission) {
return data.getOrCreateIdByProjector(this.imgUrl, player, globalPos);
}
var imgId = data.getIdByUrl(this.imgUrl);
if (imgId.isPresent()) {
return imgId.orElseThrow();
}
}
return UUID.randomUUID();
});
if (!newId.equals(oldId)) {
tile.setImageLocation(newId);
data.applyIdChangeByProjector(oldId, newId, player, globalPos);
}
tile.setImageLocation(newId);
data.applyIdChangeByProjector(oldId, newId, player, globalPos);
// update color and dimension
tile.setColorARGB(this.color);
tile.setDimension(new Vector2f(this.dimensionX, this.dimensionY));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import net.minecraft.network.chat.Component;
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.MenuProvider;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
Expand All @@ -26,10 +27,13 @@
import net.minecraftforge.fml.DistExecutor;
import org.joml.*;
import org.teacon.slides.ModRegistries;
import org.teacon.slides.admin.SlidePermission;
import org.teacon.slides.network.ProjectorUpdatePacket;
import org.teacon.slides.renderer.SlideState;
import org.teacon.slides.url.ProjectorURL;
import org.teacon.slides.url.ProjectorURLSavedData;

import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.List;
import java.util.Optional;
Expand Down Expand Up @@ -189,8 +193,16 @@ public CompoundTag getUpdateTag() {
}

@Override
public AbstractContainerMenu createMenu(int containerId, Inventory inventory, Player player) {
return new ProjectorContainerMenu(containerId, this);
public @Nullable AbstractContainerMenu createMenu(int id, Inventory inventory, Player currentPlayer) {
if (currentPlayer instanceof ServerPlayer player) {
var canInteract = SlidePermission.canInteract(player);
if (canInteract) {
var data = ProjectorURLSavedData.get(player.getLevel());
var canCreate = SlidePermission.canInteractCreateUrl(currentPlayer);
return new ProjectorContainerMenu(id, new ProjectorUpdatePacket(this, canCreate, data::getUrlById));
}
}
return null;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import org.teacon.slides.ModRegistries;
import org.teacon.slides.admin.SlidePermission;
import org.teacon.slides.network.ProjectorUpdatePacket;
import org.teacon.slides.url.ProjectorURLSavedData;

import javax.annotation.ParametersAreNonnullByDefault;

Expand All @@ -23,18 +24,21 @@
public final class ProjectorContainerMenu extends AbstractContainerMenu {
public final ProjectorUpdatePacket updatePacket;

public ProjectorContainerMenu(int containerId, ProjectorBlockEntity entity) {
public ProjectorContainerMenu(int containerId, ProjectorUpdatePacket updatePacket) {
super(ModRegistries.MENU.get(), containerId);
this.updatePacket = new ProjectorUpdatePacket(entity, null, null);
this.updatePacket = updatePacket;
}

public ProjectorContainerMenu(int containerId, Inventory inventory, FriendlyByteBuf buf) {
super(ModRegistries.MENU.get(), containerId);
this.updatePacket = new ProjectorUpdatePacket(buf);
}

public static void openGui(Player player, ProjectorBlockEntity tile) {
NetworkHooks.openScreen(((ServerPlayer) player), tile, new ProjectorUpdatePacket(tile, null, null)::write);
public static void openGui(Player currentPlayer, ProjectorBlockEntity tile) {
var player = (ServerPlayer) currentPlayer;
var data = ProjectorURLSavedData.get(player.getLevel());
var canCreate = SlidePermission.canInteractCreateUrl(currentPlayer);
NetworkHooks.openScreen(player, tile, new ProjectorUpdatePacket(tile, canCreate, data::getUrlById)::write);
}

public static MenuType<?> create() {
Expand Down
61 changes: 41 additions & 20 deletions src/main/java/org/teacon/slides/screen/ProjectorScreen.java
Original file line number Diff line number Diff line change
Expand Up @@ -85,21 +85,24 @@ public final class ProjectorScreen extends AbstractContainerScreen<ProjectorCont

private final ProjectorUpdatePacket mUpdatePacket;

private @Nullable ProjectorURL mURL;
private @Nullable ProjectorURL mImgUrl;
private int mImageColor = 0xFFFFFFFF;
private Vector2f mImageSize = new Vector2f(1, 1);
private Vector3f mImageOffset = new Vector3f(0, 0, 0);

private boolean mImgBlocked;
// initialized after construction

private boolean mDoubleSided;
private boolean mKeepAspectRatio;
private SyncAspectRatio mSyncAspectRatio;
private ProjectorBlock.InternalRotation mRotation;

private boolean mInvalidURL = true;
// refreshed after initialization

private boolean mInvalidColor = true;
private boolean mInvalidWidth = true, mInvalidHeight = true;
private boolean mInvalidOffsetX = true, mInvalidOffsetY = true, mInvalidOffsetZ = true;
private ImageUrlStatus mImageUrlStatus = ImageUrlStatus.NO_CONTENT;

public ProjectorScreen(ProjectorContainerMenu menu, Inventory inventory, Component title) {
super(menu, inventory, title);
Expand All @@ -112,22 +115,30 @@ public ProjectorScreen(ProjectorContainerMenu menu, Inventory inventory, Compone
mDoubleSided = packet.doubleSided;
mKeepAspectRatio = packet.keepAspectRatio;
mSyncAspectRatio = packet.keepAspectRatio ? SyncAspectRatio.SYNC_WIDTH_WITH_HEIGHT : SyncAspectRatio.SYNCED;
mImgBlocked = Optional.ofNullable(packet.imgUrl).filter(u -> SlideState.getImgBlocked(u, false)).isPresent();
// url input
mURLInput = LazyWidget.of(toImageUrl(mUpdatePacket.imgUrl), EditBox::getValue, value -> {
var input = new EditBox(font, leftPos + 30, topPos + 29, 136, 16, URL_TEXT);
input.setMaxLength(URL_MAX_LENGTH);
input.setResponder(text -> {
try {
mURL = new ProjectorURL(text);
mInvalidURL = false;
mImgBlocked = SlideState.getImgBlocked(mURL, false);
mImgUrl = new ProjectorURL(text);
if (mUpdatePacket.hasCreatePermission) {
var blocked = SlideState.getImgBlocked(mImgUrl, false);
mImageUrlStatus = blocked ? ImageUrlStatus.BLOCKED : ImageUrlStatus.NORMAL;
} else {
var invalid = SlideState.getImgBlocked(mImgUrl, true);
mImageUrlStatus = invalid ? ImageUrlStatus.INVALID : ImageUrlStatus.NORMAL;
}
} catch (IllegalArgumentException e) {
mURL = null;
mInvalidURL = StringUtils.isNotBlank(text);
mImgBlocked = false;
mImgUrl = null;
mImageUrlStatus = StringUtils.isNotBlank(text) ? ImageUrlStatus.INVALID : ImageUrlStatus.NO_CONTENT;
}
input.setTextColor(mInvalidURL ? 0xE04B4B : mImgBlocked ? 0xE0E04B : 0xE0E0E0);
input.setTextColor(switch (mImageUrlStatus) {
case NORMAL -> 0xE0E0E0;
case BLOCKED -> 0xE0E04B;
case INVALID -> 0xE04B4B;
case NO_CONTENT -> 0x4B4B4B;
});
});
input.setValue(value);
return input;
Expand Down Expand Up @@ -364,26 +375,32 @@ public void removed() {
var tilePos = mUpdatePacket.pos;
var level = Objects.requireNonNull(minecraft).level;
if (level != null && level.getBlockEntity(tilePos) instanceof ProjectorBlockEntity tile) {
var invalidSize = mInvalidWidth || mInvalidHeight;
var invalidOffset = mInvalidOffsetX || mInvalidOffsetY || mInvalidOffsetZ;
if (!mInvalidURL && !Objects.equals(mURL, mUpdatePacket.imgUrl)) {
var urlFallback = (ProjectorURL) null;
var urlRemoved = mImageUrlStatus == ImageUrlStatus.NO_CONTENT && mUpdatePacket.imgUrl != null;
var urlChanged = mImageUrlStatus == ImageUrlStatus.NORMAL && !Objects.equals(mImgUrl, mUpdatePacket.imgUrl);
if (urlRemoved || urlChanged) {
// apply random uuid and wait for server updates
urlFallback = urlRemoved ? null : mImgUrl;
tile.setImageLocation(UUID.randomUUID());
}
if (!mInvalidColor) {
var validColor = !mInvalidColor;
if (validColor) {
tile.setColorARGB(mImageColor);
}
if (!invalidSize) {
var validSize = !mInvalidWidth && !mInvalidHeight;
if (validSize) {
tile.setDimension(mImageSize);
}
if (!invalidOffset) {
var validOffset = !mInvalidOffsetX && !mInvalidOffsetY && !mInvalidOffsetZ;
if (validOffset) {
tile.setSlideOffset(mImageOffset);
}
var state = tile.getBlockState().setValue(ProjectorBlock.ROTATION, mRotation);
level.setBlock(tilePos, state, Block.UPDATE_NONE);
tile.setDoubleSided(mDoubleSided);
tile.setKeepAspectRatio(mKeepAspectRatio);
new ProjectorUpdatePacket(tile, mURL, null).sendToServer();
var urlFallbackOptional = Optional.ofNullable(urlFallback);
new ProjectorUpdatePacket(tile, mUpdatePacket.hasCreatePermission, u -> urlFallbackOptional).sendToServer();
}
}

Expand Down Expand Up @@ -435,7 +452,7 @@ protected void renderBg(PoseStack stack, float partialTicks, int mouseX, int mou
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
RenderSystem.setShaderTexture(0, GUI_TEXTURE);
blit(stack, leftPos, topPos, 0, 0, imageWidth, imageHeight);
if (mImgBlocked) {
if (mImageUrlStatus == ImageUrlStatus.INVALID || mImageUrlStatus == ImageUrlStatus.BLOCKED) {
blit(stack, leftPos + 9, topPos + 27, 179, 53, 18, 19);
}
}
Expand Down Expand Up @@ -489,7 +506,7 @@ private void syncAspectRatioTick() {
if (!mURLInput.get().isFocused()) {
if (mSyncAspectRatio != SyncAspectRatio.SYNCED && !mInvalidWidth && !mInvalidHeight) {
var slide = SlideState.getSlide(mUpdatePacket.imgId);
var aspect = slide.getImageAspectRatio();
var aspect = slide == null ? Float.NaN : slide.getImageAspectRatio();
if (!Float.isNaN(aspect)) {
if (mSyncAspectRatio == SyncAspectRatio.SYNC_WIDTH_WITH_HEIGHT) {
var newSizeByHeight = new Vector2f(mImageSize.y * aspect, mImageSize.y);
Expand Down Expand Up @@ -627,6 +644,10 @@ protected void updateWidgetNarration(NarrationElementOutput output) {
}
}

private enum ImageUrlStatus {
NORMAL, BLOCKED, INVALID, NO_CONTENT
}

private enum SyncAspectRatio {
SYNCED, SYNC_WIDTH_WITH_HEIGHT, SYNC_HEIGHT_WITH_WIDTH
}
Expand Down

0 comments on commit 554c19a

Please sign in to comment.