-1

In my server, anyone is free to enter and visit server members' buildings in default adventure mode.

However, there are some areas that we don't want non-member players to enter.

So I want to create an entry prohibited area with the command:

When a non-member player approaches, a particle wall will appear to indicate that the area is inaccessible, and the non-member player will be automatically teleported to the outside when he or she steps into the area.

And for member players, there will be nothing changed.


I have ideas to implementing this feature, but I don't know how to use command blocks or mcfunctions to complete it.

The main problem is "how to make loops, Basic addition / subtraction, and logical judgments, in a commend block or mcfunction". In my sentence, 'loop' means repeatedly running a command with different position parameters each time. For example, the first execution uses coordinates 1 2 3, the second execution uses 1 2 4, and then 1 2 5, and so on, until it met the boundary conditions.

I think this idea might be a little difficult to say it clear, so I have written some TypeScript codes.

////////////////
// Data
////////////////

const prohibited_area = {
  x: {
    from: 0,
    to: 10,
  },
  z: {
    from: 0,
    to: 10,
  }
};
const door_position = [1, 2, 3];
const display_distance = 10;

////////////////
// Existing Feature
////////////////

/**
 * keep unauthorized players out of entry prohibited areas
 * 
 * NOTE: May be teleport them to nearest position outside 
 * will be better then a fixed position infront of door
 */
a_command_block(
  `tp ${positionition_range(
    [prohibited_area.x.from, prohibited_area.x.to],
    [prohibited_area.z.from, prohibited_area.z.to]
  )} ` +
  `${door_position.join(" ")}`,
  {
    blockType: "Repeat",
    condition: false,
    redstone: false,
  }
)

////////////////
// New Feature: Make the edge visible with particles
////////////////

// Detect Players
const player_list = positionition_range(
  [prohibited_area.x.from - display_distance, prohibited_area.x.to + display_distance],
  [prohibited_area.z.from - display_distance, prohibited_area.z.to + display_distance]
) as Array<playerposition>

// Generate Particles for each nearby player
player_list.forEach(player => {
  // Check the player's position
  const left = player.x < prohibited_area.x.from;
  const right = player.x > prohibited_area.x.to;
  const front = player.z < prohibited_area.z.from;
  const back = player.z > prohibited_area.z.to;

  // Generate particles based on player's position
  if (left) generate_particles("z", prohibited_area.x.from, player.y, player.z);
  else if (right) generate_particles("z", prohibited_area.x.to, player.y, player.z);

  if (front) generate_particles("x", player.x, player.y, prohibited_area.z.from);
  if (back) generate_particles("x", player.x, player.y, prohibited_area.z.to);
  // How to "generate_particles" has been written below
})

/**
 * `generate_particles` Display a 5x5x1 vertical square plane, made of barrier particles
 * BTW, how to delete particles or generate them in different sizes?
 */
function generate_particles(side: "x" | "z", centerX: number, centerY: number, centerZ: number) {
  const centerHori = side == "x" ? centerX : centerZ;
  for (let hori = centerHori - 2; hori < centerHori + 2; hori++) {
    if (hori < prohibited_area[side].from || hori > prohibited_area[side].to) continue;
    for (let vert = centerY - 2; vert < centerY + 2; vert++) {
      executeCommand(
        `/particle minecraft:block_marker{block_state:"barrier"}` +
        `${(side == "x" ? hori : centerX) + 0.5} ${vert + 0.5} ${(side == "z" ? hori : centerZ) + 0.5}`
      )
    }
  }
}

////////////////
// Other Definition that can be understood by name without content
////////////////

type TypeOfCommandBlock = "Impulse" | "Chain" | "Repeat";
type playerposition = { x: number, y: number, z: number };
function a_command_block(
  _command: string,
  _option: { blockType: TypeOfCommandBlock, condition: boolean, redstone: boolean } = {
    blockType: "Impulse",
    condition: false,
    redstone: true,
  }) {
  // ...
};
function executeCommand(_command: string) {
  // ...
};
function positionition_range(x: [number, number], z: [number, number]): unknown {
  return `@a[tag=!visitor,` +
    `x=${x[0]},y=-100,z=${z[0]},` +
    `dx=${x[1] - x[0]},dy=450,dz=${z[1] - z[0]}]`
}
7
  • 1
    Hi, please go through the list posted here. We can help with specific obstacles, but can't (won't) write your code for you.
    – Joachim
    Commented Jul 23 at 20:21
  • @Joachim Yeah, I know. So I have provided the exact difficulties I am currently experiencing, that is: "how to make loops, Basic addition / subtraction, and logical judgments, in a commend block or mcfunction" If you think I provided too much additional information, I can modify the question to make it clear. Commented Jul 24 at 4:09
  • @Joachim I have searched a lot, and I find nothing. I believe that my typescript code is the part of "What you've tried so far". BTW, I'm using MC 1.21 Fabric with carpet & tweakeroo. I am currently stuck on how to implement these logic and process controls. Commented Jul 24 at 4:15
  • @Joachim as you said, I'm not excepting someone will write code for me. I'm here asking a cookbook to read. Commented Jul 24 at 4:17
  • 2
    Asking for recommendations on external sources is off-topic here. You're right in a sense that you've provided the "what have you tried" part, but conceptualizing is not really trying, I'm afraid. My point was mostly that it seems you have an extensive idea that you want to translate, but don't have an idea of how to start. We can definitely help with the separate parts, though (once you start translating your concept to MC-readable code and hit a snag).
    – Joachim
    Commented Jul 24 at 8:35

1 Answer 1

2

Thanks to @LostXOR, I have finally implemented it.

This is the script I have done, modifying the data in get-env() can apply it to any location.

I share these codes under MIT license. Feel free to share, edit, or even sell my work. Just don't delete the header comment.

// Ivory Barrier v1.1.0
// Ivor. 2024. MIT License
// https://github.com/minecraftfen/

get_env(key) -> (
  {
    'area' -> {
      'x' -> {
        'from' -> 123,
        'to' -> 456
      },
      'z' -> {
        'from' -> 123,
        'to' -> 456
      }
    },
    'door_pos' -> [130, 64, 130], // Where should intruders be transported when a safe landing point cannot be found
    'show_dis' -> 10, // How far away will target entities see barrier effect
    'expel_dis' -> 5.5, // How far will the barrier teleport intruder
    'visitor_tag' -> 'visitor', // Entities holding this label will be ignored by the barrier
    'target' -> 'player' // entity type to keep out, one type only.
  }:key
);
generate_particles(centerX, centerY, centerZ, isSideX, e) -> (
  area = get_env('area');
  centerX = clamp(area:'x':'from', floor(centerX), area:'x':'to');
  centerY = floor(centerY);
  centerZ = clamp(area:'z':'from', floor(centerZ), area:'z':'to');
  area = get_env('area');
  centerHori = if(isSideX, centerX, centerZ);
  range = area:if(isSideX,'x','z');
  c_for(hori = centerHori - 2, hori <= centerHori + 2, hori+=1,
    if(
      (hori < range:'from') || (hori > range:'to'),
      continue()
    );
    c_for(vert = centerY - 2, vert <= centerY + 2, vert+=1,
      if(
        (abs(vert - centerY) == 2) &&
        (abs(hori - centerHori) == 2),
        continue()
      );
      particle('minecraft:block_marker{block_state:"barrier"}', if(isSideX, hori, centerX) + 0.5, vert + 0.5, if(isSideX, centerZ, hori) + 0.5, 1, 0, 0, e)
    )
  )
);
nbt2uuid(nbt) -> (
  nbt = split(',',slice(nbt,3,46));
  c_for(id = 0, id < length(nbt),id += 1,
    tmp = number(nbt:id);
    nbt:id = str('%x',if(tmp < 0, tmp + 2^32, tmp));
    nbt:id = '0' * (8 - length(nbt:id)) + nbt:id;
  );
  str('%s%s%s%s%s%s%s%s-%s%s%s%s-%s%s%s%s-%s%s%s%s-%s%s%s%s%s%s%s%s%s%s%s%s',split(join('',nbt)))
);
search(list,value) -> (
  c_for(item = 0, item < length(list), item += 1,
    if(list:item == value, return(item))
  );
  return(-1)
);
pos_range(x1,z1,x2,z2) -> (
  '@e[type=' + get_env('target') + ',tag=!' + get_env('visitor_tag') + ',' +
  'x=' + x1 + ',y=-100,z=' + z1 +
  ',dx=' + (x2-x1) + ',dy=450,dz='+(z2-z1)+']'
);
find_surface(x,y,z) -> (
  x = floor(x);
  y = floor(y);
  z = floor(z);
  c_for(new_y = y, block(x,new_y,z) != block('void_air'), new_y += 1,
    if(!suffocates(x, new_y, z) && !suffocates(x, new_y+1, z), break());
    if(new_y > 320,return('failed'))
  );
  return(new_y);
);
to_surface(e,pos) -> (
  y = find_surface(pos:0,pos:1,pos:2);
  if(type(y) == 'string',
    modify(e, 'pos', pos:0, get_env('door_pos')),
    modify(e, 'pos', pos:0, find_surface(pos:0,pos:1,pos:2), pos:2)
  )
);
get_list() -> (
  area = get_env('area');
  show_dis = get_env('show_dis');
  entitys = entity_selector(pos_range(
    area:'x':'from' - show_dis,
    area:'z':'from' - show_dis,
    area:'x':'to' + show_dis,
    area:'z':'to' + show_dis
  ));
);
clamp(min,value,max) -> max(min,min(value,max));
own_tag(e,tag) -> (
  if(!e, return(false));
  search(query(e, 'scoreboard_tags'), tag) > -1
);
owner_own_tag(e,tag) -> (
  ownerid = query(e, 'nbt', 'Owner');
  if(!ownerid, return(false));
  owner = entity_id(nbt2uuid(ownerid));
  if(!owner, return(false));
  return(own_tag(owner,tag))
);
__on_tick() -> (
  area = get_env('area');
  show_dis = get_env('show_dis');
  entitys = entity_selector(pos_range(
    area:'x':'from' - show_dis,
    area:'z':'from' - show_dis,
    area:'x':'to' + show_dis,
    area:'z':'to' + show_dis
  ));
  c_for(i = 0, i < length(entitys), i += 1,
    if(!own_tag(owner,'not_' + get_env('visitor_tag')),
      if(owner_own_tag(entitys:i,get_env('visitor_tag')),
        modify(entitys:i,'tag',get_env('visitor_tag'));
        continue()
      );
      modify(entitys:i, 'tag', 'not_' + get_env('visitor_tag'));
    );
    pos = query(entitys:i, 'pos');
    in_x = false;
    in_z = false;
    if (pos:0 < area:'x':'from',
      generate_particles(area:'x':'from', (pos:1)+1, pos:2, false, entitys:i),
      if(pos:0 > area:'x':'to',
        generate_particles(area:'x':'to', (pos:1)+1, pos:2, false, entitys:i),
        in_x = true
      )
    );
    if (pos:2 < area:'z':'from',
      generate_particles(pos:0, (pos:1)+1, area:'z':'from', true, entitys:i),
      if(pos:2 > area:'z':'to',
        generate_particles(pos:0, (pos:1)+1, area:'z':'to', true, entitys:i),
        in_z = true
      )
    );
    if(in_x && in_z,
      middle_x = (area:'x':'to' + area:'x':'from') / 2;
      middle_z = (area:'z':'to' + area:'z':'from') / 2;
      dis_x = if(pos:0 < middle_x,
        pos:0 - area:'x':'from',
        area:'x':'to' - pos:0
      );
      dis_z = if(pos:2 < middle_z,
        pos:2 - area:'z':'from',
        area:'z':'to' - pos:2
      );
      expel_dis = get_env('expel_dis');
      if(dis_x < dis_z,
        pos:0 = if(pos:0 < middle_x,
          area:'x':'from' - expel_dis,
          area:'x':'to' + expel_dis
        ),
        pos:2 = if(pos:2 < middle_z,
          area:'z':'from' - expel_dis,
          area:'z':'to' + expel_dis
        )
      );
      to_surface(entitys:i,pos)
    )
  )
)
4
  • Hi @user24100575, congrats on finding a solution that works for you! I suggest removing your email from the header -- it opens you up to spam, without (IMO) much benefit. Leaving your Github username as an identifier might be enough for attribution. If you do decide to remove your email address, I'd suggest also raising a (self-)flag, to ask for moderator help to purge it from the revision history.
    – Schism
    Commented Jul 26 at 3:15
  • @Schism Thank you for reminding me. I have updated it, please delete all previous versions except for the latest one. Commented Jul 26 at 11:16
  • @user24100575 please accept your own answer, it's the little green checkmark under your arrows.
    – Cole Busby
    Commented Jul 26 at 18:21
  • @ColeBusby Okey I have done that. Commented Jul 27 at 10:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.