How to trick a daylight sensor

Discussion in 'Spigot Plugin Development' started by Justin393, Sep 6, 2018.

  1. Is there a way to trick a daylight sensor into thinking that it is a different time of day than it really is? I wrote a plugin that creates TimeZones (I run a server with a custom Earth map, so it makes sense) the way the plugin works is by using WorldGuard regions with custom flags such as UTC+10, etc to detect what timezone a player is in. When a player moves between regions my plugin tracks what timezone they're in and updates the player time accordingly.

    Server time is reflected at UTC+0 and if a player is in UTC+1 I add an hour to their client time, etc. This works perfectly fine except for 2 cases so far. Mobs will spawn when the server time is night, but for a player in a different timezone it would appear to be the middle of the day. I have an idea on how to fix this and that is not why I'm asking for help.

    The issue that is stumping me is Daylight sensors. How can I trick a daylight sensor into thinking it is day when a player's client time is day, but the server says it is night?
     
  2. MiniDigger

    Supporter

    mmmh. I think I would use the redstone events and just fake the output.
     
  3. I think packets would be your friend, here. Modify the BlockState per-player? But that might get messy...
     
  4. The issue described is server side, not client side. So packets are not the answer.
     
  5. Working with clientside time has no implications of it being a server issue. The server doesn't care about what time the client is on, only what time the server itself is on. There's no way to run certain things based on a client's time. Hence, packets, because you need to display certain things per player in their respective time.
     
  6. Redstone events for what exactly? Let's say the player's client time shows 9:00pm, but the server says it's 3:00pm. No event would be fired from the daylight sensor detecting a different time, so how would I detect any redstone change to manipulate it?
     
  7. MiniDigger

    Supporter

    I would need to look at the source, but doesnt the detector output some current if there is some light? It's more than a simple on/off, right?
     
  8. MiniDigger

    Supporter

    You don't need to display stuff based on clients time. You need to change stuff based on location. The client time is based on that location too, so all clients at the same location have the same client time, no need to send them different stuff. Everybody who can view the daylight detector will have the same time.
     
    • Like Like x 1
  9. Ahhh I see. I must've definitely read the post wrong at first lol. Oops
     
  10. Code (Text):
    int i = world.getBrightness(EnumSkyBlock.SKY, blockposition) - world.c();
    Is used to detect the brightness

    World#getBrightness does
    Code (Text):
    this.getChunkAtWorldCoords(blockposition).getBrightness(enumskyblock, blockposition))
    Which gets the 'ChunkSection' of the specific blockposition, does some checks and in the end(in 1.13.1) returns the light level
    but another method exists which lets you(i think?) modify the value returned(Looks like World#a(EnumSkyBlock, BlockPosition, int) in 1.13.1)

    But tbh this is all useless as it'll be overridden when someone updates something in that chunk section.

    I would go into ChunkSection find ChunkSection#a and see where it is used(likely only Chunk), then find where it's used for that Chunk(likely world?) and see where it sets it based on the time after updates. You can do a couple things with this information.
    1. Edit the bytecode after runtime.
    2. See if any events are called AFTER the update and update the value yourself based on your custom time.

    Or just modify the bytecode of BlockDayLightDetector#b
    Also found this LightAPI which is pretty much the same methods I showed above but with methods to ignore NMS imports.

    Also if you edit the light update to check for your worldguard time it'll fix both the spawn issue & daylight detectors. But I doubt this will be easy without using some named mapping(forge/mcp) and especially not easy if you plan to do this with just spigot events. Interesting idea of changing the light level and definitely something I would look into myself sometime in the future when I feel like diving into minecraft
     
    #11 Borlea, Sep 7, 2018
    Last edited: Sep 7, 2018
  11. There would be a red stone event for that, yes. The issue is if the server time is the middle of the night (No light, no event), but client time is middle of the day. Everything would be working as intended, but the player would think their sensor should be working. What I might just do is whenever a player places a detector, log it to a file and every 5 minutes or so, scan the file, check the positions of the detectors and either check the light level do some math to figure out the client time.

    Checking the light level is a very interesting idea, one that I did not think of. I solved the mob spawning issue last night by checking CreatureSpawnEvent for a hostile entity, checking the location to see if it was in a worldguard region, and then doing math to figure out the time in that region and cancelling the event accordingly.