Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Basic NFC Modem functionality for Pocket Computer #1689

Open
wants to merge 6 commits into
base: mc-1.20.x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;

Expand Down Expand Up @@ -161,6 +162,17 @@ public static PacketNetwork getWirelessNetwork(MinecraftServer server) {
return getInstance().getWirelessNetwork(server);
}

/**
* Attempt to get the NFC network for a player.
*
* @param server The current Minecraft server.
* @param entity The entity whose NFC network should be obtained.
* @return The NFC network, or {@code null} if it could not be fetched.
*/
public static PacketNetwork getNfcNetwork(MinecraftServer server, Entity entity) {
return getInstance().getNfcNetwork(server, entity);
}

/**
* Register a custom {@link ILuaAPI}, which may be added onto all computers without requiring a peripheral.
* <p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,19 @@ public interface PacketNetwork {
* @see PacketReceiver#receiveDifferentDimension(Packet)
*/
void transmitInterdimensional(Packet packet);

static void tryTransmit(PacketReceiver receiver, Packet packet, double range, boolean interdimensional) {
var sender = packet.sender();
if (receiver.getLevel() == sender.getLevel()) {
var receiveRange = Math.max(range, receiver.getRange()); // Ensure range is symmetrical
var distanceSq = receiver.getPosition().distanceToSqr(sender.getPosition());
if (interdimensional || receiver.isInterdimensional() || distanceSq <= receiveRange * receiveRange) {
receiver.receiveSameDimension(packet, Math.sqrt(distanceSq));
}
} else {
if (interdimensional || receiver.isInterdimensional()) {
receiver.receiveDifferentDimension(packet);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,22 +47,40 @@ public interface IPocketAccess {
void setColour(int colour);

/**
* Get the colour of this pocket computer's light as a RGB number.
* Get the primary colour of this pocket computer's light as a RGB number.
*
* @return The colour this light is. This will be a RGB colour between {@code 0x000000} and {@code 0xFFFFFF} or
* @return The primary colour this light is. This will be a RGB colour between {@code 0x000000} and {@code 0xFFFFFF} or
* -1 if it has no colour.
* @see #setLight(int)
* @see #setLightPrimary(int)
*/
int getLight();
int getLightPrimary();

/**
* Set the colour of the pocket computer's light to a RGB number.
* Set the primary colour of the pocket computer's light to a RGB number.
*
* @param colour The colour this modem's light will be changed to. This should be a RGB colour between
* @param colour The primary colour this modem's light will be changed to. This should be a RGB colour between
* {@code 0x000000} and {@code 0xFFFFFF} or -1 to reset to the default colour.
* @see #getLight()
* @see #getLightPrimary()
*/
void setLight(int colour);
void setLightPrimary(int colour);

/**
* Get the secondary colour of this pocket computer's light as a RGB number.
*
* @return The secondary colour this light is. This will be a RGB colour between {@code 0x000000} and {@code 0xFFFFFF} or
* -1 if it has no colour.
* @see #setLightSecondary(int)
*/
int getLightSecondary();

/**
* Set the secondary colour of the pocket computer's light to a RGB number.
*
* @param colour The secondary colour this modem's light will be changed to. This should be a RGB colour between
* {@code 0x000000} and {@code 0xFFFFFF} or -1 to reset to the default colour.
* @see #getLightSecondary()
*/
void setLightSecondary(int colour);

/**
* Get the upgrade-specific NBT.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import org.jetbrains.annotations.ApiStatus;
Expand Down Expand Up @@ -61,6 +62,8 @@ static ComputerCraftAPIService get() {

PacketNetwork getWirelessNetwork(MinecraftServer server);

PacketNetwork getNfcNetwork(MinecraftServer server, Entity entity);

void registerAPIFactory(ILuaAPIFactory factory);

WiredNode createWiredNodeForElement(WiredElement element);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ public static long getRenderFrame() {
return renderFrame;
}

public static int getTick() {
return tick;
}

public static void onTick() {
tick++;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,9 @@ public void handlePlayRecord(BlockPos pos, @Nullable SoundEvent sound, @Nullable
}

@Override
public void handlePocketComputerData(int instanceId, ComputerState state, int lightState, TerminalState terminal) {
public void handlePocketComputerData(int instanceId, ComputerState state, int primaryLightState, int secondaryLightState, TerminalState terminal) {
var computer = ClientPocketComputers.get(instanceId, terminal.colour);
computer.setState(state, lightState);
computer.setState(state, primaryLightState, secondaryLightState);
if (terminal.hasTerminal()) computer.setTerminal(terminal);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

package dan200.computercraft.client.pocket;

import dan200.computercraft.client.FrameInfo;
import dan200.computercraft.core.terminal.Terminal;
import dan200.computercraft.shared.computer.core.ComputerState;
import dan200.computercraft.shared.computer.terminal.NetworkedTerminal;
Expand All @@ -24,14 +25,42 @@
public class PocketComputerData {
private final NetworkedTerminal terminal;
private ComputerState state = ComputerState.OFF;
private int lightColour = -1;
private int primaryLightColour = -1;
private int secondaryLightColour = -1;

public PocketComputerData(boolean colour) {
terminal = new NetworkedTerminal(Config.pocketTermWidth, Config.pocketTermHeight, colour);
}

public int getLightState() {
return state != ComputerState.OFF ? lightColour : -1;
if (state != ComputerState.OFF) {
if (secondaryLightColour == -1) {
return primaryLightColour;
} else if (primaryLightColour == -1) {
return secondaryLightColour;
} else {
double weight = (Math.sin(((double)(FrameInfo.getTick() % 41) / 40) * Math.PI * 2) + 1) / 2;
return blend(primaryLightColour, secondaryLightColour, weight);
}
}
return -1;
}

private static int blend(int a, int b, double weight) {
int[][] rgb = {
{ a >> 16, b >> 16 },
{ (a & 0x00ff00) >> 8, (b & 0x00ff00) >> 8 },
{ a & 0x0000ff, b & 0x0000ff },
};
int[] channels = new int[3];
for (int i = 0; i < 3; i++) {
channels[i] = (int)Math.sqrt(Math.pow(rgb[i][0], 2) * weight + Math.pow(rgb[i][1], 2) * (1 - weight));
}
int color = 0;
for (int channel : channels) {
color = (color << 8) + channel;
}
return color;
}

public Terminal getTerminal() {
Expand All @@ -42,9 +71,10 @@ public ComputerState getState() {
return state;
}

public void setState(ComputerState state, int lightColour) {
public void setState(ComputerState state, int primaryLightColour, int secondaryLightColor) {
this.state = state;
this.lightColour = lightColour;
this.primaryLightColour = primaryLightColour;
this.secondaryLightColour = secondaryLightColor;
}

public void setTerminal(TerminalState state) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;

Expand Down Expand Up @@ -100,6 +101,11 @@ public final PacketNetwork getWirelessNetwork(MinecraftServer server) {
return ServerContext.get(server).wirelessNetwork();
}

@Override
public final PacketNetwork getNfcNetwork(MinecraftServer server, Entity entity) {
return ServerContext.get(server).nfcNetwork(entity);
}

@Override
public final void registerAPIFactory(ILuaAPIFactory factory) {
ApiFactories.register(factory);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,12 @@
import dan200.computercraft.shared.CommonHooks;
import dan200.computercraft.shared.computer.metrics.GlobalMetrics;
import dan200.computercraft.shared.config.ConfigSpec;
import dan200.computercraft.shared.peripheral.modem.wireless.NFCNetworkManager;
import dan200.computercraft.shared.peripheral.modem.wireless.WirelessNetwork;
import dan200.computercraft.shared.util.IDAssigner;
import net.minecraft.SharedConstants;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.storage.LevelResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -64,6 +66,7 @@ public final class ServerContext {
private final MainThread mainThread;
private final IDAssigner idAssigner;
private final WirelessNetwork wirelessNetwork = new WirelessNetwork();
private final NFCNetworkManager nfcNetworkManager = new NFCNetworkManager();
private final Path storageDir;

private ServerContext(MinecraftServer server) {
Expand Down Expand Up @@ -209,6 +212,18 @@ public PacketNetwork wirelessNetwork() {
return wirelessNetwork;
}

/**
* Get a player's NFC network.
* <p>
* Use {@link ComputerCraftAPI#getNfcNetwork(MinecraftServer, Entity)} instead of this method.
* @param entity The entity whose NFC network should be obtained.
* @return The NFC network.
*/
public PacketNetwork nfcNetwork(Entity entity) {
PacketNetwork network = nfcNetworkManager.get(entity);
return network == null ? nfcNetworkManager.addNetwork(entity) : network;
}

private record Environment(MinecraftServer server) implements GlobalEnvironment {
@Override
public @Nullable Mount createResourceMount(String domain, String subPath) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public interface ClientNetworkContext {

void handlePlayRecord(BlockPos pos, @Nullable SoundEvent sound, @Nullable String name);

void handlePocketComputerData(int instanceId, ComputerState state, int lightState, TerminalState terminal);
void handlePocketComputerData(int instanceId, ComputerState state, int primaryLightColor, int secondaryLightColor, TerminalState terminal);

void handlePocketComputerDeleted(int instanceId);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,34 +19,38 @@
public class PocketComputerDataMessage implements NetworkMessage<ClientNetworkContext> {
private final int instanceId;
private final ComputerState state;
private final int lightState;
private final int primaryLightState;
private final int secondaryLightState;
private final TerminalState terminal;

public PocketComputerDataMessage(PocketServerComputer computer, boolean sendTerminal) {
instanceId = computer.getInstanceID();
state = computer.getState();
lightState = computer.getLight();
primaryLightState = computer.getLightPrimary();
secondaryLightState = computer.getLightSecondary();
terminal = sendTerminal ? computer.getTerminalState() : new TerminalState((NetworkedTerminal) null);
}

public PocketComputerDataMessage(FriendlyByteBuf buf) {
instanceId = buf.readVarInt();
state = buf.readEnum(ComputerState.class);
lightState = buf.readVarInt();
primaryLightState = buf.readVarInt();
secondaryLightState = buf.readVarInt();
terminal = new TerminalState(buf);
}

@Override
public void write(FriendlyByteBuf buf) {
buf.writeVarInt(instanceId);
buf.writeEnum(state);
buf.writeVarInt(lightState);
buf.writeVarInt(primaryLightState);
buf.writeVarInt(secondaryLightState);
terminal.write(buf);
}

@Override
public void handle(ClientNetworkContext context) {
context.handlePocketComputerData(instanceId, state, lightState, terminal);
context.handlePocketComputerData(instanceId, state, primaryLightState, secondaryLightState, terminal);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// SPDX-FileCopyrightText: 2017 The CC: Tweaked Developers
//
// SPDX-License-Identifier: MPL-2.0

package dan200.computercraft.shared.peripheral.modem.wireless;

import net.minecraft.world.entity.Entity;

import javax.annotation.Nullable;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class NFCNetworkManager {
private final Map<Entity, WirelessNetwork> networks = new ConcurrentHashMap<>();

public WirelessNetwork addNetwork(Entity entity) {
if (!networks.containsKey(entity)) {
networks.put(entity, new WirelessNetwork(() -> networks.remove(entity)));
}
return networks.get(entity);
}

public void removeNetwork(Entity entity) {
networks.remove(entity);
}

public @Nullable WirelessNetwork get(Entity entity) {
return networks.get(entity);
}
}
Loading
Loading